diff options
| author | Oleksandr Kozaruk <oleksandr.kozaruk@globallogic.com> | 2015-07-23 17:46:15 -0700 |
|---|---|---|
| committer | Evan Wilson <evan@oliodevices.com> | 2015-07-31 11:35:32 -0700 |
| commit | ff2e45d50c4a20d87b5084b0eafa9e1c868760d3 (patch) | |
| tree | c8e5fe18360f64d5b09a83875209de3c29ce5f0e | |
| parent | b84e453fe0ff5aa369fc0e8b370cc58000466f69 (diff) | |
| download | olio-linux-3.10-ff2e45d50c4a20d87b5084b0eafa9e1c868760d3.tar.xz olio-linux-3.10-ff2e45d50c4a20d87b5084b0eafa9e1c868760d3.zip | |
olio: ili9342: Remove suspend/resume.
We put display to sleep mode when display disable function is called,
and sleep out in display enable function.
Also, now we don't need to cal display init function, thus it should
take less time to turn display on after resume.
Change-Id: I02c21f5824c8735850353671e679bcab7b0383c4
Signed-off-by: Evan Wilson <evan@oliodevices.com>
| -rw-r--r-- | drivers/video/omap2/displays/panel-ili9342.c | 323 |
1 files changed, 111 insertions, 212 deletions
diff --git a/drivers/video/omap2/displays/panel-ili9342.c b/drivers/video/omap2/displays/panel-ili9342.c index 42f23fdb4ff..228a69b7688 100644 --- a/drivers/video/omap2/displays/panel-ili9342.c +++ b/drivers/video/omap2/displays/panel-ili9342.c @@ -38,6 +38,11 @@ #define oliodebug(...) #endif +#define CMD_SLEEP_IN 0x10 +#define CMD_SLEEP_OUT 0x11 +#define CMD_DISP_OFF 0x28 +#define CMD_DISP_ON 0x29 + struct panel_config { struct omap_video_timings timings; @@ -82,14 +87,86 @@ static struct panel_config ili9342_panels[] = { }; struct panel_drv_data { - struct omap_dss_device *dssdev; - struct panel_config *panel_config; + unsigned long hw_guard_end; /* next value of jiffies + when we can issue the + next sleep in/out command */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + struct spi_device *spi; + struct mutex lock; }; +static struct panel_drv_data ili9342_drv_data; + +static int ili9342_spi_write(struct spi_device *spi, bool cmd, unsigned char val) { + unsigned short buf; + struct spi_message m; + struct spi_transfer t = { + .tx_buf = &buf, + .len = 2, + .bits_per_word = 9, + }; + + buf = cmd ? 0 : (1 << 8); + buf |= val; + dev_dbg(&spi->dev, "SPI sync: %x", buf); + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + if (spi_sync(spi, &m) < 0) { + dev_err(&spi->dev, "SPI sync failed."); + return -EINVAL; + } + + return 0; +} + +static int ili9342_write_cmd(struct spi_device *spi, unsigned char val) { + return ili9342_spi_write(spi, 1, val); +} + +static int ili9342_write_data(struct spi_device *spi, unsigned char val) { + return ili9342_spi_write(spi, 0, val); +} + +static void hw_guard_start(struct panel_drv_data *md, int guard_msec) +{ + md->hw_guard_wait = msecs_to_jiffies(guard_msec); + md->hw_guard_end = jiffies + md->hw_guard_wait; +} + +static void hw_guard_wait(struct panel_drv_data *md) +{ + unsigned long wait = md->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= md->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +static void set_sleep_mode(struct panel_drv_data *drv_data, int on) +{ + int cmd = on ? CMD_SLEEP_IN : CMD_SLEEP_OUT; + /* + * We have to keep 120msec between sleep in/out commands. + * (8.2.11, 8.2.12). + */ + hw_guard_wait(drv_data); + ili9342_write_cmd(drv_data->spi, cmd); + hw_guard_start(drv_data, 120); +} + +static void set_display_state(struct panel_drv_data *drv_data, int enabled) +{ + int cmd = enabled ? CMD_DISP_ON : CMD_DISP_OFF; + + ili9342_write_cmd(drv_data->spi, cmd); +} + static int ili9342_panel_power_on(struct omap_dss_device *dssdev) { int r; @@ -104,11 +181,10 @@ static int ili9342_panel_power_on(struct omap_dss_device *dssdev) r = omapdss_dpi_display_enable(dssdev); if (r) - goto err0; + return r; /* wait couple of vsyncs until enabling the LCD */ - if (panel_config->power_on_delay) - msleep(panel_config->power_on_delay); + msleep(panel_config->power_on_delay); if (dssdev->platform_enable) { r = dssdev->platform_enable(dssdev); @@ -116,10 +192,13 @@ static int ili9342_panel_power_on(struct omap_dss_device *dssdev) goto err1; } + set_sleep_mode(drv_data, 0); + usleep_range(5000, 10000); + set_display_state(drv_data, 1); + return 0; err1: omapdss_dpi_display_disable(dssdev); -err0: return r; } @@ -131,12 +210,15 @@ static void ili9342_panel_power_off(struct omap_dss_device *dssdev) if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return; + set_display_state(drv_data, 0); + set_sleep_mode(drv_data, 1); + msleep(100); + if (dssdev->platform_disable) dssdev->platform_disable(dssdev); /* wait couple of vsyncs after disabling the LCD */ - if (panel_config->power_off_delay) - msleep(panel_config->power_off_delay); + msleep(panel_config->power_off_delay); omapdss_dpi_display_disable(dssdev); } @@ -144,12 +226,12 @@ static void ili9342_panel_power_off(struct omap_dss_device *dssdev) static int ili9342_panel_probe(struct omap_dss_device *dssdev) { struct panel_config *panel_config = NULL; - struct panel_drv_data *drv_data = NULL; + struct panel_drv_data *drv_data = &ili9342_drv_data; int i; dev_dbg(&dssdev->dev, "probe\n"); - printk ("OLIO %s entered\n", __FUNCTION__); + printk ("OLIO %s entered\n", __FUNCTION__); if (!dssdev || !dssdev->name) return -EINVAL; @@ -168,10 +250,6 @@ static int ili9342_panel_probe(struct omap_dss_device *dssdev) dssdev->panel.timings = panel_config->timings; - drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); - if (!drv_data) - return -ENOMEM; - drv_data->dssdev = dssdev; drv_data->panel_config = panel_config; @@ -198,10 +276,10 @@ static int ili9342_panel_enable(struct omap_dss_device *dssdev) r = ili9342_panel_power_on(dssdev); if (r) - goto err; + goto ret; dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; -err: +ret: mutex_unlock(&drv_data->lock); return r; @@ -253,9 +331,7 @@ static int ili9342_panel_check_timings(struct omap_dss_device *dssdev, int r; mutex_lock(&drv_data->lock); - r = dpi_check_timings(dssdev, timings); - mutex_unlock(&drv_data->lock); return r; @@ -265,40 +341,6 @@ static int ili9342_get_recommended_bpp(struct omap_dss_device *dssdev) { return 24; } - -/*************************************************************************** - * suspend & resume - * - * For now, this is all handled by the SPI driver (see below). - * Leaving this functions here should we change our minds. - */ - -static int ili9342_disp_suspend (struct device * dev) { - printk ("OLIO: %s Suspending display.\n", __FUNCTION__); - ili9342_panel_disable(to_dss_device(dev)); - return 0; -} - -static int ili9342_disp_resume (struct device * dev) { - printk ("OLIO: %s Resuming display.\n", __FUNCTION__); - ili9342_panel_enable(to_dss_device(dev)); - return 0; -} - -#if defined(CONFIG_HAS_AMBIENTMODE) -static int ili9342_panel_disable_wrapper (struct omap_dss_device *display) { - printk ("OLIO: %s Suspending display.\n", __FUNCTION__); - ili9342_panel_disable(display); - return 0; -} -#endif - - -static struct dev_pm_ops ili9342_disp_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ili9342_disp_suspend, ili9342_disp_resume) -}; - - static struct omap_dss_driver ili9342_driver = { .probe = ili9342_panel_probe, .remove = __exit_p(ili9342_panel_remove), @@ -312,66 +354,12 @@ static struct omap_dss_driver ili9342_driver = { .get_recommended_bpp = ili9342_get_recommended_bpp, -#if 0 -#if defined(CONFIG_HAS_AMBIENTMODE) - .resume = ili9342_panel_enable, - .suspend = ili9342_panel_disable_wrapper, -#endif -#endif - .driver = { .name = "ili9342_panel", .owner = THIS_MODULE, - .pm = &ili9342_disp_pm_ops, }, }; -/* ====================================================================== */ - -/* Here follows the SPI driver - it's required by the panel, but the - * coupling is rather weak. It registers another driver. - */ - -/* ====================================================================== */ - -static struct regulator *spi_regulator; - -static int ili9342_spi_write(struct spi_device *spi, bool cmd, unsigned char val) { - unsigned short buf; - struct spi_message m; - struct spi_transfer t = { - .tx_buf = &buf, - .len = 2, - .bits_per_word = 9, - }; - int r; - - if(cmd) { - buf = 0; - } else { - buf = 1 << 8; - } - buf |= val; - - dev_dbg(&spi->dev, "SPI sync: %x", buf); - spi_message_init(&m); - spi_message_add_tail(&t, &m); - r = spi_sync(spi, &m); - if(r < 0) { - dev_err(&spi->dev, "SPI sync failed."); - return -EINVAL; - } - return 0; -} - -static int ili9342_write_cmd(struct spi_device *spi, unsigned char val) { - return ili9342_spi_write(spi, 1, val); -} - -static int ili9342_write_data(struct spi_device *spi, unsigned char val) { - return ili9342_spi_write(spi, 0, val); -} - static inline void ili9342_init_seq(struct spi_device *spi) { ili9342_write_cmd(spi, 0xC8); ili9342_write_data(spi, 0xFF); @@ -474,75 +462,41 @@ static inline void ili9342_init_seq(struct spi_device *spi) { ili9342_write_cmd(spi, 0x29); } +static inline int ili9342_init_reset_gpio(int reset_gpio) +{ + if (gpio_request_one(reset_gpio, GPIOF_OUT_INIT_LOW, "ili9342-reset")) + return -EINVAL; -static inline void init_ili9342_hw (struct spi_device *spi) { - struct omap_dss_device *panel = spi->dev.platform_data; - - gpio_set_value(panel->reset_gpio, 1); + gpio_set_value(reset_gpio, 1); mdelay(1); - gpio_set_value(panel->reset_gpio, 0); + gpio_set_value(reset_gpio, 0); mdelay(50); - gpio_set_value(panel->reset_gpio, 1); + gpio_set_value(reset_gpio, 1); mdelay(120); - ili9342_init_seq(spi); + return 0; } -static inline int init_ili9342_spi(struct spi_device *spi) { +static int ili9342_spi_probe(struct spi_device *spi) +{ + struct panel_drv_data *drv_data = &ili9342_drv_data; struct omap_dss_device *panel = spi->dev.platform_data; - int reset_gpio; - if(!panel->reset_gpio) { - dev_err(&spi->dev, "platform data requires reset\n"); - return -EINVAL; - } - - reset_gpio = panel->reset_gpio; + printk ("OLIO %s entered\n", __FUNCTION__); if (!panel) { dev_err(&spi->dev, "no platform data\n"); return -EINVAL; } - if(gpio_request_one(reset_gpio, GPIOF_OUT_INIT_LOW, "ili9342-reset")) { - dev_err(&spi->dev, "Could not request reset gpio %d", panel->reset_gpio); + if (ili9342_init_reset_gpio(panel->reset_gpio)) { + dev_err(&spi->dev, "Could not request reset gpio %d", + panel->reset_gpio); return -EINVAL; } - if(gpio_export(reset_gpio, 0)) { - dev_err(&spi->dev, "Could not export reset gpio %d", panel->reset_gpio); - return -EINVAL; - } - - init_ili9342_hw (spi); - - return 0; -} - -static int ili9342_spi_probe(struct spi_device *spi) -{ - int err; - int ret; - - spi_regulator = devm_regulator_get(&spi->dev, "vdd"); - - printk ("OLIO %s entered\n", __FUNCTION__); - - if (IS_ERR(spi_regulator)) { - dev_err(&spi->dev, "regulator get failed\n"); - err = PTR_ERR(spi_regulator); - spi_regulator = NULL; - return err; - } - - ret = regulator_enable(spi_regulator); - - if (ret) { - dev_err(&spi->dev, "Failed to enable vdd: %d\n", ret); - return ret; - } - - init_ili9342_spi(spi); + drv_data->spi = spi; + ili9342_init_seq(spi); return omap_dss_register_driver(&ili9342_driver); } @@ -555,67 +509,12 @@ static int ili9342_spi_remove(struct spi_device *spi) return 0; } -static int ili9342_suspend(struct device *dev) { - int ret; - - oliodebug ("OLIO %s:%s Suspending SPI for %s\n", __FILE__, __FUNCTION__, dev_name(dev)); - - ret = regulator_disable(spi_regulator); - if (ret) { - dev_err(dev, "Failed to disable vdd:%d\n", - ret); - return ret; - } - - return 0; -} - - -static int ili9342_resume(struct device *dev) { - int ret; - - /* HACK WARNING: We need an spi_device here. If, as can be assumed, - * the device pointer passed in points to a device in an spi_device, - * it's the first device in the spi_device struct. In other words, - * it's address is the same as the spi_device and a cast should be OK. - */ - - /* IF, otoh, that's an incorrect assumption ... then this will lead - * to horrible crashes. But oh well, you can't win 'em all. - */ - - struct spi_device * spi = (struct spi_device *) dev; - - oliodebug ("OLIO %s:%s Resuming SPI for %s\n", __FILE__, __FUNCTION__, dev_name(dev)); - - ret = regulator_enable(spi_regulator); - - if (ret) { - dev_err(&spi->dev, "Failed to enable vdd: %d\n", ret); - return ret; - } - - /* ili9342_init_seq(spi); */ - init_ili9342_hw (spi); - - return 0; -} - - -static struct dev_pm_ops ili9342_pm_ops = { - /* SET_SYSTEM_SLEEP_PM_OPS(ili9342_suspend, ili9342_resume) */ - .suspend_late = ili9342_suspend, - .resume_early = ili9342_resume, -}; - - static struct spi_driver ili9342_spi_driver = { .probe = ili9342_spi_probe, .remove = ili9342_spi_remove, .driver = { .name = "ili9342-spi", .owner = THIS_MODULE, - .pm = &ili9342_pm_ops, }, }; |