From bd4b7e8e84ab43a13a4620b001d52d373c2122b3 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Sat, 4 Apr 2009 14:15:48 -0400 Subject: Fixed the LCM driver state transition delay and pixel clock issue Space transition between sleep-in and sleep-out of at least 120 ms as mentionned in the spec. Also, made sure the LCM is moved into sleep state before the pixel clock is turned off. To do so, I've modified glamo-fb to send FB_BLANK_POWERDOWN before turning off the pixel clock. Also fixed various violation of coding style. This patch should reduce the risk of white screen. Signed-off-by: Nicolas Dufresne --- drivers/video/display/jbt6k74.c | 141 ++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 62 deletions(-) (limited to 'drivers/video/display/jbt6k74.c') diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 9add1c6bf8a..4524be34df2 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -31,6 +31,7 @@ #include #include #include +#include enum jbt_register { JBT_REG_SLEEP_IN = 0x10, @@ -117,12 +118,18 @@ struct jbt_info { struct notifier_block fb_notif; u16 tx_buf[8]; u16 reg_cache[0xEE]; - int have_resumed; + struct timespec last_sleep; }; #define JBT_COMMAND 0x000 #define JBT_DATA 0x100 +static inline unsigned int timespec_sub_ms(struct timespec lhs, + struct timespec rhs) +{ + struct timespec ts = timespec_sub(lhs, rhs); + return (ts.tv_sec * MSEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_MSEC); +} static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg) { @@ -179,7 +186,7 @@ static int jbt_init_regs(struct jbt_info *jbt) { int rc; - dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", + dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", jbt->normal_state == JBT_STATE_QVGA_NORMAL ? 'Q' : ' '); rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01); @@ -268,36 +275,25 @@ static int sleep_to_normal(struct jbt_info *jbt) { int rc; - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); - - /* Quad mode off */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); - - /* AVDD on, XVDD on */ - rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); - - /* Output control */ - rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9); + /* Make sure we are 120 ms after SLEEP_OUT */ + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), + jbt->last_sleep); + if (sleep_time < 120) + mdelay(120 - sleep_time); - /* Turn on display */ - rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON); + if (jbt->normal_state == JBT_STATE_NORMAL) { + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); - /* Sleep mode off */ - rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); - - return rc ? -EIO : 0; -} - -static int sleep_to_qvga_normal(struct jbt_info *jbt) -{ - int rc; - - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); + /* Quad mode off */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); + } else { + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); - /* Quad mode on */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); + /* Quad mode on */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); + } /* AVDD on, XVDD on */ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); @@ -310,6 +306,10 @@ static int sleep_to_qvga_normal(struct jbt_info *jbt) /* Sleep mode off */ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); + jbt->last_sleep = current_kernel_time(); + + /* Allow the booster and display controller to restart stably */ + mdelay(5); return rc ? -EIO : 0; } @@ -318,9 +318,19 @@ static int normal_to_sleep(struct jbt_info *jbt) { int rc; + /* Make sure we are 120 ms after SLEEP_OUT */ + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), + jbt->last_sleep); + if (sleep_time < 120) + mdelay(120 - sleep_time); + 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); + jbt->last_sleep = current_kernel_time(); + + /* Allow the internal circuits to stop automatically */ + mdelay(5); return rc ? -EIO : 0; } @@ -335,8 +345,9 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) { int rc = -EINVAL; - dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, " - "new_state=%s)\n", jbt_state_names[jbt->state], jbt_state_names[new_state]); + dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, new_state=%s)\n", + jbt_state_names[jbt->state], + jbt_state_names[new_state]); mutex_lock(&jbt->lock); @@ -363,7 +374,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* first transition into sleep */ rc = standby_to_sleep(jbt); /* then transition into normal */ - rc |= sleep_to_qvga_normal(jbt); + rc |= sleep_to_normal(jbt); break; } break; @@ -376,10 +387,8 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) rc = sleep_to_standby(jbt); break; case JBT_STATE_NORMAL: - rc = sleep_to_normal(jbt); - break; case JBT_STATE_QVGA_NORMAL: - rc = sleep_to_qvga_normal(jbt); + rc = sleep_to_normal(jbt); break; } break; @@ -405,7 +414,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* third transition into sleep */ rc |= standby_to_sleep(jbt); /* fourth transition into normal */ - rc |= sleep_to_qvga_normal(jbt); + rc |= sleep_to_normal(jbt); break; } break; @@ -436,12 +445,13 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) } break; } - + if (rc == 0) jbt->state = new_state; else - dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", jbt_state_names[new_state]); - + dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", + jbt_state_names[new_state]); + mutex_unlock(&jbt->lock); return rc; @@ -525,18 +535,27 @@ static ssize_t gamma_write(struct device *dev, struct device_attribute *attr, static ssize_t reset_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + int rc; struct jbt_info *jbt = dev_get_drvdata(dev); - struct jbt6k74_platform_data *jbt6k74_pdata = jbt->spi_dev->dev.platform_data; + struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data; dev_info(dev, "**** jbt6k74 reset\n"); - jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + mutex_lock(&jbt->lock); + + jbt->state = JBT_STATE_DEEP_STANDBY; /* hard reset the jbt6k74 */ - mutex_lock(&jbt->lock); - (jbt6k74_pdata->reset)(0, 0); + (pdata->reset)(0, 0); mdelay(1); - (jbt6k74_pdata->reset)(0, 1); + (pdata->reset)(0, 1); + mdelay(120); + + rc = jbt_reg_write_nodata(jbt, 0x01); + if (rc < 0) + dev_err(&jbt->spi_dev->dev, "cannot soft reset\n"); + mdelay(120); + mutex_unlock(&jbt->lock); jbt6k74_enter_state(jbt, jbt->normal_state); @@ -572,31 +591,30 @@ static int fb_notifier_callback(struct notifier_block *self, struct fb_event *evdata = data; int fb_blank; + jbt = container_of(self, struct jbt_info, fb_notif); + + dev_dbg(&jbt->spi_dev->dev, "jbt6k74 event=%lu\n", event); + if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) return 0; fb_blank = *(int *)evdata->data; - jbt = container_of(self, struct jbt_info, fb_notif); - switch (fb_blank) { case FB_BLANK_UNBLANK: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n"); + dev_dbg(&jbt->spi_dev->dev, "unblank\n"); jbt6k74_enter_state(jbt, jbt->normal_state); break; case FB_BLANK_NORMAL: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n"); + dev_dbg(&jbt->spi_dev->dev, "blank\n"); break; case FB_BLANK_VSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n"); + dev_dbg(&jbt->spi_dev->dev, "vsync suspend\n"); break; case FB_BLANK_HSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 hsync suspend\n"); + dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n"); break; case FB_BLANK_POWERDOWN: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n"); - /* FIXME DEEP STANDBY wihtout suspend causes WSOD at cold - * temperature on certain devices. */ - /*jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);*/ + dev_dbg(&jbt->spi_dev->dev, "powerdown\n"); jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); break; } @@ -610,7 +628,7 @@ static int __devinit jbt_probe(struct spi_device *spi) { int rc; struct jbt_info *jbt; - struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; + struct jbt6k74_platform_data *pdata = spi->dev.platform_data; /* the controller doesn't have a MISO pin; we can't do detection */ @@ -631,6 +649,7 @@ static int __devinit jbt_probe(struct spi_device *spi) jbt->spi_dev = spi; jbt->normal_state = JBT_STATE_NORMAL; jbt->state = JBT_STATE_DEEP_STANDBY; + jbt->last_sleep = current_kernel_time(); mutex_init(&jbt->lock); dev_set_drvdata(&spi->dev, jbt); @@ -654,8 +673,8 @@ static int __devinit jbt_probe(struct spi_device *spi) goto err_sysfs; } - if (jbt6k74_pdata->probe_completed) - (jbt6k74_pdata->probe_completed)(&spi->dev); + if (pdata->probe_completed) + (pdata->probe_completed)(&spi->dev); return 0; @@ -693,8 +712,6 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); - jbt->have_resumed = 0; - dev_info(&spi->dev, "**** jbt6k74 suspend end\n"); return 0; @@ -703,14 +720,14 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) 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; + struct jbt6k74_platform_data *pdata = spi->dev.platform_data; dev_info(&spi->dev, "**** jbt6k74 resume start\n"); jbt6k74_enter_state(jbt, jbt->normal_state); - if (jbt6k74_pdata->resuming) - (jbt6k74_pdata->resuming)(0); + if (pdata->resuming) + (pdata->resuming)(0); dev_info(&spi->dev, "**** jbt6k74 resume end\n"); -- cgit v1.2.3 From d9a7be9aab65cd86981d60806041ac11fe514277 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 13 Apr 2009 10:43:30 -0400 Subject: fbcon: Cleaned unnecessary debugging output (fix bug 2265) Cleaned unnecessary debugging output. Signed-off-by: Nicolas Dufresne --- drivers/video/display/jbt6k74.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/video/display/jbt6k74.c') diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 4524be34df2..5d7a6519de9 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -523,7 +523,7 @@ 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); + dev_info(dev, "writing gama %lu\n", val & 0xff); mutex_lock(&jbt->lock); jbt_reg_write(jbt, reg, val & 0xff); @@ -539,7 +539,7 @@ static ssize_t reset_write(struct device *dev, struct device_attribute *attr, struct jbt_info *jbt = dev_get_drvdata(dev); struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data; - dev_info(dev, "**** jbt6k74 reset\n"); + dev_info(dev, "reset\n"); mutex_lock(&jbt->lock); @@ -593,7 +593,7 @@ static int fb_notifier_callback(struct notifier_block *self, jbt = container_of(self, struct jbt_info, fb_notif); - dev_dbg(&jbt->spi_dev->dev, "jbt6k74 event=%lu\n", event); + dev_dbg(&jbt->spi_dev->dev, "event=%lu\n", event); if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) return 0; @@ -712,7 +712,7 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); - dev_info(&spi->dev, "**** jbt6k74 suspend end\n"); + dev_info(&spi->dev, "suspended\n"); return 0; } @@ -722,14 +722,12 @@ int jbt6k74_resume(struct spi_device *spi) struct jbt_info *jbt = dev_get_drvdata(&spi->dev); struct jbt6k74_platform_data *pdata = spi->dev.platform_data; - dev_info(&spi->dev, "**** jbt6k74 resume start\n"); - jbt6k74_enter_state(jbt, jbt->normal_state); if (pdata->resuming) (pdata->resuming)(0); - dev_info(&spi->dev, "**** jbt6k74 resume end\n"); + dev_info(&spi->dev, "resumed\n"); return 0; } -- cgit v1.2.3 From aa2dbc74bed8cf60e591c654ba1882011b9a8ece Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Sun, 19 Apr 2009 11:16:56 -0500 Subject: Revert "Fixed the LCM driver state transition delay and pixel clock issue" This reverts commit bd4b7e8e84ab43a13a4620b001d52d373c2122b3 which brought WSOD back for some devices. It was reported that the problem does not happen with Qi and it seem it is good news. See: https://docs.openmoko.org/trac/ticket/2274 Conflicts: drivers/video/display/jbt6k74.c --- drivers/video/display/jbt6k74.c | 136 ++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 75 deletions(-) (limited to 'drivers/video/display/jbt6k74.c') diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 5d7a6519de9..0307ed5318f 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -31,7 +31,6 @@ #include #include #include -#include enum jbt_register { JBT_REG_SLEEP_IN = 0x10, @@ -118,18 +117,12 @@ struct jbt_info { struct notifier_block fb_notif; u16 tx_buf[8]; u16 reg_cache[0xEE]; - struct timespec last_sleep; + int have_resumed; }; #define JBT_COMMAND 0x000 #define JBT_DATA 0x100 -static inline unsigned int timespec_sub_ms(struct timespec lhs, - struct timespec rhs) -{ - struct timespec ts = timespec_sub(lhs, rhs); - return (ts.tv_sec * MSEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_MSEC); -} static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg) { @@ -186,7 +179,7 @@ static int jbt_init_regs(struct jbt_info *jbt) { int rc; - dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", + dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", jbt->normal_state == JBT_STATE_QVGA_NORMAL ? 'Q' : ' '); rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01); @@ -275,25 +268,36 @@ static int sleep_to_normal(struct jbt_info *jbt) { int rc; - /* Make sure we are 120 ms after SLEEP_OUT */ - unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), - jbt->last_sleep); - if (sleep_time < 120) - mdelay(120 - sleep_time); + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); - if (jbt->normal_state == JBT_STATE_NORMAL) { - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); + /* Quad mode off */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); - /* Quad mode off */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); - } else { - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); + /* AVDD on, XVDD on */ + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); - /* Quad mode on */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); - } + /* Output control */ + rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9); + + /* Turn on display */ + rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON); + + /* Sleep mode off */ + rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); + + return rc ? -EIO : 0; +} + +static int sleep_to_qvga_normal(struct jbt_info *jbt) +{ + int rc; + + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); + + /* Quad mode on */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); /* AVDD on, XVDD on */ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); @@ -306,10 +310,6 @@ static int sleep_to_normal(struct jbt_info *jbt) /* Sleep mode off */ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); - jbt->last_sleep = current_kernel_time(); - - /* Allow the booster and display controller to restart stably */ - mdelay(5); return rc ? -EIO : 0; } @@ -318,19 +318,9 @@ static int normal_to_sleep(struct jbt_info *jbt) { int rc; - /* Make sure we are 120 ms after SLEEP_OUT */ - unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), - jbt->last_sleep); - if (sleep_time < 120) - mdelay(120 - sleep_time); - 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); - jbt->last_sleep = current_kernel_time(); - - /* Allow the internal circuits to stop automatically */ - mdelay(5); return rc ? -EIO : 0; } @@ -345,9 +335,8 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) { int rc = -EINVAL; - dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, new_state=%s)\n", - jbt_state_names[jbt->state], - jbt_state_names[new_state]); + dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, " + "new_state=%s)\n", jbt_state_names[jbt->state], jbt_state_names[new_state]); mutex_lock(&jbt->lock); @@ -374,7 +363,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* first transition into sleep */ rc = standby_to_sleep(jbt); /* then transition into normal */ - rc |= sleep_to_normal(jbt); + rc |= sleep_to_qvga_normal(jbt); break; } break; @@ -387,9 +376,11 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) rc = sleep_to_standby(jbt); break; case JBT_STATE_NORMAL: - case JBT_STATE_QVGA_NORMAL: rc = sleep_to_normal(jbt); break; + case JBT_STATE_QVGA_NORMAL: + rc = sleep_to_qvga_normal(jbt); + break; } break; case JBT_STATE_NORMAL: @@ -414,7 +405,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* third transition into sleep */ rc |= standby_to_sleep(jbt); /* fourth transition into normal */ - rc |= sleep_to_normal(jbt); + rc |= sleep_to_qvga_normal(jbt); break; } break; @@ -445,13 +436,12 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) } break; } - + if (rc == 0) jbt->state = new_state; else - dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", - jbt_state_names[new_state]); - + dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", jbt_state_names[new_state]); + mutex_unlock(&jbt->lock); return rc; @@ -535,27 +525,18 @@ static ssize_t gamma_write(struct device *dev, struct device_attribute *attr, static ssize_t reset_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int rc; struct jbt_info *jbt = dev_get_drvdata(dev); - struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data; + struct jbt6k74_platform_data *jbt6k74_pdata = jbt->spi_dev->dev.platform_data; dev_info(dev, "reset\n"); - mutex_lock(&jbt->lock); - - jbt->state = JBT_STATE_DEEP_STANDBY; + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); /* hard reset the jbt6k74 */ - (pdata->reset)(0, 0); + mutex_lock(&jbt->lock); + (jbt6k74_pdata->reset)(0, 0); mdelay(1); - (pdata->reset)(0, 1); - mdelay(120); - - rc = jbt_reg_write_nodata(jbt, 0x01); - if (rc < 0) - dev_err(&jbt->spi_dev->dev, "cannot soft reset\n"); - mdelay(120); - + (jbt6k74_pdata->reset)(0, 1); mutex_unlock(&jbt->lock); jbt6k74_enter_state(jbt, jbt->normal_state); @@ -599,22 +580,26 @@ static int fb_notifier_callback(struct notifier_block *self, return 0; fb_blank = *(int *)evdata->data; + switch (fb_blank) { case FB_BLANK_UNBLANK: - dev_dbg(&jbt->spi_dev->dev, "unblank\n"); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n"); jbt6k74_enter_state(jbt, jbt->normal_state); break; case FB_BLANK_NORMAL: - dev_dbg(&jbt->spi_dev->dev, "blank\n"); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n"); break; case FB_BLANK_VSYNC_SUSPEND: - dev_dbg(&jbt->spi_dev->dev, "vsync suspend\n"); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n"); break; case FB_BLANK_HSYNC_SUSPEND: - dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n"); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 hsync suspend\n"); break; case FB_BLANK_POWERDOWN: - dev_dbg(&jbt->spi_dev->dev, "powerdown\n"); + dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n"); + /* FIXME DEEP STANDBY wihtout suspend causes WSOD at cold + * temperature on certain devices. */ + /*jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);*/ jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); break; } @@ -628,7 +613,7 @@ static int __devinit jbt_probe(struct spi_device *spi) { int rc; struct jbt_info *jbt; - struct jbt6k74_platform_data *pdata = spi->dev.platform_data; + struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; /* the controller doesn't have a MISO pin; we can't do detection */ @@ -649,7 +634,6 @@ static int __devinit jbt_probe(struct spi_device *spi) jbt->spi_dev = spi; jbt->normal_state = JBT_STATE_NORMAL; jbt->state = JBT_STATE_DEEP_STANDBY; - jbt->last_sleep = current_kernel_time(); mutex_init(&jbt->lock); dev_set_drvdata(&spi->dev, jbt); @@ -673,8 +657,8 @@ static int __devinit jbt_probe(struct spi_device *spi) goto err_sysfs; } - if (pdata->probe_completed) - (pdata->probe_completed)(&spi->dev); + if (jbt6k74_pdata->probe_completed) + (jbt6k74_pdata->probe_completed)(&spi->dev); return 0; @@ -712,6 +696,8 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + jbt->have_resumed = 0; + dev_info(&spi->dev, "suspended\n"); return 0; @@ -720,12 +706,12 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) int jbt6k74_resume(struct spi_device *spi) { struct jbt_info *jbt = dev_get_drvdata(&spi->dev); - struct jbt6k74_platform_data *pdata = spi->dev.platform_data; + struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; jbt6k74_enter_state(jbt, jbt->normal_state); - if (pdata->resuming) - (pdata->resuming)(0); + if (jbt6k74_pdata->resuming) + (jbt6k74_pdata->resuming)(0); dev_info(&spi->dev, "resumed\n"); -- cgit v1.2.3 From 08c73c0533ec33dba5676d1124634dd1654aef8b Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Sun, 19 Apr 2009 14:41:33 -0500 Subject: Revert "Revert "Fixed the LCM driver state transition delay and pixel clock issue"" This reverts commit aa2dbc74bed8cf60e591c654ba1882011b9a8ece. Reverting the revert. Sorry for the noise. Check: http://lists.openmoko.org/pipermail/openmoko-kernel/2009-April/010023.html --- drivers/video/display/jbt6k74.c | 136 ++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 61 deletions(-) (limited to 'drivers/video/display/jbt6k74.c') diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c index 0307ed5318f..5d7a6519de9 100644 --- a/drivers/video/display/jbt6k74.c +++ b/drivers/video/display/jbt6k74.c @@ -31,6 +31,7 @@ #include #include #include +#include enum jbt_register { JBT_REG_SLEEP_IN = 0x10, @@ -117,12 +118,18 @@ struct jbt_info { struct notifier_block fb_notif; u16 tx_buf[8]; u16 reg_cache[0xEE]; - int have_resumed; + struct timespec last_sleep; }; #define JBT_COMMAND 0x000 #define JBT_DATA 0x100 +static inline unsigned int timespec_sub_ms(struct timespec lhs, + struct timespec rhs) +{ + struct timespec ts = timespec_sub(lhs, rhs); + return (ts.tv_sec * MSEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_MSEC); +} static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg) { @@ -179,7 +186,7 @@ static int jbt_init_regs(struct jbt_info *jbt) { int rc; - dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", + dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", jbt->normal_state == JBT_STATE_QVGA_NORMAL ? 'Q' : ' '); rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01); @@ -268,36 +275,25 @@ static int sleep_to_normal(struct jbt_info *jbt) { int rc; - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); - - /* Quad mode off */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); - - /* AVDD on, XVDD on */ - rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); + /* Make sure we are 120 ms after SLEEP_OUT */ + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), + jbt->last_sleep); + if (sleep_time < 120) + mdelay(120 - sleep_time); - /* Output control */ - rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9); - - /* Turn on display */ - rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON); + if (jbt->normal_state == JBT_STATE_NORMAL) { + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80); - /* Sleep mode off */ - rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); - - return rc ? -EIO : 0; -} - -static int sleep_to_qvga_normal(struct jbt_info *jbt) -{ - int rc; - - /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ - rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); + /* Quad mode off */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00); + } else { + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */ + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81); - /* Quad mode on */ - rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); + /* Quad mode on */ + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22); + } /* AVDD on, XVDD on */ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16); @@ -310,6 +306,10 @@ static int sleep_to_qvga_normal(struct jbt_info *jbt) /* Sleep mode off */ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT); + jbt->last_sleep = current_kernel_time(); + + /* Allow the booster and display controller to restart stably */ + mdelay(5); return rc ? -EIO : 0; } @@ -318,9 +318,19 @@ static int normal_to_sleep(struct jbt_info *jbt) { int rc; + /* Make sure we are 120 ms after SLEEP_OUT */ + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(), + jbt->last_sleep); + if (sleep_time < 120) + mdelay(120 - sleep_time); + 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); + jbt->last_sleep = current_kernel_time(); + + /* Allow the internal circuits to stop automatically */ + mdelay(5); return rc ? -EIO : 0; } @@ -335,8 +345,9 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) { int rc = -EINVAL; - dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, " - "new_state=%s)\n", jbt_state_names[jbt->state], jbt_state_names[new_state]); + dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, new_state=%s)\n", + jbt_state_names[jbt->state], + jbt_state_names[new_state]); mutex_lock(&jbt->lock); @@ -363,7 +374,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* first transition into sleep */ rc = standby_to_sleep(jbt); /* then transition into normal */ - rc |= sleep_to_qvga_normal(jbt); + rc |= sleep_to_normal(jbt); break; } break; @@ -376,10 +387,8 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) rc = sleep_to_standby(jbt); break; case JBT_STATE_NORMAL: - rc = sleep_to_normal(jbt); - break; case JBT_STATE_QVGA_NORMAL: - rc = sleep_to_qvga_normal(jbt); + rc = sleep_to_normal(jbt); break; } break; @@ -405,7 +414,7 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) /* third transition into sleep */ rc |= standby_to_sleep(jbt); /* fourth transition into normal */ - rc |= sleep_to_qvga_normal(jbt); + rc |= sleep_to_normal(jbt); break; } break; @@ -436,12 +445,13 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state) } break; } - + if (rc == 0) jbt->state = new_state; else - dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", jbt_state_names[new_state]); - + dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", + jbt_state_names[new_state]); + mutex_unlock(&jbt->lock); return rc; @@ -525,18 +535,27 @@ static ssize_t gamma_write(struct device *dev, struct device_attribute *attr, static ssize_t reset_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + int rc; struct jbt_info *jbt = dev_get_drvdata(dev); - struct jbt6k74_platform_data *jbt6k74_pdata = jbt->spi_dev->dev.platform_data; + struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data; dev_info(dev, "reset\n"); - jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + mutex_lock(&jbt->lock); + + jbt->state = JBT_STATE_DEEP_STANDBY; /* hard reset the jbt6k74 */ - mutex_lock(&jbt->lock); - (jbt6k74_pdata->reset)(0, 0); + (pdata->reset)(0, 0); mdelay(1); - (jbt6k74_pdata->reset)(0, 1); + (pdata->reset)(0, 1); + mdelay(120); + + rc = jbt_reg_write_nodata(jbt, 0x01); + if (rc < 0) + dev_err(&jbt->spi_dev->dev, "cannot soft reset\n"); + mdelay(120); + mutex_unlock(&jbt->lock); jbt6k74_enter_state(jbt, jbt->normal_state); @@ -580,26 +599,22 @@ static int fb_notifier_callback(struct notifier_block *self, return 0; fb_blank = *(int *)evdata->data; - switch (fb_blank) { case FB_BLANK_UNBLANK: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n"); + dev_dbg(&jbt->spi_dev->dev, "unblank\n"); jbt6k74_enter_state(jbt, jbt->normal_state); break; case FB_BLANK_NORMAL: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n"); + dev_dbg(&jbt->spi_dev->dev, "blank\n"); break; case FB_BLANK_VSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n"); + dev_dbg(&jbt->spi_dev->dev, "vsync suspend\n"); break; case FB_BLANK_HSYNC_SUSPEND: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 hsync suspend\n"); + dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n"); break; case FB_BLANK_POWERDOWN: - dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n"); - /* FIXME DEEP STANDBY wihtout suspend causes WSOD at cold - * temperature on certain devices. */ - /*jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);*/ + dev_dbg(&jbt->spi_dev->dev, "powerdown\n"); jbt6k74_enter_state(jbt, JBT_STATE_SLEEP); break; } @@ -613,7 +628,7 @@ static int __devinit jbt_probe(struct spi_device *spi) { int rc; struct jbt_info *jbt; - struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; + struct jbt6k74_platform_data *pdata = spi->dev.platform_data; /* the controller doesn't have a MISO pin; we can't do detection */ @@ -634,6 +649,7 @@ static int __devinit jbt_probe(struct spi_device *spi) jbt->spi_dev = spi; jbt->normal_state = JBT_STATE_NORMAL; jbt->state = JBT_STATE_DEEP_STANDBY; + jbt->last_sleep = current_kernel_time(); mutex_init(&jbt->lock); dev_set_drvdata(&spi->dev, jbt); @@ -657,8 +673,8 @@ static int __devinit jbt_probe(struct spi_device *spi) goto err_sysfs; } - if (jbt6k74_pdata->probe_completed) - (jbt6k74_pdata->probe_completed)(&spi->dev); + if (pdata->probe_completed) + (pdata->probe_completed)(&spi->dev); return 0; @@ -696,8 +712,6 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); - jbt->have_resumed = 0; - dev_info(&spi->dev, "suspended\n"); return 0; @@ -706,12 +720,12 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) 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; + struct jbt6k74_platform_data *pdata = spi->dev.platform_data; jbt6k74_enter_state(jbt, jbt->normal_state); - if (jbt6k74_pdata->resuming) - (jbt6k74_pdata->resuming)(0); + if (pdata->resuming) + (pdata->resuming)(0); dev_info(&spi->dev, "resumed\n"); -- cgit v1.2.3