From 62b3330f97b940c715a8931abc7161c99362abaa Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 4 Dec 2008 17:49:02 +0000 Subject: [PATCH] jbt6k74_no_deep_sleep.patch This patch from https://docs.openmoko.org/trac/ticket/1841 defeats deep sleep on the LCM ASIC and is reported to stop the WSOD behaviour on LCMs that exhibit it. --- drivers/video/display/jbt6k74.c | 114 ++++++++++++++++++++++----------------- 1 files changed, 65 insertions(+), 49 deletions(-) diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 9570543..0635823 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -252,22 +252,36 @@ static int jbt_init_regs(struct jbt_info *jbt, int qvga) return rc ? -EIO : 0; } -static int standby_to_sleep(struct jbt_info *jbt) +int jbt6k74_display_onoff(struct jbt_info *jbt, int on) { - int rc; - - /* three times command zero */ - rc = jbt_reg_write_nodata(jbt, 0x00); - mdelay(1); - rc |= jbt_reg_write_nodata(jbt, 0x00); - mdelay(1); - rc |= jbt_reg_write_nodata(jbt, 0x00); - mdelay(1); - - /* deep standby out */ - rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17); + if (on) + return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON); + else + return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF); +} +EXPORT_SYMBOL_GPL(jbt6k74_display_onoff); - return rc ? -EIO : 0; +static int standby_to_sleep(struct jbt_info *jbt) +{ + static int once = 0; + if (!once++) { + int rc; + + /* three times command zero */ + rc = jbt_reg_write_nodata(jbt, 0x00); + mdelay(1); + rc |= jbt_reg_write_nodata(jbt, 0x00); + mdelay(1); + rc |= jbt_reg_write_nodata(jbt, 0x00); + mdelay(1); + + /* deep standby out */ + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17); + + return rc ? -EIO : 0; + } + else + return 0; } static int sleep_to_normal(struct jbt_info *jbt) @@ -292,6 +306,9 @@ static int sleep_to_normal(struct jbt_info *jbt) /* initialize register set */ rc |= jbt_init_regs(jbt, 0); + /* Turn on display */ + rc |= jbt6k74_display_onoff(jbt, 1); + return rc ? -EIO : 0; } @@ -317,6 +334,9 @@ static int sleep_to_qvga_normal(struct jbt_info *jbt) /* initialize register set for qvga*/ rc |= jbt_init_regs(jbt, 1); + /* Turn on display */ + rc |= jbt6k74_display_onoff(jbt, 1); + return rc ? -EIO : 0; } @@ -324,7 +344,8 @@ static int normal_to_sleep(struct jbt_info *jbt) { int rc; - rc = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF); + rc = jbt6k74_display_onoff(jbt, 0); + rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF); rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002); rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN); @@ -333,7 +354,11 @@ static int normal_to_sleep(struct jbt_info *jbt) static int sleep_to_standby(struct jbt_info *jbt) { +#if 0 return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00); +#else + return 0; +#endif } /* frontend function */ @@ -436,6 +461,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) } break; } + if (rc == 0) jbt->state = new_state; @@ -443,15 +469,6 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) } EXPORT_SYMBOL_GPL(jbt6k74_enter_state); -int jbt6k74_display_onoff(struct jbt_info *jbt, int on) -{ - if (on) - return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON); - else - return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF); -} -EXPORT_SYMBOL_GPL(jbt6k74_display_onoff); - static ssize_t state_read(struct device *dev, struct device_attribute *attr, char *buf) { @@ -475,17 +492,6 @@ static ssize_t state_write(struct device *dev, struct device_attribute *attr, rc = jbt6k74_enter_state(jbt, i); if (rc) return rc; - switch (i) { - case JBT_STATE_NORMAL: - case JBT_STATE_QVGA_NORMAL: - /* Enable display again after deep-standby */ - rc = jbt6k74_display_onoff(jbt, 1); - if (rc) - return rc; - break; - default: - break; - } return count; } } @@ -528,6 +534,8 @@ static ssize_t gamma_write(struct device *dev, struct device_attribute *attr, int reg = reg_by_string(attr->attr.name); unsigned long val = simple_strtoul(buf, NULL, 10); + dev_info(dev, "**** jbt6k74 writing gama %lu\n", val & 0xff); + jbt_reg_write(jbt, reg, val & 0xff); return count; @@ -567,19 +575,27 @@ static int fb_notifier_callback(struct notifier_block *self, switch (fb_blank) { case FB_BLANK_UNBLANK: + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n"); + break; case FB_BLANK_NORMAL: - jbt6k74_enter_state(jbt, JBT_STATE_NORMAL); - jbt6k74_display_onoff(jbt, 1); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n"); + /*jbt6k74_enter_state(jbt, JBT_STATE_NORMAL); + jbt6k74_display_onoff(jbt, 1); */ break; case FB_BLANK_VSYNC_SUSPEND: + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n"); + break; case FB_BLANK_HSYNC_SUSPEND: + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 hsync suspend\n"); /* FIXME: we disable SLEEP since it would result in * a visible artefact (white screen) before the backlight * is dimmed to a dark enough level */ /* jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); */ + /*jbt6k74_display_onoff(jbt, 0);*/ break; case FB_BLANK_POWERDOWN: - jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n"); + /*jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);*/ break; } @@ -621,16 +637,10 @@ static int __devinit jbt_probe(struct spi_device *spi) goto err_free_drvdata; } - rc = jbt6k74_display_onoff(jbt, 1); - if (rc < 0) { - dev_err(&spi->dev, "cannot switch display on\n"); - goto err_standby; - } - rc = sysfs_create_group(&spi->dev.kobj, &jbt_attr_group); if (rc < 0) { dev_err(&spi->dev, "cannot create sysfs group\n"); - goto err_off; + goto err_standby; } jbt->fb_notif.notifier_call = fb_notifier_callback; @@ -644,8 +654,6 @@ static int __devinit jbt_probe(struct spi_device *spi) err_sysfs: sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group); -err_off: - jbt6k74_display_onoff(jbt, 0); err_standby: jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); err_free_drvdata: @@ -676,6 +684,8 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) struct jbt_info *jbt = dev_get_drvdata(&spi->dev); struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; + dev_info(&spi->dev, "**** jbt6k74 suspend start\n"); + /* platform can register resume dependencies here, if any */ if (jbt6k74_pdata->suspending) (jbt6k74_pdata->suspending)(0, spi); @@ -689,6 +699,8 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) /* (jbt6k74_pdata->reset)(0, 0); */ + dev_info(&spi->dev, "**** jbt6k74 suspend end\n"); + return 0; } @@ -697,6 +709,7 @@ int jbt6k74_resume(struct spi_device *spi) struct jbt_info *jbt = dev_get_drvdata(&spi->dev); struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; + dev_info(&spi->dev, "**** jbt6k74 resume start\n"); if (jbt6k74_pdata->all_dependencies_resumed) if (!(jbt6k74_pdata->all_dependencies_resumed)(0)) return 0; @@ -704,8 +717,10 @@ int jbt6k74_resume(struct spi_device *spi) /* we can get called twice with all dependencies resumed if our core * resume callback is last of all. Protect against doing anything twice */ - if (jbt->have_resumed) + if (jbt->have_resumed) { + dev_info(&spi->dev, "**** jbt6k74 already resumed\n"); return 0; + } jbt->have_resumed |= 1; @@ -717,11 +732,12 @@ int jbt6k74_resume(struct spi_device *spi) jbt6k74_enter_state(jbt, JBT_STATE_NORMAL); break; } - jbt6k74_display_onoff(jbt, 1); if (jbt6k74_pdata->resuming) (jbt6k74_pdata->resuming)(0); + dev_info(&spi->dev, "**** jbt6k74 resume end\n"); + return 0; } EXPORT_SYMBOL_GPL(jbt6k74_resume); -- 1.5.6.5