]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/msm/mddi_sharp.c
Staging: add MSM framebuffer driver
[net-next-2.6.git] / drivers / staging / msm / mddi_sharp.c
1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17
18 #include "msm_fb.h"
19 #include "mddihost.h"
20 #include "mddihosti.h"
21
22 #define SHARP_QVGA_PRIM 1
23 #define SHARP_128X128_SECD 2
24
25 extern uint32 mddi_host_core_version;
26 static boolean mddi_debug_prim_wait = FALSE;
27 static boolean mddi_sharp_vsync_wake = TRUE;
28 static boolean mddi_sharp_monitor_refresh_value = TRUE;
29 static boolean mddi_sharp_report_refresh_measurements = FALSE;
30 static uint32 mddi_sharp_rows_per_second = 13830;       /* 5200000/376 */
31 static uint32 mddi_sharp_rows_per_refresh = 338;
32 static uint32 mddi_sharp_usecs_per_refresh = 24440;     /* (376+338)/5200000 */
33 static boolean mddi_sharp_debug_60hz_refresh = FALSE;
34
35 extern mddi_gpio_info_type mddi_gpio;
36 extern boolean mddi_vsync_detect_enabled;
37 static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
38 static void *mddi_sharp_vsync_handler_arg;
39 static uint16 mddi_sharp_vsync_attempts;
40
41 static void mddi_sharp_prim_lcd_init(void);
42 static void mddi_sharp_sub_lcd_init(void);
43 static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
44 static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
45                                          void *);
46 static void mddi_sharp_lcd_vsync_detected(boolean detected);
47 static struct msm_panel_common_pdata *mddi_sharp_pdata;
48
49 #define REG_SYSCTL    0x0000
50 #define REG_INTR    0x0006
51 #define REG_CLKCNF    0x000C
52 #define REG_CLKDIV1    0x000E
53 #define REG_CLKDIV2    0x0010
54
55 #define REG_GIOD    0x0040
56 #define REG_GIOA    0x0042
57
58 #define REG_AGM      0x010A
59 #define REG_FLFT    0x0110
60 #define REG_FRGT    0x0112
61 #define REG_FTOP    0x0114
62 #define REG_FBTM    0x0116
63 #define REG_FSTRX    0x0118
64 #define REG_FSTRY    0x011A
65 #define REG_VRAM    0x0202
66 #define REG_SSDCTL    0x0330
67 #define REG_SSD0    0x0332
68 #define REG_PSTCTL1    0x0400
69 #define REG_PSTCTL2    0x0402
70 #define REG_PTGCTL    0x042A
71 #define REG_PTHP    0x042C
72 #define REG_PTHB    0x042E
73 #define REG_PTHW    0x0430
74 #define REG_PTHF    0x0432
75 #define REG_PTVP    0x0434
76 #define REG_PTVB    0x0436
77 #define REG_PTVW    0x0438
78 #define REG_PTVF    0x043A
79 #define REG_VBLKS    0x0458
80 #define REG_VBLKE    0x045A
81 #define REG_SUBCTL    0x0700
82 #define REG_SUBTCMD    0x0702
83 #define REG_SUBTCMDD  0x0704
84 #define REG_REVBYTE    0x0A02
85 #define REG_REVCNT    0x0A04
86 #define REG_REVATTR    0x0A06
87 #define REG_REVFMT    0x0A08
88
89 #define SHARP_SUB_UNKNOWN 0xffffffff
90 #define SHARP_SUB_HYNIX 1
91 #define SHARP_SUB_ROHM  2
92
93 static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
94
95 static void sub_through_write(int sub_rs, uint32 sub_data)
96 {
97         mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
98
99         /* CS=1,RD=1,WE=1,RS=sub_rs */
100         mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
101
102         /* CS=0,RD=1,WE=1,RS=sub_rs */
103         mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
104
105         /* CS=0,RD=1,WE=0,RS=sub_rs */
106         mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
107
108         /* CS=0,RD=1,WE=1,RS=sub_rs */
109         mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
110
111         /* CS=1,RD=1,WE=1,RS=sub_rs */
112         mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
113 }
114
115 static uint32 sub_through_read(int sub_rs)
116 {
117         uint32 sub_data;
118
119         /* CS=1,RD=1,WE=1,RS=sub_rs */
120         mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
121
122         /* CS=0,RD=1,WE=1,RS=sub_rs */
123         mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
124
125         /* CS=0,RD=1,WE=0,RS=sub_rs */
126         mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
127
128         mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
129
130         /* CS=0,RD=1,WE=1,RS=sub_rs */
131         mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
132
133         /* CS=1,RD=1,WE=1,RS=sub_rs */
134         mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
135
136         return sub_data;
137 }
138
139 static void serigo(uint32 ssd)
140 {
141         uint32 ssdctl;
142
143         mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
144         ssdctl = ((ssdctl & 0xE7) | 0x02);
145
146         mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
147         mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
148
149         do {
150                 mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
151         } while ((ssdctl & 0x0002) != 0);
152
153         if (mddi_debug_prim_wait)
154                 mddi_wait(2);
155 }
156
157 static void mddi_sharp_lcd_powerdown(void)
158 {
159         serigo(0x0131);
160         serigo(0x0300);
161         mddi_wait(40);
162         serigo(0x0135);
163         mddi_wait(20);
164         serigo(0x2122);
165         mddi_wait(20);
166         serigo(0x0201);
167         mddi_wait(20);
168         serigo(0x2100);
169         mddi_wait(20);
170         serigo(0x2000);
171         mddi_wait(20);
172
173         mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
174         mddi_wait(100);
175         mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
176         mddi_wait(2);
177         mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
178         mddi_wait(2);
179         mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
180         mddi_wait(2);
181         mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */
182         mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
183         mddi_wait(2);
184 }
185
186 static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
187 {
188         uint32 regdata;
189         int32 level;
190         int max = mfd->panel_info.bl_max;
191         int min = mfd->panel_info.bl_min;
192
193         if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
194                 level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
195                                                           max,
196                                                           min);
197
198                 if (level < 0)
199                         return;
200
201                 /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
202                 /* Set lower 3 GPIOs as Outputs (set to 0) */
203                 mddi_queue_register_read(REG_GIOA, &regdata, TRUE, 0);
204                 mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
205
206                 /* Set lower 3 GPIOs as level */
207                 mddi_queue_register_read(REG_GIOD, &regdata, TRUE, 0);
208                 mddi_queue_register_write(REG_GIOD,
209                           (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
210         }
211 }
212
213 static void mddi_sharp_prim_lcd_init(void)
214 {
215         mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
216         mddi_wait(1);
217         mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
218         mddi_wait(5);
219         mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
220         mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
221
222         /* new reg write below */
223         if (mddi_sharp_debug_60hz_refresh)
224                 mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
225         else
226                 mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
227
228         mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
229         mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
230         mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
231         mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
232         mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
233         if (mddi_sharp_debug_60hz_refresh)
234                 mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
235         else
236                 mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
237
238         mddi_wait(1);
239
240         mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
241         mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
242         mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
243         mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
244
245         mddi_wait(1);
246
247         /* vram_color set REG_AGM???? */
248         mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
249
250         mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
251         mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
252         mddi_wait(1);
253         mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
254         mddi_wait(10);
255
256         serigo(0x0701);
257         /* software reset */
258         mddi_wait(1);
259         /* Wait over 50us */
260
261         serigo(0x0400);
262         /* DCLK~ACHSYNC~ACVSYNC polarity setting */
263         serigo(0x2900);
264         /* EEPROM start read address setting */
265         serigo(0x2606);
266         /* EEPROM start read register setting */
267         mddi_wait(20);
268         /* Wait over 20ms */
269
270         serigo(0x0503);
271         /* Horizontal timing setting */
272         serigo(0x062C);
273         /* Veritical timing setting */
274         serigo(0x2001);
275         /* power initialize setting(VDC2) */
276         mddi_wait(20);
277         /* Wait over 20ms */
278
279         serigo(0x2120);
280         /* Initialize power setting(CPS) */
281         mddi_wait(20);
282         /* Wait over 20ms */
283
284         serigo(0x2130);
285         /* Initialize power setting(CPS) */
286         mddi_wait(20);
287         /* Wait over 20ms */
288
289         serigo(0x2132);
290         /* Initialize power setting(CPS) */
291         mddi_wait(10);
292         /* Wait over 10ms */
293
294         serigo(0x2133);
295         /* Initialize power setting(CPS) */
296         mddi_wait(20);
297         /* Wait over 20ms */
298
299         serigo(0x0200);
300         /* Panel initialize release(INIT) */
301         mddi_wait(1);
302         /* Wait over 1ms */
303
304         serigo(0x0131);
305         /* Panel setting(CPS) */
306         mddi_wait(1);
307         /* Wait over 1ms */
308
309         mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
310
311         /* if (FFA LCD is upside down) -> serigo(0x0100); */
312         serigo(0x0130);
313
314         /* Black mask release(display ON) */
315         mddi_wait(1);
316         /* Wait over 1ms */
317
318         if (mddi_sharp_vsync_wake) {
319                 mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
320                 mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
321         }
322
323         /* Set the MDP pixel data attributes for Primary Display */
324         mddi_host_write_pix_attr_reg(0x00C3);
325         return;
326
327 }
328
329 void mddi_sharp_sub_lcd_init(void)
330 {
331
332         mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
333         mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
334         mddi_wait(100);
335
336         mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
337         mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
338         mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
339         mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
340         mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
341         mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
342         mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
343         mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
344         mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
345         mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
346         mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
347         mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
348         mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
349
350         /* Now the sub display..... */
351         /* Reset High */
352         mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
353         /* CS=1,RD=1,WE=1,RS=1 */
354         mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
355         mddi_wait(1);
356         /* Wait 5us */
357
358         if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
359                 uint32 data;
360
361                 sub_through_write(1, 0x05);
362                 sub_through_write(1, 0x6A);
363                 sub_through_write(1, 0x1D);
364                 sub_through_write(1, 0x05);
365                 data = sub_through_read(1);
366                 if (data == 0x6A) {
367                         sharp_subpanel_type = SHARP_SUB_HYNIX;
368                 } else {
369                         sub_through_write(0, 0x36);
370                         sub_through_write(1, 0xA8);
371                         sub_through_write(0, 0x09);
372                         data = sub_through_read(1);
373                         data = sub_through_read(1);
374                         if (data == 0x54) {
375                                 sub_through_write(0, 0x36);
376                                 sub_through_write(1, 0x00);
377                                 sharp_subpanel_type = SHARP_SUB_ROHM;
378                         }
379                 }
380         }
381
382         if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
383                 sub_through_write(1, 0x00);     /* Display setting 1 */
384                 sub_through_write(1, 0x04);
385                 sub_through_write(1, 0x01);
386                 sub_through_write(1, 0x05);
387                 sub_through_write(1, 0x0280);
388                 sub_through_write(1, 0x0301);
389                 sub_through_write(1, 0x0402);
390                 sub_through_write(1, 0x0500);
391                 sub_through_write(1, 0x0681);
392                 sub_through_write(1, 0x077F);
393                 sub_through_write(1, 0x08C0);
394                 sub_through_write(1, 0x0905);
395                 sub_through_write(1, 0x0A02);
396                 sub_through_write(1, 0x0B00);
397                 sub_through_write(1, 0x0C00);
398                 sub_through_write(1, 0x0D00);
399                 sub_through_write(1, 0x0E00);
400                 sub_through_write(1, 0x0F00);
401
402                 sub_through_write(1, 0x100B);   /* Display setting 2 */
403                 sub_through_write(1, 0x1103);
404                 sub_through_write(1, 0x1237);
405                 sub_through_write(1, 0x1300);
406                 sub_through_write(1, 0x1400);
407                 sub_through_write(1, 0x1500);
408                 sub_through_write(1, 0x1605);
409                 sub_through_write(1, 0x1700);
410                 sub_through_write(1, 0x1800);
411                 sub_through_write(1, 0x192E);
412                 sub_through_write(1, 0x1A00);
413                 sub_through_write(1, 0x1B00);
414                 sub_through_write(1, 0x1C00);
415
416                 sub_through_write(1, 0x151A);   /* Power setting */
417
418                 sub_through_write(1, 0x2002);   /* Gradation Palette setting */
419                 sub_through_write(1, 0x2107);
420                 sub_through_write(1, 0x220C);
421                 sub_through_write(1, 0x2310);
422                 sub_through_write(1, 0x2414);
423                 sub_through_write(1, 0x2518);
424                 sub_through_write(1, 0x261C);
425                 sub_through_write(1, 0x2720);
426                 sub_through_write(1, 0x2824);
427                 sub_through_write(1, 0x2928);
428                 sub_through_write(1, 0x2A2B);
429                 sub_through_write(1, 0x2B2E);
430                 sub_through_write(1, 0x2C31);
431                 sub_through_write(1, 0x2D34);
432                 sub_through_write(1, 0x2E37);
433                 sub_through_write(1, 0x2F3A);
434                 sub_through_write(1, 0x303C);
435                 sub_through_write(1, 0x313E);
436                 sub_through_write(1, 0x323F);
437                 sub_through_write(1, 0x3340);
438                 sub_through_write(1, 0x3441);
439                 sub_through_write(1, 0x3543);
440                 sub_through_write(1, 0x3646);
441                 sub_through_write(1, 0x3749);
442                 sub_through_write(1, 0x384C);
443                 sub_through_write(1, 0x394F);
444                 sub_through_write(1, 0x3A52);
445                 sub_through_write(1, 0x3B59);
446                 sub_through_write(1, 0x3C60);
447                 sub_through_write(1, 0x3D67);
448                 sub_through_write(1, 0x3E6E);
449                 sub_through_write(1, 0x3F7F);
450                 sub_through_write(1, 0x4001);
451                 sub_through_write(1, 0x4107);
452                 sub_through_write(1, 0x420C);
453                 sub_through_write(1, 0x4310);
454                 sub_through_write(1, 0x4414);
455                 sub_through_write(1, 0x4518);
456                 sub_through_write(1, 0x461C);
457                 sub_through_write(1, 0x4720);
458                 sub_through_write(1, 0x4824);
459                 sub_through_write(1, 0x4928);
460                 sub_through_write(1, 0x4A2B);
461                 sub_through_write(1, 0x4B2E);
462                 sub_through_write(1, 0x4C31);
463                 sub_through_write(1, 0x4D34);
464                 sub_through_write(1, 0x4E37);
465                 sub_through_write(1, 0x4F3A);
466                 sub_through_write(1, 0x503C);
467                 sub_through_write(1, 0x513E);
468                 sub_through_write(1, 0x523F);
469                 sub_through_write(1, 0x5340);
470                 sub_through_write(1, 0x5441);
471                 sub_through_write(1, 0x5543);
472                 sub_through_write(1, 0x5646);
473                 sub_through_write(1, 0x5749);
474                 sub_through_write(1, 0x584C);
475                 sub_through_write(1, 0x594F);
476                 sub_through_write(1, 0x5A52);
477                 sub_through_write(1, 0x5B59);
478                 sub_through_write(1, 0x5C60);
479                 sub_through_write(1, 0x5D67);
480                 sub_through_write(1, 0x5E6E);
481                 sub_through_write(1, 0x5F7E);
482                 sub_through_write(1, 0x6000);
483                 sub_through_write(1, 0x6107);
484                 sub_through_write(1, 0x620C);
485                 sub_through_write(1, 0x6310);
486                 sub_through_write(1, 0x6414);
487                 sub_through_write(1, 0x6518);
488                 sub_through_write(1, 0x661C);
489                 sub_through_write(1, 0x6720);
490                 sub_through_write(1, 0x6824);
491                 sub_through_write(1, 0x6928);
492                 sub_through_write(1, 0x6A2B);
493                 sub_through_write(1, 0x6B2E);
494                 sub_through_write(1, 0x6C31);
495                 sub_through_write(1, 0x6D34);
496                 sub_through_write(1, 0x6E37);
497                 sub_through_write(1, 0x6F3A);
498                 sub_through_write(1, 0x703C);
499                 sub_through_write(1, 0x713E);
500                 sub_through_write(1, 0x723F);
501                 sub_through_write(1, 0x7340);
502                 sub_through_write(1, 0x7441);
503                 sub_through_write(1, 0x7543);
504                 sub_through_write(1, 0x7646);
505                 sub_through_write(1, 0x7749);
506                 sub_through_write(1, 0x784C);
507                 sub_through_write(1, 0x794F);
508                 sub_through_write(1, 0x7A52);
509                 sub_through_write(1, 0x7B59);
510                 sub_through_write(1, 0x7C60);
511                 sub_through_write(1, 0x7D67);
512                 sub_through_write(1, 0x7E6E);
513                 sub_through_write(1, 0x7F7D);
514
515                 sub_through_write(1, 0x1851);   /* Display on */
516
517                 mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
518
519                 /* 1 pixel / 1 post clock */
520                 mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
521
522                 /* SUB LCD select */
523                 mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
524
525                 /* RS=0,command initiate number=0,select master mode */
526                 mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
527
528                 /* Sub LCD Data transform start */
529                 mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
530
531         } else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
532
533                 sub_through_write(0, 0x01);     /* Display setting */
534                 sub_through_write(1, 0x00);
535
536                 mddi_wait(1);
537                 /* Wait 100us  <----- ******* Update 2005/01/24 */
538
539                 sub_through_write(0, 0xB6);
540                 sub_through_write(1, 0x0C);
541                 sub_through_write(1, 0x4A);
542                 sub_through_write(1, 0x20);
543                 sub_through_write(0, 0x3A);
544                 sub_through_write(1, 0x05);
545                 sub_through_write(0, 0xB7);
546                 sub_through_write(1, 0x01);
547                 sub_through_write(0, 0xBA);
548                 sub_through_write(1, 0x20);
549                 sub_through_write(1, 0x02);
550                 sub_through_write(0, 0x25);
551                 sub_through_write(1, 0x4F);
552                 sub_through_write(0, 0xBB);
553                 sub_through_write(1, 0x00);
554                 sub_through_write(0, 0x36);
555                 sub_through_write(1, 0x00);
556                 sub_through_write(0, 0xB1);
557                 sub_through_write(1, 0x05);
558                 sub_through_write(0, 0xBE);
559                 sub_through_write(1, 0x80);
560                 sub_through_write(0, 0x26);
561                 sub_through_write(1, 0x01);
562                 sub_through_write(0, 0x2A);
563                 sub_through_write(1, 0x02);
564                 sub_through_write(1, 0x81);
565                 sub_through_write(0, 0x2B);
566                 sub_through_write(1, 0x00);
567                 sub_through_write(1, 0x7F);
568
569                 sub_through_write(0, 0x2C);
570                 sub_through_write(0, 0x11);     /* Sleep mode off */
571
572                 mddi_wait(1);
573                 /* Wait 100 ms <----- ******* Update 2005/01/24 */
574
575                 sub_through_write(0, 0x29);     /* Display on */
576                 sub_through_write(0, 0xB3);
577                 sub_through_write(1, 0x20);
578                 sub_through_write(1, 0xAA);
579                 sub_through_write(1, 0xA0);
580                 sub_through_write(1, 0x20);
581                 sub_through_write(1, 0x30);
582                 sub_through_write(1, 0xA6);
583                 sub_through_write(1, 0xFF);
584                 sub_through_write(1, 0x9A);
585                 sub_through_write(1, 0x9F);
586                 sub_through_write(1, 0xAF);
587                 sub_through_write(1, 0xBC);
588                 sub_through_write(1, 0xCF);
589                 sub_through_write(1, 0xDF);
590                 sub_through_write(1, 0x20);
591                 sub_through_write(1, 0x9C);
592                 sub_through_write(1, 0x8A);
593
594                 sub_through_write(0, 0x002C);   /* Display on */
595
596                 /* 1 pixel / 2 post clock */
597                 mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
598
599                 /* SUB LCD select */
600                 mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
601
602                 /* RS=1,command initiate number=0,select master mode */
603                 mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
604
605                 /* Sub LCD Data transform start */
606                 mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
607
608         }
609
610         /* Set the MDP pixel data attributes for Sub Display */
611         mddi_host_write_pix_attr_reg(0x00C0);
612 }
613
614 void mddi_sharp_lcd_vsync_detected(boolean detected)
615 {
616         /* static timetick_type start_time = 0; */
617         static struct timeval start_time;
618         static boolean first_time = TRUE;
619         /* uint32 mdp_cnt_val = 0; */
620         /* timetick_type elapsed_us; */
621         struct timeval now;
622         uint32 elapsed_us;
623         uint32 num_vsyncs;
624
625         if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
626                 if ((detected) && (mddi_sharp_monitor_refresh_value)) {
627                         /* if (start_time != 0) */
628                         if (!first_time) {
629                                 jiffies_to_timeval(jiffies, &now);
630                                 elapsed_us =
631                                     (now.tv_sec - start_time.tv_sec) * 1000000 +
632                                     now.tv_usec - start_time.tv_usec;
633                                 /*
634                                 * LCD is configured for a refresh every usecs,
635                                 * so to determine the number of vsyncs that
636                                 * have occurred since the last measurement add
637                                 * half that to the time difference and divide
638                                 * by the refresh rate.
639                                 */
640                                 num_vsyncs = (elapsed_us +
641                                               (mddi_sharp_usecs_per_refresh >>
642                                                1)) /
643                                     mddi_sharp_usecs_per_refresh;
644                                 /*
645                                  * LCD is configured for * hsyncs (rows) per
646                                  * refresh cycle. Calculate new rows_per_second
647                                  * value based upon these new measurements.
648                                  * MDP can update with this new value.
649                                  */
650                                 mddi_sharp_rows_per_second =
651                                     (mddi_sharp_rows_per_refresh * 1000 *
652                                      num_vsyncs) / (elapsed_us / 1000);
653                         }
654                         /* start_time = timetick_get(); */
655                         first_time = FALSE;
656                         jiffies_to_timeval(jiffies, &start_time);
657                         if (mddi_sharp_report_refresh_measurements) {
658                                 /* mdp_cnt_val = MDP_LINE_COUNT; */
659                         }
660                 }
661                 /* if detected = TRUE, client initiated wakeup was detected */
662                 if (mddi_sharp_vsync_handler != NULL) {
663                         (*mddi_sharp_vsync_handler)
664                             (mddi_sharp_vsync_handler_arg);
665                         mddi_sharp_vsync_handler = NULL;
666                 }
667                 mddi_vsync_detect_enabled = FALSE;
668                 mddi_sharp_vsync_attempts = 0;
669                 /* need to clear this vsync wakeup */
670                 if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
671                         MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
672                 }
673                 if (!detected) {
674                         /* give up after 5 failed attempts but show error */
675                         MDDI_MSG_NOTICE("Vsync detection failed!\n");
676                 } else if ((mddi_sharp_monitor_refresh_value) &&
677                         (mddi_sharp_report_refresh_measurements)) {
678                         MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
679                                 mddi_sharp_rows_per_second);
680                 }
681         } else
682                 /* if detected = FALSE, we woke up from hibernation, but did not
683                  * detect client initiated wakeup.
684                  */
685                 mddi_sharp_vsync_attempts++;
686 }
687
688 /* ISR to be executed */
689 void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
690 {
691         boolean error = FALSE;
692         unsigned long flags;
693
694         /* Disable interrupts */
695         spin_lock_irqsave(&mddi_host_spin_lock, flags);
696         /* INTLOCK(); */
697
698         if (mddi_sharp_vsync_handler != NULL)
699                 error = TRUE;
700
701         /* Register the handler for this particular GROUP interrupt source */
702         mddi_sharp_vsync_handler = handler;
703         mddi_sharp_vsync_handler_arg = arg;
704
705         /* Restore interrupts */
706         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
707         /* INTFREE(); */
708
709         if (error)
710                 MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
711
712         /* Enable the vsync wakeup */
713         mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
714
715         mddi_sharp_vsync_attempts = 1;
716         mddi_vsync_detect_enabled = TRUE;
717 }                               /* mddi_sharp_vsync_set_handler */
718
719 static int mddi_sharp_lcd_on(struct platform_device *pdev)
720 {
721         struct msm_fb_data_type *mfd;
722
723         mfd = platform_get_drvdata(pdev);
724
725         if (!mfd)
726                 return -ENODEV;
727
728         if (mfd->key != MFD_KEY)
729                 return -EINVAL;
730
731         if (mfd->panel.id == SHARP_QVGA_PRIM)
732                 mddi_sharp_prim_lcd_init();
733         else
734                 mddi_sharp_sub_lcd_init();
735
736         return 0;
737 }
738
739 static int mddi_sharp_lcd_off(struct platform_device *pdev)
740 {
741         mddi_sharp_lcd_powerdown();
742         return 0;
743 }
744
745 static int __init mddi_sharp_probe(struct platform_device *pdev)
746 {
747         if (pdev->id == 0) {
748                 mddi_sharp_pdata = pdev->dev.platform_data;
749                 return 0;
750         }
751
752         msm_fb_add_device(pdev);
753
754         return 0;
755 }
756
757 static struct platform_driver this_driver = {
758         .probe  = mddi_sharp_probe,
759         .driver = {
760                 .name   = "mddi_sharp_qvga",
761         },
762 };
763
764 static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
765         .on = mddi_sharp_lcd_on,
766         .off = mddi_sharp_lcd_off,
767         .set_backlight = mddi_sharp_lcd_set_backlight,
768         .set_vsync_notifier = mddi_sharp_vsync_set_handler,
769 };
770
771 static struct platform_device this_device_0 = {
772         .name   = "mddi_sharp_qvga",
773         .id     = SHARP_QVGA_PRIM,
774         .dev    = {
775                 .platform_data = &mddi_sharp_panel_data0,
776         }
777 };
778
779 static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
780         .on = mddi_sharp_lcd_on,
781         .off = mddi_sharp_lcd_off,
782 };
783
784 static struct platform_device this_device_1 = {
785         .name   = "mddi_sharp_qvga",
786         .id     = SHARP_128X128_SECD,
787         .dev    = {
788                 .platform_data = &mddi_sharp_panel_data1,
789         }
790 };
791
792 static int __init mddi_sharp_init(void)
793 {
794         int ret;
795         struct msm_panel_info *pinfo;
796
797 #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
798         u32 id;
799
800         ret = msm_fb_detect_client("mddi_sharp_qvga");
801         if (ret == -ENODEV)
802                 return 0;
803
804         if (ret) {
805                 id = mddi_get_client_id();
806
807                 if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
808                         return 0;
809         }
810 #endif
811         if (mddi_host_core_version > 8) {
812                 /* can use faster refresh with newer hw revisions */
813                 mddi_sharp_debug_60hz_refresh = TRUE;
814
815                 /* Timing variables for tracking vsync */
816                 /* dot_clock = 6.00MHz
817                  * horizontal count = 296
818                  * vertical count = 338
819                  * refresh rate = 6000000/(296+338) = 60Hz
820                  */
821                 mddi_sharp_rows_per_second = 20270;     /* 6000000/296 */
822                 mddi_sharp_rows_per_refresh = 338;
823                 mddi_sharp_usecs_per_refresh = 16674;   /* (296+338)/6000000 */
824         } else {
825                 /* Timing variables for tracking vsync */
826                 /* dot_clock = 5.20MHz
827                  * horizontal count = 376
828                  * vertical count = 338
829                  * refresh rate = 5200000/(376+338) = 41Hz
830                  */
831                 mddi_sharp_rows_per_second = 13830;     /* 5200000/376 */
832                 mddi_sharp_rows_per_refresh = 338;
833                 mddi_sharp_usecs_per_refresh = 24440;   /* (376+338)/5200000 */
834         }
835
836         ret = platform_driver_register(&this_driver);
837         if (!ret) {
838                 pinfo = &mddi_sharp_panel_data0.panel_info;
839                 pinfo->xres = 240;
840                 pinfo->yres = 320;
841                 pinfo->type = MDDI_PANEL;
842                 pinfo->pdest = DISPLAY_1;
843                 pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
844                 pinfo->wait_cycle = 0;
845                 pinfo->bpp = 18;
846                 pinfo->fb_num = 2;
847                 pinfo->clk_rate = 122880000;
848                 pinfo->clk_min = 120000000;
849                 pinfo->clk_max = 125000000;
850                 pinfo->lcd.vsync_enable = TRUE;
851                 pinfo->lcd.refx100 =
852                         (mddi_sharp_rows_per_second * 100) /
853                         mddi_sharp_rows_per_refresh;
854                 pinfo->lcd.v_back_porch = 12;
855                 pinfo->lcd.v_front_porch = 6;
856                 pinfo->lcd.v_pulse_width = 0;
857                 pinfo->lcd.hw_vsync_mode = FALSE;
858                 pinfo->lcd.vsync_notifier_period = (1 * HZ);
859                 pinfo->bl_max = 7;
860                 pinfo->bl_min = 1;
861
862                 ret = platform_device_register(&this_device_0);
863                 if (ret)
864                         platform_driver_unregister(&this_driver);
865
866                 pinfo = &mddi_sharp_panel_data1.panel_info;
867                 pinfo->xres = 128;
868                 pinfo->yres = 128;
869                 pinfo->type = MDDI_PANEL;
870                 pinfo->pdest = DISPLAY_2;
871                 pinfo->mddi.vdopkt = 0x400;
872                 pinfo->wait_cycle = 0;
873                 pinfo->bpp = 18;
874                 pinfo->clk_rate = 122880000;
875                 pinfo->clk_min = 120000000;
876                 pinfo->clk_max = 125000000;
877                 pinfo->fb_num = 2;
878
879                 ret = platform_device_register(&this_device_1);
880                 if (ret) {
881                         platform_device_unregister(&this_device_0);
882                         platform_driver_unregister(&this_driver);
883                 }
884         }
885
886         if (!ret)
887                 mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
888
889         return ret;
890 }
891
892 module_init(mddi_sharp_init);