upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / video / samsung / ld9040.c
1 /*
2  * ld9040 AMOLED LCD panel driver.
3  *
4  * Author: Donghwa Lee  <dh09.lee@samsung.com>
5  *
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
45 /*ADDED_BY_JMSHIN_20110831_For_Intelligent_Overheating_Protection++*/
46 #ifdef CONFIG_BL_OVERHEATING_PROTECTION
47 #define OVERHEATING_LIMIT_BRIGHTNESS 17     /*limit brightness is 230cd */
48 #endif
49 /*ADDED_BY_JMSHIN_20110831_For_Intelligent_Overheating_Protection--*/
50
51 #define power_is_on(pwr)        ((pwr) <= FB_BLANK_NORMAL)
52
53 struct ld9040 {
54         struct device                   *dev;
55         struct spi_device               *spi;
56         unsigned int                    power;
57         unsigned int                    current_brightness;
58         unsigned int                    acl_enable;
59         unsigned int                    cur_acl;
60
61         struct lcd_device               *ld;
62         struct backlight_device         *bd;
63         struct lcd_platform_data        *lcd_pd;
64 };
65
66 struct ld9040 *global_lcd;  /*ADDED_BY_JMSHIN_20110824_For_Platform_Lockup_Info*/
67
68 static const unsigned short seq_swreset[] = {
69         0x01, COMMAND_ONLY,
70         ENDDEF, 0x00
71 };
72
73 static const unsigned short seq_user_setting[] = {
74         0xF0, 0x5A,
75
76         DATA_ONLY, 0x5A,
77         ENDDEF, 0x00
78 };
79
80 static const unsigned short seq_elvss_49[] = {
81         0xB2, 0x10,
82
83         DATA_ONLY, 0x10,
84         DATA_ONLY, 0x10,
85         DATA_ONLY, 0x10,
86         ENDDEF, 0x00
87 };
88
89 static const unsigned short seq_elvss_41[] = {
90         0xB2, 0x17,
91         DATA_ONLY, 0x17,
92         DATA_ONLY, 0x17,
93         DATA_ONLY, 0x17,
94         ENDDEF, 0x00
95 };
96
97 static const unsigned short seq_elvss_39[] = {
98         0xB2, 0x1A,
99         DATA_ONLY, 0x1A,
100         DATA_ONLY, 0x1A,
101         DATA_ONLY, 0x1A,
102         ENDDEF, 0x00
103 };
104
105 static const unsigned short seq_elvss_35[] = {
106         0xB2, 0x1E,
107         DATA_ONLY, 0x1E,
108         DATA_ONLY, 0x1E,
109         DATA_ONLY, 0x1E,
110         ENDDEF, 0x00
111 };
112 static const unsigned short seq_elvss_on[] = {
113         0xB1, 0x0D,
114
115         DATA_ONLY, 0x00,
116         DATA_ONLY, 0x16,
117         ENDDEF, 0x00
118 };
119
120 static const unsigned short seq_acl_on[] = {
121         0xC1, 0x4D,
122
123         DATA_ONLY, 0x96,
124         DATA_ONLY, 0x1D,
125         DATA_ONLY, 0x00,
126         DATA_ONLY, 0x00,
127         DATA_ONLY, 0x01,
128         DATA_ONLY, 0xDF,
129         DATA_ONLY, 0x00,
130         DATA_ONLY, 0x00,
131         DATA_ONLY, 0x03,
132         DATA_ONLY, 0x1F,
133         DATA_ONLY, 0x00,
134         DATA_ONLY, 0x00,
135         DATA_ONLY, 0x00,
136         DATA_ONLY, 0x00,
137         DATA_ONLY, 0x00,
138         DATA_ONLY, 0x01,
139         DATA_ONLY, 0x08,
140         DATA_ONLY, 0x0F,
141         DATA_ONLY, 0x16,
142         DATA_ONLY, 0x1D,
143         DATA_ONLY, 0x24,
144         DATA_ONLY, 0x2A,
145         DATA_ONLY, 0x31,
146         DATA_ONLY, 0x38,
147         DATA_ONLY, 0x3F,
148         DATA_ONLY, 0x46,
149         0xC0, 0x01,
150
151         ENDDEF, 0x00
152 };
153
154 static const unsigned short seq_acl_off[] = {
155         0xC0, 0x00,
156
157         ENDDEF, 0x00
158 };
159
160 static const unsigned short seq_acl_40p[] = {
161         0xC1, 0x4D,
162
163         DATA_ONLY, 0x96,
164         DATA_ONLY, 0x1D,
165         DATA_ONLY, 0x00,
166         DATA_ONLY, 0x00,
167         DATA_ONLY, 0x01,
168         DATA_ONLY, 0xDF,
169         DATA_ONLY, 0x00,
170         DATA_ONLY, 0x00,
171         DATA_ONLY, 0x03,
172         DATA_ONLY, 0x1F,
173         DATA_ONLY, 0x00,
174         DATA_ONLY, 0x00,
175         DATA_ONLY, 0x00,
176         DATA_ONLY, 0x00,
177         DATA_ONLY, 0x00,
178         DATA_ONLY, 0x01,
179         DATA_ONLY, 0x06,
180         DATA_ONLY, 0x11,
181         DATA_ONLY, 0x1A,
182         DATA_ONLY, 0x20,
183         DATA_ONLY, 0x25,
184         DATA_ONLY, 0x29,
185         DATA_ONLY, 0x2D,
186         DATA_ONLY, 0x30,
187         DATA_ONLY, 0x33,
188         DATA_ONLY, 0x35,
189         0xC0, 0x01,
190
191         ENDDEF, 0x00
192 };
193
194 static const unsigned short seq_acl_43p[] = {
195         0xC1, 0x4D,
196
197         DATA_ONLY, 0x96,
198         DATA_ONLY, 0x1D,
199         DATA_ONLY, 0x00,
200         DATA_ONLY, 0x00,
201         DATA_ONLY, 0x01,
202         DATA_ONLY, 0xDF,
203         DATA_ONLY, 0x00,
204         DATA_ONLY, 0x00,
205         DATA_ONLY, 0x03,
206         DATA_ONLY, 0x1F,
207         DATA_ONLY, 0x00,
208         DATA_ONLY, 0x00,
209         DATA_ONLY, 0x00,
210         DATA_ONLY, 0x00,
211         DATA_ONLY, 0x00,
212         DATA_ONLY, 0x01,
213         DATA_ONLY, 0x07,
214         DATA_ONLY, 0x12,
215         DATA_ONLY, 0x1C,
216         DATA_ONLY, 0x23,
217         DATA_ONLY, 0x29,
218         DATA_ONLY, 0x2D,
219         DATA_ONLY, 0x31,
220         DATA_ONLY, 0x34,
221         DATA_ONLY, 0x37,
222         DATA_ONLY, 0x3A,
223         0xC0, 0x01,
224
225         ENDDEF, 0x00
226 };
227
228 static const unsigned short seq_acl_45p[] = {
229         0xC1, 0x4D,
230
231         DATA_ONLY, 0x96,
232         DATA_ONLY, 0x1D,
233         DATA_ONLY, 0x00,
234         DATA_ONLY, 0x00,
235         DATA_ONLY, 0x01,
236         DATA_ONLY, 0xDF,
237         DATA_ONLY, 0x00,
238         DATA_ONLY, 0x00,
239         DATA_ONLY, 0x03,
240         DATA_ONLY, 0x1F,
241         DATA_ONLY, 0x00,
242         DATA_ONLY, 0x00,
243         DATA_ONLY, 0x00,
244         DATA_ONLY, 0x00,
245         DATA_ONLY, 0x00,
246         DATA_ONLY, 0x01,
247         DATA_ONLY, 0x07,
248         DATA_ONLY, 0x13,
249         DATA_ONLY, 0x1E,
250         DATA_ONLY, 0x25,
251         DATA_ONLY, 0x2B,
252         DATA_ONLY, 0x30,
253         DATA_ONLY, 0x34,
254         DATA_ONLY, 0x37,
255         DATA_ONLY, 0x3A,
256         DATA_ONLY, 0x3D,
257         0xC0, 0x01,
258
259         ENDDEF, 0x00
260 };
261
262 static const unsigned short seq_acl_47p[] = {
263         0xC1, 0x4D,
264
265         DATA_ONLY, 0x96,
266         DATA_ONLY, 0x1D,
267         DATA_ONLY, 0x00,
268         DATA_ONLY, 0x00,
269         DATA_ONLY, 0x01,
270         DATA_ONLY, 0xDF,
271         DATA_ONLY, 0x00,
272         DATA_ONLY, 0x00,
273         DATA_ONLY, 0x03,
274         DATA_ONLY, 0x1F,
275         DATA_ONLY, 0x00,
276         DATA_ONLY, 0x00,
277         DATA_ONLY, 0x00,
278         DATA_ONLY, 0x00,
279         DATA_ONLY, 0x00,
280         DATA_ONLY, 0x01,
281         DATA_ONLY, 0x07,
282         DATA_ONLY, 0x14,
283         DATA_ONLY, 0x20,
284         DATA_ONLY, 0x28,
285         DATA_ONLY, 0x2E,
286         DATA_ONLY, 0x33,
287         DATA_ONLY, 0x37,
288         DATA_ONLY, 0x3B,
289         DATA_ONLY, 0x3E,
290         DATA_ONLY, 0x41,
291         0xC0, 0x01,
292
293         ENDDEF, 0x00
294 };
295
296 static const unsigned short seq_acl_48p[] = {
297         0xC1, 0x4D,
298
299         DATA_ONLY, 0x96,
300         DATA_ONLY, 0x1D,
301         DATA_ONLY, 0x00,
302         DATA_ONLY, 0x00,
303         DATA_ONLY, 0x01,
304         DATA_ONLY, 0xDF,
305         DATA_ONLY, 0x00,
306         DATA_ONLY, 0x00,
307         DATA_ONLY, 0x03,
308         DATA_ONLY, 0x1F,
309         DATA_ONLY, 0x00,
310         DATA_ONLY, 0x00,
311         DATA_ONLY, 0x00,
312         DATA_ONLY, 0x00,
313         DATA_ONLY, 0x00,
314         DATA_ONLY, 0x01,
315         DATA_ONLY, 0x08,
316         DATA_ONLY, 0x15,
317         DATA_ONLY, 0x20,
318         DATA_ONLY, 0x29,
319         DATA_ONLY, 0x2F,
320         DATA_ONLY, 0x34,
321         DATA_ONLY, 0x39,
322         DATA_ONLY, 0x3D,
323         DATA_ONLY, 0x40,
324         DATA_ONLY, 0x43,
325         0xC0, 0x01,
326
327         ENDDEF, 0x00
328 };
329
330 static const unsigned short seq_acl_50p[] = {
331         0xC1, 0x4D,
332
333         DATA_ONLY, 0x96,
334         DATA_ONLY, 0x1D,
335         DATA_ONLY, 0x00,
336         DATA_ONLY, 0x00,
337         DATA_ONLY, 0x01,
338         DATA_ONLY, 0xDF,
339         DATA_ONLY, 0x00,
340         DATA_ONLY, 0x00,
341         DATA_ONLY, 0x03,
342         DATA_ONLY, 0x1F,
343         DATA_ONLY, 0x00,
344         DATA_ONLY, 0x00,
345         DATA_ONLY, 0x00,
346         DATA_ONLY, 0x00,
347         DATA_ONLY, 0x00,
348         DATA_ONLY, 0x01,
349         DATA_ONLY, 0x08,
350         DATA_ONLY, 0x16,
351         DATA_ONLY, 0x22,
352         DATA_ONLY, 0x2B,
353         DATA_ONLY, 0x31,
354         DATA_ONLY, 0x37,
355         DATA_ONLY, 0x3B,
356         DATA_ONLY, 0x3F,
357         DATA_ONLY, 0x43,
358         DATA_ONLY, 0x46,
359         0xC0, 0x01,
360
361         ENDDEF, 0x00
362 };
363
364 static const unsigned short seq_gtcon[] = {
365         0xF7, 0x09,
366
367         DATA_ONLY, 0x00,
368         DATA_ONLY, 0x00,
369         ENDDEF, 0x00
370 };
371
372 static const unsigned short seq_panel_condition[] = {
373         0xF8, 0x05,
374
375         DATA_ONLY, 0x65,
376         DATA_ONLY, 0x96,
377         DATA_ONLY, 0x71,
378         DATA_ONLY, 0x7D,
379         DATA_ONLY, 0x19,
380         DATA_ONLY, 0x3B,
381         DATA_ONLY, 0x0D,
382         DATA_ONLY, 0x19,
383         DATA_ONLY, 0x7E,
384         DATA_ONLY, 0x0D,
385         DATA_ONLY, 0xE2,
386         DATA_ONLY, 0x00,
387         DATA_ONLY, 0x00,
388         DATA_ONLY, 0x7E,
389         DATA_ONLY, 0x7D,
390         DATA_ONLY, 0x07,
391         DATA_ONLY, 0x07,
392         DATA_ONLY, 0x20,
393         DATA_ONLY, 0x20,
394         DATA_ONLY, 0x20,
395         DATA_ONLY, 0x02,
396         DATA_ONLY, 0x02,
397         ENDDEF, 0x00
398 };
399
400 static const unsigned short seq_gamma_set1[] = {
401         0xF9, 0x00,
402
403         DATA_ONLY, 0xA7,
404         DATA_ONLY, 0xB4,
405         DATA_ONLY, 0xAE,
406         DATA_ONLY, 0xBF,
407         DATA_ONLY, 0x00,
408         DATA_ONLY, 0x91,
409         DATA_ONLY, 0x00,
410         DATA_ONLY, 0xB2,
411         DATA_ONLY, 0xB4,
412         DATA_ONLY, 0xAA,
413         DATA_ONLY, 0xBB,
414         DATA_ONLY, 0x00,
415         DATA_ONLY, 0xAC,
416         DATA_ONLY, 0x00,
417         DATA_ONLY, 0xB3,
418         DATA_ONLY, 0xB1,
419         DATA_ONLY, 0xAA,
420         DATA_ONLY, 0xBC,
421         DATA_ONLY, 0x00,
422         DATA_ONLY, 0xB3,
423         ENDDEF, 0x00
424 };
425
426 static const unsigned short seq_gamma_ctrl[] = {
427         0xFB, 0x02,
428
429         DATA_ONLY, 0x5A,
430         ENDDEF, 0x00
431 };
432
433 static const unsigned short seq_gamma_start[] = {
434         0xF9, COMMAND_ONLY,
435
436         ENDDEF, 0x00
437 };
438
439 static const unsigned short seq_apon[] = {
440         0xF3, 0x00,
441
442         DATA_ONLY, 0x00,
443         DATA_ONLY, 0x00,
444         DATA_ONLY, 0x0A,
445         DATA_ONLY, 0x02,
446         ENDDEF, 0x00
447 };
448
449 static const unsigned short seq_display_ctrl[] = {
450         0xF2, 0x02,
451
452         DATA_ONLY, 0x08,
453         DATA_ONLY, 0x08,
454         DATA_ONLY, 0x10,
455         DATA_ONLY, 0x10,
456         ENDDEF, 0x00
457 };
458
459 static const unsigned short seq_manual_pwr[] = {
460         0xB0, 0x04,
461         ENDDEF, 0x00
462 };
463
464 static const unsigned short seq_pwr_ctrl[] = {
465         0xF4, 0x0A,
466
467         DATA_ONLY, 0x87,
468         DATA_ONLY, 0x25,
469         DATA_ONLY, 0x6A,
470         DATA_ONLY, 0x44,
471         DATA_ONLY, 0x02,
472         DATA_ONLY, 0x88,
473         ENDDEF, 0x00
474 };
475
476 static const unsigned short seq_sleep_out[] = {
477         0x11, COMMAND_ONLY,
478         ENDDEF, 0x00
479 };
480
481 static const unsigned short seq_sleep_in[] = {
482         0x10, COMMAND_ONLY,
483         ENDDEF, 0x00
484 };
485
486 static const unsigned short seq_display_on[] = {
487         0x29, COMMAND_ONLY,
488         ENDDEF, 0x00
489 };
490
491 static const unsigned short seq_display_off[] = {
492         0x28, COMMAND_ONLY,
493         ENDDEF, 0x00
494 };
495
496 static const unsigned short seq_vci1_1st_en[] = {
497         0xF3, 0x10,
498
499         DATA_ONLY, 0x00,
500         DATA_ONLY, 0x00,
501         DATA_ONLY, 0x00,
502         DATA_ONLY, 0x02,
503         ENDDEF, 0x00
504 };
505
506 static const unsigned short seq_vl1_en[] = {
507         0xF3, 0x11,
508
509         DATA_ONLY, 0x00,
510         DATA_ONLY, 0x00,
511         DATA_ONLY, 0x00,
512         DATA_ONLY, 0x02,
513         ENDDEF, 0x00
514 };
515
516 static const unsigned short seq_vl2_en[] = {
517         0xF3, 0x13,
518
519         DATA_ONLY, 0x00,
520         DATA_ONLY, 0x00,
521         DATA_ONLY, 0x00,
522         DATA_ONLY, 0x02,
523         ENDDEF, 0x00
524 };
525
526 static const unsigned short seq_vci1_2nd_en[] = {
527         0xF3, 0x33,
528
529         DATA_ONLY, 0x00,
530         DATA_ONLY, 0x00,
531         DATA_ONLY, 0x00,
532         DATA_ONLY, 0x02,
533         ENDDEF, 0x00
534 };
535
536 static const unsigned short seq_vl3_en[] = {
537         0xF3, 0x37,
538
539         DATA_ONLY, 0x00,
540         DATA_ONLY, 0x00,
541         DATA_ONLY, 0x00,
542         DATA_ONLY, 0x02,
543         ENDDEF, 0x00
544 };
545
546 static const unsigned short seq_vreg1_amp_en[] = {
547         0xF3, 0x37,
548
549         DATA_ONLY, 0x01,
550         DATA_ONLY, 0x00,
551         DATA_ONLY, 0x00,
552         DATA_ONLY, 0x02,
553         ENDDEF, 0x00
554 };
555
556 static const unsigned short seq_vgh_amp_en[] = {
557         0xF3, 0x37,
558
559         DATA_ONLY, 0x11,
560         DATA_ONLY, 0x00,
561         DATA_ONLY, 0x00,
562         DATA_ONLY, 0x02,
563         ENDDEF, 0x00
564 };
565
566 static const unsigned short seq_vgl_amp_en[] = {
567         0xF3, 0x37,
568
569         DATA_ONLY, 0x31,
570         DATA_ONLY, 0x00,
571         DATA_ONLY, 0x00,
572         DATA_ONLY, 0x02,
573         ENDDEF, 0x00
574 };
575
576 static const unsigned short seq_vmos_amp_en[] = {
577         0xF3, 0x37,
578
579         DATA_ONLY, 0xB1,
580         DATA_ONLY, 0x00,
581         DATA_ONLY, 0x00,
582         DATA_ONLY, 0x03,
583         ENDDEF, 0x00
584 };
585
586 static const unsigned short seq_vint_amp_en[] = {
587         0xF3, 0x37,
588
589         DATA_ONLY, 0xF1,
590         /* DATA_ONLY, 0x71,     VMOS/VBL/VBH not used */
591         DATA_ONLY, 0x00,
592         DATA_ONLY, 0x00,
593         DATA_ONLY, 0x03,
594         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
595         ENDDEF, 0x00
596 };
597
598 static const unsigned short seq_vbh_amp_en[] = {
599         0xF3, 0x37,
600
601         DATA_ONLY, 0xF9,
602         DATA_ONLY, 0x00,
603         DATA_ONLY, 0x00,
604         DATA_ONLY, 0x03,
605         ENDDEF, 0x00
606 };
607
608 static const unsigned short seq_vbl_amp_en[] = {
609         0xF3, 0x37,
610
611         DATA_ONLY, 0xFD,
612         DATA_ONLY, 0x00,
613         DATA_ONLY, 0x00,
614         DATA_ONLY, 0x03,
615         ENDDEF, 0x00
616 };
617
618 static const unsigned short seq_gam_amp_en[] = {
619         0xF3, 0x37,
620
621         DATA_ONLY, 0xFF,
622         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
623         DATA_ONLY, 0x00,
624         DATA_ONLY, 0x00,
625         DATA_ONLY, 0x03,
626         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
627         ENDDEF, 0x00
628 };
629
630 static const unsigned short seq_sd_amp_en[] = {
631         0xF3, 0x37,
632
633         DATA_ONLY, 0xFF,
634         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
635         DATA_ONLY, 0x80,
636         DATA_ONLY, 0x00,
637         DATA_ONLY, 0x03,
638         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
639         ENDDEF, 0x00
640 };
641
642 static const unsigned short seq_gls_en[] = {
643         0xF3, 0x37,
644
645         DATA_ONLY, 0xFF,
646         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
647         DATA_ONLY, 0x81,
648         DATA_ONLY, 0x00,
649         DATA_ONLY, 0x03,
650         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
651         ENDDEF, 0x00
652 };
653
654 static const unsigned short seq_els_en[] = {
655         0xF3, 0x37,
656
657         DATA_ONLY, 0xFF,
658         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
659         DATA_ONLY, 0x83,
660         DATA_ONLY, 0x00,
661         DATA_ONLY, 0x03,
662         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
663         ENDDEF, 0x00
664 };
665
666 static const unsigned short seq_el_on[] = {
667         0xF3, 0x37,
668
669         DATA_ONLY, 0xFF,
670         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
671         DATA_ONLY, 0x87,
672         DATA_ONLY, 0x00,
673         DATA_ONLY, 0x03,
674         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
675         ENDDEF, 0x00
676 };
677
678 static int ld9040_spi_write_byte(struct ld9040 *lcd, int addr, int data)
679 {
680         u16 buf[1];
681         struct spi_message msg;
682
683         struct spi_transfer xfer = {
684                 .len            = 2,
685                 .tx_buf         = buf,
686         };
687
688         buf[0] = (addr << 8) | data;
689
690         spi_message_init(&msg);
691         spi_message_add_tail(&xfer, &msg);
692
693         return spi_sync(lcd->spi, &msg);
694 }
695
696 static int ld9040_spi_write(struct ld9040 *lcd, unsigned char address,
697         unsigned char command)
698 {
699         int ret = 0;
700
701         if (address != DATA_ONLY)
702                 ret = ld9040_spi_write_byte(lcd, 0x0, address);
703         if (command != COMMAND_ONLY)
704                 ret = ld9040_spi_write_byte(lcd, 0x1, command);
705
706         return ret;
707 }
708
709 static int ld9040_panel_send_sequence(struct ld9040 *lcd,
710         const unsigned short *wbuf)
711 {
712         int ret = 0, i = 0;
713
714         while ((wbuf[i] & DEFMASK) != ENDDEF) {
715                 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
716                         ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]);
717                         if (ret)
718                                 break;
719                 } else
720                         udelay(wbuf[i+1]*1000);
721                 i += 2;
722         }
723
724         return ret;
725 }
726
727 static int _ld9040_gamma_ctl(struct ld9040 *lcd, const unsigned int *gamma)
728 {
729         unsigned int i = 0;
730         int ret = 0;
731
732         /* start gamma table updating. */
733         ret = ld9040_panel_send_sequence(lcd, seq_gamma_start);
734         if (ret) {
735                 dev_err(lcd->dev, "failed to disable gamma table updating.\n");
736                 goto gamma_err;
737         }
738
739         for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
740                 ret = ld9040_spi_write(lcd, DATA_ONLY, gamma[i]);
741                 if (ret) {
742                         dev_err(lcd->dev, "failed to set gamma table.\n");
743                         goto gamma_err;
744                 }
745         }
746
747         /* update gamma table. */
748         ret = ld9040_panel_send_sequence(lcd, seq_gamma_ctrl);
749         if (ret)
750                 dev_err(lcd->dev, "failed to update gamma table.\n");
751
752 gamma_err:
753         return ret;
754 }
755
756 static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma)
757 {
758         int ret = 0;
759
760         ret = _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
761
762         return ret;
763 }
764
765 static int ld9040_set_elvss(struct ld9040 *lcd, int brightness)
766 {
767         int ret = 0;
768
769         switch (brightness) {
770         case 0 ... 4: /* 30cd ~ 100cd */
771                 ret = ld9040_panel_send_sequence(lcd, seq_elvss_49);
772                 break;
773         case 5 ... 10: /* 110cd ~ 160cd */
774                 ret = ld9040_panel_send_sequence(lcd, seq_elvss_41);
775                 break;
776         case 11 ... 14: /* 170cd ~ 200cd */
777                 ret = ld9040_panel_send_sequence(lcd, seq_elvss_39);
778                 break;
779         case 15 ... 24: /* 210cd ~ 300cd */
780                 ret = ld9040_panel_send_sequence(lcd, seq_elvss_35);
781                 break;
782         default:
783                 break;
784         }
785         dev_dbg(lcd->dev, "level  = %d\n", brightness);
786
787         if (ret) {
788                 dev_err(lcd->dev, "failed to initialize ldi.\n");
789                 return -EIO;
790         }
791         return ret;
792 }
793
794 static int ld9040_set_acl(struct ld9040 *lcd, int brightness)
795 {
796         int ret = 0;
797
798         if (lcd->acl_enable) {
799                 if (lcd->cur_acl == 0) {
800                         if (brightness == 0 || brightness == 1) {
801                                 ret = ld9040_panel_send_sequence(lcd,
802                                                         seq_acl_off);
803                                 dev_dbg(&lcd->ld->dev, "cur_acl=%d\n",
804                                                         lcd->cur_acl);
805                         } else
806                                 ret = ld9040_panel_send_sequence(lcd,
807                                                         seq_acl_on);
808                 }
809
810                 switch (brightness) {
811                 case 0 ... 1: /* 30cd ~ 40cd */
812                         ret = ld9040_panel_send_sequence(lcd, seq_acl_off);
813                         lcd->cur_acl = 0;
814                         dev_dbg(lcd->dev,
815                                 "ACL_cutoff_set Percentage : off!!\n");
816                         break;
817                 case 2 ... 12: /* 70cd ~ 180cd */
818                         ret = ld9040_panel_send_sequence(lcd, seq_acl_40p);
819                         lcd->cur_acl = 40;
820                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 40!!\n");
821                         break;
822                 case 13: /* 190cd */
823                         ret = ld9040_panel_send_sequence(lcd, seq_acl_43p);
824                         lcd->cur_acl = 43;
825                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 43!!\n");
826                         break;
827                 case 14: /* 200cd */
828                         ret = ld9040_panel_send_sequence(lcd, seq_acl_45p);
829                         lcd->cur_acl = 45;
830                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 45!!\n");
831                         break;
832                 case 15: /* 210cd */
833                         ret = ld9040_panel_send_sequence(lcd, seq_acl_47p);
834                         lcd->cur_acl = 47;
835                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 47!!\n");
836                         break;
837                 case 16: /* 220cd */
838                         ret = ld9040_panel_send_sequence(lcd, seq_acl_48p);
839                         lcd->cur_acl = 48;
840                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 48!!\n");
841                         break;
842                 default:
843                         ret = ld9040_panel_send_sequence(lcd, seq_acl_50p);
844                         lcd->cur_acl = 50;
845                         dev_dbg(lcd->dev, "ACL_cutoff_set Percentage : 50!!\n");
846                         break;
847                 }
848         } else {
849                 ret = ld9040_panel_send_sequence(lcd, seq_acl_on);
850                 lcd->cur_acl = 0;
851                 dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
852         }
853
854         if (ret) {
855                 dev_err(lcd->dev, "failed to initialize ldi.\n");
856                 return -EIO;
857         }
858         return ret;
859 }
860
861 static int ld9040_ldi_init(struct ld9040 *lcd)
862 {
863         int ret, i;
864         static const unsigned short *init_seq[] = {
865                 seq_user_setting,
866                 seq_panel_condition,
867                 seq_display_ctrl,
868                 seq_manual_pwr,
869                 seq_elvss_on,
870                 seq_acl_on,
871                 seq_gtcon,
872                 seq_gamma_set1,
873                 seq_gamma_ctrl,
874                 seq_sleep_out,
875         };
876
877         for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
878                 ret = ld9040_panel_send_sequence(lcd, init_seq[i]);
879                 /* workaround: minimum delay time for transferring CMD */
880                 udelay(300);
881                 if (ret)
882                         break;
883         }
884
885         return ret;
886 }
887
888 /*ADDED_BY_JMSHIN_20110824_For_Platform_Lockup_Info++*/
889 int bkl_warning_operation(int on_off,int gamma)
890 {
891         int ret;
892         printk("++currently, alarm_mode is operating++ \n");
893         if(!global_lcd)
894                 return -EFAULT;
895
896         if(on_off)
897                 ret= ld9040_gamma_ctl(global_lcd, gamma);
898         else
899                 ret = ld9040_gamma_ctl(global_lcd, global_lcd->bd->props.brightness);//current status!!
900
901         printk("--currently, alarm_mode is operating-- \n");
902         return ret;
903
904 }
905 EXPORT_SYMBOL(bkl_warning_operation);
906 /*ADDED_BY_JMSHIN_20110824_For_Platform_Lockup_Info--*/
907
908 static int ld9040_ldi_enable(struct ld9040 *lcd)
909 {
910         int ret = 0;
911
912         ret = ld9040_panel_send_sequence(lcd, seq_display_on);
913
914         return ret;
915 }
916
917 static int ld9040_ldi_disable(struct ld9040 *lcd)
918 {
919         int ret;
920
921         ret = ld9040_panel_send_sequence(lcd, seq_display_off);
922         ret = ld9040_panel_send_sequence(lcd, seq_sleep_in);
923
924         return ret;
925 }
926
927 static int ld9040_power_on(struct ld9040 *lcd)
928 {
929         int ret = 0;
930         struct lcd_platform_data *pd = NULL;
931
932         pd = lcd->lcd_pd;
933         if (!pd) {
934                 dev_err(lcd->dev, "platform data is NULL.\n");
935                 return -EFAULT;
936         }
937
938         if (!pd->power_on) {
939                 dev_err(lcd->dev, "power_on is NULL.\n");
940                 return -EFAULT;
941         } else {
942                 pd->power_on(lcd->ld, 1);
943                 mdelay(pd->power_on_delay);
944         }
945
946         /**
947          * if lcd panel was on at bootloader then
948          * it doesn't need to reset and to have initial setting.
949          */
950         if (lcd->lcd_pd->lcd_enabled) {
951                 /* just one time. */
952                 lcd->lcd_pd->lcd_enabled = 0;
953
954                 return 0;
955         }
956
957         if (!pd->reset) {
958                 dev_err(lcd->dev, "reset is NULL.\n");
959                 return -EFAULT;
960         } else {
961                 pd->reset(lcd->ld);
962                 mdelay(pd->reset_delay);
963         }
964
965         ret = ld9040_ldi_init(lcd);
966         if (ret) {
967                 dev_err(lcd->dev, "failed to initialize ldi.\n");
968                 return ret;
969         }
970
971         ret = ld9040_ldi_enable(lcd);
972         if (ret) {
973                 dev_err(lcd->dev, "failed to enable ldi.\n");
974                 return ret;
975         }
976
977         return 0;
978 }
979
980 static int ld9040_power_off(struct ld9040 *lcd)
981 {
982         int ret = 0;
983         struct lcd_platform_data *pd = NULL;
984
985         pd = lcd->lcd_pd;
986         if (!pd) {
987                 dev_err(lcd->dev, "platform data is NULL.\n");
988                 return -EFAULT;
989         }
990
991         mdelay(100);
992
993         ret = ld9040_ldi_disable(lcd);
994         if (ret) {
995                 dev_err(lcd->dev, "lcd setting failed.\n");
996                 return -EIO;
997         }
998
999         mdelay(pd->power_off_delay);
1000
1001         if (!pd->power_on) {
1002                 dev_err(lcd->dev, "power_on is NULL.\n");
1003                 return -EFAULT;
1004         } else
1005                 pd->power_on(lcd->ld, 0);
1006
1007         return 0;
1008 }
1009
1010 static int ld9040_power(struct ld9040 *lcd, int power)
1011 {
1012         int ret = 0;
1013
1014         if (power_is_on(power) && !power_is_on(lcd->power))
1015                 ret = ld9040_power_on(lcd);
1016         else if (!power_is_on(power) && power_is_on(lcd->power))
1017                 ret = ld9040_power_off(lcd);
1018
1019         if (!ret)
1020                 lcd->power = power;
1021
1022         return ret;
1023 }
1024
1025 static int ld9040_early_set_power(struct lcd_device *ld, int power)
1026 {
1027         struct ld9040 *lcd = lcd_get_data(ld);
1028         int ret = -EINVAL;
1029
1030         if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
1031                 power != FB_BLANK_NORMAL) {
1032                 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
1033                 return -EINVAL;
1034         }
1035
1036         if (!power_is_on(power) && power_is_on(lcd->power)) {
1037                 ret = ld9040_power_off(lcd);
1038                 if (!ret)
1039                         lcd->power = power;
1040         }
1041
1042         return ret;
1043 }
1044
1045 static int ld9040_set_power(struct lcd_device *ld, int power)
1046 {
1047         struct ld9040 *lcd = lcd_get_data(ld);
1048         int ret = -EINVAL;
1049
1050         if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
1051                 power != FB_BLANK_NORMAL) {
1052                 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
1053                 return -EINVAL;
1054         }
1055
1056         if (power_is_on(power) && !power_is_on(lcd->power)) {
1057                 struct backlight_device *bd = lcd->bd;
1058                 ret = ld9040_power_on(lcd);
1059                 if (!ret)
1060                         lcd->power = power;
1061                 ld9040_gamma_ctl(lcd, bd->props.brightness);
1062         } else
1063                 ld9040_early_set_power(ld, power);
1064
1065         return ret;
1066 }
1067
1068 static int ld9040_get_power(struct lcd_device *ld)
1069 {
1070         struct ld9040 *lcd = lcd_get_data(ld);
1071
1072         return lcd->power;
1073 }
1074
1075 static int ld9040_get_brightness(struct backlight_device *bd)
1076 {
1077         return bd->props.brightness;
1078 }
1079
1080 static int ld9040_set_brightness(struct backlight_device *bd)
1081 {
1082         int ret = 0, brightness = bd->props.brightness;
1083         struct ld9040 *lcd = bl_get_data(bd);
1084
1085         ret = ld9040_set_elvss(lcd, brightness);
1086         if (ret) {
1087                 dev_err(lcd->dev, "lcd brightness setting failed.\n");
1088                 return -EIO;
1089         }
1090
1091         ret = ld9040_set_acl(lcd, brightness);
1092         if (ret) {
1093                 dev_err(lcd->dev, "lcd brightness setting failed.\n");
1094                 return -EIO;
1095         }
1096
1097 /*ADDED_BY_JMSHIN_20110831_For_Intelligent_Overheating_Protection++*/
1098 #ifdef CONFIG_BL_OVERHEATING_PROTECTION
1099        if (bd->props.overheating && (brightness > OVERHEATING_LIMIT_BRIGHTNESS)) {
1100                 dev_err(&bd->dev, "brightness should be lower than %d on overheating protection \n", OVERHEATING_LIMIT_BRIGHTNESS);
1101
1102                 ret = ld9040_gamma_ctl(lcd, OVERHEATING_LIMIT_BRIGHTNESS);
1103                 if (ret) {
1104                         dev_err(&bd->dev, "lcd brightness setting failed.\n");
1105                         return -EIO;
1106                 }
1107                 /* bd->props.brightness = OVERHEATING_LIMIT_BRIGHTNESS; */
1108
1109                 dev_err(&bd->dev, "brightness changed to %d \n", OVERHEATING_LIMIT_BRIGHTNESS);
1110                 return 0;
1111        }
1112 #endif
1113 /*ADDED_BY_JMSHIN_20110831_For_Intelligent_Overheating_Protection--*/
1114
1115         if (brightness < MIN_BRIGHTNESS ||
1116                 brightness > bd->props.max_brightness) {
1117                 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
1118                         MIN_BRIGHTNESS, MAX_BRIGHTNESS);
1119                 return -EINVAL;
1120         }
1121
1122         ret = ld9040_gamma_ctl(lcd, bd->props.brightness);
1123         if (ret) {
1124                 dev_err(&bd->dev, "lcd brightness setting failed.\n");
1125                 return -EIO;
1126         }
1127
1128         return ret;
1129 }
1130
1131 static struct lcd_ops ld9040_lcd_ops = {
1132         .early_set_power = ld9040_early_set_power,
1133         .set_power = ld9040_set_power,
1134         .get_power = ld9040_get_power,
1135 };
1136
1137 static const struct backlight_ops ld9040_backlight_ops  = {
1138         .get_brightness = ld9040_get_brightness,
1139         .update_status = ld9040_set_brightness,
1140 };
1141
1142 static ssize_t acl_control_show(struct device *dev, struct
1143         device_attribute * attr, char *buf)
1144 {
1145         struct ld9040 *lcd = dev_get_drvdata(dev);
1146         char temp[3];
1147
1148         sprintf(temp, "%d\n", lcd->acl_enable);
1149         strcpy(buf, temp);
1150
1151         return strlen(buf);
1152 }
1153
1154 static ssize_t acl_control_store(struct device *dev, struct
1155         device_attribute * attr, const char *buf, size_t size)
1156 {
1157         struct ld9040 *lcd = dev_get_drvdata(dev);
1158         unsigned int value;
1159         int rc, ret;
1160
1161         rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value);
1162         if (rc < 0)
1163                 return rc;
1164
1165         if (lcd->acl_enable != value) {
1166                 dev_info(dev, "acl control changed from %d to %d\n",
1167                                                 lcd->acl_enable, value);
1168                 lcd->acl_enable = value;
1169                 ret = ld9040_set_acl(lcd, lcd->bd->props.brightness);
1170         }
1171
1172         return size;
1173 }
1174
1175 static DEVICE_ATTR(acl_control, 0664, acl_control_show, acl_control_store);
1176
1177 static int ld9040_probe(struct spi_device *spi)
1178 {
1179         int ret = 0;
1180         struct ld9040 *lcd = NULL;
1181         struct lcd_device *ld = NULL;
1182         struct backlight_device *bd = NULL;
1183
1184         lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
1185         if (!lcd)
1186                 return -ENOMEM;
1187
1188         /* ld9040 lcd panel uses 3-wire 9bits SPI Mode. */
1189         spi->bits_per_word = 9;
1190
1191         ret = spi_setup(spi);
1192         if (ret < 0) {
1193                 dev_err(&spi->dev, "spi setup failed.\n");
1194                 goto out_free_lcd;
1195         }
1196
1197         lcd->spi = spi;
1198         lcd->dev = &spi->dev;
1199
1200         lcd->lcd_pd = spi->dev.platform_data;
1201         if (!lcd->lcd_pd) {
1202                 dev_err(&spi->dev, "platform data is NULL.\n");
1203                 goto out_free_lcd;
1204         }
1205
1206         ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
1207         if (IS_ERR(ld)) {
1208                 ret = PTR_ERR(ld);
1209                 goto out_free_lcd;
1210         }
1211
1212         lcd->ld = ld;
1213
1214         bd = backlight_device_register("ld9040-bl", &spi->dev,
1215                 lcd, &ld9040_backlight_ops, NULL);
1216         if (IS_ERR(ld)) {
1217                 ret = PTR_ERR(ld);
1218                 goto out_free_lcd;
1219         }
1220
1221         bd->props.max_brightness = MAX_BRIGHTNESS;
1222         bd->props.brightness = MAX_BRIGHTNESS;
1223         lcd->bd = bd;
1224
1225         /*
1226          * if lcd panel was off from bootloader then
1227          * current lcd status is powerdown and then
1228          * it enables lcd panel.
1229          */
1230         lcd->power = FB_BLANK_POWERDOWN;
1231
1232         ld9040_power(lcd, FB_BLANK_UNBLANK);
1233
1234         global_lcd=lcd; /*ADDED_BY_JMSHIN_20110824_For_Platform_Lockup_Info*/
1235
1236         lcd->acl_enable = 1;
1237         lcd->cur_acl = 0;
1238
1239         ret = device_create_file(&lcd->ld->dev, &dev_attr_acl_control);
1240         if (ret < 0)
1241                 dev_err(&lcd->ld->dev, "failed to add sysfs entries\n");
1242
1243         dev_set_drvdata(&spi->dev, lcd);
1244
1245         dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
1246         return 0;
1247
1248 out_free_lcd:
1249         kfree(lcd);
1250         return ret;
1251 }
1252
1253 static int __devexit ld9040_remove(struct spi_device *spi)
1254 {
1255         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
1256
1257         ld9040_power(lcd, FB_BLANK_POWERDOWN);
1258         lcd_device_unregister(lcd->ld);
1259         kfree(lcd);
1260
1261         return 0;
1262 }
1263
1264 #if defined(CONFIG_PM)
1265 static unsigned int in_hibernation;    /*Added For backlight control on fastboot case*/
1266
1267 static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
1268 {
1269         int ret = 0;
1270         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
1271
1272         dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
1273
1274         /*
1275          * when lcd panel is suspend, lcd panel becomes off
1276          * regardless of status.
1277          */
1278         switch (mesg.event) {
1279         case PM_EVENT_SUSPEND:
1280                 ret = ld9040_power(lcd, FB_BLANK_POWERDOWN);
1281                 break;
1282 /*Added For backlight control on fastboot case++*/
1283         case PM_EVENT_FREEZE:
1284                 in_hibernation = 1;
1285                 break;
1286 /*Added For backlight control on fastboot case--*/
1287         }
1288
1289         return ret;
1290 }
1291
1292 static int ld9040_resume(struct spi_device *spi)
1293 {
1294         int ret = 0;
1295
1296 #if 0
1297         /*
1298          * In SLP Platform, lcd power on when recieved FB callback only.
1299          * thus we don't power on in resume function.
1300          * (plese refer "#define power_is_on(pwr)").
1301          */
1302         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
1303
1304         lcd->power = FB_BLANK_POWERDOWN;
1305
1306         ret = ld9040_power(lcd, FB_BLANK_UNBLANK);
1307 #endif
1308 /*Added For backlight control on fastboot case++*/
1309         if (in_hibernation) {
1310                 in_hibernation = 0;
1311                 ret = spi_setup(spi);
1312                 if (ret < 0) {
1313                     printk("LCD_DEBUG : spi_setup failed\n");
1314                 }
1315         }
1316 /*Added For backlight control on fastboot case--*/
1317         return ret;
1318 }
1319 #else
1320 #define ld9040_suspend          NULL
1321 #define ld9040_resume           NULL
1322 #endif
1323
1324 /* Power down all displays on reboot, poweroff or halt. */
1325 static void ld9040_shutdown(struct spi_device *spi)
1326 {
1327         struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
1328
1329         ld9040_power(lcd, FB_BLANK_POWERDOWN);
1330 }
1331
1332 static struct spi_driver ld9040_driver = {
1333         .driver = {
1334                 .name   = "ld9040",
1335                 .bus    = &spi_bus_type,
1336                 .owner  = THIS_MODULE,
1337         },
1338         .probe          = ld9040_probe,
1339         .remove         = __devexit_p(ld9040_remove),
1340         .shutdown       = ld9040_shutdown,
1341         .suspend        = ld9040_suspend,
1342         .resume         = ld9040_resume,
1343 };
1344
1345 static int __init ld9040_init(void)
1346 {
1347         return spi_register_driver(&ld9040_driver);
1348 }
1349
1350 static void __exit ld9040_exit(void)
1351 {
1352         spi_unregister_driver(&ld9040_driver);
1353 }
1354
1355 module_init(ld9040_init);
1356 module_exit(ld9040_exit);
1357
1358 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1359 MODULE_DESCRIPTION("ld9040 LCD Driver");
1360 MODULE_LICENSE("GPL");
1361