dm: do not forward ioctls from logical volumes to the underlying device
[platform/adaptation/renesas_rcar/renesas_kernel.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         int acbi;       /* ac-bias pin transitions per interrupt */
44         /* Unit: line clocks */
45         int acb;        /* ac-bias pin frequency */
46
47         enum omap_panel_config config;
48
49         int power_on_delay;
50         int power_off_delay;
51
52         /*
53          * Used to match device to panel configuration
54          * when use generic panel driver
55          */
56         const char *name;
57 };
58
59 /* Panel configurations */
60 static struct panel_config generic_dpi_panels[] = {
61         /* Sharp LQ043T1DG01 */
62         {
63                 {
64                         .x_res          = 480,
65                         .y_res          = 272,
66
67                         .pixel_clock    = 9000,
68
69                         .hsw            = 42,
70                         .hfp            = 3,
71                         .hbp            = 2,
72
73                         .vsw            = 11,
74                         .vfp            = 3,
75                         .vbp            = 2,
76                 },
77                 .acbi                   = 0x0,
78                 .acb                    = 0x0,
79                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
80                                         OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
81                 .power_on_delay         = 50,
82                 .power_off_delay        = 100,
83                 .name                   = "sharp_lq",
84         },
85
86         /* Sharp LS037V7DW01 */
87         {
88                 {
89                         .x_res          = 480,
90                         .y_res          = 640,
91
92                         .pixel_clock    = 19200,
93
94                         .hsw            = 2,
95                         .hfp            = 1,
96                         .hbp            = 28,
97
98                         .vsw            = 1,
99                         .vfp            = 1,
100                         .vbp            = 1,
101                 },
102                 .acbi                   = 0x0,
103                 .acb                    = 0x28,
104                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
105                                                 OMAP_DSS_LCD_IHS,
106                 .power_on_delay         = 50,
107                 .power_off_delay        = 100,
108                 .name                   = "sharp_ls",
109         },
110
111         /* Toppoly TDO35S */
112         {
113                 {
114                         .x_res          = 480,
115                         .y_res          = 640,
116
117                         .pixel_clock    = 26000,
118
119                         .hfp            = 104,
120                         .hsw            = 8,
121                         .hbp            = 8,
122
123                         .vfp            = 4,
124                         .vsw            = 2,
125                         .vbp            = 2,
126                 },
127                 .acbi                   = 0x0,
128                 .acb                    = 0x0,
129                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
130                                         OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC |
131                                         OMAP_DSS_LCD_ONOFF,
132                 .power_on_delay         = 0,
133                 .power_off_delay        = 0,
134                 .name                   = "toppoly_tdo35s",
135         },
136
137         /* Samsung LTE430WQ-F0C */
138         {
139                 {
140                         .x_res          = 480,
141                         .y_res          = 272,
142
143                         .pixel_clock    = 9200,
144
145                         .hfp            = 8,
146                         .hsw            = 41,
147                         .hbp            = 45 - 41,
148
149                         .vfp            = 4,
150                         .vsw            = 10,
151                         .vbp            = 12 - 10,
152                 },
153                 .acbi                   = 0x0,
154                 .acb                    = 0x0,
155                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
156                                                 OMAP_DSS_LCD_IHS,
157                 .power_on_delay         = 0,
158                 .power_off_delay        = 0,
159                 .name                   = "samsung_lte430wq_f0c",
160         },
161
162         /* Seiko 70WVW1TZ3Z3 */
163         {
164                 {
165                         .x_res          = 800,
166                         .y_res          = 480,
167
168                         .pixel_clock    = 33000,
169
170                         .hsw            = 128,
171                         .hfp            = 10,
172                         .hbp            = 10,
173
174                         .vsw            = 2,
175                         .vfp            = 4,
176                         .vbp            = 11,
177                 },
178                 .acbi                   = 0x0,
179                 .acb                    = 0x0,
180                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
181                                                 OMAP_DSS_LCD_IHS,
182                 .power_on_delay         = 0,
183                 .power_off_delay        = 0,
184                 .name                   = "seiko_70wvw1tz3",
185         },
186
187         /* Powertip PH480272T */
188         {
189                 {
190                         .x_res          = 480,
191                         .y_res          = 272,
192
193                         .pixel_clock    = 9000,
194
195                         .hsw            = 40,
196                         .hfp            = 2,
197                         .hbp            = 2,
198
199                         .vsw            = 10,
200                         .vfp            = 2,
201                         .vbp            = 2,
202                 },
203                 .acbi                   = 0x0,
204                 .acb                    = 0x0,
205                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
206                                           OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
207                 .power_on_delay         = 0,
208                 .power_off_delay        = 0,
209                 .name                   = "powertip_ph480272t",
210         },
211
212         /* Innolux AT070TN83 */
213         {
214                 {
215                         .x_res          = 800,
216                         .y_res          = 480,
217
218                         .pixel_clock    = 40000,
219
220                         .hsw            = 48,
221                         .hfp            = 1,
222                         .hbp            = 1,
223
224                         .vsw            = 3,
225                         .vfp            = 12,
226                         .vbp            = 25,
227                 },
228                 .acbi                   = 0x0,
229                 .acb                    = 0x28,
230                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
231                                           OMAP_DSS_LCD_IHS,
232                 .power_on_delay         = 0,
233                 .power_off_delay        = 0,
234                 .name                   = "innolux_at070tn83",
235         },
236
237         /* NEC NL2432DR22-11B */
238         {
239                 {
240                         .x_res          = 240,
241                         .y_res          = 320,
242
243                         .pixel_clock    = 5400,
244
245                         .hsw            = 3,
246                         .hfp            = 3,
247                         .hbp            = 39,
248
249                         .vsw            = 1,
250                         .vfp            = 2,
251                         .vbp            = 7,
252                 },
253                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
254                                                 OMAP_DSS_LCD_IHS,
255                 .name                   = "nec_nl2432dr22-11b",
256         },
257
258         /* Unknown panel used in OMAP H4 */
259         {
260                 {
261                         .x_res          = 240,
262                         .y_res          = 320,
263
264                         .pixel_clock    = 6250,
265
266                         .hsw            = 15,
267                         .hfp            = 15,
268                         .hbp            = 60,
269
270                         .vsw            = 1,
271                         .vfp            = 1,
272                         .vbp            = 1,
273                 },
274                 .config                 = OMAP_DSS_LCD_TFT,
275
276                 .name                   = "h4",
277         },
278
279         /* Unknown panel used in Samsung OMAP2 Apollon */
280         {
281                 {
282                         .x_res          = 480,
283                         .y_res          = 272,
284
285                         .pixel_clock    = 6250,
286
287                         .hsw            = 41,
288                         .hfp            = 2,
289                         .hbp            = 2,
290
291                         .vsw            = 10,
292                         .vfp            = 2,
293                         .vbp            = 2,
294                 },
295                 .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
296                                                 OMAP_DSS_LCD_IHS,
297
298                 .name                   = "apollon",
299         },
300 };
301
302 struct panel_drv_data {
303
304         struct omap_dss_device *dssdev;
305
306         struct panel_config *panel_config;
307 };
308
309 static inline struct panel_generic_dpi_data
310 *get_panel_data(const struct omap_dss_device *dssdev)
311 {
312         return (struct panel_generic_dpi_data *) dssdev->data;
313 }
314
315 static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
316 {
317         int r;
318         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
319         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
320         struct panel_config *panel_config = drv_data->panel_config;
321
322         if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
323                 return 0;
324
325         r = omapdss_dpi_display_enable(dssdev);
326         if (r)
327                 goto err0;
328
329         /* wait couple of vsyncs until enabling the LCD */
330         if (panel_config->power_on_delay)
331                 msleep(panel_config->power_on_delay);
332
333         if (panel_data->platform_enable) {
334                 r = panel_data->platform_enable(dssdev);
335                 if (r)
336                         goto err1;
337         }
338
339         return 0;
340 err1:
341         omapdss_dpi_display_disable(dssdev);
342 err0:
343         return r;
344 }
345
346 static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
347 {
348         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
349         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
350         struct panel_config *panel_config = drv_data->panel_config;
351
352         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
353                 return;
354
355         if (panel_data->platform_disable)
356                 panel_data->platform_disable(dssdev);
357
358         /* wait couple of vsyncs after disabling the LCD */
359         if (panel_config->power_off_delay)
360                 msleep(panel_config->power_off_delay);
361
362         omapdss_dpi_display_disable(dssdev);
363 }
364
365 static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
366 {
367         struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
368         struct panel_config *panel_config = NULL;
369         struct panel_drv_data *drv_data = NULL;
370         int i;
371
372         dev_dbg(&dssdev->dev, "probe\n");
373
374         if (!panel_data || !panel_data->name)
375                 return -EINVAL;
376
377         for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
378                 if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
379                         panel_config = &generic_dpi_panels[i];
380                         break;
381                 }
382         }
383
384         if (!panel_config)
385                 return -EINVAL;
386
387         dssdev->panel.config = panel_config->config;
388         dssdev->panel.timings = panel_config->timings;
389         dssdev->panel.acb = panel_config->acb;
390         dssdev->panel.acbi = panel_config->acbi;
391
392         drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
393         if (!drv_data)
394                 return -ENOMEM;
395
396         drv_data->dssdev = dssdev;
397         drv_data->panel_config = panel_config;
398
399         dev_set_drvdata(&dssdev->dev, drv_data);
400
401         return 0;
402 }
403
404 static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
405 {
406         struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
407
408         dev_dbg(&dssdev->dev, "remove\n");
409
410         kfree(drv_data);
411
412         dev_set_drvdata(&dssdev->dev, NULL);
413 }
414
415 static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
416 {
417         int r = 0;
418
419         r = generic_dpi_panel_power_on(dssdev);
420         if (r)
421                 return r;
422
423         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
424
425         return 0;
426 }
427
428 static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
429 {
430         generic_dpi_panel_power_off(dssdev);
431
432         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
433 }
434
435 static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
436 {
437         generic_dpi_panel_power_off(dssdev);
438
439         dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
440
441         return 0;
442 }
443
444 static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
445 {
446         int r = 0;
447
448         r = generic_dpi_panel_power_on(dssdev);
449         if (r)
450                 return r;
451
452         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
453
454         return 0;
455 }
456
457 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
458                 struct omap_video_timings *timings)
459 {
460         dpi_set_timings(dssdev, timings);
461 }
462
463 static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
464                 struct omap_video_timings *timings)
465 {
466         *timings = dssdev->panel.timings;
467 }
468
469 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
470                 struct omap_video_timings *timings)
471 {
472         return dpi_check_timings(dssdev, timings);
473 }
474
475 static struct omap_dss_driver dpi_driver = {
476         .probe          = generic_dpi_panel_probe,
477         .remove         = __exit_p(generic_dpi_panel_remove),
478
479         .enable         = generic_dpi_panel_enable,
480         .disable        = generic_dpi_panel_disable,
481         .suspend        = generic_dpi_panel_suspend,
482         .resume         = generic_dpi_panel_resume,
483
484         .set_timings    = generic_dpi_panel_set_timings,
485         .get_timings    = generic_dpi_panel_get_timings,
486         .check_timings  = generic_dpi_panel_check_timings,
487
488         .driver         = {
489                 .name   = "generic_dpi_panel",
490                 .owner  = THIS_MODULE,
491         },
492 };
493
494 static int __init generic_dpi_panel_drv_init(void)
495 {
496         return omap_dss_register_driver(&dpi_driver);
497 }
498
499 static void __exit generic_dpi_panel_drv_exit(void)
500 {
501         omap_dss_unregister_driver(&dpi_driver);
502 }
503
504 module_init(generic_dpi_panel_drv_init);
505 module_exit(generic_dpi_panel_drv_exit);
506 MODULE_LICENSE("GPL");