OMAPDSS: Remove passive matrix LCD support (part 4)
[linux-3.10.git] / drivers / video / omap2 / displays / panel-generic-dpi.c
1 /*
2  * Generic DPI Panels support
3  *
4  * Copyright (C) 2010 Canonical Ltd.
5  * Author: Bryan Wu <bryan.wu@canonical.com>
6  *
7  * LCD panel driver for Sharp LQ043T1DG01
8  *
9  * Copyright (C) 2009 Texas Instruments Inc
10  * Author: Vaibhav Hiremath <hvaibhav@ti.com>
11  *
12  * LCD panel driver for Toppoly TDO35S
13  *
14  * Copyright (C) 2009 CompuLab, Ltd.
15  * Author: Mike Rapoport <mike@compulab.co.il>
16  *
17  * Copyright (C) 2008 Nokia Corporation
18  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
19  *
20  * This program is free software; you can redistribute it and/or modify it
21  * under the terms of the GNU General Public License version 2 as published by
22  * the Free Software Foundation.
23  *
24  * This program is distributed in the hope that it will be useful, but WITHOUT
25  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
27  * more details.
28  *
29  * You should have received a copy of the GNU General Public License along with
30  * this program.  If not, see <http://www.gnu.org/licenses/>.
31  */
32
33 #include <linux/module.h>
34 #include <linux/delay.h>
35 #include <linux/slab.h>
36 #include <video/omapdss.h>
37
38 #include <video/omap-panel-generic-dpi.h>
39
40 struct panel_config {
41         struct omap_video_timings timings;
42
43         enum omap_panel_config config;
44
45         int power_on_delay;
46         int power_off_delay;
47
48         /*
49          * Used to match device to panel configuration
50          * when use generic panel driver
51          */
52         const char *name;
53 };
54
55 /* Panel configurations */
56 static struct panel_config generic_dpi_panels[] = {
57         /* Sharp LQ043T1DG01 */
58         {
59                 {
60                         .x_res          = 480,
61                         .y_res          = 272,
62
63                         .pixel_clock    = 9000,
64
65                         .hsw            = 42,
66                         .hfp            = 3,
67                         .hbp            = 2,
68
69                         .vsw            = 11,
70                         .vfp            = 3,
71                         .vbp            = 2,
72                 },
73                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
74                                                 OMAP_DSS_LCD_IEO,
75                 .power_on_delay         = 50,
76                 .power_off_delay        = 100,
77                 .name                   = "sharp_lq",
78         },
79
80         /* Sharp LS037V7DW01 */
81         {
82                 {
83                         .x_res          = 480,
84                         .y_res          = 640,
85
86                         .pixel_clock    = 19200,
87
88                         .hsw            = 2,
89                         .hfp            = 1,
90                         .hbp            = 28,
91
92                         .vsw            = 1,
93                         .vfp            = 1,
94                         .vbp            = 1,
95                 },
96                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
97                 .power_on_delay         = 50,
98                 .power_off_delay        = 100,
99                 .name                   = "sharp_ls",
100         },
101
102         /* Toppoly TDO35S */
103         {
104                 {
105                         .x_res          = 480,
106                         .y_res          = 640,
107
108                         .pixel_clock    = 26000,
109
110                         .hfp            = 104,
111                         .hsw            = 8,
112                         .hbp            = 8,
113
114                         .vfp            = 4,
115                         .vsw            = 2,
116                         .vbp            = 2,
117                 },
118                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
119                                                 OMAP_DSS_LCD_IPC |
120                                                 OMAP_DSS_LCD_ONOFF,
121                 .power_on_delay         = 0,
122                 .power_off_delay        = 0,
123                 .name                   = "toppoly_tdo35s",
124         },
125
126         /* Samsung LTE430WQ-F0C */
127         {
128                 {
129                         .x_res          = 480,
130                         .y_res          = 272,
131
132                         .pixel_clock    = 9200,
133
134                         .hfp            = 8,
135                         .hsw            = 41,
136                         .hbp            = 45 - 41,
137
138                         .vfp            = 4,
139                         .vsw            = 10,
140                         .vbp            = 12 - 10,
141                 },
142                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
143                 .power_on_delay         = 0,
144                 .power_off_delay        = 0,
145                 .name                   = "samsung_lte430wq_f0c",
146         },
147
148         /* Seiko 70WVW1TZ3Z3 */
149         {
150                 {
151                         .x_res          = 800,
152                         .y_res          = 480,
153
154                         .pixel_clock    = 33000,
155
156                         .hsw            = 128,
157                         .hfp            = 10,
158                         .hbp            = 10,
159
160                         .vsw            = 2,
161                         .vfp            = 4,
162                         .vbp            = 11,
163                 },
164                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
165                 .power_on_delay         = 0,
166                 .power_off_delay        = 0,
167                 .name                   = "seiko_70wvw1tz3",
168         },
169
170         /* Powertip PH480272T */
171         {
172                 {
173                         .x_res          = 480,
174                         .y_res          = 272,
175
176                         .pixel_clock    = 9000,
177
178                         .hsw            = 40,
179                         .hfp            = 2,
180                         .hbp            = 2,
181
182                         .vsw            = 10,
183                         .vfp            = 2,
184                         .vbp            = 2,
185                 },
186                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
187                                                 OMAP_DSS_LCD_IEO,
188                 .power_on_delay         = 0,
189                 .power_off_delay        = 0,
190                 .name                   = "powertip_ph480272t",
191         },
192
193         /* Innolux AT070TN83 */
194         {
195                 {
196                         .x_res          = 800,
197                         .y_res          = 480,
198
199                         .pixel_clock    = 40000,
200
201                         .hsw            = 48,
202                         .hfp            = 1,
203                         .hbp            = 1,
204
205                         .vsw            = 3,
206                         .vfp            = 12,
207                         .vbp            = 25,
208                 },
209                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
210                 .power_on_delay         = 0,
211                 .power_off_delay        = 0,
212                 .name                   = "innolux_at070tn83",
213         },
214
215         /* NEC NL2432DR22-11B */
216         {
217                 {
218                         .x_res          = 240,
219                         .y_res          = 320,
220
221                         .pixel_clock    = 5400,
222
223                         .hsw            = 3,
224                         .hfp            = 3,
225                         .hbp            = 39,
226
227                         .vsw            = 1,
228                         .vfp            = 2,
229                         .vbp            = 7,
230                 },
231                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
232                 .name                   = "nec_nl2432dr22-11b",
233         },
234
235         /* Unknown panel used in OMAP H4 */
236         {
237                 {
238                         .x_res          = 240,
239                         .y_res          = 320,
240
241                         .pixel_clock    = 6250,
242
243                         .hsw            = 15,
244                         .hfp            = 15,
245                         .hbp            = 60,
246
247                         .vsw            = 1,
248                         .vfp            = 1,
249                         .vbp            = 1,
250                 },
251                 .name                   = "h4",
252         },
253
254         /* Unknown panel used in Samsung OMAP2 Apollon */
255         {
256                 {
257                         .x_res          = 480,
258                         .y_res          = 272,
259
260                         .pixel_clock    = 6250,
261
262                         .hsw            = 41,
263                         .hfp            = 2,
264                         .hbp            = 2,
265
266                         .vsw            = 10,
267                         .vfp            = 2,
268                         .vbp            = 2,
269                 },
270                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
271
272                 .name                   = "apollon",
273         },
274         /* FocalTech ETM070003DH6 */
275         {
276                 {
277                         .x_res          = 800,
278                         .y_res          = 480,
279
280                         .pixel_clock    = 28000,
281
282                         .hsw            = 48,
283                         .hfp            = 40,
284                         .hbp            = 40,
285
286                         .vsw            = 3,
287                         .vfp            = 13,
288                         .vbp            = 29,
289                 },
290                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
291                 .name                   = "focaltech_etm070003dh6",
292         },
293
294         /* Microtips Technologies - UMSH-8173MD */
295         {
296                 {
297                         .x_res          = 800,
298                         .y_res          = 480,
299
300                         .pixel_clock    = 34560,
301
302                         .hsw            = 13,
303                         .hfp            = 101,
304                         .hbp            = 101,
305
306                         .vsw            = 23,
307                         .vfp            = 1,
308                         .vbp            = 1,
309                 },
310                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
311                                                 OMAP_DSS_LCD_IPC,
312                 .power_on_delay         = 0,
313                 .power_off_delay        = 0,
314                 .name                   = "microtips_umsh_8173md",
315         },
316
317         /* OrtusTech COM43H4M10XTC */
318         {
319                 {
320                         .x_res          = 480,
321                         .y_res          = 272,
322
323                         .pixel_clock    = 8000,
324
325                         .hsw            = 41,
326                         .hfp            = 8,
327                         .hbp            = 4,
328
329                         .vsw            = 10,
330                         .vfp            = 4,
331                         .vbp            = 2,
332                 },
333                 .name                   = "ortustech_com43h4m10xtc",
334         },
335
336         /* Innolux AT080TN52 */
337         {
338                 {
339                         .x_res = 800,
340                         .y_res = 600,
341
342                         .pixel_clock    = 41142,
343
344                         .hsw            = 20,
345                         .hfp            = 210,
346                         .hbp            = 46,
347
348                         .vsw            = 10,
349                         .vfp            = 12,
350                         .vbp            = 23,
351                 },
352                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
353                                                 OMAP_DSS_LCD_IEO,
354
355                 .name                   = "innolux_at080tn52",
356         },
357
358         /* Mitsubishi AA084SB01 */
359         {
360                 {
361                         .x_res          = 800,
362                         .y_res          = 600,
363                         .pixel_clock    = 40000,
364
365                         .hsw            = 1,
366                         .hfp            = 254,
367                         .hbp            = 1,
368
369                         .vsw            = 1,
370                         .vfp            = 26,
371                         .vbp            = 1,
372                 },
373                 .name                   = "mitsubishi_aa084sb01",
374         },
375         /* EDT ET0500G0DH6 */
376         {
377                 {
378                         .x_res          = 800,
379                         .y_res          = 480,
380                         .pixel_clock    = 33260,
381
382                         .hsw            = 128,
383                         .hfp            = 216,
384                         .hbp            = 40,
385
386                         .vsw            = 2,
387                         .vfp            = 35,
388                         .vbp            = 10,
389                 },
390                 .name                   = "edt_et0500g0dh6",
391         },
392
393         /* Prime-View PD050VL1 */
394         {
395                 {
396                         .x_res          = 640,
397                         .y_res          = 480,
398
399                         .pixel_clock    = 25000,
400
401                         .hsw            = 96,
402                         .hfp            = 18,
403                         .hbp            = 46,
404
405                         .vsw            = 2,
406                         .vfp            = 10,
407                         .vbp            = 33,
408                 },
409                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
410                                                 OMAP_DSS_LCD_IPC,
411                 .name                   = "primeview_pd050vl1",
412         },
413
414         /* Prime-View PM070WL4 */
415         {
416                 {
417                         .x_res          = 800,
418                         .y_res          = 480,
419
420                         .pixel_clock    = 32000,
421
422                         .hsw            = 128,
423                         .hfp            = 42,
424                         .hbp            = 86,
425
426                         .vsw            = 2,
427                         .vfp            = 10,
428                         .vbp            = 33,
429                 },
430                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
431                                                 OMAP_DSS_LCD_IPC,
432                 .name                   = "primeview_pm070wl4",
433         },
434
435         /* Prime-View PD104SLF */
436         {
437                 {
438                         .x_res          = 800,
439                         .y_res          = 600,
440
441                         .pixel_clock    = 40000,
442
443                         .hsw            = 128,
444                         .hfp            = 42,
445                         .hbp            = 86,
446
447                         .vsw            = 4,
448                         .vfp            = 1,
449                         .vbp            = 23,
450                 },
451                 .config                 = OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS |
452                                                 OMAP_DSS_LCD_IPC,
453                 .name                   = "primeview_pd104slf",
454         },
455 };
456
457 struct panel_drv_data {
458
459         struct omap_dss_device *dssdev;
460
461         struct panel_config *panel_config;
462 };
463
464 static inline struct panel_generic_dpi_data
465 *get_panel_data(const struct omap_dss_device *dssdev)
466 {
467         return (struct panel_generic_dpi_data *) dssdev->data;
468 }
469
470 static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
471 {
472         int r;
473         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
474         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
475         struct panel_config *panel_config = drv_data->panel_config;
476
477         if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
478                 return 0;
479
480         r = omapdss_dpi_display_enable(dssdev);
481         if (r)
482                 goto err0;
483
484         /* wait couple of vsyncs until enabling the LCD */
485         if (panel_config->power_on_delay)
486                 msleep(panel_config->power_on_delay);
487
488         if (panel_data->platform_enable) {
489                 r = panel_data->platform_enable(dssdev);
490                 if (r)
491                         goto err1;
492         }
493
494         return 0;
495 err1:
496         omapdss_dpi_display_disable(dssdev);
497 err0:
498         return r;
499 }
500
501 static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
502 {
503         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
504         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
505         struct panel_config *panel_config = drv_data->panel_config;
506
507         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
508                 return;
509
510         if (panel_data->platform_disable)
511                 panel_data->platform_disable(dssdev);
512
513         /* wait couple of vsyncs after disabling the LCD */
514         if (panel_config->power_off_delay)
515                 msleep(panel_config->power_off_delay);
516
517         omapdss_dpi_display_disable(dssdev);
518 }
519
520 static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
521 {
522         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
523         struct panel_config *panel_config = NULL;
524         struct panel_drv_data *drv_data = NULL;
525         int i;
526
527         dev_dbg(&dssdev->dev, "probe\n");
528
529         if (!panel_data || !panel_data->name)
530                 return -EINVAL;
531
532         for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
533                 if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
534                         panel_config = &generic_dpi_panels[i];
535                         break;
536                 }
537         }
538
539         if (!panel_config)
540                 return -EINVAL;
541
542         dssdev->panel.config = panel_config->config;
543         dssdev->panel.timings = panel_config->timings;
544
545         drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
546         if (!drv_data)
547                 return -ENOMEM;
548
549         drv_data->dssdev = dssdev;
550         drv_data->panel_config = panel_config;
551
552         dev_set_drvdata(&dssdev->dev, drv_data);
553
554         return 0;
555 }
556
557 static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
558 {
559         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
560
561         dev_dbg(&dssdev->dev, "remove\n");
562
563         kfree(drv_data);
564
565         dev_set_drvdata(&dssdev->dev, NULL);
566 }
567
568 static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
569 {
570         int r = 0;
571
572         r = generic_dpi_panel_power_on(dssdev);
573         if (r)
574                 return r;
575
576         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
577
578         return 0;
579 }
580
581 static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
582 {
583         generic_dpi_panel_power_off(dssdev);
584
585         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
586 }
587
588 static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
589 {
590         generic_dpi_panel_power_off(dssdev);
591
592         dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
593
594         return 0;
595 }
596
597 static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
598 {
599         int r = 0;
600
601         r = generic_dpi_panel_power_on(dssdev);
602         if (r)
603                 return r;
604
605         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
606
607         return 0;
608 }
609
610 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
611                 struct omap_video_timings *timings)
612 {
613         dpi_set_timings(dssdev, timings);
614 }
615
616 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
617                 struct omap_video_timings *timings)
618 {
619         return dpi_check_timings(dssdev, timings);
620 }
621
622 static struct omap_dss_driver dpi_driver = {
623         .probe          = generic_dpi_panel_probe,
624         .remove         = __exit_p(generic_dpi_panel_remove),
625
626         .enable         = generic_dpi_panel_enable,
627         .disable        = generic_dpi_panel_disable,
628         .suspend        = generic_dpi_panel_suspend,
629         .resume         = generic_dpi_panel_resume,
630
631         .set_timings    = generic_dpi_panel_set_timings,
632         .check_timings  = generic_dpi_panel_check_timings,
633
634         .driver         = {
635                 .name   = "generic_dpi_panel",
636                 .owner  = THIS_MODULE,
637         },
638 };
639
640 static int __init generic_dpi_panel_drv_init(void)
641 {
642         return omap_dss_register_driver(&dpi_driver);
643 }
644
645 static void __exit generic_dpi_panel_drv_exit(void)
646 {
647         omap_dss_unregister_driver(&dpi_driver);
648 }
649
650 module_init(generic_dpi_panel_drv_init);
651 module_exit(generic_dpi_panel_drv_exit);
652 MODULE_LICENSE("GPL");