drivers/video/backlight/ld9040.c: small fixes
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / video / backlight / ld9040.c
1 /*
2  * ld9040 AMOLED LCD panel driver.
3  *
4  * Copyright (c) 2011 Samsung Electronics
5  * Author: Donghwa Lee  <dh09.lee@samsung.com>
6  * Derived from drivers/video/backlight/s6e63m0.c
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #include <linux/wait.h>
24 #include <linux/fb.h>
25 #include <linux/delay.h>
26 #include <linux/gpio.h>
27 #include <linux/spi/spi.h>
28 #include <linux/irq.h>
29 #include <linux/interrupt.h>
30 #include <linux/kernel.h>
31 #include <linux/lcd.h>
32 #include <linux/backlight.h>
33
34 #include "ld9040_gamma.h"
35
36 #define SLEEPMSEC               0x1000
37 #define ENDDEF                  0x2000
38 #define DEFMASK                 0xFF00
39 #define COMMAND_ONLY            0xFE
40 #define DATA_ONLY               0xFF
41
42 #define MIN_BRIGHTNESS          0
43 #define MAX_BRIGHTNESS          24
44 #define power_is_on(pwr)        ((pwr) <= FB_BLANK_NORMAL)
45
46 struct ld9040 {
47         struct device                   *dev;
48         struct spi_device               *spi;
49         unsigned int                    power;
50         unsigned int                    current_brightness;
51
52         struct lcd_device               *ld;
53         struct backlight_device         *bd;
54         struct lcd_platform_data        *lcd_pd;
55 };
56
57 static const unsigned short seq_swreset[] = {
58         0x01, COMMAND_ONLY,
59         ENDDEF, 0x00
60 };
61
62 static const unsigned short seq_user_setting[] = {
63         0xF0, 0x5A,
64
65         DATA_ONLY, 0x5A,
66         ENDDEF, 0x00
67 };
68
69 static const unsigned short seq_elvss_on[] = {
70         0xB1, 0x0D,
71
72         DATA_ONLY, 0x00,
73         DATA_ONLY, 0x16,
74         ENDDEF, 0x00
75 };
76
77 static const unsigned short seq_gtcon[] = {
78         0xF7, 0x09,
79
80         DATA_ONLY, 0x00,
81         DATA_ONLY, 0x00,
82         ENDDEF, 0x00
83 };
84
85 static const unsigned short seq_panel_condition[] = {
86         0xF8, 0x05,
87
88         DATA_ONLY, 0x65,
89         DATA_ONLY, 0x96,
90         DATA_ONLY, 0x71,
91         DATA_ONLY, 0x7D,
92         DATA_ONLY, 0x19,
93         DATA_ONLY, 0x3B,
94         DATA_ONLY, 0x0D,
95         DATA_ONLY, 0x19,
96         DATA_ONLY, 0x7E,
97         DATA_ONLY, 0x0D,
98         DATA_ONLY, 0xE2,
99         DATA_ONLY, 0x00,
100         DATA_ONLY, 0x00,
101         DATA_ONLY, 0x7E,
102         DATA_ONLY, 0x7D,
103         DATA_ONLY, 0x07,
104         DATA_ONLY, 0x07,
105         DATA_ONLY, 0x20,
106         DATA_ONLY, 0x20,
107         DATA_ONLY, 0x20,
108         DATA_ONLY, 0x02,
109         DATA_ONLY, 0x02,
110         ENDDEF, 0x00
111 };
112
113 static const unsigned short seq_gamma_set1[] = {
114         0xF9, 0x00,
115
116         DATA_ONLY, 0xA7,
117         DATA_ONLY, 0xB4,
118         DATA_ONLY, 0xAE,
119         DATA_ONLY, 0xBF,
120         DATA_ONLY, 0x00,
121         DATA_ONLY, 0x91,
122         DATA_ONLY, 0x00,
123         DATA_ONLY, 0xB2,
124         DATA_ONLY, 0xB4,
125         DATA_ONLY, 0xAA,
126         DATA_ONLY, 0xBB,
127         DATA_ONLY, 0x00,
128         DATA_ONLY, 0xAC,
129         DATA_ONLY, 0x00,
130         DATA_ONLY, 0xB3,
131         DATA_ONLY, 0xB1,
132         DATA_ONLY, 0xAA,
133         DATA_ONLY, 0xBC,
134         DATA_ONLY, 0x00,
135         DATA_ONLY, 0xB3,
136         ENDDEF, 0x00
137 };
138
139 static const unsigned short seq_gamma_ctrl[] = {
140         0xFB, 0x02,
141
142         DATA_ONLY, 0x5A,
143         ENDDEF, 0x00
144 };
145
146 static const unsigned short seq_gamma_start[] = {
147         0xF9, COMMAND_ONLY,
148
149         ENDDEF, 0x00
150 };
151
152 static const unsigned short seq_apon[] = {
153         0xF3, 0x00,
154
155         DATA_ONLY, 0x00,
156         DATA_ONLY, 0x00,
157         DATA_ONLY, 0x0A,
158         DATA_ONLY, 0x02,
159         ENDDEF, 0x00
160 };
161
162 static const unsigned short seq_display_ctrl[] = {
163         0xF2, 0x02,
164
165         DATA_ONLY, 0x08,
166         DATA_ONLY, 0x08,
167         DATA_ONLY, 0x10,
168         DATA_ONLY, 0x10,
169         ENDDEF, 0x00
170 };
171
172 static const unsigned short seq_manual_pwr[] = {
173         0xB0, 0x04,
174         ENDDEF, 0x00
175 };
176
177 static const unsigned short seq_pwr_ctrl[] = {
178         0xF4, 0x0A,
179
180         DATA_ONLY, 0x87,
181         DATA_ONLY, 0x25,
182         DATA_ONLY, 0x6A,
183         DATA_ONLY, 0x44,
184         DATA_ONLY, 0x02,
185         DATA_ONLY, 0x88,
186         ENDDEF, 0x00
187 };
188
189 static const unsigned short seq_sleep_out[] = {
190         0x11, COMMAND_ONLY,
191         ENDDEF, 0x00
192 };
193
194 static const unsigned short seq_sleep_in[] = {
195         0x10, COMMAND_ONLY,
196         ENDDEF, 0x00
197 };
198
199 static const unsigned short seq_display_on[] = {
200         0x29, COMMAND_ONLY,
201         ENDDEF, 0x00
202 };
203
204 static const unsigned short seq_display_off[] = {
205         0x28, COMMAND_ONLY,
206         ENDDEF, 0x00
207 };
208
209 static const unsigned short seq_vci1_1st_en[] = {
210         0xF3, 0x10,
211
212         DATA_ONLY, 0x00,
213         DATA_ONLY, 0x00,
214         DATA_ONLY, 0x00,
215         DATA_ONLY, 0x02,
216         ENDDEF, 0x00
217 };
218
219 static const unsigned short seq_vl1_en[] = {
220         0xF3, 0x11,
221
222         DATA_ONLY, 0x00,
223         DATA_ONLY, 0x00,
224         DATA_ONLY, 0x00,
225         DATA_ONLY, 0x02,
226         ENDDEF, 0x00
227 };
228
229 static const unsigned short seq_vl2_en[] = {
230         0xF3, 0x13,
231
232         DATA_ONLY, 0x00,
233         DATA_ONLY, 0x00,
234         DATA_ONLY, 0x00,
235         DATA_ONLY, 0x02,
236         ENDDEF, 0x00
237 };
238
239 static const unsigned short seq_vci1_2nd_en[] = {
240         0xF3, 0x33,
241
242         DATA_ONLY, 0x00,
243         DATA_ONLY, 0x00,
244         DATA_ONLY, 0x00,
245         DATA_ONLY, 0x02,
246         ENDDEF, 0x00
247 };
248
249 static const unsigned short seq_vl3_en[] = {
250         0xF3, 0x37,
251
252         DATA_ONLY, 0x00,
253         DATA_ONLY, 0x00,
254         DATA_ONLY, 0x00,
255         DATA_ONLY, 0x02,
256         ENDDEF, 0x00
257 };
258
259 static const unsigned short seq_vreg1_amp_en[] = {
260         0xF3, 0x37,
261
262         DATA_ONLY, 0x01,
263         DATA_ONLY, 0x00,
264         DATA_ONLY, 0x00,
265         DATA_ONLY, 0x02,
266         ENDDEF, 0x00
267 };
268
269 static const unsigned short seq_vgh_amp_en[] = {
270         0xF3, 0x37,
271
272         DATA_ONLY, 0x11,
273         DATA_ONLY, 0x00,
274         DATA_ONLY, 0x00,
275         DATA_ONLY, 0x02,
276         ENDDEF, 0x00
277 };
278
279 static const unsigned short seq_vgl_amp_en[] = {
280         0xF3, 0x37,
281
282         DATA_ONLY, 0x31,
283         DATA_ONLY, 0x00,
284         DATA_ONLY, 0x00,
285         DATA_ONLY, 0x02,
286         ENDDEF, 0x00
287 };
288
289 static const unsigned short seq_vmos_amp_en[] = {
290         0xF3, 0x37,
291
292         DATA_ONLY, 0xB1,
293         DATA_ONLY, 0x00,
294         DATA_ONLY, 0x00,
295         DATA_ONLY, 0x03,
296         ENDDEF, 0x00
297 };
298
299 static const unsigned short seq_vint_amp_en[] = {
300         0xF3, 0x37,
301
302         DATA_ONLY, 0xF1,
303         /* DATA_ONLY, 0x71,     VMOS/VBL/VBH not used */
304         DATA_ONLY, 0x00,
305         DATA_ONLY, 0x00,
306         DATA_ONLY, 0x03,
307         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
308         ENDDEF, 0x00
309 };
310
311 static const unsigned short seq_vbh_amp_en[] = {
312         0xF3, 0x37,
313
314         DATA_ONLY, 0xF9,
315         DATA_ONLY, 0x00,
316         DATA_ONLY, 0x00,
317         DATA_ONLY, 0x03,
318         ENDDEF, 0x00
319 };
320
321 static const unsigned short seq_vbl_amp_en[] = {
322         0xF3, 0x37,
323
324         DATA_ONLY, 0xFD,
325         DATA_ONLY, 0x00,
326         DATA_ONLY, 0x00,
327         DATA_ONLY, 0x03,
328         ENDDEF, 0x00
329 };
330
331 static const unsigned short seq_gam_amp_en[] = {
332         0xF3, 0x37,
333
334         DATA_ONLY, 0xFF,
335         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
336         DATA_ONLY, 0x00,
337         DATA_ONLY, 0x00,
338         DATA_ONLY, 0x03,
339         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
340         ENDDEF, 0x00
341 };
342
343 static const unsigned short seq_sd_amp_en[] = {
344         0xF3, 0x37,
345
346         DATA_ONLY, 0xFF,
347         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
348         DATA_ONLY, 0x80,
349         DATA_ONLY, 0x00,
350         DATA_ONLY, 0x03,
351         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
352         ENDDEF, 0x00
353 };
354
355 static const unsigned short seq_gls_en[] = {
356         0xF3, 0x37,
357
358         DATA_ONLY, 0xFF,
359         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
360         DATA_ONLY, 0x81,
361         DATA_ONLY, 0x00,
362         DATA_ONLY, 0x03,
363         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
364         ENDDEF, 0x00
365 };
366
367 static const unsigned short seq_els_en[] = {
368         0xF3, 0x37,
369
370         DATA_ONLY, 0xFF,
371         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
372         DATA_ONLY, 0x83,
373         DATA_ONLY, 0x00,
374         DATA_ONLY, 0x03,
375         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
376         ENDDEF, 0x00
377 };
378
379 static const unsigned short seq_el_on[] = {
380         0xF3, 0x37,
381
382         DATA_ONLY, 0xFF,
383         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
384         DATA_ONLY, 0x87,
385         DATA_ONLY, 0x00,
386         DATA_ONLY, 0x03,
387         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
388         ENDDEF, 0x00
389 };
390
391 static int ld9040_spi_write_byte(struct ld9040 *lcd, int addr, int data)
392 {
393         u16 buf[1];
394         struct spi_message msg;
395
396         struct spi_transfer xfer = {
397                 .len            = 2,
398                 .tx_buf         = buf,
399         };
400
401         buf[0] = (addr << 8) | data;
402
403         spi_message_init(&msg);
404         spi_message_add_tail(&xfer, &msg);
405
406         return spi_sync(lcd->spi, &msg);
407 }
408
409 static int ld9040_spi_write(struct ld9040 *lcd, unsigned char address,
410         unsigned char command)
411 {
412         int ret = 0;
413
414         if (address != DATA_ONLY)
415                 ret = ld9040_spi_write_byte(lcd, 0x0, address);
416         if (command != COMMAND_ONLY)
417                 ret = ld9040_spi_write_byte(lcd, 0x1, command);
418
419         return ret;
420 }
421
422 static int ld9040_panel_send_sequence(struct ld9040 *lcd,
423         const unsigned short *wbuf)
424 {
425         int ret = 0, i = 0;
426
427         while ((wbuf[i] & DEFMASK) != ENDDEF) {
428                 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
429                         ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]);
430                         if (ret)
431                                 break;
432                 } else
433                         udelay(wbuf[i+1]*1000);
434                 i += 2;
435         }
436
437         return ret;
438 }
439
440 static int _ld9040_gamma_ctl(struct ld9040 *lcd, const unsigned int *gamma)
441 {
442         unsigned int i = 0;
443         int ret = 0;
444
445         /* start gamma table updating. */
446         ret = ld9040_panel_send_sequence(lcd, seq_gamma_start);
447         if (ret) {
448                 dev_err(lcd->dev, "failed to disable gamma table updating.\n");
449                 goto gamma_err;
450         }
451
452         for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
453                 ret = ld9040_spi_write(lcd, DATA_ONLY, gamma[i]);
454                 if (ret) {
455                         dev_err(lcd->dev, "failed to set gamma table.\n");
456                         goto gamma_err;
457                 }
458         }
459
460         /* update gamma table. */
461         ret = ld9040_panel_send_sequence(lcd, seq_gamma_ctrl);
462         if (ret)
463                 dev_err(lcd->dev, "failed to update gamma table.\n");
464
465 gamma_err:
466         return ret;
467 }
468
469 static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma)
470 {
471         int ret = 0;
472
473         ret = _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
474
475         return ret;
476 }
477
478
479 static int ld9040_ldi_init(struct ld9040 *lcd)
480 {
481         int ret, i;
482         static const unsigned short *init_seq[] = {
483                 seq_user_setting,
484                 seq_panel_condition,
485                 seq_display_ctrl,
486                 seq_manual_pwr,
487                 seq_elvss_on,
488                 seq_gtcon,
489                 seq_gamma_set1,
490                 seq_gamma_ctrl,
491                 seq_sleep_out,
492         };
493
494         for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
495                 ret = ld9040_panel_send_sequence(lcd, init_seq[i]);
496                 /* workaround: minimum delay time for transferring CMD */
497                 udelay(300);
498                 if (ret)
499                         break;
500         }
501
502         return ret;
503 }
504
505 static int ld9040_ldi_enable(struct ld9040 *lcd)
506 {
507         int ret = 0;
508
509         ret = ld9040_panel_send_sequence(lcd, seq_display_on);
510
511         return ret;
512 }
513
514 static int ld9040_ldi_disable(struct ld9040 *lcd)
515 {
516         int ret;
517
518         ret = ld9040_panel_send_sequence(lcd, seq_display_off);
519         ret = ld9040_panel_send_sequence(lcd, seq_sleep_in);
520
521         return ret;
522 }
523
524 static int ld9040_power_on(struct ld9040 *lcd)
525 {
526         int ret = 0;
527         struct lcd_platform_data *pd = NULL;
528         pd = lcd->lcd_pd;
529         if (!pd) {
530                 dev_err(lcd->dev, "platform data is NULL.\n");
531                 return -EFAULT;
532         }
533
534         if (!pd->power_on) {
535                 dev_err(lcd->dev, "power_on is NULL.\n");
536                 return -EFAULT;
537         } else {
538                 pd->power_on(lcd->ld, 1);
539                 mdelay(pd->power_on_delay);
540         }
541
542         if (!pd->reset) {
543                 dev_err(lcd->dev, "reset is NULL.\n");
544                 return -EFAULT;
545         } else {
546                 pd->reset(lcd->ld);
547                 mdelay(pd->reset_delay);
548         }
549
550         ret = ld9040_ldi_init(lcd);
551         if (ret) {
552                 dev_err(lcd->dev, "failed to initialize ldi.\n");
553                 return ret;
554         }
555
556         ret = ld9040_ldi_enable(lcd);
557         if (ret) {
558                 dev_err(lcd->dev, "failed to enable ldi.\n");
559                 return ret;
560         }
561
562         return 0;
563 }
564
565 static int ld9040_power_off(struct ld9040 *lcd)
566 {
567         int ret = 0;
568         struct lcd_platform_data *pd = NULL;
569
570         pd = lcd->lcd_pd;
571         if (!pd) {
572                 dev_err(lcd->dev, "platform data is NULL.\n");
573                 return -EFAULT;
574         }
575
576         ret = ld9040_ldi_disable(lcd);
577         if (ret) {
578                 dev_err(lcd->dev, "lcd setting failed.\n");
579                 return -EIO;
580         }
581
582         mdelay(pd->power_off_delay);
583
584         if (!pd->power_on) {
585                 dev_err(lcd->dev, "power_on is NULL.\n");
586                 return -EFAULT;
587         } else
588                 pd->power_on(lcd->ld, 0);
589
590         return 0;
591 }
592
593 static int ld9040_power(struct ld9040 *lcd, int power)
594 {
595         int ret = 0;
596
597         if (power_is_on(power) && !power_is_on(lcd->power))
598                 ret = ld9040_power_on(lcd);
599         else if (!power_is_on(power) && power_is_on(lcd->power))
600                 ret = ld9040_power_off(lcd);
601
602         if (!ret)
603                 lcd->power = power;
604
605         return ret;
606 }
607
608 static int ld9040_set_power(struct lcd_device *ld, int power)
609 {
610         struct ld9040 *lcd = lcd_get_data(ld);
611
612         if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
613                 power != FB_BLANK_NORMAL) {
614                 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
615                 return -EINVAL;
616         }
617
618         return ld9040_power(lcd, power);
619 }
620
621 static int ld9040_get_power(struct lcd_device *ld)
622 {
623         struct ld9040 *lcd = lcd_get_data(ld);
624
625         return lcd->power;
626 }
627
628 static int ld9040_get_brightness(struct backlight_device *bd)
629 {
630         return bd->props.brightness;
631 }
632
633 static int ld9040_set_brightness(struct backlight_device *bd)
634 {
635         int ret = 0, brightness = bd->props.brightness;
636         struct ld9040 *lcd = bl_get_data(bd);
637
638         if (brightness < MIN_BRIGHTNESS ||
639                 brightness > bd->props.max_brightness) {
640                 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
641                         MIN_BRIGHTNESS, MAX_BRIGHTNESS);
642                 return -EINVAL;
643         }
644
645         ret = ld9040_gamma_ctl(lcd, bd->props.brightness);
646         if (ret) {
647                 dev_err(&bd->dev, "lcd brightness setting failed.\n");
648                 return -EIO;
649         }
650
651         return ret;
652 }
653
654 static struct lcd_ops ld9040_lcd_ops = {
655         .set_power = ld9040_set_power,
656         .get_power = ld9040_get_power,
657 };
658
659 static const struct backlight_ops ld9040_backlight_ops  = {
660         .get_brightness = ld9040_get_brightness,
661         .update_status = ld9040_set_brightness,
662 };
663
664
665 static int ld9040_probe(struct spi_device *spi)
666 {
667         int ret = 0;
668         struct ld9040 *lcd = NULL;
669         struct lcd_device *ld = NULL;
670         struct backlight_device *bd = NULL;
671
672         lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
673         if (!lcd)
674                 return -ENOMEM;
675
676         /* ld9040 lcd panel uses 3-wire 9bits SPI Mode. */
677         spi->bits_per_word = 9;
678
679         ret = spi_setup(spi);
680         if (ret < 0) {
681                 dev_err(&spi->dev, "spi setup failed.\n");
682                 goto out_free_lcd;
683         }
684
685         lcd->spi = spi;
686         lcd->dev = &spi->dev;
687
688         lcd->lcd_pd = spi->dev.platform_data;
689         if (!lcd->lcd_pd) {
690                 dev_err(&spi->dev, "platform data is NULL.\n");
691                 goto out_free_lcd;
692         }
693
694         ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
695         if (IS_ERR(ld)) {
696                 ret = PTR_ERR(ld);
697                 goto out_free_lcd;
698         }
699
700         lcd->ld = ld;
701
702         bd = backlight_device_register("ld9040-bl", &spi->dev,
703                 lcd, &ld9040_backlight_ops, NULL);
704         if (IS_ERR(bd)) {
705                 ret = PTR_ERR(bd);
706                 goto out_unregister_lcd;
707         }
708
709         bd->props.max_brightness = MAX_BRIGHTNESS;
710         bd->props.brightness = MAX_BRIGHTNESS;
711         lcd->bd = bd;
712
713         /*
714          * if lcd panel was on from bootloader like u-boot then
715          * do not lcd on.
716          */
717         if (!lcd->lcd_pd->lcd_enabled) {
718                 /*
719                  * if lcd panel was off from bootloader then
720                  * current lcd status is powerdown and then
721                  * it enables lcd panel.
722                  */
723                 lcd->power = FB_BLANK_POWERDOWN;
724
725                 ld9040_power(lcd, FB_BLANK_UNBLANK);
726         } else
727                 lcd->power = FB_BLANK_UNBLANK;
728
729         dev_set_drvdata(&spi->dev, lcd);
730
731         dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
732         return 0;
733
734 out_unregister_lcd:
735         lcd_device_unregister(lcd->ld);
736 out_free_lcd:
737         kfree(lcd);
738         return ret;
739 }
740
741 static int __devexit ld9040_remove(struct spi_device *spi)
742 {
743         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
744
745         ld9040_power(lcd, FB_BLANK_POWERDOWN);
746         backlight_device_unregister(lcd->bd);
747         lcd_device_unregister(lcd->ld);
748         kfree(lcd);
749
750         return 0;
751 }
752
753 #if defined(CONFIG_PM)
754 static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
755 {
756         int ret = 0;
757         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
758
759         dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
760
761         /*
762          * when lcd panel is suspend, lcd panel becomes off
763          * regardless of status.
764          */
765         ret = ld9040_power(lcd, FB_BLANK_POWERDOWN);
766
767         return ret;
768 }
769
770 static int ld9040_resume(struct spi_device *spi)
771 {
772         int ret = 0;
773         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
774
775         lcd->power = FB_BLANK_POWERDOWN;
776
777         ret = ld9040_power(lcd, FB_BLANK_UNBLANK);
778
779         return ret;
780 }
781 #else
782 #define ld9040_suspend          NULL
783 #define ld9040_resume           NULL
784 #endif
785
786 /* Power down all displays on reboot, poweroff or halt. */
787 static void ld9040_shutdown(struct spi_device *spi)
788 {
789         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
790
791         ld9040_power(lcd, FB_BLANK_POWERDOWN);
792 }
793
794 static struct spi_driver ld9040_driver = {
795         .driver = {
796                 .name   = "ld9040",
797                 .bus    = &spi_bus_type,
798                 .owner  = THIS_MODULE,
799         },
800         .probe          = ld9040_probe,
801         .remove         = __devexit_p(ld9040_remove),
802         .shutdown       = ld9040_shutdown,
803         .suspend        = ld9040_suspend,
804         .resume         = ld9040_resume,
805 };
806
807 static int __init ld9040_init(void)
808 {
809         return spi_register_driver(&ld9040_driver);
810 }
811
812 static void __exit ld9040_exit(void)
813 {
814         spi_unregister_driver(&ld9040_driver);
815 }
816
817 module_init(ld9040_init);
818 module_exit(ld9040_exit);
819
820 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
821 MODULE_DESCRIPTION("ld9040 LCD Driver");
822 MODULE_LICENSE("GPL");