1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "msm_fb.h"
19
20#include <linux/memory.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/time.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include "linux/proc_fs.h"
27
28#include <linux/delay.h>
29
30#include <mach/hardware.h>
31#include <linux/io.h>
32
33#include <asm/system.h>
34#include <asm/mach-types.h>
35
36
37
38#ifdef FEATURE_PM1000
39#include "pm1000.h"
40#endif
41
42
43#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
44#include "pm.h"
45#endif
46
47#ifdef DISP_DEVICE_18BPP
48#undef DISP_DEVICE_18BPP
49#define DISP_DEVICE_16BPP
50#endif
51
52#define QCIF_WIDTH 176
53#define QCIF_HEIGHT 220
54
55static void *DISP_CMD_PORT;
56static void *DISP_DATA_PORT;
57
58#define DISP_CMD_DISON 0xaf
59#define DISP_CMD_DISOFF 0xae
60#define DISP_CMD_DISNOR 0xa6
61#define DISP_CMD_DISINV 0xa7
62#define DISP_CMD_DISCTL 0xca
63#define DISP_CMD_GCP64 0xcb
64#define DISP_CMD_GCP16 0xcc
65#define DISP_CMD_GSSET 0xcd
66#define DISP_GS_2 0x02
67#define DISP_GS_16 0x01
68#define DISP_GS_64 0x00
69#define DISP_CMD_SLPIN 0x95
70#define DISP_CMD_SLPOUT 0x94
71#define DISP_CMD_SD_PSET 0x75
72#define DISP_CMD_MD_PSET 0x76
73#define DISP_CMD_SD_CSET 0x15
74#define DISP_CMD_MD_CSET 0x16
75#define DISP_CMD_DATCTL 0xbc
76#define DISP_DATCTL_666 0x08
77#define DISP_DATCTL_565 0x28
78#define DISP_DATCTL_444 0x38
79#define DISP_CMD_RAMWR 0x5c
80#define DISP_CMD_RAMRD 0x5d
81#define DISP_CMD_PTLIN 0xa8
82#define DISP_CMD_PTLOUT 0xa9
83#define DISP_CMD_ASCSET 0xaa
84#define DISP_CMD_SCSTART 0xab
85#define DISP_CMD_VOLCTL 0xc6
86#define DISP_VOLCTL_TONE 0x80
87#define DISP_CMD_NOp 0x25
88#define DISP_CMD_OSSEL 0xd0
89#define DISP_CMD_3500KSET 0xd1
90#define DISP_CMD_3500KEND 0xd2
91#define DISP_CMD_14MSET 0xd3
92#define DISP_CMD_14MEND 0xd4
93
94#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
95
96#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
97
98#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
99
100
101
102#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
103 DISP_CMD_OUT(DISP_CMD_SD_PSET) \
104 DISP_DATA_OUT((ulhc_row) & 0xFF) \
105 DISP_DATA_OUT((ulhc_row) >> 8) \
106 DISP_DATA_OUT((lrhc_row) & 0xFF) \
107 DISP_DATA_OUT((lrhc_row) >> 8) \
108 DISP_CMD_OUT(DISP_CMD_SD_CSET) \
109 DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
110 DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
111 DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
112 DISP_DATA_OUT(((lrhc_col)+2) >> 8)
113
114#define DISP_MIN_CONTRAST 0
115#define DISP_MAX_CONTRAST 127
116#define DISP_DEFAULT_CONTRAST 80
117
118#define DISP_MIN_BACKLIGHT 0
119#define DISP_MAX_BACKLIGHT 15
120#define DISP_DEFAULT_BACKLIGHT 2
121
122#define WAIT_SEC(sec) mdelay((sec)/1000)
123
124static word disp_area_start_row;
125static word disp_area_end_row;
126static byte disp_contrast = DISP_DEFAULT_CONTRAST;
127static boolean disp_powered_up;
128static boolean disp_initialized = FALSE;
129
130
131
132static boolean display_on = FALSE;
133static void epsonQcif_disp_init(struct platform_device *pdev);
134static void epsonQcif_disp_set_contrast(word contrast);
135static void epsonQcif_disp_set_display_area(word start_row, word end_row);
136static int epsonQcif_disp_off(struct platform_device *pdev);
137static int epsonQcif_disp_on(struct platform_device *pdev);
138static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
139
140volatile word databack;
141static void epsonQcif_disp_init(struct platform_device *pdev)
142{
143 struct msm_fb_data_type *mfd;
144
145 int i;
146
147 if (disp_initialized)
148 return;
149
150 mfd = platform_get_drvdata(pdev);
151
152 DISP_CMD_PORT = mfd->cmd_port;
153 DISP_DATA_PORT = mfd->data_port;
154
155
156 DISP_CMD_OUT(DISP_CMD_SLPIN);
157
158
159 DISP_CMD_OUT(DISP_CMD_DISOFF);
160
161
162 DISP_CMD_OUT(DISP_CMD_DISNOR);
163
164
165 DISP_CMD_OUT(DISP_CMD_DATCTL);
166 DISP_DATA_OUT(DISP_DATCTL_565);
167
168
169 DISP_CMD_OUT(DISP_CMD_DISCTL);
170 DISP_DATA_OUT(0x1c);
171 DISP_DATA_OUT(0x02);
172 DISP_DATA_OUT(0x82);
173 DISP_DATA_OUT(0x00);
174 DISP_DATA_OUT(0x00);
175 DISP_DATA_OUT(0xe0);
176 DISP_DATA_OUT(0x00);
177 DISP_DATA_OUT(0xdc);
178 DISP_DATA_OUT(0x00);
179 DISP_DATA_OUT(0x02);
180 DISP_DATA_OUT(0x00);
181
182
183 DISP_CMD_OUT(DISP_CMD_GCP64);
184 DISP_DATA_OUT(0x08);
185 DISP_DATA_OUT(0x00);
186 DISP_DATA_OUT(0x2a);
187 DISP_DATA_OUT(0x00);
188 DISP_DATA_OUT(0x4e);
189 DISP_DATA_OUT(0x00);
190 DISP_DATA_OUT(0x6b);
191 DISP_DATA_OUT(0x00);
192 DISP_DATA_OUT(0x88);
193 DISP_DATA_OUT(0x00);
194 DISP_DATA_OUT(0xa3);
195 DISP_DATA_OUT(0x00);
196 DISP_DATA_OUT(0xba);
197 DISP_DATA_OUT(0x00);
198 DISP_DATA_OUT(0xd1);
199 DISP_DATA_OUT(0x00);
200 DISP_DATA_OUT(0xe5);
201 DISP_DATA_OUT(0x00);
202 DISP_DATA_OUT(0xf3);
203 DISP_DATA_OUT(0x00);
204 DISP_DATA_OUT(0x03);
205 DISP_DATA_OUT(0x01);
206 DISP_DATA_OUT(0x13);
207 DISP_DATA_OUT(0x01);
208 DISP_DATA_OUT(0x22);
209 DISP_DATA_OUT(0x01);
210 DISP_DATA_OUT(0x2f);
211 DISP_DATA_OUT(0x01);
212 DISP_DATA_OUT(0x3b);
213 DISP_DATA_OUT(0x01);
214 DISP_DATA_OUT(0x46);
215 DISP_DATA_OUT(0x01);
216 DISP_DATA_OUT(0x51);
217 DISP_DATA_OUT(0x01);
218 DISP_DATA_OUT(0x5b);
219 DISP_DATA_OUT(0x01);
220 DISP_DATA_OUT(0x64);
221 DISP_DATA_OUT(0x01);
222 DISP_DATA_OUT(0x6c);
223 DISP_DATA_OUT(0x01);
224 DISP_DATA_OUT(0x74);
225 DISP_DATA_OUT(0x01);
226 DISP_DATA_OUT(0x7c);
227 DISP_DATA_OUT(0x01);
228 DISP_DATA_OUT(0x83);
229 DISP_DATA_OUT(0x01);
230 DISP_DATA_OUT(0x8a);
231 DISP_DATA_OUT(0x01);
232 DISP_DATA_OUT(0x91);
233 DISP_DATA_OUT(0x01);
234 DISP_DATA_OUT(0x98);
235 DISP_DATA_OUT(0x01);
236 DISP_DATA_OUT(0x9f);
237 DISP_DATA_OUT(0x01);
238 DISP_DATA_OUT(0xa6);
239 DISP_DATA_OUT(0x01);
240 DISP_DATA_OUT(0xac);
241 DISP_DATA_OUT(0x01);
242 DISP_DATA_OUT(0xb2);
243 DISP_DATA_OUT(0x01);
244 DISP_DATA_OUT(0xb7);
245 DISP_DATA_OUT(0x01);
246 DISP_DATA_OUT(0xbc);
247 DISP_DATA_OUT(0x01);
248 DISP_DATA_OUT(0xc1);
249 DISP_DATA_OUT(0x01);
250 DISP_DATA_OUT(0xc6);
251 DISP_DATA_OUT(0x01);
252 DISP_DATA_OUT(0xcb);
253 DISP_DATA_OUT(0x01);
254 DISP_DATA_OUT(0xd0);
255 DISP_DATA_OUT(0x01);
256 DISP_DATA_OUT(0xd4);
257 DISP_DATA_OUT(0x01);
258 DISP_DATA_OUT(0xd8);
259 DISP_DATA_OUT(0x01);
260 DISP_DATA_OUT(0xdc);
261 DISP_DATA_OUT(0x01);
262 DISP_DATA_OUT(0xe0);
263 DISP_DATA_OUT(0x01);
264 DISP_DATA_OUT(0xe4);
265 DISP_DATA_OUT(0x01);
266 DISP_DATA_OUT(0xe8);
267 DISP_DATA_OUT(0x01);
268 DISP_DATA_OUT(0xec);
269 DISP_DATA_OUT(0x01);
270 DISP_DATA_OUT(0xf0);
271 DISP_DATA_OUT(0x01);
272 DISP_DATA_OUT(0xf4);
273 DISP_DATA_OUT(0x01);
274 DISP_DATA_OUT(0xf8);
275 DISP_DATA_OUT(0x01);
276 DISP_DATA_OUT(0xfb);
277 DISP_DATA_OUT(0x01);
278 DISP_DATA_OUT(0xfe);
279 DISP_DATA_OUT(0x01);
280 DISP_DATA_OUT(0x01);
281 DISP_DATA_OUT(0x02);
282 DISP_DATA_OUT(0x03);
283 DISP_DATA_OUT(0x02);
284 DISP_DATA_OUT(0x05);
285 DISP_DATA_OUT(0x02);
286 DISP_DATA_OUT(0x07);
287 DISP_DATA_OUT(0x02);
288 DISP_DATA_OUT(0x09);
289 DISP_DATA_OUT(0x02);
290 DISP_DATA_OUT(0x0b);
291 DISP_DATA_OUT(0x02);
292 DISP_DATA_OUT(0x0d);
293 DISP_DATA_OUT(0x02);
294 DISP_DATA_OUT(0x0f);
295 DISP_DATA_OUT(0x02);
296 DISP_DATA_OUT(0x11);
297 DISP_DATA_OUT(0x02);
298 DISP_DATA_OUT(0x13);
299 DISP_DATA_OUT(0x02);
300 DISP_DATA_OUT(0x15);
301 DISP_DATA_OUT(0x02);
302 DISP_DATA_OUT(0x17);
303 DISP_DATA_OUT(0x02);
304 DISP_DATA_OUT(0x19);
305 DISP_DATA_OUT(0x02);
306 DISP_DATA_OUT(0x1b);
307 DISP_DATA_OUT(0x02);
308 DISP_DATA_OUT(0x1c);
309 DISP_DATA_OUT(0x02);
310
311
312 DISP_CMD_OUT(DISP_CMD_GCP16);
313 DISP_DATA_OUT(0x1a);
314 DISP_DATA_OUT(0x32);
315 DISP_DATA_OUT(0x42);
316 DISP_DATA_OUT(0x4c);
317 DISP_DATA_OUT(0x58);
318 DISP_DATA_OUT(0x5f);
319 DISP_DATA_OUT(0x66);
320 DISP_DATA_OUT(0x6b);
321 DISP_DATA_OUT(0x70);
322 DISP_DATA_OUT(0x74);
323 DISP_DATA_OUT(0x78);
324 DISP_DATA_OUT(0x7b);
325 DISP_DATA_OUT(0x7e);
326 DISP_DATA_OUT(0x80);
327 DISP_DATA_OUT(0x82);
328
329
330 DISP_CMD_OUT(DISP_CMD_MD_CSET);
331 DISP_DATA_OUT(0xff);
332 DISP_DATA_OUT(0x03);
333 DISP_DATA_OUT(0xff);
334 DISP_DATA_OUT(0x03);
335
336
337 DISP_CMD_OUT(DISP_CMD_MD_PSET);
338 DISP_DATA_OUT(0xff);
339 DISP_DATA_OUT(0x01);
340 DISP_DATA_OUT(0xff);
341 DISP_DATA_OUT(0x01);
342
343
344 DISP_CMD_OUT(DISP_CMD_SD_CSET);
345 DISP_DATA_OUT(0x02);
346 DISP_DATA_OUT(0x00);
347 DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
348 DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
349
350
351 DISP_CMD_OUT(DISP_CMD_SD_PSET);
352 DISP_DATA_OUT(0x00);
353 DISP_DATA_OUT(0x00);
354 DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
355 DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
356
357
358 DISP_CMD_OUT(DISP_CMD_GSSET);
359 DISP_DATA_OUT(DISP_GS_64);
360
361 DISP_CMD_OUT(DISP_CMD_OSSEL);
362 DISP_DATA_OUT(0);
363
364
365 DISP_CMD_OUT(DISP_CMD_SLPOUT);
366
367 WAIT_SEC(40000);
368
369
370 DISP_CMD_OUT(DISP_CMD_VOLCTL);
371 DISP_DATA_OUT(DISP_VOLCTL_TONE);
372
373 WAIT_SEC(40000);
374
375
376 DISP_CMD_OUT(DISP_CMD_VOLCTL);
377 DISP_DATA_OUT(DISP_DEFAULT_CONTRAST);
378
379
380 DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
381 DISP_CMD_OUT(DISP_CMD_RAMWR);
382 for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
383 DISP_DATA_OUT(0xffff);
384
385 DISP_CMD_OUT(DISP_CMD_RAMRD);
386 databack = DISP_DATA_IN();
387 databack = DISP_DATA_IN();
388 databack = DISP_DATA_IN();
389 databack = DISP_DATA_IN();
390
391 WAIT_SEC(80000);
392
393 DISP_CMD_OUT(DISP_CMD_DISON);
394
395 disp_area_start_row = 0;
396 disp_area_end_row = QCIF_HEIGHT - 1;
397 disp_powered_up = TRUE;
398 disp_initialized = TRUE;
399 epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
400 display_on = TRUE;
401}
402
403static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
404{
405 if (!disp_initialized)
406 return;
407
408 DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
409 DISP_CMD_OUT(DISP_CMD_RAMWR);
410}
411
412static void epsonQcif_disp_set_display_area(word start_row, word end_row)
413{
414 if (!disp_initialized)
415 return;
416
417 if ((start_row == disp_area_start_row)
418 && (end_row == disp_area_end_row))
419 return;
420 disp_area_start_row = start_row;
421 disp_area_end_row = end_row;
422
423
424
425 if (end_row >= QCIF_HEIGHT)
426 end_row = QCIF_HEIGHT - 1;
427 if (start_row > end_row)
428 start_row = end_row;
429
430
431
432
433 if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
434
435 DISP_CMD_OUT(DISP_CMD_PTLOUT);
436 WAIT_SEC(10000);
437 DISP_CMD_OUT(DISP_CMD_DISOFF);
438 WAIT_SEC(100000);
439 DISP_CMD_OUT(DISP_CMD_GSSET);
440 DISP_DATA_OUT(DISP_GS_64);
441 WAIT_SEC(100000);
442 DISP_CMD_OUT(DISP_CMD_DISON);
443 } else {
444
445 DISP_CMD_OUT(DISP_CMD_PTLIN);
446 DISP_DATA_OUT(start_row);
447 DISP_DATA_OUT(start_row >> 8);
448 DISP_DATA_OUT(end_row);
449 DISP_DATA_OUT(end_row >> 8);
450 DISP_CMD_OUT(DISP_CMD_GSSET);
451 DISP_DATA_OUT(DISP_GS_2);
452 }
453}
454
455static int epsonQcif_disp_off(struct platform_device *pdev)
456{
457 if (!disp_initialized)
458 epsonQcif_disp_init(pdev);
459
460 if (display_on) {
461 DISP_CMD_OUT(DISP_CMD_DISOFF);
462 DISP_CMD_OUT(DISP_CMD_SLPIN);
463 display_on = FALSE;
464 }
465
466 return 0;
467}
468
469static int epsonQcif_disp_on(struct platform_device *pdev)
470{
471 if (!disp_initialized)
472 epsonQcif_disp_init(pdev);
473
474 if (!display_on) {
475 DISP_CMD_OUT(DISP_CMD_SLPOUT);
476 WAIT_SEC(40000);
477 DISP_CMD_OUT(DISP_CMD_DISON);
478 epsonQcif_disp_set_contrast(disp_contrast);
479 display_on = TRUE;
480 }
481
482 return 0;
483}
484
485static void epsonQcif_disp_set_contrast(word contrast)
486{
487 if (!disp_initialized)
488 return;
489
490
491 DISP_CMD_OUT(DISP_CMD_VOLCTL);
492 DISP_DATA_OUT(DISP_VOLCTL_TONE);
493
494 WAIT_SEC(40000);
495
496
497 DISP_CMD_OUT(DISP_CMD_VOLCTL);
498 if (contrast > 127)
499 contrast = 127;
500 DISP_DATA_OUT(contrast);
501 disp_contrast = (byte) contrast;
502}
503
504static void epsonQcif_disp_clear_screen_area(
505 word start_row, word end_row, word start_column, word end_column) {
506 int32 i;
507
508
509 DISP_SET_RECT(start_row, end_row, start_column, end_column);
510 DISP_CMD_OUT(DISP_CMD_RAMWR);
511 i = (end_row - start_row + 1) * (end_column - start_column + 1);
512 for (; i > 0; i--)
513 DISP_DATA_OUT(0xffff);
514}
515
516static int __init epsonQcif_probe(struct platform_device *pdev)
517{
518 msm_fb_add_device(pdev);
519
520 return 0;
521}
522
523static struct platform_driver this_driver = {
524 .probe = epsonQcif_probe,
525 .driver = {
526 .name = "ebi2_epson_qcif",
527 },
528};
529
530static struct msm_fb_panel_data epsonQcif_panel_data = {
531 .on = epsonQcif_disp_on,
532 .off = epsonQcif_disp_off,
533 .set_rect = epsonQcif_disp_set_rect,
534};
535
536static struct platform_device this_device = {
537 .name = "ebi2_epson_qcif",
538 .id = 0,
539 .dev = {
540 .platform_data = &epsonQcif_panel_data,
541 }
542};
543
544static int __init epsonQcif_init(void)
545{
546 int ret;
547 struct msm_panel_info *pinfo;
548
549 ret = platform_driver_register(&this_driver);
550 if (!ret) {
551 pinfo = &epsonQcif_panel_data.panel_info;
552 pinfo->xres = QCIF_WIDTH;
553 pinfo->yres = QCIF_HEIGHT;
554 pinfo->type = EBI2_PANEL;
555 pinfo->pdest = DISPLAY_2;
556 pinfo->wait_cycle = 0x808000;
557 pinfo->bpp = 16;
558 pinfo->fb_num = 2;
559 pinfo->lcd.vsync_enable = FALSE;
560
561 ret = platform_device_register(&this_device);
562 if (ret)
563 platform_driver_unregister(&this_driver);
564 }
565
566 return ret;
567}
568
569module_init(epsonQcif_init);
570