diff options
-rw-r--r-- | drivers/video/backlight/l4f00242t03.c | 97 |
1 files changed, 75 insertions, 22 deletions
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 6d9ba0e2b0c5..5d25743bf8e2 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
@@ -25,7 +25,7 @@ | |||
25 | struct l4f00242t03_priv { | 25 | struct l4f00242t03_priv { |
26 | struct spi_device *spi; | 26 | struct spi_device *spi; |
27 | struct lcd_device *ld; | 27 | struct lcd_device *ld; |
28 | unsigned int lcd_on:1; | 28 | int lcd_state; |
29 | struct regulator *io_reg; | 29 | struct regulator *io_reg; |
30 | struct regulator *core_reg; | 30 | struct regulator *core_reg; |
31 | }; | 31 | }; |
@@ -67,6 +67,29 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) | |||
67 | spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); | 67 | spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); |
68 | } | 68 | } |
69 | 69 | ||
70 | static void l4f00242t03_lcd_powerdown(struct spi_device *spi) | ||
71 | { | ||
72 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | ||
73 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
74 | |||
75 | dev_dbg(&spi->dev, "Powering down LCD\n"); | ||
76 | |||
77 | gpio_set_value(pdata->data_enable_gpio, 0); | ||
78 | |||
79 | if (priv->io_reg) | ||
80 | regulator_disable(priv->io_reg); | ||
81 | |||
82 | if (priv->core_reg) | ||
83 | regulator_disable(priv->core_reg); | ||
84 | } | ||
85 | |||
86 | static int l4f00242t03_lcd_power_get(struct lcd_device *ld) | ||
87 | { | ||
88 | struct l4f00242t03_priv *priv = lcd_get_data(ld); | ||
89 | |||
90 | return priv->lcd_state; | ||
91 | } | ||
92 | |||
70 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) | 93 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) |
71 | { | 94 | { |
72 | struct l4f00242t03_priv *priv = lcd_get_data(ld); | 95 | struct l4f00242t03_priv *priv = lcd_get_data(ld); |
@@ -79,35 +102,52 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) | |||
79 | const u16 disoff = 0x28; | 102 | const u16 disoff = 0x28; |
80 | 103 | ||
81 | if (power <= FB_BLANK_NORMAL) { | 104 | if (power <= FB_BLANK_NORMAL) { |
82 | if (priv->lcd_on) | 105 | if (priv->lcd_state <= FB_BLANK_NORMAL) { |
83 | return 0; | 106 | /* Do nothing, the LCD is running */ |
84 | 107 | } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { | |
85 | dev_dbg(&spi->dev, "turning on LCD\n"); | 108 | dev_dbg(&spi->dev, "Resuming LCD\n"); |
86 | 109 | ||
87 | spi_write(spi, (const u8 *)&slpout, sizeof(u16)); | 110 | spi_write(spi, (const u8 *)&slpout, sizeof(u16)); |
88 | msleep(60); | 111 | msleep(60); |
89 | spi_write(spi, (const u8 *)&dison, sizeof(u16)); | 112 | spi_write(spi, (const u8 *)&dison, sizeof(u16)); |
90 | 113 | } else { | |
91 | priv->lcd_on = 1; | 114 | /* priv->lcd_state == FB_BLANK_POWERDOWN */ |
115 | l4f00242t03_lcd_init(spi); | ||
116 | priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; | ||
117 | l4f00242t03_lcd_power_set(priv->ld, power); | ||
118 | } | ||
119 | } else if (power < FB_BLANK_POWERDOWN) { | ||
120 | if (priv->lcd_state <= FB_BLANK_NORMAL) { | ||
121 | /* Send the display in standby */ | ||
122 | dev_dbg(&spi->dev, "Standby the LCD\n"); | ||
123 | |||
124 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); | ||
125 | msleep(60); | ||
126 | spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | ||
127 | } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { | ||
128 | /* Do nothing, the LCD is already in standby */ | ||
129 | } else { | ||
130 | /* priv->lcd_state == FB_BLANK_POWERDOWN */ | ||
131 | l4f00242t03_lcd_init(spi); | ||
132 | priv->lcd_state = FB_BLANK_UNBLANK; | ||
133 | l4f00242t03_lcd_power_set(ld, power); | ||
134 | } | ||
92 | } else { | 135 | } else { |
93 | if (!priv->lcd_on) | 136 | /* power == FB_BLANK_POWERDOWN */ |
94 | return 0; | 137 | /* Clear the screen before shutting down */ |
95 | |||
96 | dev_dbg(&spi->dev, "turning off LCD\n"); | ||
97 | |||
98 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); | 138 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); |
99 | msleep(60); | 139 | msleep(60); |
100 | spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | 140 | l4f00242t03_lcd_powerdown(spi); |
101 | |||
102 | priv->lcd_on = 0; | ||
103 | } | 141 | } |
104 | 142 | ||
143 | priv->lcd_state = power; | ||
144 | |||
105 | return 0; | 145 | return 0; |
106 | } | 146 | } |
107 | 147 | ||
108 | static struct lcd_ops l4f_ops = { | 148 | static struct lcd_ops l4f_ops = { |
109 | .set_power = l4f00242t03_lcd_power_set, | 149 | .set_power = l4f00242t03_lcd_power_set, |
110 | .get_power = NULL, | 150 | .get_power = l4f00242t03_lcd_power_get, |
111 | }; | 151 | }; |
112 | 152 | ||
113 | static int __devinit l4f00242t03_probe(struct spi_device *spi) | 153 | static int __devinit l4f00242t03_probe(struct spi_device *spi) |
@@ -187,7 +227,8 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
187 | /* Init the LCD */ | 227 | /* Init the LCD */ |
188 | l4f00242t03_reset(pdata->reset_gpio); | 228 | l4f00242t03_reset(pdata->reset_gpio); |
189 | l4f00242t03_lcd_init(spi); | 229 | l4f00242t03_lcd_init(spi); |
190 | l4f00242t03_lcd_power_set(priv->ld, 1); | 230 | priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; |
231 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_UNBLANK); | ||
191 | 232 | ||
192 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); | 233 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); |
193 | 234 | ||
@@ -214,9 +255,11 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
214 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 255 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); |
215 | struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; | 256 | struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; |
216 | 257 | ||
217 | l4f00242t03_lcd_power_set(priv->ld, 0); | 258 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); |
218 | lcd_device_unregister(priv->ld); | 259 | lcd_device_unregister(priv->ld); |
219 | 260 | ||
261 | dev_set_drvdata(&spi->dev, NULL); | ||
262 | |||
220 | gpio_free(pdata->data_enable_gpio); | 263 | gpio_free(pdata->data_enable_gpio); |
221 | gpio_free(pdata->reset_gpio); | 264 | gpio_free(pdata->reset_gpio); |
222 | 265 | ||
@@ -230,6 +273,15 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
230 | return 0; | 273 | return 0; |
231 | } | 274 | } |
232 | 275 | ||
276 | static void l4f00242t03_shutdown(struct spi_device *spi) | ||
277 | { | ||
278 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
279 | |||
280 | if (priv) | ||
281 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); | ||
282 | |||
283 | } | ||
284 | |||
233 | static struct spi_driver l4f00242t03_driver = { | 285 | static struct spi_driver l4f00242t03_driver = { |
234 | .driver = { | 286 | .driver = { |
235 | .name = "l4f00242t03", | 287 | .name = "l4f00242t03", |
@@ -237,6 +289,7 @@ static struct spi_driver l4f00242t03_driver = { | |||
237 | }, | 289 | }, |
238 | .probe = l4f00242t03_probe, | 290 | .probe = l4f00242t03_probe, |
239 | .remove = __devexit_p(l4f00242t03_remove), | 291 | .remove = __devexit_p(l4f00242t03_remove), |
292 | .shutdown = l4f00242t03_shutdown, | ||
240 | }; | 293 | }; |
241 | 294 | ||
242 | static __init int l4f00242t03_init(void) | 295 | static __init int l4f00242t03_init(void) |