Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
display.c
Go to the documentation of this file.
1 /*
2  * linux/drivers/video/omap2/dss/display.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <[email protected]>
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;
49  bool enabled;
50 
51  r = strtobool(buf, &enabled);
52  if (r)
53  return r;
54 
55  if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
56  if (enabled) {
57  r = dssdev->driver->enable(dssdev);
58  if (r)
59  return r;
60  } else {
61  dssdev->driver->disable(dssdev);
62  }
63  }
64 
65  return size;
66 }
67 
68 static ssize_t display_tear_show(struct device *dev,
69  struct device_attribute *attr, char *buf)
70 {
71  struct omap_dss_device *dssdev = to_dss_device(dev);
72  return snprintf(buf, PAGE_SIZE, "%d\n",
73  dssdev->driver->get_te ?
74  dssdev->driver->get_te(dssdev) : 0);
75 }
76 
77 static ssize_t display_tear_store(struct device *dev,
78  struct device_attribute *attr, const char *buf, size_t size)
79 {
80  struct omap_dss_device *dssdev = to_dss_device(dev);
81  int r;
82  bool te;
83 
84  if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
85  return -ENOENT;
86 
87  r = strtobool(buf, &te);
88  if (r)
89  return r;
90 
91  r = dssdev->driver->enable_te(dssdev, te);
92  if (r)
93  return r;
94 
95  return size;
96 }
97 
98 static ssize_t display_timings_show(struct device *dev,
99  struct device_attribute *attr, char *buf)
100 {
101  struct omap_dss_device *dssdev = to_dss_device(dev);
102  struct omap_video_timings t;
103 
104  if (!dssdev->driver->get_timings)
105  return -ENOENT;
106 
107  dssdev->driver->get_timings(dssdev, &t);
108 
109  return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
110  t.pixel_clock,
111  t.x_res, t.hfp, t.hbp, t.hsw,
112  t.y_res, t.vfp, t.vbp, t.vsw);
113 }
114 
115 static ssize_t display_timings_store(struct device *dev,
116  struct device_attribute *attr, const char *buf, size_t size)
117 {
118  struct omap_dss_device *dssdev = to_dss_device(dev);
119  struct omap_video_timings t = dssdev->panel.timings;
120  int r, found;
121 
122  if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
123  return -ENOENT;
124 
125  found = 0;
126 #ifdef CONFIG_OMAP2_DSS_VENC
127  if (strncmp("pal", buf, 3) == 0) {
129  found = 1;
130  } else if (strncmp("ntsc", buf, 4) == 0) {
132  found = 1;
133  }
134 #endif
135  if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
136  &t.pixel_clock,
137  &t.x_res, &t.hfp, &t.hbp, &t.hsw,
138  &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
139  return -EINVAL;
140 
141  r = dssdev->driver->check_timings(dssdev, &t);
142  if (r)
143  return r;
144 
145  dssdev->driver->disable(dssdev);
146  dssdev->driver->set_timings(dssdev, &t);
147  r = dssdev->driver->enable(dssdev);
148  if (r)
149  return r;
150 
151  return size;
152 }
153 
154 static ssize_t display_rotate_show(struct device *dev,
155  struct device_attribute *attr, char *buf)
156 {
157  struct omap_dss_device *dssdev = to_dss_device(dev);
158  int rotate;
159  if (!dssdev->driver->get_rotate)
160  return -ENOENT;
161  rotate = dssdev->driver->get_rotate(dssdev);
162  return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
163 }
164 
165 static ssize_t display_rotate_store(struct device *dev,
166  struct device_attribute *attr, const char *buf, size_t size)
167 {
168  struct omap_dss_device *dssdev = to_dss_device(dev);
169  int rot, r;
170 
171  if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
172  return -ENOENT;
173 
174  r = kstrtoint(buf, 0, &rot);
175  if (r)
176  return r;
177 
178  r = dssdev->driver->set_rotate(dssdev, rot);
179  if (r)
180  return r;
181 
182  return size;
183 }
184 
185 static ssize_t display_mirror_show(struct device *dev,
186  struct device_attribute *attr, char *buf)
187 {
188  struct omap_dss_device *dssdev = to_dss_device(dev);
189  int mirror;
190  if (!dssdev->driver->get_mirror)
191  return -ENOENT;
192  mirror = dssdev->driver->get_mirror(dssdev);
193  return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
194 }
195 
196 static ssize_t display_mirror_store(struct device *dev,
197  struct device_attribute *attr, const char *buf, size_t size)
198 {
199  struct omap_dss_device *dssdev = to_dss_device(dev);
200  int r;
201  bool mirror;
202 
203  if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
204  return -ENOENT;
205 
206  r = strtobool(buf, &mirror);
207  if (r)
208  return r;
209 
210  r = dssdev->driver->set_mirror(dssdev, mirror);
211  if (r)
212  return r;
213 
214  return size;
215 }
216 
217 static ssize_t display_wss_show(struct device *dev,
218  struct device_attribute *attr, char *buf)
219 {
220  struct omap_dss_device *dssdev = to_dss_device(dev);
221  unsigned int wss;
222 
223  if (!dssdev->driver->get_wss)
224  return -ENOENT;
225 
226  wss = dssdev->driver->get_wss(dssdev);
227 
228  return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
229 }
230 
231 static ssize_t display_wss_store(struct device *dev,
232  struct device_attribute *attr, const char *buf, size_t size)
233 {
234  struct omap_dss_device *dssdev = to_dss_device(dev);
235  u32 wss;
236  int r;
237 
238  if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
239  return -ENOENT;
240 
241  r = kstrtou32(buf, 0, &wss);
242  if (r)
243  return r;
244 
245  if (wss > 0xfffff)
246  return -EINVAL;
247 
248  r = dssdev->driver->set_wss(dssdev, wss);
249  if (r)
250  return r;
251 
252  return size;
253 }
254 
255 static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
256  display_enabled_show, display_enabled_store);
257 static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
258  display_tear_show, display_tear_store);
260  display_timings_show, display_timings_store);
261 static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
262  display_rotate_show, display_rotate_store);
263 static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
264  display_mirror_show, display_mirror_store);
265 static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
266  display_wss_show, display_wss_store);
267 
268 static struct device_attribute *display_sysfs_attrs[] = {
269  &dev_attr_enabled,
270  &dev_attr_tear_elim,
271  &dev_attr_timings,
272  &dev_attr_rotate,
273  &dev_attr_mirror,
274  &dev_attr_wss,
275  NULL
276 };
277 
279  u16 *xres, u16 *yres)
280 {
281  *xres = dssdev->panel.timings.x_res;
282  *yres = dssdev->panel.timings.y_res;
283 }
285 
287 {
288  switch (dssdev->type) {
290  if (dssdev->phy.dpi.data_lines == 24)
291  return 24;
292  else
293  return 16;
294 
296  if (dssdev->ctrl.pixel_size == 24)
297  return 24;
298  else
299  return 16;
301  if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
302  return 24;
303  else
304  return 16;
308  return 24;
309  default:
310  BUG();
311  return 0;
312  }
313 }
315 
317  struct omap_video_timings *timings)
318 {
319  *timings = dssdev->panel.timings;
320 }
322 
323 /*
324  * Connect dssdev to a manager if the manager is free or if force is specified.
325  * Connect all overlays to that manager if they are free or if force is
326  * specified.
327  */
328 static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
329 {
330  struct omap_dss_output *out;
331  struct omap_overlay_manager *mgr;
332  int i, r;
333 
334  out = omapdss_get_output_from_dssdev(dssdev);
335 
336  WARN_ON(dssdev->output);
337  WARN_ON(out->device);
338 
339  r = omapdss_output_set_device(out, dssdev);
340  if (r) {
341  DSSERR("failed to connect output to new device\n");
342  return r;
343  }
344 
345  mgr = omap_dss_get_overlay_manager(dssdev->channel);
346 
347  if (mgr->output && !force)
348  return 0;
349 
350  if (mgr->output)
351  mgr->unset_output(mgr);
352 
353  r = mgr->set_output(mgr, out);
354  if (r) {
355  DSSERR("failed to connect manager to output of new device\n");
356 
357  /* remove the output-device connection we just made */
359  return r;
360  }
361 
362  for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
363  struct omap_overlay *ovl = omap_dss_get_overlay(i);
364 
365  if (!ovl->manager || force) {
366  if (ovl->manager)
367  ovl->unset_manager(ovl);
368 
369  r = ovl->set_manager(ovl, mgr);
370  if (r) {
371  DSSERR("failed to set initial overlay\n");
372  return r;
373  }
374  }
375  }
376 
377  return 0;
378 }
379 
380 static void dss_uninit_connections(struct omap_dss_device *dssdev)
381 {
382  if (dssdev->output) {
383  struct omap_overlay_manager *mgr = dssdev->output->manager;
384 
385  if (mgr)
386  mgr->unset_output(mgr);
387 
389  }
390 }
391 
393  struct omap_dss_device *dssdev)
394 {
395  struct device_attribute *attr;
396  int i, r;
397  const char *def_disp_name = dss_get_default_display_name();
398  bool force;
399 
400  force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
401  dss_init_connections(dssdev, force);
402 
403  /* create device sysfs files */
404  i = 0;
405  while ((attr = display_sysfs_attrs[i++]) != NULL) {
406  r = device_create_file(&dssdev->dev, attr);
407  if (r) {
408  for (i = i - 2; i >= 0; i--) {
409  attr = display_sysfs_attrs[i];
410  device_remove_file(&dssdev->dev, attr);
411  }
412 
413  dss_uninit_connections(dssdev);
414 
415  DSSERR("failed to create sysfs file\n");
416  return r;
417  }
418  }
419 
420  /* create display? sysfs links */
421  r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
422  dev_name(&dssdev->dev));
423  if (r) {
424  while ((attr = display_sysfs_attrs[i++]) != NULL)
425  device_remove_file(&dssdev->dev, attr);
426 
427  dss_uninit_connections(dssdev);
428 
429  DSSERR("failed to create sysfs display link\n");
430  return r;
431  }
432 
433  return 0;
434 }
435 
437  struct omap_dss_device *dssdev)
438 {
439  struct device_attribute *attr;
440  int i = 0;
441 
442  sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
443 
444  while ((attr = display_sysfs_attrs[i++]) != NULL)
445  device_remove_file(&dssdev->dev, attr);
446 
447  dss_uninit_connections(dssdev);
448 }
449 
450 static int dss_suspend_device(struct device *dev, void *data)
451 {
452  int r;
453  struct omap_dss_device *dssdev = to_dss_device(dev);
454 
455  if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
456  dssdev->activate_after_resume = false;
457  return 0;
458  }
459 
460  if (!dssdev->driver->suspend) {
461  DSSERR("display '%s' doesn't implement suspend\n",
462  dssdev->name);
463  return -ENOSYS;
464  }
465 
466  r = dssdev->driver->suspend(dssdev);
467  if (r)
468  return r;
469 
470  dssdev->activate_after_resume = true;
471 
472  return 0;
473 }
474 
476 {
477  int r;
478  struct bus_type *bus = dss_get_bus();
479 
480  r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
481  if (r) {
482  /* resume all displays that were suspended */
484  return r;
485  }
486 
487  return 0;
488 }
489 
490 static int dss_resume_device(struct device *dev, void *data)
491 {
492  int r;
493  struct omap_dss_device *dssdev = to_dss_device(dev);
494 
495  if (dssdev->activate_after_resume && dssdev->driver->resume) {
496  r = dssdev->driver->resume(dssdev);
497  if (r)
498  return r;
499  }
500 
501  dssdev->activate_after_resume = false;
502 
503  return 0;
504 }
505 
507 {
508  struct bus_type *bus = dss_get_bus();
509 
510  return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
511 }
512 
513 static int dss_disable_device(struct device *dev, void *data)
514 {
515  struct omap_dss_device *dssdev = to_dss_device(dev);
516 
517  if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
518  dssdev->driver->disable(dssdev);
519 
520  return 0;
521 }
522 
524 {
525  struct bus_type *bus = dss_get_bus();
526  bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
527 }
528 
529 
531 {
532  get_device(&dssdev->dev);
533 }
535 
537 {
538  put_device(&dssdev->dev);
539 }
541 
542 /* ref count of the found device is incremented. ref count
543  * of from-device is decremented. */
545 {
546  struct device *dev;
547  struct device *dev_start = NULL;
548  struct omap_dss_device *dssdev = NULL;
549 
550  int match(struct device *dev, void *data)
551  {
552  return 1;
553  }
554 
555  if (from)
556  dev_start = &from->dev;
557  dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
558  if (dev)
559  dssdev = to_dss_device(dev);
560  if (from)
561  put_device(&from->dev);
562 
563  return dssdev;
564 }
566 
568  int (*match)(struct omap_dss_device *dssdev, void *data))
569 {
570  struct omap_dss_device *dssdev = NULL;
571 
572  while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
573  if (match(dssdev, data))
574  return dssdev;
575  }
576 
577  return NULL;
578 }
580 
582 {
583  if (!dssdev->driver) {
584  DSSDBG("no driver\n");
585  return -ENODEV;
586  }
587 
588  if (!try_module_get(dssdev->dev.driver->owner)) {
589  return -ENODEV;
590  }
591 
592  return 0;
593 }
595 
597 {
598  module_put(dssdev->dev.driver->owner);
599 }
601