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

Reply via email to