Commit 95558ad15b2b679fb8b312d3fd637acea854ba2f
Committed by
Linus Torvalds
1 parent
5c2202f9c8
Exists in
master
and in
7 other branches
drivers/video/backlight/l4f00242t03.c: full implement fb power states for this lcd
Complete the support of fb power states managing correctly the regulators bound to this driver. Signed-off-by: Alberto Panizzo <maramaopercheseimorto@gmail.com> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Marek Vasut <marek.vasut@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: Axel Lin <axel.lin@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 75 additions and 22 deletions Side-by-side Diff
drivers/video/backlight/l4f00242t03.c
... | ... | @@ -25,7 +25,7 @@ |
25 | 25 | struct l4f00242t03_priv { |
26 | 26 | struct spi_device *spi; |
27 | 27 | struct lcd_device *ld; |
28 | - unsigned int lcd_on:1; | |
28 | + int lcd_state; | |
29 | 29 | struct regulator *io_reg; |
30 | 30 | struct regulator *core_reg; |
31 | 31 | }; |
... | ... | @@ -67,6 +67,29 @@ |
67 | 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 | 93 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) |
71 | 94 | { |
72 | 95 | struct l4f00242t03_priv *priv = lcd_get_data(ld); |
73 | 96 | |
74 | 97 | |
75 | 98 | |
76 | 99 | |
77 | 100 | |
78 | 101 | |
... | ... | @@ -79,35 +102,52 @@ |
79 | 102 | const u16 disoff = 0x28; |
80 | 103 | |
81 | 104 | if (power <= FB_BLANK_NORMAL) { |
82 | - if (priv->lcd_on) | |
83 | - return 0; | |
105 | + if (priv->lcd_state <= FB_BLANK_NORMAL) { | |
106 | + /* Do nothing, the LCD is running */ | |
107 | + } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { | |
108 | + dev_dbg(&spi->dev, "Resuming LCD\n"); | |
84 | 109 | |
85 | - dev_dbg(&spi->dev, "turning on LCD\n"); | |
110 | + spi_write(spi, (const u8 *)&slpout, sizeof(u16)); | |
111 | + msleep(60); | |
112 | + spi_write(spi, (const u8 *)&dison, sizeof(u16)); | |
113 | + } else { | |
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"); | |
86 | 123 | |
87 | - spi_write(spi, (const u8 *)&slpout, sizeof(u16)); | |
88 | - msleep(60); | |
89 | - spi_write(spi, (const u8 *)&dison, sizeof(u16)); | |
90 | - | |
91 | - priv->lcd_on = 1; | |
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 | 135 | } else { |
93 | - if (!priv->lcd_on) | |
94 | - return 0; | |
95 | - | |
96 | - dev_dbg(&spi->dev, "turning off LCD\n"); | |
97 | - | |
136 | + /* power == FB_BLANK_POWERDOWN */ | |
137 | + /* Clear the screen before shutting down */ | |
98 | 138 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); |
99 | 139 | msleep(60); |
100 | - spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | |
101 | - | |
102 | - priv->lcd_on = 0; | |
140 | + l4f00242t03_lcd_powerdown(spi); | |
103 | 141 | } |
104 | 142 | |
143 | + priv->lcd_state = power; | |
144 | + | |
105 | 145 | return 0; |
106 | 146 | } |
107 | 147 | |
108 | 148 | static struct lcd_ops l4f_ops = { |
109 | 149 | .set_power = l4f00242t03_lcd_power_set, |
110 | - .get_power = NULL, | |
150 | + .get_power = l4f00242t03_lcd_power_get, | |
111 | 151 | }; |
112 | 152 | |
113 | 153 | static int __devinit l4f00242t03_probe(struct spi_device *spi) |
... | ... | @@ -187,7 +227,8 @@ |
187 | 227 | /* Init the LCD */ |
188 | 228 | l4f00242t03_reset(pdata->reset_gpio); |
189 | 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 | 233 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); |
193 | 234 | |
194 | 235 | |
... | ... | @@ -214,9 +255,11 @@ |
214 | 255 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); |
215 | 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 | 259 | lcd_device_unregister(priv->ld); |
219 | 260 | |
261 | + dev_set_drvdata(&spi->dev, NULL); | |
262 | + | |
220 | 263 | gpio_free(pdata->data_enable_gpio); |
221 | 264 | gpio_free(pdata->reset_gpio); |
222 | 265 | |
... | ... | @@ -230,6 +273,15 @@ |
230 | 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 | 285 | static struct spi_driver l4f00242t03_driver = { |
234 | 286 | .driver = { |
235 | 287 | .name = "l4f00242t03", |
... | ... | @@ -237,6 +289,7 @@ |
237 | 289 | }, |
238 | 290 | .probe = l4f00242t03_probe, |
239 | 291 | .remove = __devexit_p(l4f00242t03_remove), |
292 | + .shutdown = l4f00242t03_shutdown, | |
240 | 293 | }; |
241 | 294 | |
242 | 295 | static __init int l4f00242t03_init(void) |