- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / video / omap2 / dss / display.c
1 /*
2  * linux/drivers/video/omap2/dss/display.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #define DSS_SUBSYS_NAME "DISPLAY"
24
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/jiffies.h>
28 #include <linux/list.h>
29 #include <linux/platform_device.h>
30
31 #include <plat/display.h>
32 #include "dss.h"
33
34 static LIST_HEAD(display_list);
35
36 static ssize_t display_enabled_show(struct device *dev,
37                 struct device_attribute *attr, char *buf)
38 {
39         struct omap_dss_device *dssdev = to_dss_device(dev);
40         bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
41
42         return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
43 }
44
45 static ssize_t display_enabled_store(struct device *dev,
46                 struct device_attribute *attr,
47                 const char *buf, size_t size)
48 {
49         struct omap_dss_device *dssdev = to_dss_device(dev);
50         bool enabled, r;
51
52         enabled = simple_strtoul(buf, NULL, 10);
53
54         if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
55                 if (enabled) {
56                         r = dssdev->enable(dssdev);
57                         if (r)
58                                 return r;
59                 } else {
60                         dssdev->disable(dssdev);
61                 }
62         }
63
64         return size;
65 }
66
67 static ssize_t display_upd_mode_show(struct device *dev,
68                 struct device_attribute *attr, char *buf)
69 {
70         struct omap_dss_device *dssdev = to_dss_device(dev);
71         enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
72         if (dssdev->get_update_mode)
73                 mode = dssdev->get_update_mode(dssdev);
74         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
75 }
76
77 static ssize_t display_upd_mode_store(struct device *dev,
78                 struct device_attribute *attr,
79                 const char *buf, size_t size)
80 {
81         struct omap_dss_device *dssdev = to_dss_device(dev);
82         int val, r;
83         enum omap_dss_update_mode mode;
84
85         val = simple_strtoul(buf, NULL, 10);
86
87         switch (val) {
88         case OMAP_DSS_UPDATE_DISABLED:
89         case OMAP_DSS_UPDATE_AUTO:
90         case OMAP_DSS_UPDATE_MANUAL:
91                 mode = (enum omap_dss_update_mode)val;
92                 break;
93         default:
94                 return -EINVAL;
95         }
96
97         r = dssdev->set_update_mode(dssdev, mode);
98         if (r)
99                 return r;
100
101         return size;
102 }
103
104 static ssize_t display_tear_show(struct device *dev,
105                 struct device_attribute *attr, char *buf)
106 {
107         struct omap_dss_device *dssdev = to_dss_device(dev);
108         return snprintf(buf, PAGE_SIZE, "%d\n",
109                         dssdev->get_te ? dssdev->get_te(dssdev) : 0);
110 }
111
112 static ssize_t display_tear_store(struct device *dev,
113                 struct device_attribute *attr, const char *buf, size_t size)
114 {
115         struct omap_dss_device *dssdev = to_dss_device(dev);
116         unsigned long te;
117         int r;
118
119         if (!dssdev->enable_te || !dssdev->get_te)
120                 return -ENOENT;
121
122         te = simple_strtoul(buf, NULL, 0);
123
124         r = dssdev->enable_te(dssdev, te);
125         if (r)
126                 return r;
127
128         return size;
129 }
130
131 static ssize_t display_timings_show(struct device *dev,
132                 struct device_attribute *attr, char *buf)
133 {
134         struct omap_dss_device *dssdev = to_dss_device(dev);
135         struct omap_video_timings t;
136
137         if (!dssdev->get_timings)
138                 return -ENOENT;
139
140         dssdev->get_timings(dssdev, &t);
141
142         return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
143                         t.pixel_clock,
144                         t.x_res, t.hfp, t.hbp, t.hsw,
145                         t.y_res, t.vfp, t.vbp, t.vsw);
146 }
147
148 static ssize_t display_timings_store(struct device *dev,
149                 struct device_attribute *attr, const char *buf, size_t size)
150 {
151         struct omap_dss_device *dssdev = to_dss_device(dev);
152         struct omap_video_timings t;
153         int r, found;
154
155         if (!dssdev->set_timings || !dssdev->check_timings)
156                 return -ENOENT;
157
158         found = 0;
159 #ifdef CONFIG_OMAP2_DSS_VENC
160         if (strncmp("pal", buf, 3) == 0) {
161                 t = omap_dss_pal_timings;
162                 found = 1;
163         } else if (strncmp("ntsc", buf, 4) == 0) {
164                 t = omap_dss_ntsc_timings;
165                 found = 1;
166         }
167 #endif
168         if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
169                                 &t.pixel_clock,
170                                 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
171                                 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
172                 return -EINVAL;
173
174         r = dssdev->check_timings(dssdev, &t);
175         if (r)
176                 return r;
177
178         dssdev->set_timings(dssdev, &t);
179
180         return size;
181 }
182
183 static ssize_t display_rotate_show(struct device *dev,
184                 struct device_attribute *attr, char *buf)
185 {
186         struct omap_dss_device *dssdev = to_dss_device(dev);
187         int rotate;
188         if (!dssdev->get_rotate)
189                 return -ENOENT;
190         rotate = dssdev->get_rotate(dssdev);
191         return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
192 }
193
194 static ssize_t display_rotate_store(struct device *dev,
195                 struct device_attribute *attr, const char *buf, size_t size)
196 {
197         struct omap_dss_device *dssdev = to_dss_device(dev);
198         unsigned long rot;
199         int r;
200
201         if (!dssdev->set_rotate || !dssdev->get_rotate)
202                 return -ENOENT;
203
204         rot = simple_strtoul(buf, NULL, 0);
205
206         r = dssdev->set_rotate(dssdev, rot);
207         if (r)
208                 return r;
209
210         return size;
211 }
212
213 static ssize_t display_mirror_show(struct device *dev,
214                 struct device_attribute *attr, char *buf)
215 {
216         struct omap_dss_device *dssdev = to_dss_device(dev);
217         int mirror;
218         if (!dssdev->get_mirror)
219                 return -ENOENT;
220         mirror = dssdev->get_mirror(dssdev);
221         return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
222 }
223
224 static ssize_t display_mirror_store(struct device *dev,
225                 struct device_attribute *attr, const char *buf, size_t size)
226 {
227         struct omap_dss_device *dssdev = to_dss_device(dev);
228         unsigned long mirror;
229         int r;
230
231         if (!dssdev->set_mirror || !dssdev->get_mirror)
232                 return -ENOENT;
233
234         mirror = simple_strtoul(buf, NULL, 0);
235
236         r = dssdev->set_mirror(dssdev, mirror);
237         if (r)
238                 return r;
239
240         return size;
241 }
242
243 static ssize_t display_wss_show(struct device *dev,
244                 struct device_attribute *attr, char *buf)
245 {
246         struct omap_dss_device *dssdev = to_dss_device(dev);
247         unsigned int wss;
248
249         if (!dssdev->get_wss)
250                 return -ENOENT;
251
252         wss = dssdev->get_wss(dssdev);
253
254         return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
255 }
256
257 static ssize_t display_wss_store(struct device *dev,
258                 struct device_attribute *attr, const char *buf, size_t size)
259 {
260         struct omap_dss_device *dssdev = to_dss_device(dev);
261         unsigned long wss;
262         int r;
263
264         if (!dssdev->get_wss || !dssdev->set_wss)
265                 return -ENOENT;
266
267         if (strict_strtoul(buf, 0, &wss))
268                 return -EINVAL;
269
270         if (wss > 0xfffff)
271                 return -EINVAL;
272
273         r = dssdev->set_wss(dssdev, wss);
274         if (r)
275                 return r;
276
277         return size;
278 }
279
280 static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
281                 display_enabled_show, display_enabled_store);
282 static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
283                 display_upd_mode_show, display_upd_mode_store);
284 static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
285                 display_tear_show, display_tear_store);
286 static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
287                 display_timings_show, display_timings_store);
288 static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
289                 display_rotate_show, display_rotate_store);
290 static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
291                 display_mirror_show, display_mirror_store);
292 static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
293                 display_wss_show, display_wss_store);
294
295 static struct device_attribute *display_sysfs_attrs[] = {
296         &dev_attr_enabled,
297         &dev_attr_update_mode,
298         &dev_attr_tear_elim,
299         &dev_attr_timings,
300         &dev_attr_rotate,
301         &dev_attr_mirror,
302         &dev_attr_wss,
303         NULL
304 };
305
306 static void default_get_resolution(struct omap_dss_device *dssdev,
307                         u16 *xres, u16 *yres)
308 {
309         *xres = dssdev->panel.timings.x_res;
310         *yres = dssdev->panel.timings.y_res;
311 }
312
313 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
314                 u32 fifo_size, enum omap_burst_size *burst_size,
315                 u32 *fifo_low, u32 *fifo_high)
316 {
317         unsigned burst_size_bytes;
318
319         *burst_size = OMAP_DSS_BURST_16x32;
320         burst_size_bytes = 16 * 32 / 8;
321
322         *fifo_high = fifo_size - 1;
323         *fifo_low = fifo_size - burst_size_bytes;
324 }
325
326 static int default_wait_vsync(struct omap_dss_device *dssdev)
327 {
328         unsigned long timeout = msecs_to_jiffies(500);
329         u32 irq;
330
331         if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
332                 irq = DISPC_IRQ_EVSYNC_ODD;
333         else
334                 irq = DISPC_IRQ_VSYNC;
335
336         return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
337 }
338
339 static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
340 {
341         if (dssdev->panel.recommended_bpp)
342                 return dssdev->panel.recommended_bpp;
343
344         switch (dssdev->type) {
345         case OMAP_DISPLAY_TYPE_DPI:
346                 if (dssdev->phy.dpi.data_lines == 24)
347                         return 24;
348                 else
349                         return 16;
350
351         case OMAP_DISPLAY_TYPE_DBI:
352         case OMAP_DISPLAY_TYPE_DSI:
353                 if (dssdev->ctrl.pixel_size == 24)
354                         return 24;
355                 else
356                         return 16;
357         case OMAP_DISPLAY_TYPE_VENC:
358         case OMAP_DISPLAY_TYPE_SDI:
359                 return 24;
360                 return 24;
361         default:
362                 BUG();
363         }
364 }
365
366 /* Checks if replication logic should be used. Only use for active matrix,
367  * when overlay is in RGB12U or RGB16 mode, and LCD interface is
368  * 18bpp or 24bpp */
369 bool dss_use_replication(struct omap_dss_device *dssdev,
370                 enum omap_color_mode mode)
371 {
372         int bpp;
373
374         if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
375                 return false;
376
377         if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
378                         (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
379                 return false;
380
381         switch (dssdev->type) {
382         case OMAP_DISPLAY_TYPE_DPI:
383                 bpp = dssdev->phy.dpi.data_lines;
384                 break;
385         case OMAP_DISPLAY_TYPE_VENC:
386         case OMAP_DISPLAY_TYPE_SDI:
387                 bpp = 24;
388                 break;
389         case OMAP_DISPLAY_TYPE_DBI:
390         case OMAP_DISPLAY_TYPE_DSI:
391                 bpp = dssdev->ctrl.pixel_size;
392                 break;
393         default:
394                 BUG();
395         }
396
397         return bpp > 16;
398 }
399
400 void dss_init_device(struct platform_device *pdev,
401                 struct omap_dss_device *dssdev)
402 {
403         struct device_attribute *attr;
404         int i;
405         int r;
406
407         switch (dssdev->type) {
408         case OMAP_DISPLAY_TYPE_DPI:
409 #ifdef CONFIG_OMAP2_DSS_RFBI
410         case OMAP_DISPLAY_TYPE_DBI:
411 #endif
412 #ifdef CONFIG_OMAP2_DSS_SDI
413         case OMAP_DISPLAY_TYPE_SDI:
414 #endif
415 #ifdef CONFIG_OMAP2_DSS_DSI
416         case OMAP_DISPLAY_TYPE_DSI:
417 #endif
418 #ifdef CONFIG_OMAP2_DSS_VENC
419         case OMAP_DISPLAY_TYPE_VENC:
420 #endif
421                 break;
422         default:
423                 DSSERR("Support for display '%s' not compiled in.\n",
424                                 dssdev->name);
425                 return;
426         }
427
428         dssdev->get_resolution = default_get_resolution;
429         dssdev->get_recommended_bpp = default_get_recommended_bpp;
430         dssdev->wait_vsync = default_wait_vsync;
431
432         switch (dssdev->type) {
433         case OMAP_DISPLAY_TYPE_DPI:
434                 r = dpi_init_display(dssdev);
435                 break;
436 #ifdef CONFIG_OMAP2_DSS_RFBI
437         case OMAP_DISPLAY_TYPE_DBI:
438                 r = rfbi_init_display(dssdev);
439                 break;
440 #endif
441 #ifdef CONFIG_OMAP2_DSS_VENC
442         case OMAP_DISPLAY_TYPE_VENC:
443                 r = venc_init_display(dssdev);
444                 break;
445 #endif
446 #ifdef CONFIG_OMAP2_DSS_SDI
447         case OMAP_DISPLAY_TYPE_SDI:
448                 r = sdi_init_display(dssdev);
449                 break;
450 #endif
451 #ifdef CONFIG_OMAP2_DSS_DSI
452         case OMAP_DISPLAY_TYPE_DSI:
453                 r = dsi_init_display(dssdev);
454                 break;
455 #endif
456         default:
457                 BUG();
458         }
459
460         if (r) {
461                 DSSERR("failed to init display %s\n", dssdev->name);
462                 return;
463         }
464
465         /* create device sysfs files */
466         i = 0;
467         while ((attr = display_sysfs_attrs[i++]) != NULL) {
468                 r = device_create_file(&dssdev->dev, attr);
469                 if (r)
470                         DSSERR("failed to create sysfs file\n");
471         }
472
473         /* create display? sysfs links */
474         r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
475                         dev_name(&dssdev->dev));
476         if (r)
477                 DSSERR("failed to create sysfs display link\n");
478 }
479
480 void dss_uninit_device(struct platform_device *pdev,
481                 struct omap_dss_device *dssdev)
482 {
483         struct device_attribute *attr;
484         int i = 0;
485
486         sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
487
488         while ((attr = display_sysfs_attrs[i++]) != NULL)
489                 device_remove_file(&dssdev->dev, attr);
490
491         if (dssdev->manager)
492                 dssdev->manager->unset_device(dssdev->manager);
493 }
494
495 static int dss_suspend_device(struct device *dev, void *data)
496 {
497         int r;
498         struct omap_dss_device *dssdev = to_dss_device(dev);
499
500         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
501                 dssdev->activate_after_resume = false;
502                 return 0;
503         }
504
505         if (!dssdev->suspend) {
506                 DSSERR("display '%s' doesn't implement suspend\n",
507                                 dssdev->name);
508                 return -ENOSYS;
509         }
510
511         r = dssdev->suspend(dssdev);
512         if (r)
513                 return r;
514
515         dssdev->activate_after_resume = true;
516
517         return 0;
518 }
519
520 int dss_suspend_all_devices(void)
521 {
522         int r;
523         struct bus_type *bus = dss_get_bus();
524
525         r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
526         if (r) {
527                 /* resume all displays that were suspended */
528                 dss_resume_all_devices();
529                 return r;
530         }
531
532         return 0;
533 }
534
535 static int dss_resume_device(struct device *dev, void *data)
536 {
537         int r;
538         struct omap_dss_device *dssdev = to_dss_device(dev);
539
540         if (dssdev->activate_after_resume && dssdev->resume) {
541                 r = dssdev->resume(dssdev);
542                 if (r)
543                         return r;
544         }
545
546         dssdev->activate_after_resume = false;
547
548         return 0;
549 }
550
551 int dss_resume_all_devices(void)
552 {
553         struct bus_type *bus = dss_get_bus();
554
555         return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
556 }
557
558 static int dss_disable_device(struct device *dev, void *data)
559 {
560         struct omap_dss_device *dssdev = to_dss_device(dev);
561         dssdev->disable(dssdev);
562         return 0;
563 }
564
565 void dss_disable_all_devices(void)
566 {
567         struct bus_type *bus = dss_get_bus();
568         bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
569 }
570
571
572 void omap_dss_get_device(struct omap_dss_device *dssdev)
573 {
574         get_device(&dssdev->dev);
575 }
576 EXPORT_SYMBOL(omap_dss_get_device);
577
578 void omap_dss_put_device(struct omap_dss_device *dssdev)
579 {
580         put_device(&dssdev->dev);
581 }
582 EXPORT_SYMBOL(omap_dss_put_device);
583
584 /* ref count of the found device is incremented. ref count
585  * of from-device is decremented. */
586 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
587 {
588         struct device *dev;
589         struct device *dev_start = NULL;
590         struct omap_dss_device *dssdev = NULL;
591
592         int match(struct device *dev, void *data)
593         {
594                 /* skip panels connected to controllers */
595                 if (to_dss_device(dev)->panel.ctrl)
596                         return 0;
597
598                 return 1;
599         }
600
601         if (from)
602                 dev_start = &from->dev;
603         dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
604         if (dev)
605                 dssdev = to_dss_device(dev);
606         if (from)
607                 put_device(&from->dev);
608
609         return dssdev;
610 }
611 EXPORT_SYMBOL(omap_dss_get_next_device);
612
613 struct omap_dss_device *omap_dss_find_device(void *data,
614                 int (*match)(struct omap_dss_device *dssdev, void *data))
615 {
616         struct omap_dss_device *dssdev = NULL;
617
618         while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
619                 if (match(dssdev, data))
620                         return dssdev;
621         }
622
623         return NULL;
624 }
625 EXPORT_SYMBOL(omap_dss_find_device);
626
627 int omap_dss_start_device(struct omap_dss_device *dssdev)
628 {
629         int r;
630
631         if (!dssdev->driver) {
632                 DSSDBG("no driver\n");
633                 r = -ENODEV;
634                 goto err0;
635         }
636
637         if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
638                 DSSDBG("no panel driver\n");
639                 r = -ENODEV;
640                 goto err0;
641         }
642
643         if (!try_module_get(dssdev->dev.driver->owner)) {
644                 r = -ENODEV;
645                 goto err0;
646         }
647
648         if (dssdev->ctrl.panel) {
649                 if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
650                         r = -ENODEV;
651                         goto err1;
652                 }
653         }
654
655         return 0;
656 err1:
657         module_put(dssdev->dev.driver->owner);
658 err0:
659         return r;
660 }
661 EXPORT_SYMBOL(omap_dss_start_device);
662
663 void omap_dss_stop_device(struct omap_dss_device *dssdev)
664 {
665         if (dssdev->ctrl.panel)
666                 module_put(dssdev->ctrl.panel->dev.driver->owner);
667
668         module_put(dssdev->dev.driver->owner);
669 }
670 EXPORT_SYMBOL(omap_dss_stop_device);
671