From 3d71204efba10914e339b411471877b81cf1e5d9 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-lcm-reinit-post-resume.patch

---
 arch/arm/mach-s3c2440/mach-gta02.c |   12 +++++++++
 drivers/mfd/glamo/glamo-core.c     |   15 ++++++++++-
 drivers/mfd/glamo/glamo-spi-gpio.c |   38 ++++++++++++++++++++++++++--
 drivers/video/display/jbt6k74.c    |   47 ++++++++++++++++++++++++++++++++----
 include/linux/glamofb.h            |    1 +
 include/linux/jbt6k74.h            |    8 ++++++
 6 files changed, 111 insertions(+), 10 deletions(-)
 create mode 100644 include/linux/jbt6k74.h

diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index f2b1b66..750fd97 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -76,6 +76,7 @@
 #include <asm/plat-s3c24xx/cpu.h>
 #include <asm/plat-s3c24xx/pm.h>
 #include <asm/plat-s3c24xx/udc.h>
+#include <linux/jbt6k74.h>
 
 #include <linux/glamofb.h>
 
@@ -756,10 +757,21 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = {
 
 /* SPI: LCM control interface attached to Glamo3362 */
 
+void gta02_jbt6k74_reset(int devidx, int level)
+{
+	glamo_lcm_reset(level);
+}
+
+
+const struct jbt6k74_platform_data jbt6k74_pdata = {
+	.reset		= gta02_jbt6k74_reset,
+};
+
 static struct spi_board_info gta02_spi_board_info[] = {
 	{
 		.modalias	= "jbt6k74",
 		/* platform_data */
+		.platform_data	= &jbt6k74_pdata,
 		/* controller_data */
 		/* irq */
 		.max_speed_hz	= 10 * 1000 * 1000,
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index ffa4945..2076e61 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -513,6 +513,17 @@ void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
 }
 EXPORT_SYMBOL_GPL(glamo_engine_reset);
 
+void glamo_lcm_reset(int level)
+{
+	if (!glamo_handle)
+		return;
+
+	glamo_gpio_setpin(glamo_handle, GLAMO_GPIO4, level);
+	glamo_gpio_cfgpin(glamo_handle, GLAMO_GPIO4_OUTPUT);
+
+}
+EXPORT_SYMBOL_GPL(glamo_lcm_reset);
+
 enum glamo_pll {
 	GLAMO_PLL1,
 	GLAMO_PLL2,
@@ -1142,8 +1153,8 @@ static int glamo_resume(struct platform_device *pdev)
 static struct platform_driver glamo_driver = {
 	.probe		= glamo_probe,
 	.remove		= glamo_remove,
-	.suspend	= glamo_suspend,
-	.resume		= glamo_resume,
+	.suspend_late	= glamo_suspend,
+	.resume_early	= glamo_resume,
 	.driver		= {
 		.name	= "glamo3362",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mfd/glamo/glamo-spi-gpio.c b/drivers/mfd/glamo/glamo-spi-gpio.c
index 73926bd..eda7322 100644
--- a/drivers/mfd/glamo/glamo-spi-gpio.c
+++ b/drivers/mfd/glamo/glamo-spi-gpio.c
@@ -224,14 +224,46 @@ static int glamo_spigpio_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#define glamo_spigpio_suspend NULL
+/*#define glamo_spigpio_suspend NULL
 #define glamo_spigpio_resume NULL
+*/
+
+
+#ifdef CONFIG_PM
+static int glamo_spigpio_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	return 0;
+}
+
+static int glamo_spigpio_resume(struct platform_device *pdev)
+{
+	struct glamo_spigpio *sp = platform_get_drvdata(pdev);
+
+	if (!sp)
+		return 0;
+
+	/* set state of spi pins */
+	glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0);
+	glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0);
+	glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1);
+
+	glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk);
+	glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi);
+	glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs);
+	if (sp->info->pin_miso)
+		glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso);
+
+	return 0;
+}
+#endif
 
 static struct platform_driver glamo_spi_drv = {
 	.probe		= glamo_spigpio_probe,
 	.remove		= glamo_spigpio_remove,
-	.suspend	= glamo_spigpio_suspend,
-	.resume		= glamo_spigpio_resume,
+#ifdef CONFIG_PM
+	.suspend_late	= glamo_spigpio_suspend,
+	.resume_early	= glamo_spigpio_resume,
+#endif
 	.driver		= {
 		.name	= "glamo-spi-gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
index d021d7e..d7e9442 100644
--- a/drivers/video/display/jbt6k74.c
+++ b/drivers/video/display/jbt6k74.c
@@ -27,6 +27,8 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/jbt6k74.h>
 
 #include <linux/spi/spi.h>
 
@@ -114,11 +116,15 @@ struct jbt_info {
 	struct mutex lock;		/* protects tx_buf and reg_cache */
 	u16 tx_buf[8];
 	u16 reg_cache[0xEE];
+	struct work_struct work;
 };
 
 #define JBT_COMMAND	0x000
 #define JBT_DATA	0x100
 
+static void jbt_resume_work(struct work_struct *work);
+
+
 static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
 {
 	int rc;
@@ -130,6 +136,9 @@ static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
 		       1*sizeof(u16));
 	if (rc == 0)
 		jbt->reg_cache[reg] = 0;
+	else
+		printk(KERN_ERR"jbt_reg_write_nodata spi_write ret %d\n",
+		       rc);
 
 	mutex_unlock(&jbt->lock);
 
@@ -149,6 +158,8 @@ static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
 		       2*sizeof(u16));
 	if (rc == 0)
 		jbt->reg_cache[reg] = data;
+	else
+		printk(KERN_ERR"jbt_reg_write spi_write ret %d\n", rc);
 
 	mutex_unlock(&jbt->lock);
 
@@ -169,6 +180,8 @@ static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
 		       3*sizeof(u16));
 	if (rc == 0)
 		jbt->reg_cache[reg] = data;
+	else
+		printk(KERN_ERR"jbt_reg_write16 spi_write ret %d\n", rc);
 
 	mutex_unlock(&jbt->lock);
 
@@ -563,6 +576,8 @@ static int __devinit jbt_probe(struct spi_device *spi)
 	if (!jbt)
 		return -ENOMEM;
 
+	INIT_WORK(&jbt->work, jbt_resume_work);
+
 	jbt->spi_dev = spi;
 	jbt->state = JBT_STATE_DEEP_STANDBY;
 	mutex_init(&jbt->lock);
@@ -618,28 +633,50 @@ static int __devexit jbt_remove(struct spi_device *spi)
 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;
 
 	/* Save mode for resume */
 	jbt->last_state = jbt->state;
 	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
 
+	(jbt6k74_pdata->reset)(0, 0);
+
 	return 0;
 }
 
-static int jbt_resume(struct spi_device *spi)
+static void jbt_resume_work(struct work_struct *work)
 {
-	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+	struct jbt_info *jbt = container_of(work, struct jbt_info, work);
+
+	printk(KERN_INFO"jbt_resume_work waiting...\n");
+	msleep(2000);
+	printk(KERN_INFO"jbt_resume_work GO...\n");
 
-	jbt6k74_enter_state(jbt, jbt->last_state);
+	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+	msleep(100);
 
 	switch (jbt->last_state) {
-	case JBT_STATE_NORMAL:
 	case JBT_STATE_QVGA_NORMAL:
-		jbt6k74_display_onoff(jbt, 1);
+		jbt6k74_enter_state(jbt, JBT_STATE_QVGA_NORMAL);
 		break;
 	default:
+		jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
 		break;
 	}
+	jbt6k74_display_onoff(jbt, 1);
+
+	printk(KERN_INFO"jbt_resume_work done...\n");
+}
+
+static int jbt_resume(struct spi_device *spi)
+{
+	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+	struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
+
+	(jbt6k74_pdata->reset)(0, 1);
+
+	if (!schedule_work(&jbt->work))
+		dev_err(&spi->dev, "Unable to schedule LCM wakeup work\n");
 
 	return 0;
 }
diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
index 24742a2..75eefef 100644
--- a/include/linux/glamofb.h
+++ b/include/linux/glamofb.h
@@ -35,5 +35,6 @@ struct glamofb_platform_data {
 
 void glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
+void glamo_lcm_reset(int level);
 
 #endif
diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
new file mode 100644
index 0000000..3fbe178
--- /dev/null
+++ b/include/linux/jbt6k74.h
@@ -0,0 +1,8 @@
+#ifndef __JBT6K74_H__
+#define __JBT6K74_H__
+
+struct jbt6k74_platform_data {
+	void (* reset)(int devindex, int level);
+};
+
+#endif
-- 
1.5.6.3