s5pc110: neptune: Enable bd60910gu backlight
[kernel/u-boot.git] / drivers / video / s6d16a0x.c
1 /*
2  * LCD panel driver for Board based on S5PC100 and S5PC110. 
3  *
4  * Author: InKi Dae  <inki.dae@samsung.com>
5  *
6  * Derived from drivers/video/omap/lcd-apollon.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 <common.h>
24 #include <linux/types.h>
25 #include <asm/io.h>
26 #include <asm/arch/cpu.h>
27 #include <asm/arch/gpio.h>
28 #include "s5p-spi.h"
29
30 /* these machine specific platform data would be setting at universal.c */
31 struct spi_platform_data *s6d16a0x;
32
33 void cs_low_(void)
34 {
35         gpio_set_value(s6d16a0x->cs_bank, s6d16a0x->cs_num, 0);
36 }
37
38 void cs_high_(void)
39 {
40         gpio_set_value(s6d16a0x->cs_bank, s6d16a0x->cs_num, 1);
41 }
42
43 void clk_low_(void)
44 {
45         gpio_set_value(s6d16a0x->clk_bank, s6d16a0x->clk_num, 0);
46 }
47
48 void clk_high_(void)
49 {
50         gpio_set_value(s6d16a0x->clk_bank, s6d16a0x->clk_num, 1);
51 }
52
53 void si_low_(void)
54 {
55         gpio_set_value(s6d16a0x->si_bank, s6d16a0x->si_num, 0);
56 }
57
58 void si_high_(void)
59 {
60         gpio_set_value(s6d16a0x->si_bank, s6d16a0x->si_num, 1);
61 }
62
63 char so_read_(void)
64 {
65         return gpio_get_value(s6d16a0x->so_bank, s6d16a0x->so_num);
66 }
67
68 static const unsigned short SEQ_PASSWD2_SET[] = {
69         0xF1, 0x5A,
70         DATA_ONLY, 0x5A,
71
72         ENDDEF, 0x0000
73 };
74
75 static const unsigned short SEQ_DISCTL_SET[] = {
76         0xf2, 0x00,
77         DATA_ONLY, 0x00,
78         DATA_ONLY, 0x62,
79         DATA_ONLY, 0x62,
80         DATA_ONLY, 0x57,
81         DATA_ONLY, 0x57,
82         DATA_ONLY, 0x10,
83         DATA_ONLY, 0x00,
84         DATA_ONLY, 0x00,
85
86         ENDDEF, 0x0000
87 };
88
89 static const unsigned short SEQ_PWRCTL_SET[] = {
90         0xf3, 0x00,
91         DATA_ONLY, 0x10,
92         DATA_ONLY, 0x25,
93         DATA_ONLY, 0x01,
94         DATA_ONLY, 0x2D,
95         DATA_ONLY, 0x2D,
96         DATA_ONLY, 0x24,
97         DATA_ONLY, 0x2D,
98         DATA_ONLY, 0x14,
99         DATA_ONLY, 0x14,
100         DATA_ONLY, 0x12,
101         DATA_ONLY, 0x62,
102
103         ENDDEF, 0x0000
104 };
105
106 static const unsigned short SEQ_VCMCTL_SET[] = {
107         0xf4, 0x00,
108         DATA_ONLY, 0x23,
109         DATA_ONLY, 0x00,
110         DATA_ONLY, 0x4E,
111         DATA_ONLY, 0x5A,
112         DATA_ONLY, 0x00,
113         DATA_ONLY, 0x4E,
114         DATA_ONLY, 0x5A,
115         DATA_ONLY, 0x00,
116         DATA_ONLY, 0x00,
117
118         ENDDEF, 0x0000
119 };
120
121 static const unsigned short SEQ_SRCCTL_SET[] = {
122         0xf5, 0x00,
123         DATA_ONLY, 0x00,
124         DATA_ONLY, 0x57,
125         DATA_ONLY, 0x00,
126         DATA_ONLY, 0x08,
127         DATA_ONLY, 0x01,
128         DATA_ONLY, 0x14,
129         DATA_ONLY, 0x14,
130         DATA_ONLY, 0x09,
131         DATA_ONLY, 0x09,
132
133         ENDDEF, 0x0000
134 };
135
136 static const unsigned short SEQ_PANELCTL1_SET[] = {
137         0xf6, 0x02,
138         DATA_ONLY, 0x00,
139         DATA_ONLY, 0x80,
140         DATA_ONLY, 0x00,
141         DATA_ONLY, 0x44,
142         DATA_ONLY, 0x00,
143
144         ENDDEF, 0x0000
145 };
146
147 static const unsigned short SEQ_PANELCTL2_SET[] = {
148         0xf7, 0x00,
149         DATA_ONLY, 0x01,
150         DATA_ONLY, 0x00,
151         DATA_ONLY, 0xF2,
152         DATA_ONLY, 0x08,
153         DATA_ONLY, 0x00,
154         DATA_ONLY, 0x08,
155         DATA_ONLY, 0x1F,
156         DATA_ONLY, 0x08,
157         DATA_ONLY, 0x08,
158         DATA_ONLY, 0x23,
159         DATA_ONLY, 0x00,
160         DATA_ONLY, 0x07,
161         DATA_ONLY, 0x00,
162         DATA_ONLY, 0x4B,
163         DATA_ONLY, 0x00,
164         DATA_ONLY, 0x8C,
165
166         ENDDEF, 0x0000
167 };
168
169 static const unsigned short SEQ_PANELCTL3_SET[] = {
170         0xf8, 0x00,
171         DATA_ONLY, 0x01,
172         DATA_ONLY, 0x00,
173         DATA_ONLY, 0xF2,
174         DATA_ONLY, 0x08,
175         DATA_ONLY, 0x00,
176         DATA_ONLY, 0x08,
177         DATA_ONLY, 0x1F,
178         DATA_ONLY, 0x08,
179         DATA_ONLY, 0x08,
180         DATA_ONLY, 0x23,
181         DATA_ONLY, 0x00,
182         DATA_ONLY, 0x07,
183         DATA_ONLY, 0x00,
184         DATA_ONLY, 0x4B,
185         DATA_ONLY, 0x00,
186         DATA_ONLY, 0x8C,
187
188         ENDDEF, 0x0000
189 };
190
191 static const unsigned short SEQ_PANELCTL4_SET[] = {
192         0xf9, 0x00,
193         DATA_ONLY, 0x08,
194         DATA_ONLY, 0x00,
195         DATA_ONLY, 0x01,
196         DATA_ONLY, 0x00,
197         DATA_ONLY, 0x05,
198         DATA_ONLY, 0x00,
199         DATA_ONLY, 0x04,
200         DATA_ONLY, 0x00,
201         DATA_ONLY, 0x0C,
202         DATA_ONLY, 0x00,
203         DATA_ONLY, 0x0F,
204         DATA_ONLY, 0x00,
205         DATA_ONLY, 0x10,
206         DATA_ONLY, 0x00,
207         DATA_ONLY, 0x11,
208         DATA_ONLY, 0x00,
209         DATA_ONLY, 0x00,
210         DATA_ONLY, 0x00,
211         DATA_ONLY, 0x1F,
212         DATA_ONLY, 0xFF,
213         DATA_ONLY, 0xE0,
214
215         ENDDEF, 0x0000
216 };
217
218 static const unsigned short SEQ_PGAMMACTL_SET[] = {
219         0xfa, 0x1E,
220         DATA_ONLY, 0x35,
221         DATA_ONLY, 0x2C,
222         DATA_ONLY, 0x0C,
223         DATA_ONLY, 0x0E,
224         DATA_ONLY, 0x0F,
225         DATA_ONLY, 0x11,
226         DATA_ONLY, 0x04,
227         DATA_ONLY, 0x00,
228         DATA_ONLY, 0x1B,
229         DATA_ONLY, 0x10,
230         DATA_ONLY, 0x18,
231         DATA_ONLY, 0x21,
232         DATA_ONLY, 0x1F,
233         DATA_ONLY, 0x1E,
234         DATA_ONLY, 0x1E,
235         DATA_ONLY, 0x35,
236         DATA_ONLY, 0x2C,
237         DATA_ONLY, 0x0C,
238         DATA_ONLY, 0x0E,
239         DATA_ONLY, 0x0F,
240         DATA_ONLY, 0x11,
241         DATA_ONLY, 0x04,
242         DATA_ONLY, 0x01,
243         DATA_ONLY, 0x1B,
244         DATA_ONLY, 0x10,
245         DATA_ONLY, 0x18,
246         DATA_ONLY, 0x21,
247         DATA_ONLY, 0x1F,
248         DATA_ONLY, 0x1E,
249         DATA_ONLY, 0x23,
250         DATA_ONLY, 0x35,
251         DATA_ONLY, 0x2C,
252         DATA_ONLY, 0x0C,
253         DATA_ONLY, 0x0E,
254         DATA_ONLY, 0x0F,
255         DATA_ONLY, 0x11,
256         DATA_ONLY, 0x04,
257         DATA_ONLY, 0x00,
258         DATA_ONLY, 0x1B,
259         DATA_ONLY, 0x10,
260         DATA_ONLY, 0x19,
261         DATA_ONLY, 0x22,
262         DATA_ONLY, 0x22,
263         DATA_ONLY, 0x22,
264
265         ENDDEF, 0x0000
266 };
267
268 static const unsigned short SEQ_NGAMMACTL_SET[] = {
269         0xFB, 0x01,
270         DATA_ONLY, 0x1C,
271         DATA_ONLY, 0x1D,
272         DATA_ONLY, 0x1C,
273         DATA_ONLY, 0x3B,
274         DATA_ONLY, 0x43,
275         DATA_ONLY, 0x4A,
276         DATA_ONLY, 0x3F,
277         DATA_ONLY, 0x3A,
278         DATA_ONLY, 0x54,
279         DATA_ONLY, 0x4B,
280         DATA_ONLY, 0x4A,
281         DATA_ONLY, 0x48,
282         DATA_ONLY, 0x26,
283         DATA_ONLY, 0x0D,
284         DATA_ONLY, 0x01,
285         DATA_ONLY, 0x1C,
286         DATA_ONLY, 0x1D,
287         DATA_ONLY, 0x1C,
288         DATA_ONLY, 0x3B,
289         DATA_ONLY, 0x43,
290         DATA_ONLY, 0x4A,
291         DATA_ONLY, 0x3F,
292         DATA_ONLY, 0x39,
293         DATA_ONLY, 0x54,
294         DATA_ONLY, 0x4B,
295         DATA_ONLY, 0x4A,
296         DATA_ONLY, 0x48,
297         DATA_ONLY, 0x26,
298         DATA_ONLY, 0x0D,
299         DATA_ONLY, 0x01,
300         DATA_ONLY, 0x17,
301         DATA_ONLY, 0x18,
302         DATA_ONLY, 0x19,
303         DATA_ONLY, 0x39,
304         DATA_ONLY, 0x43,
305         DATA_ONLY, 0x4A,
306         DATA_ONLY, 0x3E,
307         DATA_ONLY, 0x3A,
308         DATA_ONLY, 0x54,
309         DATA_ONLY, 0x4B,
310         DATA_ONLY, 0x4A,
311         DATA_ONLY, 0x48,
312         DATA_ONLY, 0x26,
313         DATA_ONLY, 0x0D,
314
315         ENDDEF, 0x0000
316 };
317
318 static const unsigned short SEQ_CLKCTL3_SET[] = {
319         0xB7, 0x00,
320
321         DATA_ONLY, 0x11,
322         DATA_ONLY, 0x11,
323         ENDDEF, 0x0000
324 };
325
326 static const unsigned short SEQ_HOSTCTL1_SET[] = {
327         0xB8, 0x31,
328
329         DATA_ONLY, 0x11,
330         ENDDEF, 0x0000
331 };
332
333 static const unsigned short SEQ_HOSTCTL2_SET[] = {
334         0xB9, 0x00,
335
336         DATA_ONLY, 0x06,
337         ENDDEF, 0x0000
338 };
339
340 static const unsigned short SEQ_TEON_SET[] = {
341         COMMAND_ONLY, 0x35,
342
343         ENDDEF, 0x0000
344 };
345
346 static const unsigned short SEQ_CASET[] = {
347         0x2A, 0x00,
348
349         DATA_ONLY, 0x00,
350         DATA_ONLY, 0x01,
351         DATA_ONLY, 0x3F,
352         ENDDEF, 0x0000
353 };
354
355 static const unsigned short SEQ_PASET[] = {
356         0x2B, 0x00,
357
358         DATA_ONLY, 0x00,
359         DATA_ONLY, 0x01,
360         DATA_ONLY, 0xDF,
361         ENDDEF, 0x0000
362 };
363
364 static const unsigned short SEQ_COLMOD[] = {
365         0x3A, 0x77,
366         /* 0x36, 0xC4, */       /* MADCTL : Reverse display */
367
368         ENDDEF, 0x0000
369 };
370
371 static const unsigned short SEQ_WRCTRLD[] = {
372         0x53, 0x00,
373
374         ENDDEF, 0x0000
375 };
376
377 static const unsigned short SEQ_SLPOUT[] = {
378         0x11, COMMAND_ONLY,
379
380         ENDDEF, 0x0000
381 };
382
383 static const unsigned short SEQ_DISPON[] = {
384         0x29, COMMAND_ONLY,
385
386         ENDDEF, 0x0000
387 };
388
389 static const unsigned short SEQ_DISPOFF[] = {
390         0x28, COMMAND_ONLY,
391
392         ENDDEF, 0x0000
393 };
394
395 unsigned char Delay=1;
396
397 static void s6d16a0x_c110_spi_write_byte(unsigned char address, unsigned char command)
398 {
399         int     j;
400         unsigned short data;
401         data = (address << 8) + command;
402
403         cs_high_();
404         si_high_();
405         clk_high_();
406         udelay(Delay);
407
408         cs_low_();
409         udelay(Delay);
410
411         for (j = PACKET_LEN; j >= 0; j--)
412         {
413                 clk_low_();
414
415                 /* data high or low */
416                 if ((data >> j) & 0x0001)
417                         si_high_();
418                 else
419                         si_low_();
420
421                 udelay(Delay);
422
423                 clk_high_();
424                 udelay(Delay);
425         }
426
427         cs_high_();
428         udelay(Delay);
429 }
430
431 #ifdef UNUSED_FUNCTIONS
432 static unsigned char s6d16a0x_c110_spi_read_byte(unsigned char select, unsigned char address)
433 {
434         int     j;
435         static unsigned int first = 1;
436         unsigned char DELAY=1;
437         unsigned short data = 0;
438         char command = 0;
439
440         data = (select << 8) + address;
441
442         cs_high();
443         si_high();
444         clk_high();
445         udelay(DELAY);
446
447         clk_low();
448         udelay(DELAY);
449
450         for (j = PACKET_LEN + 8; j >= 0; j--)
451         {
452
453                 if (j > 7) {
454                         clk_low();
455
456                         /* data high or low */
457                         if ((data >> (j - 8)) & 0x0001)
458                                 si_high();
459                         else
460                                 si_low();
461
462                         udelay(DELAY);
463                         clk_high();
464                 } else {
465                         if (first) {
466                                 gpio_cfg_pin(s6d16a0x->so_bank, s6d16a0x->so_num, GPIO_INPUT);
467                                 first = 0;
468                         }
469
470                         clk_low();
471
472                         if (so_read() & 0x1)
473                                 command |= 1 << j;
474                         else
475                                 command |= 0 << j;
476
477                         udelay(DELAY);
478                         clk_high();
479                 }
480
481                 udelay(DELAY);
482         }
483
484         cs_high();
485         udelay(DELAY);
486
487         gpio_cfg_pin(s6d16a0x->so_bank, s6d16a0x->so_num, GPIO_OUTPUT);
488
489         return command;
490 }
491 #endif
492
493 static void s6d16a0x_spi_write(unsigned char address, unsigned char command)
494 {
495         if (address != DATA_ONLY)
496                 s6d16a0x_c110_spi_write_byte(0x0, address);
497
498         if (command != COMMAND_ONLY)
499                 s6d16a0x_c110_spi_write_byte(0x1, command);
500 }
501
502 static void s6d16a0x_panel_send_sequence(const unsigned short *wbuf)
503 {
504         int i = 0;
505
506         while ((wbuf[i] & DEFMASK) != ENDDEF) {
507                 if ((wbuf[i] & DEFMASK) != SLEEPMSEC)
508                         s6d16a0x_spi_write(wbuf[i], wbuf[i+1]);
509                 else
510                         udelay(wbuf[i+1]*1000);
511                 i += 2;
512         }
513 }
514
515 void s6d16a0x_cfg_ldo(void)
516 {
517         s6d16a0x_panel_send_sequence(SEQ_PASSWD2_SET);
518         s6d16a0x_panel_send_sequence(SEQ_DISCTL_SET);
519         s6d16a0x_panel_send_sequence(SEQ_PWRCTL_SET);
520         s6d16a0x_panel_send_sequence(SEQ_VCMCTL_SET);
521         s6d16a0x_panel_send_sequence(SEQ_SRCCTL_SET);
522         s6d16a0x_panel_send_sequence(SEQ_PANELCTL1_SET);
523         s6d16a0x_panel_send_sequence(SEQ_PANELCTL2_SET);
524         s6d16a0x_panel_send_sequence(SEQ_PANELCTL3_SET);
525         s6d16a0x_panel_send_sequence(SEQ_PANELCTL4_SET);
526         s6d16a0x_panel_send_sequence(SEQ_PGAMMACTL_SET);
527         s6d16a0x_panel_send_sequence(SEQ_NGAMMACTL_SET);
528         s6d16a0x_panel_send_sequence(SEQ_CLKCTL3_SET);
529         s6d16a0x_panel_send_sequence(SEQ_HOSTCTL1_SET);
530         s6d16a0x_panel_send_sequence(SEQ_HOSTCTL2_SET);
531         s6d16a0x_panel_send_sequence(SEQ_TEON_SET);
532         s6d16a0x_panel_send_sequence(SEQ_PASSWD2_SET);
533         s6d16a0x_panel_send_sequence(SEQ_CASET);
534         s6d16a0x_panel_send_sequence(SEQ_PASET);
535         s6d16a0x_panel_send_sequence(SEQ_COLMOD);
536         s6d16a0x_panel_send_sequence(SEQ_WRCTRLD);
537         s6d16a0x_panel_send_sequence(SEQ_SLPOUT);
538         udelay(120000);
539 }
540
541 void s6d16a0x_enable_ldo(unsigned int onoff)
542 {
543         if (onoff) {
544                 s6d16a0x_panel_send_sequence(SEQ_DISPON);
545         }
546 }
547
548 /* this function would be called at universal.c */
549 void s6d16a0x_set_platform_data(struct spi_platform_data *pd)
550 {
551         if (pd == NULL) {
552                 printf("pd is NULL.\n");
553                 return;
554         }
555
556         s6d16a0x = pd;
557 }
558