aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 00:00:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 00:00:19 -0400
commit45b583b10a8b438b970e95a7d1d4db22c9e35004 (patch)
tree14fa481598289df0459580c582b48a9d95db51f6 /drivers/video
parent154dd78d30b56ffb8b447f629bfcceb14150e5c4 (diff)
parentf19da2ce8ef5e49b8b8ea199c3601dd45d71b262 (diff)
Merge 'akpm' patch series
* Merge akpm patch series: (122 commits) drivers/connector/cn_proc.c: remove unused local Documentation/SubmitChecklist: add RCU debug config options reiserfs: use hweight_long() reiserfs: use proper little-endian bitops pnpacpi: register disabled resources drivers/rtc/rtc-tegra.c: properly initialize spinlock drivers/rtc/rtc-twl.c: check return value of twl_rtc_write_u8() in twl_rtc_set_time() drivers/rtc: add support for Qualcomm PMIC8xxx RTC drivers/rtc/rtc-s3c.c: support clock gating drivers/rtc/rtc-mpc5121.c: add support for RTC on MPC5200 init: skip calibration delay if previously done misc/eeprom: add eeprom access driver for digsy_mtc board misc/eeprom: add driver for microwire 93xx46 EEPROMs checkpatch.pl: update $logFunctions checkpatch: make utf-8 test --strict checkpatch.pl: add ability to ignore various messages checkpatch: add a "prefer __aligned" check checkpatch: validate signature styles and To: and Cc: lines checkpatch: add __rcu as a sparse modifier checkpatch: suggest using min_t or max_t ... Did this as a merge because of (trivial) conflicts in - Documentation/feature-removal-schedule.txt - arch/xtensa/include/asm/uaccess.h that were just easier to fix up in the merge than in the patch series.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/backlight/Kconfig8
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/adp8860_bl.c3
-rw-r--r--drivers/video/backlight/ams369fg06.c646
-rw-r--r--drivers/video/backlight/ld9040.c17
-rw-r--r--drivers/video/backlight/s6e63m0.c11
6 files changed, 675 insertions, 11 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 2d93c8d61ad..1e54b8b7f69 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -117,6 +117,14 @@ config LCD_LD9040
117 If you have an LD9040 Panel, say Y to enable its 117 If you have an LD9040 Panel, say Y to enable its
118 control driver. 118 control driver.
119 119
120config LCD_AMS369FG06
121 tristate "AMS369FG06 AMOLED LCD Driver"
122 depends on SPI && BACKLIGHT_CLASS_DEVICE
123 default n
124 help
125 If you have an AMS369FG06 AMOLED Panel, say Y to enable its
126 LCD control driver.
127
120endif # LCD_CLASS_DEVICE 128endif # LCD_CLASS_DEVICE
121 129
122# 130#
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index ee72adb8786..bf1dd92b752 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o 13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o 14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
15obj-$(CONFIG_LCD_LD9040) += ld9040.o 15obj-$(CONFIG_LCD_LD9040) += ld9040.o
16obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o
16 17
17obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 18obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
18obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 19obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index d2a96a421ff..183b6f63985 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -722,8 +722,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
722 goto out2; 722 goto out2;
723 } 723 }
724 724
725 bl->props.max_brightness = 725 bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
726 bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
727 726
728 data->bl = bl; 727 data->bl = bl;
729 728
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
new file mode 100644
index 00000000000..9f0a491e2a0
--- /dev/null
+++ b/drivers/video/backlight/ams369fg06.c
@@ -0,0 +1,646 @@
1/*
2 * ams369fg06 AMOLED LCD panel driver.
3 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * Derived from drivers/video/s6e63m0.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/wait.h>
25#include <linux/fb.h>
26#include <linux/delay.h>
27#include <linux/gpio.h>
28#include <linux/spi/spi.h>
29#include <linux/lcd.h>
30#include <linux/backlight.h>
31
32#define SLEEPMSEC 0x1000
33#define ENDDEF 0x2000
34#define DEFMASK 0xFF00
35#define COMMAND_ONLY 0xFE
36#define DATA_ONLY 0xFF
37
38#define MAX_GAMMA_LEVEL 5
39#define GAMMA_TABLE_COUNT 21
40
41#define MIN_BRIGHTNESS 0
42#define MAX_BRIGHTNESS 255
43#define DEFAULT_BRIGHTNESS 150
44
45struct ams369fg06 {
46 struct device *dev;
47 struct spi_device *spi;
48 unsigned int power;
49 struct lcd_device *ld;
50 struct backlight_device *bd;
51 struct lcd_platform_data *lcd_pd;
52};
53
54static const unsigned short seq_display_on[] = {
55 0x14, 0x03,
56 ENDDEF, 0x0000
57};
58
59static const unsigned short seq_display_off[] = {
60 0x14, 0x00,
61 ENDDEF, 0x0000
62};
63
64static const unsigned short seq_stand_by_on[] = {
65 0x1D, 0xA1,
66 SLEEPMSEC, 200,
67 ENDDEF, 0x0000
68};
69
70static const unsigned short seq_stand_by_off[] = {
71 0x1D, 0xA0,
72 SLEEPMSEC, 250,
73 ENDDEF, 0x0000
74};
75
76static const unsigned short seq_setting[] = {
77 0x31, 0x08,
78 0x32, 0x14,
79 0x30, 0x02,
80 0x27, 0x01,
81 0x12, 0x08,
82 0x13, 0x08,
83 0x15, 0x00,
84 0x16, 0x00,
85
86 0xef, 0xd0,
87 DATA_ONLY, 0xe8,
88
89 0x39, 0x44,
90 0x40, 0x00,
91 0x41, 0x3f,
92 0x42, 0x2a,
93 0x43, 0x27,
94 0x44, 0x27,
95 0x45, 0x1f,
96 0x46, 0x44,
97 0x50, 0x00,
98 0x51, 0x00,
99 0x52, 0x17,
100 0x53, 0x24,
101 0x54, 0x26,
102 0x55, 0x1f,
103 0x56, 0x43,
104 0x60, 0x00,
105 0x61, 0x3f,
106 0x62, 0x2a,
107 0x63, 0x25,
108 0x64, 0x24,
109 0x65, 0x1b,
110 0x66, 0x5c,
111
112 0x17, 0x22,
113 0x18, 0x33,
114 0x19, 0x03,
115 0x1a, 0x01,
116 0x22, 0xa4,
117 0x23, 0x00,
118 0x26, 0xa0,
119
120 0x1d, 0xa0,
121 SLEEPMSEC, 300,
122
123 0x14, 0x03,
124
125 ENDDEF, 0x0000
126};
127
128/* gamma value: 2.2 */
129static const unsigned int ams369fg06_22_250[] = {
130 0x00, 0x3f, 0x2a, 0x27, 0x27, 0x1f, 0x44,
131 0x00, 0x00, 0x17, 0x24, 0x26, 0x1f, 0x43,
132 0x00, 0x3f, 0x2a, 0x25, 0x24, 0x1b, 0x5c,
133};
134
135static const unsigned int ams369fg06_22_200[] = {
136 0x00, 0x3f, 0x28, 0x29, 0x27, 0x21, 0x3e,
137 0x00, 0x00, 0x10, 0x25, 0x27, 0x20, 0x3d,
138 0x00, 0x3f, 0x28, 0x27, 0x25, 0x1d, 0x53,
139};
140
141static const unsigned int ams369fg06_22_150[] = {
142 0x00, 0x3f, 0x2d, 0x29, 0x28, 0x23, 0x37,
143 0x00, 0x00, 0x0b, 0x25, 0x28, 0x22, 0x36,
144 0x00, 0x3f, 0x2b, 0x28, 0x26, 0x1f, 0x4a,
145};
146
147static const unsigned int ams369fg06_22_100[] = {
148 0x00, 0x3f, 0x30, 0x2a, 0x2b, 0x24, 0x2f,
149 0x00, 0x00, 0x00, 0x25, 0x29, 0x24, 0x2e,
150 0x00, 0x3f, 0x2f, 0x29, 0x29, 0x21, 0x3f,
151};
152
153static const unsigned int ams369fg06_22_50[] = {
154 0x00, 0x3f, 0x3c, 0x2c, 0x2d, 0x27, 0x24,
155 0x00, 0x00, 0x00, 0x22, 0x2a, 0x27, 0x23,
156 0x00, 0x3f, 0x3b, 0x2c, 0x2b, 0x24, 0x31,
157};
158
159struct ams369fg06_gamma {
160 unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
161};
162
163static struct ams369fg06_gamma gamma_table = {
164 .gamma_22_table[0] = (unsigned int *)&ams369fg06_22_50,
165 .gamma_22_table[1] = (unsigned int *)&ams369fg06_22_100,
166 .gamma_22_table[2] = (unsigned int *)&ams369fg06_22_150,
167 .gamma_22_table[3] = (unsigned int *)&ams369fg06_22_200,
168 .gamma_22_table[4] = (unsigned int *)&ams369fg06_22_250,
169};
170
171static int ams369fg06_spi_write_byte(struct ams369fg06 *lcd, int addr, int data)
172{
173 u16 buf[1];
174 struct spi_message msg;
175
176 struct spi_transfer xfer = {
177 .len = 2,
178 .tx_buf = buf,
179 };
180
181 buf[0] = (addr << 8) | data;
182
183 spi_message_init(&msg);
184 spi_message_add_tail(&xfer, &msg);
185
186 return spi_sync(lcd->spi, &msg);
187}
188
189static int ams369fg06_spi_write(struct ams369fg06 *lcd, unsigned char address,
190 unsigned char command)
191{
192 int ret = 0;
193
194 if (address != DATA_ONLY)
195 ret = ams369fg06_spi_write_byte(lcd, 0x70, address);
196 if (command != COMMAND_ONLY)
197 ret = ams369fg06_spi_write_byte(lcd, 0x72, command);
198
199 return ret;
200}
201
202static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd,
203 const unsigned short *wbuf)
204{
205 int ret = 0, i = 0;
206
207 while ((wbuf[i] & DEFMASK) != ENDDEF) {
208 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
209 ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]);
210 if (ret)
211 break;
212 } else
213 mdelay(wbuf[i+1]);
214 i += 2;
215 }
216
217 return ret;
218}
219
220static int _ams369fg06_gamma_ctl(struct ams369fg06 *lcd,
221 const unsigned int *gamma)
222{
223 unsigned int i = 0;
224 int ret = 0;
225
226 for (i = 0 ; i < GAMMA_TABLE_COUNT / 3; i++) {
227 ret = ams369fg06_spi_write(lcd, 0x40 + i, gamma[i]);
228 ret = ams369fg06_spi_write(lcd, 0x50 + i, gamma[i+7*1]);
229 ret = ams369fg06_spi_write(lcd, 0x60 + i, gamma[i+7*2]);
230 if (ret) {
231 dev_err(lcd->dev, "failed to set gamma table.\n");
232 goto gamma_err;
233 }
234 }
235
236gamma_err:
237 return ret;
238}
239
240static int ams369fg06_gamma_ctl(struct ams369fg06 *lcd, int brightness)
241{
242 int ret = 0;
243 int gamma = 0;
244
245 if ((brightness >= 0) && (brightness <= 50))
246 gamma = 0;
247 else if ((brightness > 50) && (brightness <= 100))
248 gamma = 1;
249 else if ((brightness > 100) && (brightness <= 150))
250 gamma = 2;
251 else if ((brightness > 150) && (brightness <= 200))
252 gamma = 3;
253 else if ((brightness > 200) && (brightness <= 255))
254 gamma = 4;
255
256 ret = _ams369fg06_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
257
258 return ret;
259}
260
261static int ams369fg06_ldi_init(struct ams369fg06 *lcd)
262{
263 int ret, i;
264 static const unsigned short *init_seq[] = {
265 seq_setting,
266 seq_stand_by_off,
267 };
268
269 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
270 ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
271 if (ret)
272 break;
273 }
274
275 return ret;
276}
277
278static int ams369fg06_ldi_enable(struct ams369fg06 *lcd)
279{
280 int ret, i;
281 static const unsigned short *init_seq[] = {
282 seq_stand_by_off,
283 seq_display_on,
284 };
285
286 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
287 ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
288 if (ret)
289 break;
290 }
291
292 return ret;
293}
294
295static int ams369fg06_ldi_disable(struct ams369fg06 *lcd)
296{
297 int ret, i;
298
299 static const unsigned short *init_seq[] = {
300 seq_display_off,
301 seq_stand_by_on,
302 };
303
304 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
305 ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
306 if (ret)
307 break;
308 }
309
310 return ret;
311}
312
313static int ams369fg06_power_is_on(int power)
314{
315 return ((power) <= FB_BLANK_NORMAL);
316}
317
318static int ams369fg06_power_on(struct ams369fg06 *lcd)
319{
320 int ret = 0;
321 struct lcd_platform_data *pd = NULL;
322 struct backlight_device *bd = NULL;
323
324 pd = lcd->lcd_pd;
325 if (!pd) {
326 dev_err(lcd->dev, "platform data is NULL.\n");
327 return -EFAULT;
328 }
329
330 bd = lcd->bd;
331 if (!bd) {
332 dev_err(lcd->dev, "backlight device is NULL.\n");
333 return -EFAULT;
334 }
335
336 if (!pd->power_on) {
337 dev_err(lcd->dev, "power_on is NULL.\n");
338 return -EFAULT;
339 } else {
340 pd->power_on(lcd->ld, 1);
341 mdelay(pd->power_on_delay);
342 }
343
344 if (!pd->reset) {
345 dev_err(lcd->dev, "reset is NULL.\n");
346 return -EFAULT;
347 } else {
348 pd->reset(lcd->ld);
349 mdelay(pd->reset_delay);
350 }
351
352 ret = ams369fg06_ldi_init(lcd);
353 if (ret) {
354 dev_err(lcd->dev, "failed to initialize ldi.\n");
355 return ret;
356 }
357
358 ret = ams369fg06_ldi_enable(lcd);
359 if (ret) {
360 dev_err(lcd->dev, "failed to enable ldi.\n");
361 return ret;
362 }
363
364 /* set brightness to current value after power on or resume. */
365 ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness);
366 if (ret) {
367 dev_err(lcd->dev, "lcd gamma setting failed.\n");
368 return ret;
369 }
370
371 return 0;
372}
373
374static int ams369fg06_power_off(struct ams369fg06 *lcd)
375{
376 int ret = 0;
377 struct lcd_platform_data *pd = NULL;
378
379 pd = lcd->lcd_pd;
380 if (!pd) {
381 dev_err(lcd->dev, "platform data is NULL\n");
382 return -EFAULT;
383 }
384
385 ret = ams369fg06_ldi_disable(lcd);
386 if (ret) {
387 dev_err(lcd->dev, "lcd setting failed.\n");
388 return -EIO;
389 }
390
391 mdelay(pd->power_off_delay);
392
393 if (!pd->power_on) {
394 dev_err(lcd->dev, "power_on is NULL.\n");
395 return -EFAULT;
396 } else
397 pd->power_on(lcd->ld, 0);
398
399 return 0;
400}
401
402static int ams369fg06_power(struct ams369fg06 *lcd, int power)
403{
404 int ret = 0;
405
406 if (ams369fg06_power_is_on(power) &&
407 !ams369fg06_power_is_on(lcd->power))
408 ret = ams369fg06_power_on(lcd);
409 else if (!ams369fg06_power_is_on(power) &&
410 ams369fg06_power_is_on(lcd->power))
411 ret = ams369fg06_power_off(lcd);
412
413 if (!ret)
414 lcd->power = power;
415
416 return ret;
417}
418
419static int ams369fg06_get_power(struct lcd_device *ld)
420{
421 struct ams369fg06 *lcd = lcd_get_data(ld);
422
423 return lcd->power;
424}
425
426static int ams369fg06_set_power(struct lcd_device *ld, int power)
427{
428 struct ams369fg06 *lcd = lcd_get_data(ld);
429
430 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
431 power != FB_BLANK_NORMAL) {
432 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
433 return -EINVAL;
434 }
435
436 return ams369fg06_power(lcd, power);
437}
438
439static int ams369fg06_get_brightness(struct backlight_device *bd)
440{
441 return bd->props.brightness;
442}
443
444static int ams369fg06_set_brightness(struct backlight_device *bd)
445{
446 int ret = 0;
447 int brightness = bd->props.brightness;
448 struct ams369fg06 *lcd = dev_get_drvdata(&bd->dev);
449
450 if (brightness < MIN_BRIGHTNESS ||
451 brightness > bd->props.max_brightness) {
452 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
453 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
454 return -EINVAL;
455 }
456
457 ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness);
458 if (ret) {
459 dev_err(&bd->dev, "lcd brightness setting failed.\n");
460 return -EIO;
461 }
462
463 return ret;
464}
465
466static struct lcd_ops ams369fg06_lcd_ops = {
467 .get_power = ams369fg06_get_power,
468 .set_power = ams369fg06_set_power,
469};
470
471static const struct backlight_ops ams369fg06_backlight_ops = {
472 .get_brightness = ams369fg06_get_brightness,
473 .update_status = ams369fg06_set_brightness,
474};
475
476static int __devinit ams369fg06_probe(struct spi_device *spi)
477{
478 int ret = 0;
479 struct ams369fg06 *lcd = NULL;
480 struct lcd_device *ld = NULL;
481 struct backlight_device *bd = NULL;
482 struct backlight_properties props;
483
484 lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL);
485 if (!lcd)
486 return -ENOMEM;
487
488 /* ams369fg06 lcd panel uses 3-wire 16bits SPI Mode. */
489 spi->bits_per_word = 16;
490
491 ret = spi_setup(spi);
492 if (ret < 0) {
493 dev_err(&spi->dev, "spi setup failed.\n");
494 goto out_free_lcd;
495 }
496
497 lcd->spi = spi;
498 lcd->dev = &spi->dev;
499
500 lcd->lcd_pd = spi->dev.platform_data;
501 if (!lcd->lcd_pd) {
502 dev_err(&spi->dev, "platform data is NULL\n");
503 goto out_free_lcd;
504 }
505
506 ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
507 &ams369fg06_lcd_ops);
508 if (IS_ERR(ld)) {
509 ret = PTR_ERR(ld);
510 goto out_free_lcd;
511 }
512
513 lcd->ld = ld;
514
515 memset(&props, 0, sizeof(struct backlight_properties));
516 props.type = BACKLIGHT_RAW;
517 props.max_brightness = MAX_BRIGHTNESS;
518
519 bd = backlight_device_register("ams369fg06-bl", &spi->dev, lcd,
520 &ams369fg06_backlight_ops, &props);
521 if (IS_ERR(bd)) {
522 ret = PTR_ERR(bd);
523 goto out_lcd_unregister;
524 }
525
526 bd->props.brightness = DEFAULT_BRIGHTNESS;
527 lcd->bd = bd;
528
529 if (!lcd->lcd_pd->lcd_enabled) {
530 /*
531 * if lcd panel was off from bootloader then
532 * current lcd status is powerdown and then
533 * it enables lcd panel.
534 */
535 lcd->power = FB_BLANK_POWERDOWN;
536
537 ams369fg06_power(lcd, FB_BLANK_UNBLANK);
538 } else
539 lcd->power = FB_BLANK_UNBLANK;
540
541 dev_set_drvdata(&spi->dev, lcd);
542
543 dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n");
544
545 return 0;
546
547out_lcd_unregister:
548 lcd_device_unregister(ld);
549out_free_lcd:
550 kfree(lcd);
551 return ret;
552}
553
554static int __devexit ams369fg06_remove(struct spi_device *spi)
555{
556 struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
557
558 ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
559 backlight_device_unregister(lcd->bd);
560 lcd_device_unregister(lcd->ld);
561 kfree(lcd);
562
563 return 0;
564}
565
566#if defined(CONFIG_PM)
567static unsigned int before_power;
568
569static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg)
570{
571 int ret = 0;
572 struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
573
574 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
575
576 before_power = lcd->power;
577
578 /*
579 * when lcd panel is suspend, lcd panel becomes off
580 * regardless of status.
581 */
582 ret = ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
583
584 return ret;
585}
586
587static int ams369fg06_resume(struct spi_device *spi)
588{
589 int ret = 0;
590 struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
591
592 /*
593 * after suspended, if lcd panel status is FB_BLANK_UNBLANK
594 * (at that time, before_power is FB_BLANK_UNBLANK) then
595 * it changes that status to FB_BLANK_POWERDOWN to get lcd on.
596 */
597 if (before_power == FB_BLANK_UNBLANK)
598 lcd->power = FB_BLANK_POWERDOWN;
599
600 dev_dbg(&spi->dev, "before_power = %d\n", before_power);
601
602 ret = ams369fg06_power(lcd, before_power);
603
604 return ret;
605}
606#else
607#define ams369fg06_suspend NULL
608#define ams369fg06_resume NULL
609#endif
610
611static void ams369fg06_shutdown(struct spi_device *spi)
612{
613 struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
614
615 ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
616}
617
618static struct spi_driver ams369fg06_driver = {
619 .driver = {
620 .name = "ams369fg06",
621 .bus = &spi_bus_type,
622 .owner = THIS_MODULE,
623 },
624 .probe = ams369fg06_probe,
625 .remove = __devexit_p(ams369fg06_remove),
626 .shutdown = ams369fg06_shutdown,
627 .suspend = ams369fg06_suspend,
628 .resume = ams369fg06_resume,
629};
630
631static int __init ams369fg06_init(void)
632{
633 return spi_register_driver(&ams369fg06_driver);
634}
635
636static void __exit ams369fg06_exit(void)
637{
638 spi_unregister_driver(&ams369fg06_driver);
639}
640
641module_init(ams369fg06_init);
642module_exit(ams369fg06_exit);
643
644MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
645MODULE_DESCRIPTION("ams369fg06 LCD Driver");
646MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 7281b2506a6..5934655eb1f 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -668,6 +668,7 @@ static int ld9040_probe(struct spi_device *spi)
668 struct ld9040 *lcd = NULL; 668 struct ld9040 *lcd = NULL;
669 struct lcd_device *ld = NULL; 669 struct lcd_device *ld = NULL;
670 struct backlight_device *bd = NULL; 670 struct backlight_device *bd = NULL;
671 struct backlight_properties props;
671 672
672 lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL); 673 lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
673 if (!lcd) 674 if (!lcd)
@@ -699,14 +700,17 @@ static int ld9040_probe(struct spi_device *spi)
699 700
700 lcd->ld = ld; 701 lcd->ld = ld;
701 702
703 memset(&props, 0, sizeof(struct backlight_properties));
704 props.type = BACKLIGHT_RAW;
705 props.max_brightness = MAX_BRIGHTNESS;
706
702 bd = backlight_device_register("ld9040-bl", &spi->dev, 707 bd = backlight_device_register("ld9040-bl", &spi->dev,
703 lcd, &ld9040_backlight_ops, NULL); 708 lcd, &ld9040_backlight_ops, &props);
704 if (IS_ERR(ld)) { 709 if (IS_ERR(bd)) {
705 ret = PTR_ERR(ld); 710 ret = PTR_ERR(bd);
706 goto out_free_lcd; 711 goto out_unregister_lcd;
707 } 712 }
708 713
709 bd->props.max_brightness = MAX_BRIGHTNESS;
710 bd->props.brightness = MAX_BRIGHTNESS; 714 bd->props.brightness = MAX_BRIGHTNESS;
711 lcd->bd = bd; 715 lcd->bd = bd;
712 716
@@ -731,6 +735,8 @@ static int ld9040_probe(struct spi_device *spi)
731 dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); 735 dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
732 return 0; 736 return 0;
733 737
738out_unregister_lcd:
739 lcd_device_unregister(lcd->ld);
734out_free_lcd: 740out_free_lcd:
735 kfree(lcd); 741 kfree(lcd);
736 return ret; 742 return ret;
@@ -741,6 +747,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
741 struct ld9040 *lcd = dev_get_drvdata(&spi->dev); 747 struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
742 748
743 ld9040_power(lcd, FB_BLANK_POWERDOWN); 749 ld9040_power(lcd, FB_BLANK_POWERDOWN);
750 backlight_device_unregister(lcd->bd);
744 lcd_device_unregister(lcd->ld); 751 lcd_device_unregister(lcd->ld);
745 kfree(lcd); 752 kfree(lcd);
746 753
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 322040f686c..694e5aab0d6 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -738,6 +738,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
738 struct s6e63m0 *lcd = NULL; 738 struct s6e63m0 *lcd = NULL;
739 struct lcd_device *ld = NULL; 739 struct lcd_device *ld = NULL;
740 struct backlight_device *bd = NULL; 740 struct backlight_device *bd = NULL;
741 struct backlight_properties props;
741 742
742 lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL); 743 lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
743 if (!lcd) 744 if (!lcd)
@@ -769,16 +770,18 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
769 770
770 lcd->ld = ld; 771 lcd->ld = ld;
771 772
773 memset(&props, 0, sizeof(struct backlight_properties));
774 props.type = BACKLIGHT_RAW;
775 props.max_brightness = MAX_BRIGHTNESS;
776
772 bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, 777 bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
773 &s6e63m0_backlight_ops, NULL); 778 &s6e63m0_backlight_ops, &props);
774 if (IS_ERR(bd)) { 779 if (IS_ERR(bd)) {
775 ret = PTR_ERR(bd); 780 ret = PTR_ERR(bd);
776 goto out_lcd_unregister; 781 goto out_lcd_unregister;
777 } 782 }
778 783
779 bd->props.max_brightness = MAX_BRIGHTNESS;
780 bd->props.brightness = MAX_BRIGHTNESS; 784 bd->props.brightness = MAX_BRIGHTNESS;
781 bd->props.type = BACKLIGHT_RAW;
782 lcd->bd = bd; 785 lcd->bd = bd;
783 786
784 /* 787 /*
@@ -840,7 +843,7 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
840} 843}
841 844
842#if defined(CONFIG_PM) 845#if defined(CONFIG_PM)
843unsigned int before_power; 846static unsigned int before_power;
844 847
845static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) 848static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
846{ 849{