Andy,
I've reviewed the merge of WSOD patch into andy-tracking kernel and it
does not seem to be the cause of the regression that as been reported in
bug #2126. Attached, you'll find a correction that makes state
transition atomic. That will prevent getting bad states when the driver
is altered by two of more thread.
regards,
Nicolas
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
index a1d48dd..6464298 100644
--- a/drivers/video/display/jbt6k74.c
+++ b/drivers/video/display/jbt6k74.c
@@ -128,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));
@@ -139,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;
}
@@ -149,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,
@@ -160,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;
}
@@ -169,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);
@@ -182,8 +172,6 @@ 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;
}
@@ -255,6 +243,19 @@ static int jbt_init_regs(struct jbt_info *jbt, int qvga)
static int standby_to_sleep(struct jbt_info *jbt)
{
int rc;
+ struct jbt6k74_platform_data *jbt6k74_pdata = jbt->spi_dev->dev.platform_data;
+
+ /* 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(&jbt->spi_dev->dev, "cannot soft reset\n");
+
+ mdelay(120);
/* three times command zero */
rc = jbt_reg_write_nodata(jbt, 0x00);
@@ -347,8 +348,10 @@ 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);
switch (jbt->state) {
case JBT_STATE_DEEP_STANDBY:
@@ -445,6 +448,10 @@ int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state)
if (rc == 0)
jbt->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;
}
@@ -515,9 +522,11 @@ 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_dbg(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;
}
@@ -526,24 +535,10 @@ static ssize_t reset_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
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_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);
+ dev_dbg(dev, "**** jbt6k74 reset\n");
+ jbt->last_state = jbt->state;
jbt->state = JBT_STATE_DEEP_STANDBY;
switch (jbt->last_state) {
@@ -594,26 +589,26 @@ 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");
+ dev_dbg(&jbt->spi_dev->dev, "**** jbt6k74 unblank\n");
jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
break;
case FB_BLANK_NORMAL:
- dev_info(&jbt->spi_dev->dev, "**** jbt6k74 normal\n");
+ dev_dbg(&jbt->spi_dev->dev, "**** jbt6k74 normal\n");
break;
case FB_BLANK_VSYNC_SUSPEND:
- dev_info(&jbt->spi_dev->dev, "**** jbt6k74 vsync suspend\n");
+ dev_dbg(&jbt->spi_dev->dev, "**** jbt6k74 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, "**** 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 */
+ dev_dbg(&jbt->spi_dev->dev, "**** jbt6k74 powerdown\n");
+ /* FIXME: deep standby causes WSOD on certain devices. We use
+ * sleep as workaround */
jbt6k74_enter_state(jbt, JBT_STATE_SLEEP);
break;
}
@@ -651,20 +646,6 @@ static int __devinit jbt_probe(struct spi_device *spi)
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");
@@ -720,8 +701,11 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
{
struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+ dev_info(&spi->dev, "**** jbt6k74 suspend start\n");
+
/* 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);
@@ -737,25 +721,9 @@ 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);
_______________________________________________
devel mailing list
[email protected]
https://lists.openmoko.org/mailman/listinfo/devel