diff options
Diffstat (limited to 'drivers/video/omap2/dss/display.c')
-rw-r--r-- | drivers/video/omap2/dss/display.c | 386 |
1 files changed, 3 insertions, 383 deletions
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index ccf8550fafde..0aa8ad8f9667 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -31,250 +31,6 @@ | |||
31 | #include "dss.h" | 31 | #include "dss.h" |
32 | #include "dss_features.h" | 32 | #include "dss_features.h" |
33 | 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) { | ||
128 | t = omap_dss_pal_timings; | ||
129 | found = 1; | ||
130 | } else if (strncmp("ntsc", buf, 4) == 0) { | ||
131 | t = omap_dss_ntsc_timings; | ||
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); | ||
259 | static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, | ||
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 | |||
278 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, | 34 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, |
279 | u16 *xres, u16 *yres) | 35 | u16 *xres, u16 *yres) |
280 | { | 36 | { |
@@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev, | |||
320 | } | 76 | } |
321 | EXPORT_SYMBOL(omapdss_default_get_timings); | 77 | EXPORT_SYMBOL(omapdss_default_get_timings); |
322 | 78 | ||
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 */ | ||
358 | omapdss_output_unset_device(out); | ||
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 | |||
388 | omapdss_output_unset_device(dssdev->output); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | int dss_init_device(struct platform_device *pdev, | ||
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 | |||
436 | void dss_uninit_device(struct platform_device *pdev, | ||
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) | 79 | static int dss_suspend_device(struct device *dev, void *data) |
451 | { | 80 | { |
452 | int r; | ||
453 | struct omap_dss_device *dssdev = to_dss_device(dev); | 81 | struct omap_dss_device *dssdev = to_dss_device(dev); |
454 | 82 | ||
455 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | 83 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { |
@@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data) | |||
457 | return 0; | 85 | return 0; |
458 | } | 86 | } |
459 | 87 | ||
460 | if (!dssdev->driver->suspend) { | 88 | dssdev->driver->disable(dssdev); |
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 | 89 | ||
470 | dssdev->activate_after_resume = true; | 90 | dssdev->activate_after_resume = true; |
471 | 91 | ||
@@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data) | |||
492 | int r; | 112 | int r; |
493 | struct omap_dss_device *dssdev = to_dss_device(dev); | 113 | struct omap_dss_device *dssdev = to_dss_device(dev); |
494 | 114 | ||
495 | if (dssdev->activate_after_resume && dssdev->driver->resume) { | 115 | if (dssdev->activate_after_resume) { |
496 | r = dssdev->driver->resume(dssdev); | 116 | r = dssdev->driver->enable(dssdev); |
497 | if (r) | 117 | if (r) |
498 | return r; | 118 | return r; |
499 | } | 119 | } |