aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/display/jbt6k74.c146
1 files changed, 43 insertions, 103 deletions
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
index 930c106b99c..9add1c6bf8a 100644
--- a/drivers/video/display/jbt6k74.c
+++ b/drivers/video/display/jbt6k74.c
@@ -111,8 +111,7 @@ static const char *jbt_state_names[] = {
};
struct jbt_info {
- enum jbt_state state, last_state;
- enum jbt_state normal_state; /* QVGA or VGA */
+ enum jbt_state state, normal_state;
struct spi_device *spi_dev;
struct mutex lock; /* protects tx_buf and reg_cache */
struct notifier_block fb_notif;
@@ -129,8 +128,6 @@ static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
{
int rc;
- mutex_lock(&jbt->lock);
-
jbt->tx_buf[0] = JBT_COMMAND | reg;
rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
1*sizeof(u16));
@@ -140,8 +137,6 @@ static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
printk(KERN_ERR"jbt_reg_write_nodata spi_write ret %d\n",
rc);
- mutex_unlock(&jbt->lock);
-
return rc;
}
@@ -150,8 +145,6 @@ static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
{
int rc;
- mutex_lock(&jbt->lock);
-
jbt->tx_buf[0] = JBT_COMMAND | reg;
jbt->tx_buf[1] = JBT_DATA | data;
rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
@@ -161,8 +154,6 @@ static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
else
printk(KERN_ERR"jbt_reg_write spi_write ret %d\n", rc);
- mutex_unlock(&jbt->lock);
-
return rc;
}
@@ -170,8 +161,6 @@ static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
{
int rc;
- mutex_lock(&jbt->lock);
-
jbt->tx_buf[0] = JBT_COMMAND | reg;
jbt->tx_buf[1] = JBT_DATA | (data >> 8);
jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
@@ -183,16 +172,15 @@ static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
else
printk(KERN_ERR"jbt_reg_write16 spi_write ret %d\n", rc);
- mutex_unlock(&jbt->lock);
-
return rc;
}
-static int jbt_init_regs(struct jbt_info *jbt, int qvga)
+static int jbt_init_regs(struct jbt_info *jbt)
{
int rc;
- dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", qvga ? 'Q' : ' ');
+ 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);
rc |= jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE2, 0x00);
@@ -226,7 +214,7 @@ static int jbt_init_regs(struct jbt_info *jbt, int qvga)
rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
- if (!qvga) {
+ if (jbt->normal_state != JBT_STATE_QVGA_NORMAL) {
rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
@@ -266,7 +254,12 @@ static int standby_to_sleep(struct jbt_info *jbt)
mdelay(1);
/* deep standby out */
- rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17);
+ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x11);
+ mdelay(1);
+ rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x28);
+
+ /* (re)initialize register set */
+ rc |= jbt_init_regs(jbt);
return rc ? -EIO : 0;
}
@@ -287,15 +280,12 @@ static int sleep_to_normal(struct jbt_info *jbt)
/* Output control */
rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
- /* Sleep mode off */
- rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
-
- /* initialize register set */
- rc |= jbt_init_regs(jbt, 0);
-
/* 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;
}
@@ -315,15 +305,12 @@ static int sleep_to_qvga_normal(struct jbt_info *jbt)
/* Output control */
rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
- /* Sleep mode off */
- rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
-
- /* initialize register set for qvga*/
- rc |= jbt_init_regs(jbt, 1);
-
/* 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;
}
@@ -348,8 +335,14 @@ 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=%u, "
- "new_state=%u)\n", jbt->state, 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);
+
+ if (new_state == JBT_STATE_NORMAL ||
+ new_state == JBT_STATE_QVGA_NORMAL)
+ jbt->normal_state = new_state;
switch (jbt->state) {
case JBT_STATE_DEEP_STANDBY:
@@ -446,10 +439,10 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state)
if (rc == 0)
jbt->state = new_state;
-
- if (new_state == JBT_STATE_NORMAL ||
- new_state == JBT_STATE_QVGA_NORMAL)
- jbt->normal_state = new_state;
+ else
+ dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n", jbt_state_names[new_state]);
+
+ mutex_unlock(&jbt->lock);
return rc;
}
@@ -522,7 +515,9 @@ static ssize_t gamma_write(struct device *dev, struct device_attribute *attr,
dev_info(dev, "**** jbt6k74 writing gama %lu\n", val & 0xff);
+ mutex_lock(&jbt->lock);
jbt_reg_write(jbt, reg, val & 0xff);
+ mutex_unlock(&jbt->lock);
return count;
}
@@ -532,33 +527,19 @@ static ssize_t reset_write(struct device *dev, struct device_attribute *attr,
{
struct jbt_info *jbt = dev_get_drvdata(dev);
struct jbt6k74_platform_data *jbt6k74_pdata = jbt->spi_dev->dev.platform_data;
- int rc;
dev_info(dev, "**** jbt6k74 reset\n");
- /* hard reset the jbt6k74 */
+ jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+ /* hard reset the jbt6k74 */
+ mutex_lock(&jbt->lock);
(jbt6k74_pdata->reset)(0, 0);
mdelay(1);
(jbt6k74_pdata->reset)(0, 1);
- mdelay(120);
-
- rc = jbt_reg_write_nodata(jbt, 0x01);
- if (rc < 0)
- dev_err(dev, "cannot soft reset\n");
-
- mdelay(120);
-
- jbt->state = JBT_STATE_DEEP_STANDBY;
+ mutex_unlock(&jbt->lock);
- switch (jbt->last_state) {
- case JBT_STATE_QVGA_NORMAL:
- jbt6k74_enter_state(jbt, JBT_STATE_QVGA_NORMAL);
- break;
- default:
- jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
- break;
- }
+ jbt6k74_enter_state(jbt, jbt->normal_state);
return count;
}
@@ -610,15 +591,12 @@ static int fb_notifier_callback(struct notifier_block *self,
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); */
break;
case FB_BLANK_POWERDOWN:
dev_info(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n");
- /* FIXME: deep standby causes WSOD on certain devices. We use
- * sleep as workaround */
+ /* 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;
}
@@ -651,24 +629,12 @@ static int __devinit jbt_probe(struct spi_device *spi)
return -ENOMEM;
jbt->spi_dev = spi;
+ jbt->normal_state = JBT_STATE_NORMAL;
jbt->state = JBT_STATE_DEEP_STANDBY;
mutex_init(&jbt->lock);
dev_set_drvdata(&spi->dev, jbt);
- /* hard reset the jbt6k74 */
-
- (jbt6k74_pdata->reset)(0, 0);
- mdelay(1);
- (jbt6k74_pdata->reset)(0, 1);
- mdelay(120);
-
- rc = jbt_reg_write_nodata(jbt, 0x01);
- if (rc < 0)
- dev_err(&spi->dev, "cannot soft reset\n");
-
- mdelay(120);
-
rc = jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
if (rc < 0) {
dev_err(&spi->dev, "cannot enter NORMAL state\n");
@@ -710,6 +676,7 @@ static int __devexit jbt_remove(struct spi_device *spi)
/* We don't want to switch off the display in case the user
* accidentially onloads the module (whose use count normally is 0) */
+ jbt6k74_enter_state(jbt, jbt->normal_state);
fb_unregister_client(&jbt->fb_notif);
sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
@@ -724,11 +691,7 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
{
struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
- /* Save mode for resume */
- jbt->last_state = jbt->state;
- /* FIXME: deep standby causes WSOD on certain devices. We use
- * sleep as workaround */
- jbt6k74_enter_state(jbt, JBT_STATE_SLEEP);
+ jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
jbt->have_resumed = 0;
@@ -741,33 +704,10 @@ 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;
- int rc;
dev_info(&spi->dev, "**** jbt6k74 resume start\n");
- /* hard reset the jbt6k74 */
-
- (jbt6k74_pdata->reset)(0, 0);
- mdelay(1);
- (jbt6k74_pdata->reset)(0, 1);
- mdelay(120);
-
- rc = jbt_reg_write_nodata(jbt, 0x01);
- if (rc < 0)
- dev_err(&spi->dev, "cannot soft reset\n");
-
- mdelay(120);
-
- jbt->state = JBT_STATE_DEEP_STANDBY;
-
- switch (jbt->last_state) {
- case JBT_STATE_QVGA_NORMAL:
- jbt6k74_enter_state(jbt, JBT_STATE_QVGA_NORMAL);
- break;
- default:
- jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
- break;
- }
+ jbt6k74_enter_state(jbt, jbt->normal_state);
if (jbt6k74_pdata->resuming)
(jbt6k74_pdata->resuming)(0);