Tizen 2.0 Release
[platform/kernel/u-boot.git] / drivers / video / ld9040.c
1 /*
2  * LCD panel driver for Board based on S5PC100 and S5PC110. 
3  *
4  * Author: Donghwa Lee  <dh09.lee@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 <spi.h>
29
30 enum ld9040_panel_type {
31         TYPE_M2,
32         TYPE_SM2_A1,
33         TYPE_SM2_A2,
34 };
35
36 static enum ld9040_panel_type panel_type;
37 /* these machine specific platform data would be setting at universal.c */
38 struct spi_platform_data *ld9040;
39
40 static const unsigned char SEQ_SWRESET[] = {
41         0x01, COMMAND_ONLY,
42 };
43
44 static const unsigned char SEQ_USER_SETTING[] = {
45         0xF0, 0x5A,
46
47         DATA_ONLY, 0x5A,
48 };
49
50 static const unsigned char SEQ_ELVSS_ON[] = {
51         0xB1, 0x0D,
52
53         DATA_ONLY, 0x00,
54         DATA_ONLY, 0x16,
55 };
56
57 static const unsigned short SEQ_ELVSS_ON_SM2[] = {
58         0xB1, 0x0F,
59
60         DATA_ONLY, 0x00,
61         DATA_ONLY, 0x16,
62
63         0xB2, 0x1F,
64         DATA_ONLY, 0x1F,
65         DATA_ONLY, 0x1F,
66         DATA_ONLY, 0x1F,
67 };
68
69 static const unsigned char SEQ_TEMP_SWIRE[] = {
70         0xB2, 0x06,
71
72         DATA_ONLY, 0x06,
73         DATA_ONLY, 0x06,
74         DATA_ONLY, 0x06,
75 };
76
77 static const unsigned char SEQ_GTCON[] = {
78         0xF7, 0x09,
79
80         DATA_ONLY, 0x00,
81         DATA_ONLY, 0x00,
82 };
83
84 static const unsigned char SEQ_GTCON_REV[] = {
85         0xF7, 0x07,
86
87         DATA_ONLY, 0x00,
88         DATA_ONLY, 0x00,
89 };
90
91 static const unsigned char SEQ_PANEL_CONDITION[] = {
92         0xF8, 0x05,
93
94         DATA_ONLY, 0x65,
95         DATA_ONLY, 0x96,
96         DATA_ONLY, 0x71,
97         DATA_ONLY, 0x7D,
98         DATA_ONLY, 0x19,
99         DATA_ONLY, 0x3B,
100         DATA_ONLY, 0x0D,
101         DATA_ONLY, 0x19,
102         DATA_ONLY, 0x7E,
103         DATA_ONLY, 0x0D,
104         DATA_ONLY, 0xE2,
105         DATA_ONLY, 0x00,
106         DATA_ONLY, 0x00,
107         DATA_ONLY, 0x7E,
108         DATA_ONLY, 0x7D,
109         DATA_ONLY, 0x07,
110         DATA_ONLY, 0x07,
111         DATA_ONLY, 0x20,
112         DATA_ONLY, 0x20,
113         DATA_ONLY, 0x20,
114         DATA_ONLY, 0x02,
115         DATA_ONLY, 0x02,
116 };
117
118 static const unsigned char SEQ_GAMMA_SET1[] = {
119         0xF9, 0x00,
120
121         DATA_ONLY, 0xA7,
122         DATA_ONLY, 0xB5,
123         DATA_ONLY, 0xAE,
124         DATA_ONLY, 0xBF,
125         DATA_ONLY, 0x00,
126         DATA_ONLY, 0x91,
127         DATA_ONLY, 0x00,
128         DATA_ONLY, 0xB2,
129         DATA_ONLY, 0xB4,
130         DATA_ONLY, 0xAA,
131         DATA_ONLY, 0xBB,
132         DATA_ONLY, 0x00,
133         DATA_ONLY, 0xAC,
134         DATA_ONLY, 0x00,
135         DATA_ONLY, 0xB3,
136         DATA_ONLY, 0xB1,
137         DATA_ONLY, 0xAA,
138         DATA_ONLY, 0xBC,
139         DATA_ONLY, 0x00,
140         DATA_ONLY, 0xB3,
141 };
142
143 static const unsigned char SEQ_GAMMA_CTRL[] = {
144         0xFB, 0x02,
145
146         DATA_ONLY, 0x5A,
147 };
148
149 static const unsigned char SEQ_APON[] = {
150         0xF3, 0x00,
151
152         DATA_ONLY, 0x00,
153         DATA_ONLY, 0x00,
154         DATA_ONLY, 0x0A,
155         DATA_ONLY, 0x02,
156 };
157
158 static const unsigned char SEQ_DISPCTL[] = {
159         0xF2, 0x02,
160
161         DATA_ONLY, 0x08,
162         DATA_ONLY, 0x08,
163         DATA_ONLY, 0x10,
164         DATA_ONLY, 0x10,
165 };
166
167 static const unsigned char SEQ_MANPWR[] = {
168         0xB0, 0x04,
169 };
170
171 static const unsigned char SEQ_PWR_CTRL[] = {
172         0xF4, 0x0A,
173
174         DATA_ONLY, 0x87,
175         DATA_ONLY, 0x25,
176         DATA_ONLY, 0x6A,
177         DATA_ONLY, 0x44,
178         DATA_ONLY, 0x02,
179         DATA_ONLY, 0x88,
180 };
181
182 static const unsigned char SEQ_PWR_CTRL_SM2_A1[] = {
183         0xF4, 0x0A,
184
185         DATA_ONLY, 0x87,
186         DATA_ONLY, 0x25,
187         DATA_ONLY, 0x6A,
188         DATA_ONLY, 0x44,
189         DATA_ONLY, 0x02,
190  };
191
192 static const unsigned char SEQ_PWR_CTRL_SM2_A2[] = {
193         0xF4, 0x0A,
194
195         DATA_ONLY, 0xA7,
196         DATA_ONLY, 0x25,
197         DATA_ONLY, 0x6A,
198         DATA_ONLY, 0x44,
199         DATA_ONLY, 0x02,
200 };
201
202 static const unsigned char SEQ_SLPOUT[] = {
203         0x11, COMMAND_ONLY,
204 };
205
206 static const unsigned char SEQ_SLPIN[] = {
207         0x10, COMMAND_ONLY,
208 };
209
210 static const unsigned char SEQ_DISPON[] = {
211         0x29, COMMAND_ONLY,
212 };
213
214 static const unsigned char SEQ_DISPOFF[] = {
215         0x28, COMMAND_ONLY,
216 };
217
218 static const unsigned char SEQ_VCI1_1ST_EN[] = {
219         0xF3, 0x10,
220
221         DATA_ONLY, 0x00,
222         DATA_ONLY, 0x00,
223         DATA_ONLY, 0x00,
224         DATA_ONLY, 0x02,
225 };
226
227 static const unsigned char SEQ_VL1_EN[] = {
228         0xF3, 0x11,
229
230         DATA_ONLY, 0x00,
231         DATA_ONLY, 0x00,
232         DATA_ONLY, 0x00,
233         DATA_ONLY, 0x02,
234 };
235
236 static const unsigned char SEQ_VL2_EN[] = {
237         0xF3, 0x13,
238
239         DATA_ONLY, 0x00,
240         DATA_ONLY, 0x00,
241         DATA_ONLY, 0x00,
242         DATA_ONLY, 0x02,
243 };
244
245 static const unsigned char SEQ_VCI1_2ND_EN[] = {
246         0xF3, 0x33,
247
248         DATA_ONLY, 0x00,
249         DATA_ONLY, 0x00,
250         DATA_ONLY, 0x00,
251         DATA_ONLY, 0x02,
252 };
253
254 static const unsigned char SEQ_VL3_EN[] = {
255         0xF3, 0x37,
256
257         DATA_ONLY, 0x00,
258         DATA_ONLY, 0x00,
259         DATA_ONLY, 0x00,
260         DATA_ONLY, 0x02,
261 };
262
263 static const unsigned char SEQ_VREG1_AMP_EN[] = {
264         0xF3, 0x37,
265
266         DATA_ONLY, 0x01,
267         DATA_ONLY, 0x00,
268         DATA_ONLY, 0x00,
269         DATA_ONLY, 0x02,
270 };
271
272 static const unsigned char SEQ_VGH_AMP_EN[] = {
273         0xF3, 0x37,
274
275         DATA_ONLY, 0x11,
276         DATA_ONLY, 0x00,
277         DATA_ONLY, 0x00,
278         DATA_ONLY, 0x02,
279 };
280
281 static const unsigned char SEQ_VGL_AMP_EN[] = {
282         0xF3, 0x37,
283
284         DATA_ONLY, 0x31,
285         DATA_ONLY, 0x00,
286         DATA_ONLY, 0x00,
287         DATA_ONLY, 0x02,
288 };
289
290 static const unsigned char SEQ_VMOS_AMP_EN[] = {
291         0xF3, 0x37,
292
293         DATA_ONLY, 0xB1,
294         DATA_ONLY, 0x00,
295         DATA_ONLY, 0x00,
296         DATA_ONLY, 0x03,
297 };
298
299 static const unsigned char 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 };
309
310 static const unsigned char SEQ_VBH_AMP_EN[] = {
311         0xF3, 0x37,
312
313         DATA_ONLY, 0xF9,
314         DATA_ONLY, 0x00,
315         DATA_ONLY, 0x00,
316         DATA_ONLY, 0x03,
317 };
318
319 static const unsigned char SEQ_VBL_AMP_EN[] = {
320         0xF3, 0x37,
321
322         DATA_ONLY, 0xFD,
323         DATA_ONLY, 0x00,
324         DATA_ONLY, 0x00,
325         DATA_ONLY, 0x03,
326 };
327
328 static const unsigned char SEQ_GAM_AMP_EN[] = {
329         0xF3, 0x37,
330
331         DATA_ONLY, 0xFF,
332         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
333         DATA_ONLY, 0x00,
334         DATA_ONLY, 0x00,
335         DATA_ONLY, 0x03,
336         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
337 };
338
339 static const unsigned char SEQ_SD_AMP_EN[] = {
340         0xF3, 0x37,
341
342         DATA_ONLY, 0xFF,
343         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
344         DATA_ONLY, 0x80,
345         DATA_ONLY, 0x00,
346         DATA_ONLY, 0x03,
347         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
348 };
349
350 static const unsigned char SEQ_GLS_EN[] = {
351         0xF3, 0x37,
352
353         DATA_ONLY, 0xFF,
354         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
355         DATA_ONLY, 0x81,
356         DATA_ONLY, 0x00,
357         DATA_ONLY, 0x03,
358         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
359 };
360
361 static const unsigned char SEQ_ELS_EN[] = {
362         0xF3, 0x37,
363
364         DATA_ONLY, 0xFF,
365         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
366         DATA_ONLY, 0x83,
367         DATA_ONLY, 0x00,
368         DATA_ONLY, 0x03,
369         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
370 };
371
372 static const unsigned char SEQ_EL_ON[] = {
373         0xF3, 0x37,
374
375         DATA_ONLY, 0xFF,
376         /* DATA_ONLY, 0x73,     VMOS/VBL/VBH not used */
377         DATA_ONLY, 0x87,
378         DATA_ONLY, 0x00,
379         DATA_ONLY, 0x03,
380         /* DATA_ONLY, 0x02,     VMOS/VBL/VBH not used */
381 };
382
383 static const unsigned char SEQ_ID1[] = {
384         0xDA, COMMAND_ONLY,
385 };
386
387 static const unsigned char SEQ_ID2[] = {
388         0xDB, COMMAND_ONLY,
389 };
390 static const unsigned char SEQ_ID3[] = {
391         0xDC, COMMAND_ONLY,
392 };
393
394 static void ld9040_spi_write(unsigned char address, unsigned char command)
395 {
396         if (address != DATA_ONLY)
397                 spi_gpio_write(ld9040, (unsigned int) 0x0, (unsigned int) address);
398
399         if (command != COMMAND_ONLY)
400                 spi_gpio_write(ld9040, (unsigned int) 0x1, (unsigned int) command);
401 }
402
403 static void ld9040_panel_send_sequence(const unsigned char *wbuf, unsigned int size_cmd)
404 {
405         int i = 0;
406
407         while (i < size_cmd) {
408                 ld9040_spi_write(wbuf[i], wbuf[i+1]);
409                 i += 2;
410         }
411 }
412
413 static int ld9040_spi_read(const unsigned char *wbuf, unsigned int size_cmd)
414 {
415         ld9040_panel_send_sequence(wbuf, size_cmd);
416         return spi_gpio_read(ld9040);
417 }
418
419 static int ld9040_panel_read_id(void)
420 {
421         unsigned char id[3];
422
423         id[0] = ld9040_spi_read(SEQ_ID1, ARRAY_SIZE(SEQ_ID1));
424         if (id[0]) {
425                 id[1] = ld9040_spi_read(SEQ_ID2, ARRAY_SIZE(SEQ_ID2));
426                 id[2] = ld9040_spi_read(SEQ_ID3, ARRAY_SIZE(SEQ_ID3));
427                 printf("OLED Module manufacturer : \t%x\n", id[0]);
428                 printf("OLED Module/driver version : \t%x\n", id[1]);
429                 printf("OLED module/driver : \t\t%x\n", id[2]);
430         }
431
432         switch (id[0]) {
433         case 0xa2:
434                 panel_type = TYPE_SM2_A2;
435                 break;
436         case 0xa1:
437                 panel_type = TYPE_SM2_A1;
438                 break;
439         default:
440                 panel_type = TYPE_M2;
441                 break;
442         }
443 }
444
445 void ld9040_cfg_ldo(void)
446 {
447         ld9040_panel_send_sequence(SEQ_USER_SETTING,
448                                         ARRAY_SIZE(SEQ_USER_SETTING));
449         ld9040_panel_send_sequence(SEQ_DISPCTL, ARRAY_SIZE(SEQ_DISPCTL));
450         if (ld9040->set_rev)
451                 ld9040_panel_send_sequence(SEQ_GTCON_REV, ARRAY_SIZE(SEQ_GTCON_REV));
452         else
453                 ld9040_panel_send_sequence(SEQ_GTCON, ARRAY_SIZE(SEQ_GTCON));
454         ld9040_panel_send_sequence(SEQ_PANEL_CONDITION,
455                                         ARRAY_SIZE(SEQ_PANEL_CONDITION));
456
457         ld9040_panel_read_id();
458
459         switch (panel_type) {
460         case TYPE_SM2_A1:
461                 ld9040_panel_send_sequence(SEQ_ELVSS_ON_SM2, ARRAY_SIZE(SEQ_ELVSS_ON_SM2));
462                 ld9040_panel_send_sequence(SEQ_PWR_CTRL_SM2_A1, ARRAY_SIZE(SEQ_PWR_CTRL_SM2_A1));
463                 break;
464         case TYPE_SM2_A2:
465                 ld9040_panel_send_sequence(SEQ_ELVSS_ON_SM2, ARRAY_SIZE(SEQ_ELVSS_ON_SM2));
466                 ld9040_panel_send_sequence(SEQ_PWR_CTRL_SM2_A2, ARRAY_SIZE(SEQ_PWR_CTRL_SM2_A2));
467                 break;
468         case TYPE_M2:
469                 /* fall through */
470         default:
471                 ld9040_panel_send_sequence(SEQ_MANPWR, ARRAY_SIZE(SEQ_MANPWR));
472                 ld9040_panel_send_sequence(SEQ_PWR_CTRL, ARRAY_SIZE(SEQ_PWR_CTRL));
473                 ld9040_panel_send_sequence(SEQ_ELVSS_ON, ARRAY_SIZE(SEQ_ELVSS_ON));
474                 break;
475         }
476
477         ld9040_panel_send_sequence(SEQ_GAMMA_SET1, ARRAY_SIZE(SEQ_GAMMA_SET1));
478         ld9040_panel_send_sequence(SEQ_GAMMA_CTRL, ARRAY_SIZE(SEQ_GAMMA_CTRL));
479         ld9040_panel_send_sequence(SEQ_SLPOUT, ARRAY_SIZE(SEQ_SLPOUT));
480
481         udelay(120 * 1000);
482 }
483
484 void ld9040_enable_ldo(unsigned int on)
485 {
486         if (on)
487                 ld9040_panel_send_sequence(SEQ_DISPON, ARRAY_SIZE(SEQ_DISPON));
488 }
489
490 /* this function would be called at universal.c */
491 void ld9040_set_platform_data(struct spi_platform_data *pd)
492 {
493         if (pd == NULL) {
494                 puts("pd is NULL.\n");
495                 return;
496         }
497
498         ld9040 = pd;
499 }
500