tegra: video: remove LGD 7" T4 in some condition
Min-wuk Lee [Wed, 4 Sep 2013 09:25:26 +0000 (18:25 +0900)]
This is work around. LGD WXGA 7" panel spec requests
1s delay between "panel 3v3 off" and "3v3 on" if all
panel related power rails (1v8, 3v3) are not turned off.

Precondition for work around
 - In power off, panel off then touch off.
 - In power on, touch on then panel on.

Why work around is necessary?
 - Same 1v8 rail is shared by touch and panel.
   In panel off, 3v3 rail off and 1v8 rail off
   are requested, but 1v8 rail isn't turned off
   in panel off timeframe because of touch module.
   It is possible to get panel on request without
   touch off/on control. In this case, 1S delay
   is necessary per spec. If 1v8 is turned off
   and on by touch module before panel on request,
   then, we don't need 1S delay. If 1v8 is turned
   off in panel on request time, we don't need
   1S delay, either.

Bug 1349306

Change-Id: I204b4c1a73aeff2fcd29e00a818e409a85c8a6e9
Signed-off-by: Min-wuk Lee <mlee@nvidia.com>
Reviewed-on: http://git-master/r/270026
(cherry picked from commit 5bbcc6a090796220590838ddbcd03b61afe000e4)
Reviewed-on: http://git-master/r/302785
Reviewed-by: Harry Hong <hhong@nvidia.com>
Tested-by: Harry Hong <hhong@nvidia.com>

drivers/input/touchscreen/maxim_sti.c
drivers/video/tegra/of_lcd_device_data/tegratab_lcd_dev_data.c

index c8b9c92..0adc131 100644 (file)
@@ -109,6 +109,9 @@ struct dev_data {
 #endif
 };
 
+atomic_t touch_dvdd_on = ATOMIC_INIT(0);
+static int prev_dvdd_rail_state;
+
 static struct list_head  dev_list;
 static spinlock_t        dev_lock;
 
@@ -711,6 +714,10 @@ static int regulator_control(struct dev_data *dd, bool on)
                        regulator_disable(dd->reg_dvdd);
                        return ret;
                }
+               if (prev_dvdd_rail_state == 0)
+                       atomic_set(&touch_dvdd_on, 1);
+
+               prev_dvdd_rail_state = 1;
        } else {
                if (regulator_is_enabled(dd->reg_avdd))
                        ret = regulator_disable(dd->reg_avdd);
@@ -726,6 +733,12 @@ static int regulator_control(struct dev_data *dd, bool on)
                        regulator_enable(dd->reg_avdd);
                        return ret;
                }
+
+               if (!regulator_is_enabled(dd->reg_dvdd)) {
+                       prev_dvdd_rail_state = 0;
+                       msleep(200);
+               } else
+                       prev_dvdd_rail_state = 1;
        }
 
        return 0;
@@ -1945,6 +1958,7 @@ static struct spi_driver driver = {
 static int __devinit maxim_sti_init(void)
 {
        INIT_LIST_HEAD(&dev_list);
+       prev_dvdd_rail_state = 0;
        spin_lock_init(&dev_lock);
        return spi_register_driver(&driver);
 }
index 6e85eb0..1b1d62a 100644 (file)
@@ -30,7 +30,14 @@ struct of_tegra_lcd_devdata tegratab_lgd_lcd;
 
 #define LGD_LCD_REGULATORS_COUNT               3
 
+#define WORKAROUND_TO_REMOVE_LGD7_T4_TIME      1
+
 static bool lgd_lcd_reg_requested;
+
+#if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
+extern atomic_t touch_dvdd_on;
+#endif
+
 static struct regulator *lgd_lcd_regs[LGD_LCD_REGULATORS_COUNT];
 
 static struct regulator *avdd_lcd_3v3;
@@ -103,6 +110,39 @@ static int lgd_wxga_7_0_enable(struct device *dev)
                pr_err("lgd lcd regulator get failed\n");
                goto fail;
        }
+#if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
+       /*
+        * LGD WXGA 7" panel spec requests 1s delay between
+        * "panel 3v3 off" and "3v3 on" if all panel
+        * related power rails (1v8, 3v3) are not turned off.
+
+        * precondition for work around
+        *  - In power off, panel off then touch off.
+        *  - In power on, touch on then panel on.
+
+        * why work around is necessary?
+        *  - Same 1v8 rail is shared by touch and panel.
+        *  - In panel off, 3v3 rail off and 1v8 rail off
+        *    are requested, but 1v8 rail isn't turned off
+        *    in panel off timeframe because of touch module.
+        *    It is possible to get panel on request without
+        *    touch off/on control. In this case, 1S delay
+        *    is necessary per spec. If 1v8 is turned off
+        *    and on by touch module before panel on request,
+        *    then, we don't need 1S delay. If 1v8 is turned
+        *    off in panel on request time, we don't need
+        *    1S delay, either.
+        */
+
+       if ((!atomic_read(&touch_dvdd_on)) &&
+               regulator_is_enabled(dvdd_lcd_1v8)) {
+               msleep(1000);
+       }
+       /*
+        * Clean touch_dvdd_on
+        */
+       atomic_set(&touch_dvdd_on, 0);
+#endif
 
        if (dvdd_lcd_1v8) {
                err = regulator_enable(dvdd_lcd_1v8);
@@ -152,13 +192,23 @@ fail:
 
 static int lgd_wxga_7_0_disable(void)
 {
-       msleep(100); /*MIPI off to VDD off needs to be 50~150ms per spec*/
+       msleep(50); /*MIPI off to VDD off needs to be 50~150ms per spec*/
 
        if (dvdd_lcd_1v8)
                regulator_disable(dvdd_lcd_1v8);
        if (avdd_lcd_3v3)
                regulator_disable(avdd_lcd_3v3);
+
+#if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
+       /*
+        * Clean touch_dvdd_on here.
+        * pre condition for the work around mentions
+        * the sequence in power off is "panel off => touch off".
+        */
+       atomic_set(&touch_dvdd_on, 0);
+#else
        msleep(1000); /*LCD panel VDD on needs to be 1000>ms after it's off*/
+#endif
        return 0;
 }