Merge branch 'for-linus' of git://github.com/chrismason/linux
[pandora-kernel.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/platform_device.h>
29
30 #include <video/omapdss.h>
31 #include "dss.h"
32 #include "dss_features.h"
33
34 static ssize_t display_enabled_show(struct device *dev,
35                 struct device_attribute *attr, char *buf)
36 {
37         struct omap_dss_device *dssdev = to_dss_device(dev);
38         bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
39
40         return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
41 }
42
43 static ssize_t display_enabled_store(struct device *dev,
44                 struct device_attribute *attr,
45                 const char *buf, size_t size)
46 {
47         struct omap_dss_device *dssdev = to_dss_device(dev);
48         int r, enabled;
49
50         r = kstrtoint(buf, 0, &enabled);
51         if (r)
52                 return r;
53
54         enabled = !!enabled;
55
56         if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
57                 if (enabled) {
58                         r = dssdev->driver->enable(dssdev);
59                         if (r)
60                                 return r;
61                 } else {
62                         dssdev->driver->disable(dssdev);
63                 }
64         }
65
66         return size;
67 }
68
69 static ssize_t display_tear_show(struct device *dev,
70                 struct device_attribute *attr, char *buf)
71 {
72         struct omap_dss_device *dssdev = to_dss_device(dev);
73         return snprintf(buf, PAGE_SIZE, "%d\n",
74                         dssdev->driver->get_te ?
75                         dssdev->driver->get_te(dssdev) : 0);
76 }
77
78 static ssize_t display_tear_store(struct device *dev,
79                 struct device_attribute *attr, const char *buf, size_t size)
80 {
81         struct omap_dss_device *dssdev = to_dss_device(dev);
82         int te, r;
83
84         if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
85                 return -ENOENT;
86
87         r = kstrtoint(buf, 0, &te);
88         if (r)
89                 return r;
90
91         te = !!te;
92
93         r = dssdev->driver->enable_te(dssdev, te);
94         if (r)
95                 return r;
96
97         return size;
98 }
99
100 static ssize_t display_timings_show(struct device *dev,
101                 struct device_attribute *attr, char *buf)
102 {
103         struct omap_dss_device *dssdev = to_dss_device(dev);
104         struct omap_video_timings t;
105
106         if (!dssdev->driver->get_timings)
107                 return -ENOENT;
108
109         dssdev->driver->get_timings(dssdev, &t);
110
111         return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
112                         t.pixel_clock,
113                         t.x_res, t.hfp, t.hbp, t.hsw,
114                         t.y_res, t.vfp, t.vbp, t.vsw);
115 }
116
117 static ssize_t display_timings_store(struct device *dev,
118                 struct device_attribute *attr, const char *buf, size_t size)
119 {
120         struct omap_dss_device *dssdev = to_dss_device(dev);
121         struct omap_video_timings t;
122         int r, found;
123
124         if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
125                 return -ENOENT;
126
127         found = 0;
128 #ifdef CONFIG_OMAP2_DSS_VENC
129         if (strncmp("pal", buf, 3) == 0) {
130                 t = omap_dss_pal_timings;
131                 found = 1;
132         } else if (strncmp("ntsc", buf, 4) == 0) {
133                 t = omap_dss_ntsc_timings;
134                 found = 1;
135         }
136 #endif
137         if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
138                                 &t.pixel_clock,
139                                 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
140                                 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
141                 return -EINVAL;
142
143         r = dssdev->driver->check_timings(dssdev, &t);
144         if (r)
145                 return r;
146
147         dssdev->driver->set_timings(dssdev, &t);
148
149         return size;
150 }
151
152 static ssize_t display_rotate_show(struct device *dev,
153                 struct device_attribute *attr, char *buf)
154 {
155         struct omap_dss_device *dssdev = to_dss_device(dev);
156         int rotate;
157         if (!dssdev->driver->get_rotate)
158                 return -ENOENT;
159         rotate = dssdev->driver->get_rotate(dssdev);
160         return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
161 }
162
163 static ssize_t display_rotate_store(struct device *dev,
164                 struct device_attribute *attr, const char *buf, size_t size)
165 {
166         struct omap_dss_device *dssdev = to_dss_device(dev);
167         int rot, r;
168
169         if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
170                 return -ENOENT;
171
172         r = kstrtoint(buf, 0, &rot);
173         if (r)
174                 return r;
175
176         r = dssdev->driver->set_rotate(dssdev, rot);
177         if (r)
178                 return r;
179
180         return size;
181 }
182
183 static ssize_t display_mirror_show(struct device *dev,
184                 struct device_attribute *attr, char *buf)
185 {
186         struct omap_dss_device *dssdev = to_dss_device(dev);
187         int mirror;
188         if (!dssdev->driver->get_mirror)
189                 return -ENOENT;
190         mirror = dssdev->driver->get_mirror(dssdev);
191         return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
192 }
193
194 static ssize_t display_mirror_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         int mirror, r;
199
200         if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
201                 return -ENOENT;
202
203         r = kstrtoint(buf, 0, &mirror);
204         if (r)
205                 return r;
206
207         mirror = !!mirror;
208
209         r = dssdev->driver->set_mirror(dssdev, mirror);
210         if (r)
211                 return r;
212
213         return size;
214 }
215
216 static ssize_t display_wss_show(struct device *dev,
217                 struct device_attribute *attr, char *buf)
218 {
219         struct omap_dss_device *dssdev = to_dss_device(dev);
220         unsigned int wss;
221
222         if (!dssdev->driver->get_wss)
223                 return -ENOENT;
224
225         wss = dssdev->driver->get_wss(dssdev);
226
227         return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
228 }
229
230 static ssize_t display_wss_store(struct device *dev,
231                 struct device_attribute *attr, const char *buf, size_t size)
232 {
233         struct omap_dss_device *dssdev = to_dss_device(dev);
234         u32 wss;
235         int r;
236
237         if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
238                 return -ENOENT;
239
240         r = kstrtou32(buf, 0, &wss);
241         if (r)
242                 return r;
243
244         if (wss > 0xfffff)
245                 return -EINVAL;
246
247         r = dssdev->driver->set_wss(dssdev, wss);
248         if (r)
249                 return r;
250
251         return size;
252 }
253
254 static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
255                 display_enabled_show, display_enabled_store);
256 static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
257                 display_tear_show, display_tear_store);
258 static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
259                 display_timings_show, display_timings_store);
260 static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
261                 display_rotate_show, display_rotate_store);
262 static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
263                 display_mirror_show, display_mirror_store);
264 static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
265                 display_wss_show, display_wss_store);
266
267 static struct device_attribute *display_sysfs_attrs[] = {
268         &dev_attr_enabled,
269         &dev_attr_tear_elim,
270         &dev_attr_timings,
271         &dev_attr_rotate,
272         &dev_attr_mirror,
273         &dev_attr_wss,
274         NULL
275 };
276
277 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
278                         u16 *xres, u16 *yres)
279 {
280         *xres = dssdev->panel.timings.x_res;
281         *yres = dssdev->panel.timings.y_res;
282 }
283 EXPORT_SYMBOL(omapdss_default_get_resolution);
284
285 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
286                 u32 fifo_size, u32 burst_size,
287                 u32 *fifo_low, u32 *fifo_high)
288 {
289         unsigned buf_unit = dss_feat_get_buffer_size_unit();
290
291         *fifo_high = fifo_size - buf_unit;
292         *fifo_low = fifo_size - burst_size;
293 }
294
295 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
296 {
297         switch (dssdev->type) {
298         case OMAP_DISPLAY_TYPE_DPI:
299                 if (dssdev->phy.dpi.data_lines == 24)
300                         return 24;
301                 else
302                         return 16;
303
304         case OMAP_DISPLAY_TYPE_DBI:
305         case OMAP_DISPLAY_TYPE_DSI:
306                 if (dssdev->ctrl.pixel_size == 24)
307                         return 24;
308                 else
309                         return 16;
310         case OMAP_DISPLAY_TYPE_VENC:
311         case OMAP_DISPLAY_TYPE_SDI:
312         case OMAP_DISPLAY_TYPE_HDMI:
313                 return 24;
314         default:
315                 BUG();
316         }
317 }
318 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
319
320 /* Checks if replication logic should be used. Only use for active matrix,
321  * when overlay is in RGB12U or RGB16 mode, and LCD interface is
322  * 18bpp or 24bpp */
323 bool dss_use_replication(struct omap_dss_device *dssdev,
324                 enum omap_color_mode mode)
325 {
326         int bpp;
327
328         if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
329                 return false;
330
331         if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
332                         (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
333                 return false;
334
335         switch (dssdev->type) {
336         case OMAP_DISPLAY_TYPE_DPI:
337                 bpp = dssdev->phy.dpi.data_lines;
338                 break;
339         case OMAP_DISPLAY_TYPE_HDMI:
340         case OMAP_DISPLAY_TYPE_VENC:
341         case OMAP_DISPLAY_TYPE_SDI:
342                 bpp = 24;
343                 break;
344         case OMAP_DISPLAY_TYPE_DBI:
345         case OMAP_DISPLAY_TYPE_DSI:
346                 bpp = dssdev->ctrl.pixel_size;
347                 break;
348         default:
349                 BUG();
350         }
351
352         return bpp > 16;
353 }
354
355 void dss_init_device(struct platform_device *pdev,
356                 struct omap_dss_device *dssdev)
357 {
358         struct device_attribute *attr;
359         int i;
360         int r;
361
362         switch (dssdev->type) {
363 #ifdef CONFIG_OMAP2_DSS_DPI
364         case OMAP_DISPLAY_TYPE_DPI:
365                 r = dpi_init_display(dssdev);
366                 break;
367 #endif
368 #ifdef CONFIG_OMAP2_DSS_RFBI
369         case OMAP_DISPLAY_TYPE_DBI:
370                 r = rfbi_init_display(dssdev);
371                 break;
372 #endif
373 #ifdef CONFIG_OMAP2_DSS_VENC
374         case OMAP_DISPLAY_TYPE_VENC:
375                 r = venc_init_display(dssdev);
376                 break;
377 #endif
378 #ifdef CONFIG_OMAP2_DSS_SDI
379         case OMAP_DISPLAY_TYPE_SDI:
380                 r = sdi_init_display(dssdev);
381                 break;
382 #endif
383 #ifdef CONFIG_OMAP2_DSS_DSI
384         case OMAP_DISPLAY_TYPE_DSI:
385                 r = dsi_init_display(dssdev);
386                 break;
387 #endif
388         case OMAP_DISPLAY_TYPE_HDMI:
389                 r = hdmi_init_display(dssdev);
390                 break;
391         default:
392                 DSSERR("Support for display '%s' not compiled in.\n",
393                                 dssdev->name);
394                 return;
395         }
396
397         if (r) {
398                 DSSERR("failed to init display %s\n", dssdev->name);
399                 return;
400         }
401
402         /* create device sysfs files */
403         i = 0;
404         while ((attr = display_sysfs_attrs[i++]) != NULL) {
405                 r = device_create_file(&dssdev->dev, attr);
406                 if (r)
407                         DSSERR("failed to create sysfs file\n");
408         }
409
410         /* create display? sysfs links */
411         r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
412                         dev_name(&dssdev->dev));
413         if (r)
414                 DSSERR("failed to create sysfs display link\n");
415 }
416
417 void dss_uninit_device(struct platform_device *pdev,
418                 struct omap_dss_device *dssdev)
419 {
420         struct device_attribute *attr;
421         int i = 0;
422
423         sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
424
425         while ((attr = display_sysfs_attrs[i++]) != NULL)
426                 device_remove_file(&dssdev->dev, attr);
427
428         if (dssdev->manager)
429                 dssdev->manager->unset_device(dssdev->manager);
430 }
431
432 static int dss_suspend_device(struct device *dev, void *data)
433 {
434         int r;
435         struct omap_dss_device *dssdev = to_dss_device(dev);
436
437         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
438                 dssdev->activate_after_resume = false;
439                 return 0;
440         }
441
442         if (!dssdev->driver->suspend) {
443                 DSSERR("display '%s' doesn't implement suspend\n",
444                                 dssdev->name);
445                 return -ENOSYS;
446         }
447
448         r = dssdev->driver->suspend(dssdev);
449         if (r)
450                 return r;
451
452         dssdev->activate_after_resume = true;
453
454         return 0;
455 }
456
457 int dss_suspend_all_devices(void)
458 {
459         int r;
460         struct bus_type *bus = dss_get_bus();
461
462         r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
463         if (r) {
464                 /* resume all displays that were suspended */
465                 dss_resume_all_devices();
466                 return r;
467         }
468
469         return 0;
470 }
471
472 static int dss_resume_device(struct device *dev, void *data)
473 {
474         int r;
475         struct omap_dss_device *dssdev = to_dss_device(dev);
476
477         if (dssdev->activate_after_resume && dssdev->driver->resume) {
478                 r = dssdev->driver->resume(dssdev);
479                 if (r)
480                         return r;
481         }
482
483         dssdev->activate_after_resume = false;
484
485         return 0;
486 }
487
488 int dss_resume_all_devices(void)
489 {
490         struct bus_type *bus = dss_get_bus();
491
492         return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
493 }
494
495 static int dss_disable_device(struct device *dev, void *data)
496 {
497         struct omap_dss_device *dssdev = to_dss_device(dev);
498
499         if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
500                 dssdev->driver->disable(dssdev);
501
502         return 0;
503 }
504
505 void dss_disable_all_devices(void)
506 {
507         struct bus_type *bus = dss_get_bus();
508         bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
509 }
510
511
512 void omap_dss_get_device(struct omap_dss_device *dssdev)
513 {
514         get_device(&dssdev->dev);
515 }
516 EXPORT_SYMBOL(omap_dss_get_device);
517
518 void omap_dss_put_device(struct omap_dss_device *dssdev)
519 {
520         put_device(&dssdev->dev);
521 }
522 EXPORT_SYMBOL(omap_dss_put_device);
523
524 /* ref count of the found device is incremented. ref count
525  * of from-device is decremented. */
526 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
527 {
528         struct device *dev;
529         struct device *dev_start = NULL;
530         struct omap_dss_device *dssdev = NULL;
531
532         int match(struct device *dev, void *data)
533         {
534                 return 1;
535         }
536
537         if (from)
538                 dev_start = &from->dev;
539         dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
540         if (dev)
541                 dssdev = to_dss_device(dev);
542         if (from)
543                 put_device(&from->dev);
544
545         return dssdev;
546 }
547 EXPORT_SYMBOL(omap_dss_get_next_device);
548
549 struct omap_dss_device *omap_dss_find_device(void *data,
550                 int (*match)(struct omap_dss_device *dssdev, void *data))
551 {
552         struct omap_dss_device *dssdev = NULL;
553
554         while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
555                 if (match(dssdev, data))
556                         return dssdev;
557         }
558
559         return NULL;
560 }
561 EXPORT_SYMBOL(omap_dss_find_device);
562
563 int omap_dss_start_device(struct omap_dss_device *dssdev)
564 {
565         if (!dssdev->driver) {
566                 DSSDBG("no driver\n");
567                 return -ENODEV;
568         }
569
570         if (!try_module_get(dssdev->dev.driver->owner)) {
571                 return -ENODEV;
572         }
573
574         return 0;
575 }
576 EXPORT_SYMBOL(omap_dss_start_device);
577
578 void omap_dss_stop_device(struct omap_dss_device *dssdev)
579 {
580         module_put(dssdev->dev.driver->owner);
581 }
582 EXPORT_SYMBOL(omap_dss_stop_device);
583