diff options
| -rw-r--r-- | drivers/video/mcde/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/video/mcde/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/mcde/display-ab8500.c | 5 | ||||
| -rw-r--r-- | drivers/video/mcde/display-av8100.c | 94 | ||||
| -rw-r--r-- | drivers/video/mcde/display-sony_acx424akp_dsi.c | 400 | ||||
| -rw-r--r-- | drivers/video/mcde/dsilink_regs.h | 1 | ||||
| -rw-r--r-- | drivers/video/mcde/mcde_bus.c | 4 | ||||
| -rw-r--r-- | drivers/video/mcde/mcde_fb.c | 61 | ||||
| -rw-r--r-- | drivers/video/mcde/mcde_hw.c | 170 | ||||
| -rw-r--r-- | include/video/mcde.h | 10 | ||||
| -rw-r--r-- | include/video/mcde_display-sony_acx424akp_dsi.h | 41 | ||||
| -rw-r--r-- | include/video/mcde_display.h | 1 |
12 files changed, 730 insertions, 62 deletions
diff --git a/drivers/video/mcde/Kconfig b/drivers/video/mcde/Kconfig index a1310332cf9..a2bca06b128 100644 --- a/drivers/video/mcde/Kconfig +++ b/drivers/video/mcde/Kconfig @@ -15,6 +15,10 @@ config MCDE_DISPLAY_GENERIC_DSI tristate "Generic DSI display driver" depends on FB_MCDE +config MCDE_DISPLAY_SONY_ACX424AKP_DSI + tristate "Sony acx424akp DSI display driver" + depends on FB_MCDE + config MCDE_DISPLAY_SONY_SY35560_DSI tristate "Sony sy35560 display driver" depends on FB_MCDE diff --git a/drivers/video/mcde/Makefile b/drivers/video/mcde/Makefile index 7c9324ded3a..1c6e5cde42b 100644 --- a/drivers/video/mcde/Makefile +++ b/drivers/video/mcde/Makefile @@ -3,6 +3,7 @@ mcde-objs := mcde_mod.o mcde_hw.o mcde_dss.o mcde_display.o mcde_bus.o mcde_fb obj-$(CONFIG_FB_MCDE) += mcde.o obj-$(CONFIG_MCDE_DISPLAY_GENERIC_DSI) += display-generic_dsi.o +obj-$(CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI) += display-sony_acx424akp_dsi.o obj-$(CONFIG_MCDE_DISPLAY_SONY_SY35560_DSI) += display-sony_sy35560_dsi.o obj-$(CONFIG_MCDE_DISPLAY_VUIB500_DPI) += display-vuib500-dpi.o obj-$(CONFIG_MCDE_DISPLAY_AB8500_DENC) += display-ab8500.o diff --git a/drivers/video/mcde/display-ab8500.c b/drivers/video/mcde/display-ab8500.c index 5d7f1bb92a6..789bf28cdf1 100644 --- a/drivers/video/mcde/display-ab8500.c +++ b/drivers/video/mcde/display-ab8500.c @@ -75,7 +75,8 @@ static int set_video_mode(struct mcde_display_device *ddev, static int set_power_mode(struct mcde_display_device *ddev, enum mcde_display_power_mode power_mode); static int on_first_update(struct mcde_display_device *ddev); -static int display_update(struct mcde_display_device *ddev, bool tripple_buf); +static int display_update(struct mcde_display_device *ddev, + bool tripple_buffer); static int __devinit ab8500_probe(struct mcde_display_device *ddev) { @@ -461,7 +462,7 @@ static int display_update(struct mcde_display_device *ddev, bool tripple_buffer) goto error; } ret = mcde_chnl_update(ddev->chnl_state, &ddev->update_area, - tripple_buffer); + tripple_buffer); if (ret < 0) goto error; out: diff --git a/drivers/video/mcde/display-av8100.c b/drivers/video/mcde/display-av8100.c index 688a4d17688..5602ec37ba5 100644 --- a/drivers/video/mcde/display-av8100.c +++ b/drivers/video/mcde/display-av8100.c @@ -24,6 +24,13 @@ #define SWITCH_HELPSTR ", 0=HDMI, 1=SDTV, 2=DVI\n" +/* AVI Infoframe */ +#define AVI_INFOFRAME_DATA_SIZE 13 +#define AVI_INFOFRAME_TYPE 0x82 +#define AVI_INFOFRAME_VERSION 0x02 +#define AVI_INFOFRAME_DB1 0x10 /* Active Information present */ +#define AVI_INFOFRAME_DB2 0x08 /* Active Portion Aspect ratio */ + struct cea_vesa_video_mode { u32 cea; u32 vesa_cea_nr; @@ -672,6 +679,40 @@ static struct mcde_video_mode *video_mode_get(struct mcde_display_device *ddev, return NULL; } +static u8 ceanr_get(struct mcde_display_device *ddev) +{ + int cnt; + int cea; + int vesa_cea_nr; + struct mcde_video_mode *vmode = &ddev->video_mode; + struct mcde_video_mode *vmode_try; + + if (!vmode) + return 0; + + dev_dbg(&ddev->dev, "%s\n", __func__); + + for (cnt = 0; cnt < ARRAY_SIZE(cea_vesa_video_mode); cnt++) { + vmode_try = cea_vesa_video_mode[cnt].video_mode; + cea = cea_vesa_video_mode[cnt].cea; + vesa_cea_nr = cea_vesa_video_mode[cnt].vesa_cea_nr; + + if (cea && vmode_try->xres == vmode->xres && + vmode_try->yres == vmode->yres && + vmode_try->pixclock == vmode->pixclock && + vmode_try->hbp == vmode->hbp && + vmode_try->hfp == vmode->hfp && + vmode_try->vbp == vmode->vbp && + vmode_try->vfp == vmode->vfp && + vmode_try->interlaced == vmode->interlaced) { + dev_dbg(&ddev->dev, "ceanr:%d\n", vesa_cea_nr); + return vesa_cea_nr; + } + } + + return 0; +} + #define AV8100_MAX_LEVEL 255 static int hdmi_try_video_mode( @@ -1167,6 +1208,9 @@ static int hdmi_on_first_update(struct mcde_display_device *dev) { int ret; union av8100_configuration av8100_config; + u8 *infofr_data; + int infofr_crc; + int cnt; dev->first_update = false; @@ -1235,6 +1279,45 @@ static int hdmi_on_first_update(struct mcde_display_device *dev) return ret; } + /* AVI Infoframe only if HDMI */ + if (dev->port->hdmi_sdtv_switch != HDMI_SWITCH) + goto hdmi_on_first_update_end; + + /* Create AVI Infoframe */ + av8100_config.infoframes_format.type = AVI_INFOFRAME_TYPE; + av8100_config.infoframes_format.version = AVI_INFOFRAME_VERSION; + av8100_config.infoframes_format.length = AVI_INFOFRAME_DATA_SIZE; + + /* AVI Infoframe data */ + infofr_data = &av8100_config.infoframes_format.data[0]; + memset(infofr_data, 0, AVI_INFOFRAME_DATA_SIZE); + infofr_data[0] = AVI_INFOFRAME_DB1; + infofr_data[1] = AVI_INFOFRAME_DB2; + infofr_data[3] = ceanr_get(dev); + + /* Calculate AVI Infoframe checksum */ + infofr_crc = av8100_config.infoframes_format.type + + av8100_config.infoframes_format.version + + av8100_config.infoframes_format.length; + for (cnt = 0; cnt < AVI_INFOFRAME_DATA_SIZE; cnt++) + infofr_crc += infofr_data[cnt]; + infofr_crc &= 0xFF; + av8100_config.infoframes_format.crc = 0x100 - infofr_crc; + + /* Send AVI Infoframe */ + if (av8100_conf_prep(AV8100_COMMAND_INFOFRAMES, + &av8100_config) != 0) { + dev_err(&dev->dev, "av8100_conf_prep FAIL\n"); + return -EINVAL; + } + + if (av8100_conf_w(AV8100_COMMAND_INFOFRAMES, + NULL, NULL, I2C_INTERFACE) != 0) { + dev_err(&dev->dev, "av8100_conf_w FAIL\n"); + return -EINVAL; + } + +hdmi_on_first_update_end: return ret; } @@ -1285,7 +1368,10 @@ static int hdmi_set_power_mode(struct mcde_display_device *ddev, if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY && power_mode == MCDE_DISPLAY_PM_OFF) { memset(&(ddev->video_mode), 0, sizeof(struct mcde_video_mode)); - + ret = av8100_powerscan(); + if (ret) + dev_err(&ddev->dev, "%s:av8100_powerscan failed\n" + , __func__); if (ddev->platform_disable) { ret = ddev->platform_disable(ddev); if (ret) @@ -1422,6 +1508,9 @@ static int hdmi_resume(struct mcde_display_device *ddev) { int ret; + if (ddev->chnl_state == NULL) + return 0; + /* set_power_mode will handle call platform_enable */ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY); if (ret < 0) @@ -1435,6 +1524,9 @@ static int hdmi_suspend(struct mcde_display_device *ddev, pm_message_t state) { int ret; + if (ddev->chnl_state == NULL) + return 0; + /* set_power_mode will handle call platform_disable */ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF); if (ret < 0) diff --git a/drivers/video/mcde/display-sony_acx424akp_dsi.c b/drivers/video/mcde/display-sony_acx424akp_dsi.c new file mode 100644 index 00000000000..602c85f229f --- /dev/null +++ b/drivers/video/mcde/display-sony_acx424akp_dsi.c @@ -0,0 +1,400 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * ST-Ericsson MCDE Sony acx424akp DCS display driver + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/err.h> + +#include <video/mcde_display.h> +#include <video/mcde_display-sony_acx424akp_dsi.h> + +static int display_read_deviceid(struct mcde_display_device *dev, u16 *id) +{ + struct mcde_chnl_state *chnl; + + u8 id1, id2, id3; + int len = 1; + int ret = 0; + int readret = 0; + + dev_dbg(&dev->dev, "%s: Read device id of the display\n", __func__); + + /* Acquire MCDE resources */ + chnl = mcde_chnl_get(dev->chnl_id, dev->fifo, dev->port); + if (IS_ERR(chnl)) { + ret = PTR_ERR(chnl); + dev_warn(&dev->dev, "Failed to acquire MCDE channel\n"); + goto out; + } + + /* plugnplay: use registers DA, DBh and DCh to detect display */ + readret = mcde_dsi_dcs_read(chnl, 0xDA, (u32 *)&id1, &len); + if (!readret) + readret = mcde_dsi_dcs_read(chnl, 0xDB, (u32 *)&id2, &len); + if (!readret) + readret = mcde_dsi_dcs_read(chnl, 0xDC, (u32 *)&id3, &len); + + if (readret) { + dev_info(&dev->dev, + "mcde_dsi_dcs_read failed to read display ID\n"); + goto read_fail; + } + + *id = (id3 << 8) | id2; +read_fail: + /* close MCDE channel */ + mcde_chnl_put(chnl); +out: + return 0; +} + +static int sony_acx424akp_platform_enable(struct mcde_display_device *dev) +{ + struct mcde_display_sony_acx424akp_platform_data *pdata = + dev->dev.platform_data; + + dev_dbg(&dev->dev, "%s: Reset & power on sony display\n", __func__); + + if (pdata->regulator) { + if (regulator_enable(pdata->regulator) < 0) { + dev_err(&dev->dev, "%s:Failed to enable regulator\n" + , __func__); + return -EINVAL; + } + } + if (pdata->reset_gpio) + gpio_set_value(pdata->reset_gpio, pdata->reset_high); + msleep(pdata->reset_delay); /* as per sony lcd spec */ + if (pdata->reset_gpio) + gpio_set_value(pdata->reset_gpio, !pdata->reset_high); + msleep(pdata->reset_low_delay); /* as per sony lcd spec */ + if (pdata->reset_gpio) + gpio_set_value(pdata->reset_gpio, pdata->reset_high); + msleep(pdata->reset_delay); /* as per sony lcd spec */ + + return 0; +} + +static int sony_acx424akp_platform_disable(struct mcde_display_device *dev) +{ + struct mcde_display_sony_acx424akp_platform_data *pdata = + dev->dev.platform_data; + + dev_dbg(&dev->dev, "%s:Reset & power off sony display\n", __func__); + + if (pdata->regulator) { + if (regulator_disable(pdata->regulator) < 0) { + dev_err(&dev->dev, "%s:Failed to disable regulator\n" + , __func__); + return -EINVAL; + } + } + return 0; +} + +static int sony_acx424akp_set_scan_mode(struct mcde_display_device *ddev, + enum mcde_display_power_mode power_mode) +{ + int ret = 0; + u8 param[MCDE_MAX_DSI_DIRECT_CMD_WRITE]; + + dev_dbg(&ddev->dev, "%s:Set Power mode\n", __func__); + + /* 180 rotation for SONY ACX424AKP display */ + if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY) { + param[0] = 0xAA; + ret = mcde_dsi_dcs_write(ddev->chnl_state, 0xf3, param, 1); + if (ret) + return ret; + + param[0] = 0x00; + param[1] = 0x00; + ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3); + if (ret) + return ret; + + param[0] = 0xC9; + param[1] = 0x01; + ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3); + if (ret) + return ret; + + param[0] = 0xA2; + param[1] = 0x00; + ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3); + if (ret) + return ret; + + param[0] = 0xFF; + param[1] = 0xAA; + ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3); + if (ret) + return ret; + } + return ret; +} + +static int sony_acx424akp_set_power_mode(struct mcde_display_device *ddev, + enum mcde_display_power_mode power_mode) +{ + int ret = 0; + struct mcde_display_sony_acx424akp_platform_data *pdata = + ddev->dev.platform_data; + + dev_dbg(&ddev->dev, "%s:Set Power mode\n", __func__); + + /* OFF -> STANDBY */ + if (ddev->power_mode == MCDE_DISPLAY_PM_OFF && + power_mode != MCDE_DISPLAY_PM_OFF) { + + if (ddev->platform_enable) { + ret = ddev->platform_enable(ddev); + if (ret) + return ret; + } + + ddev->power_mode = MCDE_DISPLAY_PM_STANDBY; + } + + /* STANDBY -> ON */ + if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY && + power_mode == MCDE_DISPLAY_PM_ON) { + + ret = mcde_dsi_dcs_write(ddev->chnl_state, + DCS_CMD_EXIT_SLEEP_MODE, NULL, 0); + if (ret) + return ret; + + msleep(pdata->sleep_out_delay); + + ret = mcde_dsi_dcs_write(ddev->chnl_state, + DCS_CMD_SET_DISPLAY_ON, NULL, 0); + if (ret) + return ret; + + ddev->power_mode = MCDE_DISPLAY_PM_ON; + goto set_power_and_exit; + } + /* ON -> STANDBY */ + else if (ddev->power_mode == MCDE_DISPLAY_PM_ON && + power_mode <= MCDE_DISPLAY_PM_STANDBY) { + ret = mcde_dsi_dcs_write(ddev->chnl_state, + DCS_CMD_SET_DISPLAY_OFF, NULL, 0); + if (ret) + return ret; + + ret = mcde_dsi_dcs_write(ddev->chnl_state, + DCS_CMD_ENTER_SLEEP_MODE, NULL, 0); + if (ret) + return ret; + + ddev->power_mode = MCDE_DISPLAY_PM_STANDBY; + } + + /* SLEEP -> OFF */ + if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY && + power_mode == MCDE_DISPLAY_PM_OFF) { + if (ddev->platform_disable) { + ret = ddev->platform_disable(ddev); + if (ret) + return ret; + } + ddev->power_mode = MCDE_DISPLAY_PM_OFF; + } + +set_power_and_exit: + mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode); + ret = sony_acx424akp_set_scan_mode(ddev, power_mode); + + return ret; +} + +static int __devinit sony_acx424akp_probe(struct mcde_display_device *dev) +{ + int ret = 0; + u16 id; + struct mcde_display_sony_acx424akp_platform_data *pdata = + dev->dev.platform_data; + + if (pdata == NULL) { + dev_err(&dev->dev, "%s:Platform data missing\n", __func__); + return -EINVAL; + } + + if (dev->port->type != MCDE_PORTTYPE_DSI) { + dev_err(&dev->dev, + "%s:Invalid port type %d\n", + __func__, dev->port->type); + return -EINVAL; + } + + if (!dev->platform_enable && !dev->platform_disable) { + pdata->sony_acx424akp_platform_enable = true; + if (pdata->reset_gpio) { + ret = gpio_request(pdata->reset_gpio, NULL); + if (ret) { + dev_warn(&dev->dev, + "%s:Failed to request gpio %d\n", + __func__, pdata->reset_gpio); + goto gpio_request_failed; + } + gpio_direction_output(pdata->reset_gpio, + !pdata->reset_high); + } + if (pdata->regulator_id) { + pdata->regulator = regulator_get(NULL, + pdata->regulator_id); + if (IS_ERR(pdata->regulator)) { + ret = PTR_ERR(pdata->regulator); + dev_warn(&dev->dev, + "%s:Failed to get regulator '%s'\n", + __func__, pdata->regulator_id); + pdata->regulator = NULL; + goto regulator_get_failed; + } + regulator_set_voltage(pdata->regulator, + pdata->min_supply_voltage, + pdata->max_supply_voltage); + /* + * When u-boot has display a startup screen. + * U-boot has turned on display power however the + * regulator framework does not know about that + * This is the case here, the display driver has to + * enable the regulator for the display. + */ + if (dev->power_mode == MCDE_DISPLAY_PM_STANDBY) { + ret = regulator_enable(pdata->regulator); + if (ret < 0) { + dev_err(&dev->dev, + "%s:Failed to enable regulator\n" + , __func__); + goto regulator_enable_failed; + } + } + } + } + + /* TODO: Remove when DSI send command uses interrupts */ + dev->prepare_for_update = NULL; + dev->platform_enable = sony_acx424akp_platform_enable, + dev->platform_disable = sony_acx424akp_platform_disable, + dev->set_power_mode = sony_acx424akp_set_power_mode; + + ret = display_read_deviceid(dev, &id); + + switch (id) { + case DISPLAY_SONY_ACX424AKP: + pdata->disp_panel = DISPLAY_SONY_ACX424AKP; + dev_info(&dev->dev, "Sony ACX424AKP display (ID 0x%.4X) \ + probed\n", id); + goto out; + + default: + pdata->disp_panel = DISPLAY_NONE; + dev_warn(&dev->dev, "Display not recognized\n"); + break; + } + +regulator_enable_failed: +regulator_get_failed: + if (pdata->sony_acx424akp_platform_enable && pdata->reset_gpio) + gpio_free(pdata->reset_gpio); +gpio_request_failed: +out: + return ret; +} + +static int __devexit sony_acx424akp_remove(struct mcde_display_device *dev) +{ + struct mcde_display_sony_acx424akp_platform_data *pdata = + dev->dev.platform_data; + + dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF); + + if (!pdata->sony_acx424akp_platform_enable) + return 0; + + if (pdata->regulator) + regulator_put(pdata->regulator); + if (pdata->reset_gpio) { + gpio_direction_input(pdata->reset_gpio); + gpio_free(pdata->reset_gpio); + } + + return 0; +} + +#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM) +static int sony_acx424akp_resume(struct mcde_display_device *ddev) +{ + int ret; + + /* set_power_mode will handle call platform_enable */ + ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY); + if (ret < 0) + dev_warn(&ddev->dev, "%s:Failed to resume display\n" + , __func__); + ddev->set_synchronized_update(ddev, + ddev->get_synchronized_update(ddev)); + return ret; +} + +static int sony_acx424akp_suspend(struct mcde_display_device *ddev, \ + pm_message_t state) +{ + int ret; + + /* set_power_mode will handle call platform_disable */ + ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF); + if (ret < 0) + dev_warn(&ddev->dev, "%s:Failed to suspend display\n" + , __func__); + return ret; +} +#endif + +static struct mcde_display_driver sony_acx424akp_driver = { + .probe = sony_acx424akp_probe, + .remove = sony_acx424akp_remove, +#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM) + .suspend = sony_acx424akp_suspend, + .resume = sony_acx424akp_resume, +#else + .suspend = NULL, + .resume = NULL, +#endif + .driver = { + .name = "mcde_disp_sony_acx424akp", + }, +}; + +/* Module init */ +static int __init mcde_display_sony_acx424akp_init(void) +{ + pr_info("%s\n", __func__); + + return mcde_display_driver_register(&sony_acx424akp_driver); +} +module_init(mcde_display_sony_acx424akp_init); + +static void __exit mcde_display_sony_acx424akp_exit(void) +{ + pr_info("%s\n", __func__); + + mcde_display_driver_unregister(&sony_acx424akp_driver); +} +module_exit(mcde_display_sony_acx424akp_exit); + +MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ST-Ericsson MCDE Sony ACX424AKP DCS display driver"); diff --git a/drivers/video/mcde/dsilink_regs.h b/drivers/video/mcde/dsilink_regs.h index 2322041ffec..29fa75a1752 100644 --- a/drivers/video/mcde/dsilink_regs.h +++ b/drivers/video/mcde/dsilink_regs.h @@ -474,6 +474,7 @@ #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 21 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_LONG_WRITE 57 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_READ 6 +#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SET_MAX_PKT_SIZE 55 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(__x) \ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_HEAD, \ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_##__x) diff --git a/drivers/video/mcde/mcde_bus.c b/drivers/video/mcde/mcde_bus.c index 3d7049652a1..a742aea5b3d 100644 --- a/drivers/video/mcde/mcde_bus.c +++ b/drivers/video/mcde/mcde_bus.c @@ -30,14 +30,14 @@ struct bus_type mcde_bus_type; static int mcde_suspend_device(struct device *dev, void *data) { pm_message_t* state = (pm_message_t *) data; - if (dev->driver->suspend) + if (dev->driver && dev->driver->suspend) return dev->driver->suspend(dev, *state); return 0; } static int mcde_resume_device(struct device *dev, void *data) { - if (dev->driver->resume) + if (dev->driver && dev->driver->resume) return dev->driver->resume(dev); return 0; } diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c index 628b10953f6..332e371d54b 100644 --- a/drivers/video/mcde/mcde_fb.c +++ b/drivers/video/mcde/mcde_fb.c @@ -485,6 +485,8 @@ static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev) var = &fbi->var; + ddev->check_transparency = 60; + /* Reallocate memory */ line_len = (fbi->var.bits_per_pixel * var->xres_virtual) / 8; line_len = ALIGN(line_len, MCDE_BUF_LINE_ALIGMENT); @@ -564,31 +566,47 @@ static int mcde_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) static int mcde_fb_set_par(struct fb_info *fbi) { + struct mcde_fb *mfb = to_mcde_fb(fbi); + struct mcde_display_device *ddev = fb_to_display(fbi); dev_vdbg(fbi->dev, "%s\n", __func__); - return apply_var(fbi, fb_to_display(fbi)); -} - -static int mcde_fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *fbi) -{ - dev_vdbg(fbi->dev, "%s\n", __func__); + if (mfb->ovlys[0]->state == NULL && + ddev->fictive == false) { + printk(KERN_INFO "%s() - Enable fb %p\n", + __func__, + mfb->ovlys[0]); + mcde_dss_enable_overlay(mfb->ovlys[0]); + } - /*Nothing to see here, move along*/ - return 0; + return apply_var(fbi, ddev); } -static int mcde_fb_setcmap(struct fb_cmap *cmap, struct fb_info *fbi) +static int mcde_fb_blank(int blank, struct fb_info *fbi) { + int ret = 0; + struct mcde_display_device *ddev = fb_to_display(fbi); + dev_vdbg(fbi->dev, "%s\n", __func__); - /*Nothing to see here, move along*/ - return 0; -} + if (ddev->fictive) + goto mcde_fb_blank_end; + + switch (blank) { + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + mcde_dss_disable_display(ddev); + break; + case FB_BLANK_UNBLANK: + ret = mcde_dss_enable_display(ddev); + break; + default: + ret = -EINVAL; + } -static int mcde_fb_blank(int blank, struct fb_info *fbi) -{ - return 0; +mcde_fb_blank_end: + return ret; } static int mcde_fb_pan_display(struct fb_var_screeninfo *var, @@ -633,8 +651,6 @@ static struct fb_ops fb_ops = { .fb_imageblit = sys_imageblit, .fb_check_var = mcde_fb_check_var, .fb_set_par = mcde_fb_set_par, - .fb_setcolreg = mcde_fb_setcolreg, - .fb_setcmap = mcde_fb_setcmap, .fb_blank = mcde_fb_blank, .fb_pan_display = mcde_fb_pan_display, .fb_rotate = mcde_fb_rotate, @@ -711,10 +727,6 @@ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev, if (ret) goto fb_register_failed; - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret) - dev_warn(&ddev->dev, "%s: Allocate color map memory failed!\n", __func__); - ddev->fbi = fbi; #ifdef CONFIG_HAS_EARLYSUSPEND @@ -771,10 +783,9 @@ void mcde_fb_destroy(struct mcde_display_device *dev) mcde_dss_destroy_overlay(mfb->ovlys[i]); } - fb_dealloc_cmap(&dev->fbi->cmap); - #ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&mfb->early_suspend); + if (dev->fictive == false) + unregister_early_suspend(&mfb->early_suspend); #endif unregister_framebuffer(dev->fbi); free_fb_mem(dev->fbi); diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c index 585b22f9111..4653f148b7f 100644 --- a/drivers/video/mcde/mcde_hw.c +++ b/drivers/video/mcde/mcde_hw.c @@ -32,6 +32,7 @@ static void disable_channel(struct mcde_chnl_state *chnl); static void watchdog_auto_sync_timer_function(unsigned long arg); +static int _mcde_chnl_enable(struct mcde_chnl_state *chnl); static int _mcde_chnl_apply(struct mcde_chnl_state *chnl); static void disable_flow(struct mcde_chnl_state *chnl); static void enable_channel(struct mcde_chnl_state *chnl); @@ -654,7 +655,8 @@ static void dpi_video_mode_apply(struct mcde_chnl_state *chnl) chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P_BE; else chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P; - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) chnl->tv_regs.inv_clk = true; else { chnl->tv_regs.dho = MCDE_CONFIG_TVOUT_HBORDER; @@ -720,7 +722,8 @@ static void update_dpi_registers(enum mcde_chnl chnl_id, struct tv_regs *regs) /* Horizontal timing registers */ if (!regs->sel_mode_tv || - hardware_version == MCDE_CHIP_VERSION_3_0_8) { + hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) { mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET, MCDE_TVLBALWA_LBW(regs->hsw) | MCDE_TVLBALWA_ALW(regs->alw)); @@ -898,14 +901,16 @@ static inline void mcde_handle_vcmp(struct mcde_chnl_state *chnl, u32 int_fld) chnl->port.sync_src == MCDE_SYNCSRC_OFF && chnl->port.type == MCDE_PORTTYPE_DSI && chnl->continous_running) { - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) enable_channel(chnl); mcde_wreg(MCDE_CHNL0SYNCHSW + chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET, MCDE_CHNL0SYNCHSW_SW_TRIG(true)); - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) disable_flow(chnl); mod_timer(&chnl->auto_sync_timer, jiffies + @@ -1025,7 +1030,8 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev) irq_status = dsi_rfld(i, DSI_DIRECT_CMD_STS_FLAG, TE_RECEIVED_FLAG); if (irq_status) { - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) disable_flow(chnl_from_dsi); dsi_wreg(i, DSI_DIRECT_CMD_STS_CLR, DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR(true)); @@ -1037,7 +1043,8 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev) irq_status = dsi_rfld(i, DSI_CMD_MODE_STS_FLAG, ERR_NO_TE_FLAG); if (irq_status) { - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) disable_flow(chnl_from_dsi); dsi_wreg(i, DSI_CMD_MODE_STS_CLR, DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR(true)); @@ -1130,7 +1137,8 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl) (port->sync_src == MCDE_SYNCSRC_TE1)) mcde_wreg(MCDE_CTRLC1, MCDE_CTRLC1_FIFOWTRMRK( get_output_fifo_size(MCDE_FIFO_C1))); - } else if (hardware_version == MCDE_CHIP_VERSION_3_0_8) { + } else if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) { switch (chnl->fifo) { case MCDE_FIFO_A: mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id * @@ -1480,6 +1488,18 @@ static void chnl_ovly_pixel_format_apply(struct mcde_chnl_state *chnl, mcde_chnl_col_convert_apply(chnl, &chnl->rgb_2_ycbcr); else mcde_chnl_col_convert_apply(chnl, &crycb_2_ycbcr); + } else if (port->type == MCDE_PORTTYPE_DPI) { + /* Note: YUV is not support port pixel format for DPI */ + if (ovly->pix_fmt != MCDE_OVLYPIXFMT_YCbCr422) { + /* standard case: DPI: RGB -> RGB */ + regs->col_conv = MCDE_OVL0CR_COLCCTRL_DISABLED; + } else { + /* DPI: YUV -> RGB */ + regs->col_conv = + MCDE_OVL0CR_COLCCTRL_ENABLED_SAT; + mcde_chnl_col_convert_apply(chnl, + &chnl->ycbcr_2_rgb); + } } } @@ -1611,7 +1631,8 @@ static void do_softwaretrig(struct mcde_chnl_state *chnl) * However FLOWEN must not be triggered before SOFTWARE TRIG * if rotation is enabled */ - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) enable_channel(chnl); else if ((!is_channel_enabled(chnl) && !chnl->regs.roten) || chnl->power_mode != MCDE_DISPLAY_PM_ON) @@ -1621,7 +1642,8 @@ static void do_softwaretrig(struct mcde_chnl_state *chnl) chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET, MCDE_CHNL0SYNCHSW_SW_TRIG(true)); - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) disable_flow(chnl); else enable_channel(chnl); @@ -2116,17 +2138,18 @@ static int enable_mcde_hw(void) return 0; } +#define DSI_WRITE_CMD_TIMEOUT 1000 + /* DSI */ static int mcde_dsi_direct_cmd_write(struct mcde_chnl_state *chnl, bool dcs, u8 cmd, u8 *data, int len) { - int i; + int i, ret = 0; u32 wrdat[4] = { 0, 0, 0, 0 }; u32 settings; u8 link = chnl->port.link; u8 virt_id = chnl->port.phy.dsi.virt_id; - u32 ok; - u32 error; + u32 counter = DSI_WRITE_CMD_TIMEOUT; if (len > MCDE_MAX_DSI_DIRECT_CMD_WRITE || chnl->port.type != MCDE_PORTTYPE_DSI) @@ -2134,6 +2157,7 @@ static int mcde_dsi_direct_cmd_write(struct mcde_chnl_state *chnl, mutex_lock(&mcde_hw_lock); + _mcde_chnl_enable(chnl); if (enable_mcde_hw()) { mutex_unlock(&mcde_hw_lock); return -EINVAL; @@ -2193,21 +2217,35 @@ static int mcde_dsi_direct_cmd_write(struct mcde_chnl_state *chnl, if (len > 11) dsi_wreg(link, DSI_DIRECT_CMD_WRDAT3, wrdat[3]); dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0); + dsi_wreg(link, DSI_CMD_MODE_STS_CLR, ~0); dsi_wreg(link, DSI_DIRECT_CMD_SEND, true); - /* TODO: irq wait and error check */ - mdelay(10); + /* loop will normally run zero or one time until WRITE_COMPLETED */ + while (!dsi_rfld(link, DSI_DIRECT_CMD_STS, WRITE_COMPLETED) + && --counter) + cpu_relax(); - ok = dsi_rreg(link, DSI_DIRECT_CMD_STS); - error = dsi_rreg(link, DSI_CMD_MODE_STS); - dev_vdbg(&mcde_dev->dev, "DSI Write ok %x error %x\n", ok, error); + if (!counter) { + dev_err(&mcde_dev->dev, + "%s: DSI write cmd 0x%x timeout on DSI link %u!\n", + __func__, cmd, link); + ret = -ETIME; + } else { + /* inform if >100 loops before command completion */ + if (counter < (DSI_WRITE_CMD_TIMEOUT-DSI_WRITE_CMD_TIMEOUT/10)) + dev_vdbg(&mcde_dev->dev, + "%s: %u loops for DSI command %x completion\n", + __func__, (DSI_WRITE_CMD_TIMEOUT - counter), + cmd); - dsi_wreg(link, DSI_CMD_MODE_STS_CLR, ~0); - dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0); + dev_vdbg(&mcde_dev->dev, "DSI Write ok %x error %x\n", + dsi_rreg(link, DSI_DIRECT_CMD_STS_FLAG), + dsi_rreg(link, DSI_CMD_MODE_STS_FLAG)); + } mutex_unlock(&mcde_hw_lock); - return 0; + return ret; } int mcde_dsi_generic_write(struct mcde_chnl_state *chnl, u8* para, int len) @@ -2220,7 +2258,8 @@ int mcde_dsi_dcs_write(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int len) return mcde_dsi_direct_cmd_write(chnl, true, cmd, data, len); } -int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int *len) +int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, + u8 cmd, u32 *data, int *len) { int ret = 0; u8 link = chnl->port.link; @@ -2234,6 +2273,7 @@ int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int *len) mutex_lock(&mcde_hw_lock); + _mcde_chnl_enable(chnl); if (enable_mcde_hw()) { mutex_unlock(&mcde_hw_lock); return -EINVAL; @@ -2288,6 +2328,61 @@ int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int *len) return ret; } +/* + * Set Maximum Return Packet size is a command that specifies the + * maximum size of the payload transmitted from peripheral back to + * the host processor. + * + * During power-on or reset sequence, the Maximum Return Packet Size + * is set to a default value of one. In order to be able to use + * mcde_dsi_dcs_read for reading more than 1 byte at a time, this + * parameter should be set by the host processor to the desired value + * in the initialization routine before commencing normal operation. + */ +int mcde_dsi_set_max_pkt_size(struct mcde_chnl_state *chnl, int size) +{ + u32 settings; + u8 link = chnl->port.link; + u8 virt_id = chnl->port.phy.dsi.virt_id; + + if (chnl->port.type != MCDE_PORTTYPE_DSI) + return -EINVAL; + + if (size > 4) + return -EINVAL; + + mutex_lock(&mcde_hw_lock); + + if (enable_mcde_hw()) { + mutex_unlock(&mcde_hw_lock); + return -EINVAL; + } + + /* + * Set Maximum Return Packet Size is a four-byte command packet + * (including ECC) that specifies the maximum size of the payload. + * The order of bytes is: + * Data ID, two-byte value for maximum return packet size, + * followed by the ECC byte. + */ + + settings = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(WRITE) | + DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(1) | + DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(virt_id) | + DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(size) | + DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(true); + settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM( + SET_MAX_PKT_SIZE); + dsi_wreg(link, DSI_DIRECT_CMD_MAIN_SETTINGS, settings); + dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0); + dsi_wreg(link, DSI_DIRECT_CMD_SEND, true); + + dsi_wreg(link, DSI_CMD_MODE_STS_CLR, ~0); + dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0); + + mutex_unlock(&mcde_hw_lock); + return 0; +} static void dsi_te_poll_req(struct mcde_chnl_state *chnl) { @@ -2562,7 +2657,8 @@ static void chnl_update_continous(struct mcde_chnl_state *chnl, if (chnl->port.sync_src == MCDE_SYNCSRC_TE0) { mcde_wfld(MCDE_CRC, SYCEN0, true); } else if (chnl->port.sync_src == MCDE_SYNCSRC_TE1) { - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) { + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) { mcde_wfld(MCDE_VSCRC1, VSSEL, 1); mcde_wfld(MCDE_CRC, SYCEN1, true); } else { @@ -2582,7 +2678,8 @@ static void chnl_update_continous(struct mcde_chnl_state *chnl, if (chnl->port.type == MCDE_PORTTYPE_DSI && chnl->port.sync_src == MCDE_SYNCSRC_OFF) { chnl->disable_software_trig = false; - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) { + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) { mcde_wreg(MCDE_CHNL0SYNCHSW + chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET, MCDE_CHNL0SYNCHSW_SW_TRIG(true)); @@ -2607,7 +2704,8 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl) chnl->power_mode == MCDE_DISPLAY_PM_ON) { if (chnl->port.type == MCDE_PORTTYPE_DSI && chnl->port.sync_src == MCDE_SYNCSRC_BTA) { - if (hardware_version == MCDE_CHIP_VERSION_3_0_8) + if (hardware_version == MCDE_CHIP_VERSION_3_0_8 || + hardware_version == MCDE_CHIP_VERSION_4_0_4) enable_channel(chnl); wait_while_dsi_running(chnl->port.link); dsi_te_request(chnl); @@ -2633,6 +2731,8 @@ static void chnl_update_overlay(struct mcde_chnl_state *chnl, chnl->fifo, chnl->regs.x, chnl->regs.y, chnl->regs.ppl, chnl->regs.lpf, ovly->stride, chnl->vmode.interlaced, chnl->rotation); + if (chnl->id == MCDE_CHNL_A || chnl->id == MCDE_CHNL_B) + update_col_registers(chnl->id, &chnl->col_regs); } } @@ -2678,6 +2778,13 @@ static int _mcde_chnl_update(struct mcde_chnl_state *chnl, return 0; } +static int _mcde_chnl_enable(struct mcde_chnl_state *chnl) +{ + dev_vdbg(&mcde_dev->dev, "%s\n", __func__); + chnl->enabled = true; + return 0; +} + /* API entry points */ /* MCDE channels */ struct mcde_chnl_state *mcde_chnl_get(enum mcde_chnl chnl_id, @@ -2928,7 +3035,7 @@ void mcde_chnl_enable(struct mcde_chnl_state *chnl) dev_vdbg(&mcde_dev->dev, "%s\n", __func__); mutex_lock(&mcde_hw_lock); - chnl->enabled = true; + _mcde_chnl_enable(chnl); mutex_unlock(&mcde_hw_lock); dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__); @@ -3209,8 +3316,6 @@ static int init_clocks_and_power(struct platform_device *pdev) } else { dev_dbg(&pdev->dev, "%s: No regulator id supplied\n", __func__); - ret = -EINVAL; - goto regulator_vana_err; } #endif @@ -3421,7 +3526,13 @@ static int __devinit mcde_probe(struct platform_device *pdev) development_version >= 4) { hardware_version = MCDE_CHIP_VERSION_1_0_4; mcde_dynamic_power_management = false; + num_channels = 2; + num_overlays = 3; dev_info(&mcde_dev->dev, "V1_U5500 HW\n"); + } else if (major_version == 4 && minor_version == 0 && + development_version >= 4) { + hardware_version = MCDE_CHIP_VERSION_4_0_4; + dev_info(&mcde_dev->dev, "V2_U5500 HW\n"); } else { dev_err(&mcde_dev->dev, "Unsupported HW version\n"); ret = -ENOTSUPP; @@ -3458,6 +3569,7 @@ static int __devinit mcde_probe(struct platform_device *pdev) init_timer(&channels[i].auto_sync_timer); channels[i].auto_sync_timer.function = watchdog_auto_sync_timer_function; + init_timer(&channels[i].dsi_te_timer); channels[i].dsi_te_timer.function = dsi_te_timer_function; @@ -3467,7 +3579,6 @@ static int __devinit mcde_probe(struct platform_device *pdev) return 0; failed_hardware_version: - free_irq(mcde_irq, &pdev->dev); failed_request_irq: disable_mcde_hw(true); failed_enable_clocks: @@ -3492,6 +3603,8 @@ failed_overlays_alloc: kfree(channels); channels = NULL; failed_channels_alloc: + num_channels = 0; + num_overlays = 0; return ret; } @@ -3570,7 +3683,6 @@ static struct platform_driver mcde_driver = { int __init mcde_init(void) { mutex_init(&mcde_hw_lock); - return platform_driver_register(&mcde_driver); } diff --git a/include/video/mcde.h b/include/video/mcde.h index 213f33e43fe..75992bf7d57 100644 --- a/include/video/mcde.h +++ b/include/video/mcde.h @@ -236,7 +236,7 @@ enum mcde_display_rotation { #define MCDE_FIFO_AB_SIZE 640 #define MCDE_FIFO_C0C1_SIZE 160 -#define MCDE_PIXFETCH_LARGE_WTRMRKLVL 128 +#define MCDE_PIXFETCH_LARGE_WTRMRKLVL 256 #define MCDE_PIXFETCH_MEDIUM_WTRMRKLVL 64 #define MCDE_PIXFETCH_SMALL_WTRMRKLVL 16 @@ -251,6 +251,7 @@ enum mcde_display_rotation { #define MCDE_AUTO_SYNC_WATCHDOG 5 /* Hardware versions */ +#define MCDE_CHIP_VERSION_4_0_4 4 /* U5500 V2 */ #define MCDE_CHIP_VERSION_1_0_4 3 /* U5500 V1 */ #define MCDE_CHIP_VERSION_3_0_8 2 /* U8500 V2 */ #define MCDE_CHIP_VERSION_3_0_5 1 /* U8500 V1 */ @@ -412,8 +413,11 @@ void mcde_ovly_put(struct mcde_ovly_state *ovly); #define MCDE_MAX_DSI_DIRECT_CMD_WRITE 15 int mcde_dsi_generic_write(struct mcde_chnl_state *chnl, u8* para, int len); -int mcde_dsi_dcs_write(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int len); -int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int *len); +int mcde_dsi_dcs_write(struct mcde_chnl_state *chnl, + u8 cmd, u8 *data, int len); +int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl, + u8 cmd, u32 *data, int *len); +int mcde_dsi_set_max_pkt_size(struct mcde_chnl_state *chnl, int size); /* MCDE */ diff --git a/include/video/mcde_display-sony_acx424akp_dsi.h b/include/video/mcde_display-sony_acx424akp_dsi.h new file mode 100644 index 00000000000..de862a3f28b --- /dev/null +++ b/include/video/mcde_display-sony_acx424akp_dsi.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * ST-Ericsson MCDE Sony acx424akp DCS display driver + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ +#ifndef __MCDE_DISPLAY_SONY_ACX424AKP__H__ +#define __MCDE_DISPLAY_SONY_ACX424AKP__H__ + +#include <linux/regulator/consumer.h> + +#include "mcde_display.h" + +enum display_panel_type { + DISPLAY_NONE = 0, + DISPLAY_SONY_ACX424AKP = 0x1b81, +}; + +struct mcde_display_sony_acx424akp_platform_data { + /* Platform info */ + int reset_gpio; + bool reset_high; + const char *regulator_id; + int reset_delay; /* ms */ + int reset_low_delay; /* ms */ + int sleep_out_delay; /* ms */ + enum display_panel_type disp_panel; /* display panel types */ + + /* Driver data */ + bool sony_acx424akp_platform_enable; + struct regulator *regulator; + int max_supply_voltage; + int min_supply_voltage; +}; + +#endif /* __MCDE_DISPLAY_SONY_ACX424AKP__H__ */ + diff --git a/include/video/mcde_display.h b/include/video/mcde_display.h index a5e449f6b5b..6519660f489 100644 --- a/include/video/mcde_display.h +++ b/include/video/mcde_display.h @@ -60,6 +60,7 @@ struct mcde_display_device { struct mcde_video_mode video_mode; int update_flags; bool stay_alive; + int check_transparency; /* Driver API */ void (*get_native_resolution)(struct mcde_display_device *dev, |
