diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/video/omap2/dss/display.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/video/omap2/dss/display.c')
-rw-r--r-- | drivers/video/omap2/dss/display.c | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c new file mode 100644 index 000000000000..6a74ea116d29 --- /dev/null +++ b/drivers/video/omap2/dss/display.c | |||
@@ -0,0 +1,626 @@ | |||
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->driver->enable(dssdev); | ||
57 | if (r) | ||
58 | return r; | ||
59 | } else { | ||
60 | dssdev->driver->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->driver->get_update_mode) | ||
73 | mode = dssdev->driver->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->driver->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->driver->get_te ? | ||
110 | dssdev->driver->get_te(dssdev) : 0); | ||
111 | } | ||
112 | |||
113 | static ssize_t display_tear_store(struct device *dev, | ||
114 | struct device_attribute *attr, const char *buf, size_t size) | ||
115 | { | ||
116 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
117 | unsigned long te; | ||
118 | int r; | ||
119 | |||
120 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | ||
121 | return -ENOENT; | ||
122 | |||
123 | te = simple_strtoul(buf, NULL, 0); | ||
124 | |||
125 | r = dssdev->driver->enable_te(dssdev, te); | ||
126 | if (r) | ||
127 | return r; | ||
128 | |||
129 | return size; | ||
130 | } | ||
131 | |||
132 | static ssize_t display_timings_show(struct device *dev, | ||
133 | struct device_attribute *attr, char *buf) | ||
134 | { | ||
135 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
136 | struct omap_video_timings t; | ||
137 | |||
138 | if (!dssdev->driver->get_timings) | ||
139 | return -ENOENT; | ||
140 | |||
141 | dssdev->driver->get_timings(dssdev, &t); | ||
142 | |||
143 | return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n", | ||
144 | t.pixel_clock, | ||
145 | t.x_res, t.hfp, t.hbp, t.hsw, | ||
146 | t.y_res, t.vfp, t.vbp, t.vsw); | ||
147 | } | ||
148 | |||
149 | static ssize_t display_timings_store(struct device *dev, | ||
150 | struct device_attribute *attr, const char *buf, size_t size) | ||
151 | { | ||
152 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
153 | struct omap_video_timings t; | ||
154 | int r, found; | ||
155 | |||
156 | if (!dssdev->driver->set_timings || !dssdev->driver->check_timings) | ||
157 | return -ENOENT; | ||
158 | |||
159 | found = 0; | ||
160 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
161 | if (strncmp("pal", buf, 3) == 0) { | ||
162 | t = omap_dss_pal_timings; | ||
163 | found = 1; | ||
164 | } else if (strncmp("ntsc", buf, 4) == 0) { | ||
165 | t = omap_dss_ntsc_timings; | ||
166 | found = 1; | ||
167 | } | ||
168 | #endif | ||
169 | if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu", | ||
170 | &t.pixel_clock, | ||
171 | &t.x_res, &t.hfp, &t.hbp, &t.hsw, | ||
172 | &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9) | ||
173 | return -EINVAL; | ||
174 | |||
175 | r = dssdev->driver->check_timings(dssdev, &t); | ||
176 | if (r) | ||
177 | return r; | ||
178 | |||
179 | dssdev->driver->set_timings(dssdev, &t); | ||
180 | |||
181 | return size; | ||
182 | } | ||
183 | |||
184 | static ssize_t display_rotate_show(struct device *dev, | ||
185 | struct device_attribute *attr, char *buf) | ||
186 | { | ||
187 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
188 | int rotate; | ||
189 | if (!dssdev->driver->get_rotate) | ||
190 | return -ENOENT; | ||
191 | rotate = dssdev->driver->get_rotate(dssdev); | ||
192 | return snprintf(buf, PAGE_SIZE, "%u\n", rotate); | ||
193 | } | ||
194 | |||
195 | static ssize_t display_rotate_store(struct device *dev, | ||
196 | struct device_attribute *attr, const char *buf, size_t size) | ||
197 | { | ||
198 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
199 | unsigned long rot; | ||
200 | int r; | ||
201 | |||
202 | if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) | ||
203 | return -ENOENT; | ||
204 | |||
205 | rot = simple_strtoul(buf, NULL, 0); | ||
206 | |||
207 | r = dssdev->driver->set_rotate(dssdev, rot); | ||
208 | if (r) | ||
209 | return r; | ||
210 | |||
211 | return size; | ||
212 | } | ||
213 | |||
214 | static ssize_t display_mirror_show(struct device *dev, | ||
215 | struct device_attribute *attr, char *buf) | ||
216 | { | ||
217 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
218 | int mirror; | ||
219 | if (!dssdev->driver->get_mirror) | ||
220 | return -ENOENT; | ||
221 | mirror = dssdev->driver->get_mirror(dssdev); | ||
222 | return snprintf(buf, PAGE_SIZE, "%u\n", mirror); | ||
223 | } | ||
224 | |||
225 | static ssize_t display_mirror_store(struct device *dev, | ||
226 | struct device_attribute *attr, const char *buf, size_t size) | ||
227 | { | ||
228 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
229 | unsigned long mirror; | ||
230 | int r; | ||
231 | |||
232 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | ||
233 | return -ENOENT; | ||
234 | |||
235 | mirror = simple_strtoul(buf, NULL, 0); | ||
236 | |||
237 | r = dssdev->driver->set_mirror(dssdev, mirror); | ||
238 | if (r) | ||
239 | return r; | ||
240 | |||
241 | return size; | ||
242 | } | ||
243 | |||
244 | static ssize_t display_wss_show(struct device *dev, | ||
245 | struct device_attribute *attr, char *buf) | ||
246 | { | ||
247 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
248 | unsigned int wss; | ||
249 | |||
250 | if (!dssdev->driver->get_wss) | ||
251 | return -ENOENT; | ||
252 | |||
253 | wss = dssdev->driver->get_wss(dssdev); | ||
254 | |||
255 | return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss); | ||
256 | } | ||
257 | |||
258 | static ssize_t display_wss_store(struct device *dev, | ||
259 | struct device_attribute *attr, const char *buf, size_t size) | ||
260 | { | ||
261 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
262 | unsigned long wss; | ||
263 | int r; | ||
264 | |||
265 | if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) | ||
266 | return -ENOENT; | ||
267 | |||
268 | if (strict_strtoul(buf, 0, &wss)) | ||
269 | return -EINVAL; | ||
270 | |||
271 | if (wss > 0xfffff) | ||
272 | return -EINVAL; | ||
273 | |||
274 | r = dssdev->driver->set_wss(dssdev, wss); | ||
275 | if (r) | ||
276 | return r; | ||
277 | |||
278 | return size; | ||
279 | } | ||
280 | |||
281 | static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, | ||
282 | display_enabled_show, display_enabled_store); | ||
283 | static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR, | ||
284 | display_upd_mode_show, display_upd_mode_store); | ||
285 | static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, | ||
286 | display_tear_show, display_tear_store); | ||
287 | static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, | ||
288 | display_timings_show, display_timings_store); | ||
289 | static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, | ||
290 | display_rotate_show, display_rotate_store); | ||
291 | static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, | ||
292 | display_mirror_show, display_mirror_store); | ||
293 | static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, | ||
294 | display_wss_show, display_wss_store); | ||
295 | |||
296 | static struct device_attribute *display_sysfs_attrs[] = { | ||
297 | &dev_attr_enabled, | ||
298 | &dev_attr_update_mode, | ||
299 | &dev_attr_tear_elim, | ||
300 | &dev_attr_timings, | ||
301 | &dev_attr_rotate, | ||
302 | &dev_attr_mirror, | ||
303 | &dev_attr_wss, | ||
304 | NULL | ||
305 | }; | ||
306 | |||
307 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, | ||
308 | u16 *xres, u16 *yres) | ||
309 | { | ||
310 | *xres = dssdev->panel.timings.x_res; | ||
311 | *yres = dssdev->panel.timings.y_res; | ||
312 | } | ||
313 | EXPORT_SYMBOL(omapdss_default_get_resolution); | ||
314 | |||
315 | void default_get_overlay_fifo_thresholds(enum omap_plane plane, | ||
316 | u32 fifo_size, enum omap_burst_size *burst_size, | ||
317 | u32 *fifo_low, u32 *fifo_high) | ||
318 | { | ||
319 | unsigned burst_size_bytes; | ||
320 | |||
321 | *burst_size = OMAP_DSS_BURST_16x32; | ||
322 | burst_size_bytes = 16 * 32 / 8; | ||
323 | |||
324 | *fifo_high = fifo_size - 1; | ||
325 | *fifo_low = fifo_size - burst_size_bytes; | ||
326 | } | ||
327 | |||
328 | int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | ||
329 | { | ||
330 | switch (dssdev->type) { | ||
331 | case OMAP_DISPLAY_TYPE_DPI: | ||
332 | if (dssdev->phy.dpi.data_lines == 24) | ||
333 | return 24; | ||
334 | else | ||
335 | return 16; | ||
336 | |||
337 | case OMAP_DISPLAY_TYPE_DBI: | ||
338 | case OMAP_DISPLAY_TYPE_DSI: | ||
339 | if (dssdev->ctrl.pixel_size == 24) | ||
340 | return 24; | ||
341 | else | ||
342 | return 16; | ||
343 | case OMAP_DISPLAY_TYPE_VENC: | ||
344 | case OMAP_DISPLAY_TYPE_SDI: | ||
345 | return 24; | ||
346 | return 24; | ||
347 | default: | ||
348 | BUG(); | ||
349 | } | ||
350 | } | ||
351 | EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); | ||
352 | |||
353 | /* Checks if replication logic should be used. Only use for active matrix, | ||
354 | * when overlay is in RGB12U or RGB16 mode, and LCD interface is | ||
355 | * 18bpp or 24bpp */ | ||
356 | bool dss_use_replication(struct omap_dss_device *dssdev, | ||
357 | enum omap_color_mode mode) | ||
358 | { | ||
359 | int bpp; | ||
360 | |||
361 | if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) | ||
362 | return false; | ||
363 | |||
364 | if (dssdev->type == OMAP_DISPLAY_TYPE_DPI && | ||
365 | (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0) | ||
366 | return false; | ||
367 | |||
368 | switch (dssdev->type) { | ||
369 | case OMAP_DISPLAY_TYPE_DPI: | ||
370 | bpp = dssdev->phy.dpi.data_lines; | ||
371 | break; | ||
372 | case OMAP_DISPLAY_TYPE_VENC: | ||
373 | case OMAP_DISPLAY_TYPE_SDI: | ||
374 | bpp = 24; | ||
375 | break; | ||
376 | case OMAP_DISPLAY_TYPE_DBI: | ||
377 | case OMAP_DISPLAY_TYPE_DSI: | ||
378 | bpp = dssdev->ctrl.pixel_size; | ||
379 | break; | ||
380 | default: | ||
381 | BUG(); | ||
382 | } | ||
383 | |||
384 | return bpp > 16; | ||
385 | } | ||
386 | |||
387 | void dss_init_device(struct platform_device *pdev, | ||
388 | struct omap_dss_device *dssdev) | ||
389 | { | ||
390 | struct device_attribute *attr; | ||
391 | int i; | ||
392 | int r; | ||
393 | |||
394 | switch (dssdev->type) { | ||
395 | case OMAP_DISPLAY_TYPE_DPI: | ||
396 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
397 | case OMAP_DISPLAY_TYPE_DBI: | ||
398 | #endif | ||
399 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
400 | case OMAP_DISPLAY_TYPE_SDI: | ||
401 | #endif | ||
402 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
403 | case OMAP_DISPLAY_TYPE_DSI: | ||
404 | #endif | ||
405 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
406 | case OMAP_DISPLAY_TYPE_VENC: | ||
407 | #endif | ||
408 | break; | ||
409 | default: | ||
410 | DSSERR("Support for display '%s' not compiled in.\n", | ||
411 | dssdev->name); | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | switch (dssdev->type) { | ||
416 | case OMAP_DISPLAY_TYPE_DPI: | ||
417 | r = dpi_init_display(dssdev); | ||
418 | break; | ||
419 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
420 | case OMAP_DISPLAY_TYPE_DBI: | ||
421 | r = rfbi_init_display(dssdev); | ||
422 | break; | ||
423 | #endif | ||
424 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
425 | case OMAP_DISPLAY_TYPE_VENC: | ||
426 | r = venc_init_display(dssdev); | ||
427 | break; | ||
428 | #endif | ||
429 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
430 | case OMAP_DISPLAY_TYPE_SDI: | ||
431 | r = sdi_init_display(dssdev); | ||
432 | break; | ||
433 | #endif | ||
434 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
435 | case OMAP_DISPLAY_TYPE_DSI: | ||
436 | r = dsi_init_display(dssdev); | ||
437 | break; | ||
438 | #endif | ||
439 | default: | ||
440 | BUG(); | ||
441 | } | ||
442 | |||
443 | if (r) { | ||
444 | DSSERR("failed to init display %s\n", dssdev->name); | ||
445 | return; | ||
446 | } | ||
447 | |||
448 | /* create device sysfs files */ | ||
449 | i = 0; | ||
450 | while ((attr = display_sysfs_attrs[i++]) != NULL) { | ||
451 | r = device_create_file(&dssdev->dev, attr); | ||
452 | if (r) | ||
453 | DSSERR("failed to create sysfs file\n"); | ||
454 | } | ||
455 | |||
456 | /* create display? sysfs links */ | ||
457 | r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, | ||
458 | dev_name(&dssdev->dev)); | ||
459 | if (r) | ||
460 | DSSERR("failed to create sysfs display link\n"); | ||
461 | } | ||
462 | |||
463 | void dss_uninit_device(struct platform_device *pdev, | ||
464 | struct omap_dss_device *dssdev) | ||
465 | { | ||
466 | struct device_attribute *attr; | ||
467 | int i = 0; | ||
468 | |||
469 | sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev)); | ||
470 | |||
471 | while ((attr = display_sysfs_attrs[i++]) != NULL) | ||
472 | device_remove_file(&dssdev->dev, attr); | ||
473 | |||
474 | if (dssdev->manager) | ||
475 | dssdev->manager->unset_device(dssdev->manager); | ||
476 | } | ||
477 | |||
478 | static int dss_suspend_device(struct device *dev, void *data) | ||
479 | { | ||
480 | int r; | ||
481 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
482 | |||
483 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
484 | dssdev->activate_after_resume = false; | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | if (!dssdev->driver->suspend) { | ||
489 | DSSERR("display '%s' doesn't implement suspend\n", | ||
490 | dssdev->name); | ||
491 | return -ENOSYS; | ||
492 | } | ||
493 | |||
494 | r = dssdev->driver->suspend(dssdev); | ||
495 | if (r) | ||
496 | return r; | ||
497 | |||
498 | dssdev->activate_after_resume = true; | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | int dss_suspend_all_devices(void) | ||
504 | { | ||
505 | int r; | ||
506 | struct bus_type *bus = dss_get_bus(); | ||
507 | |||
508 | r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device); | ||
509 | if (r) { | ||
510 | /* resume all displays that were suspended */ | ||
511 | dss_resume_all_devices(); | ||
512 | return r; | ||
513 | } | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int dss_resume_device(struct device *dev, void *data) | ||
519 | { | ||
520 | int r; | ||
521 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
522 | |||
523 | if (dssdev->activate_after_resume && dssdev->driver->resume) { | ||
524 | r = dssdev->driver->resume(dssdev); | ||
525 | if (r) | ||
526 | return r; | ||
527 | } | ||
528 | |||
529 | dssdev->activate_after_resume = false; | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | int dss_resume_all_devices(void) | ||
535 | { | ||
536 | struct bus_type *bus = dss_get_bus(); | ||
537 | |||
538 | return bus_for_each_dev(bus, NULL, NULL, dss_resume_device); | ||
539 | } | ||
540 | |||
541 | static int dss_disable_device(struct device *dev, void *data) | ||
542 | { | ||
543 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
544 | dssdev->driver->disable(dssdev); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | void dss_disable_all_devices(void) | ||
549 | { | ||
550 | struct bus_type *bus = dss_get_bus(); | ||
551 | bus_for_each_dev(bus, NULL, NULL, dss_disable_device); | ||
552 | } | ||
553 | |||
554 | |||
555 | void omap_dss_get_device(struct omap_dss_device *dssdev) | ||
556 | { | ||
557 | get_device(&dssdev->dev); | ||
558 | } | ||
559 | EXPORT_SYMBOL(omap_dss_get_device); | ||
560 | |||
561 | void omap_dss_put_device(struct omap_dss_device *dssdev) | ||
562 | { | ||
563 | put_device(&dssdev->dev); | ||
564 | } | ||
565 | EXPORT_SYMBOL(omap_dss_put_device); | ||
566 | |||
567 | /* ref count of the found device is incremented. ref count | ||
568 | * of from-device is decremented. */ | ||
569 | struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) | ||
570 | { | ||
571 | struct device *dev; | ||
572 | struct device *dev_start = NULL; | ||
573 | struct omap_dss_device *dssdev = NULL; | ||
574 | |||
575 | int match(struct device *dev, void *data) | ||
576 | { | ||
577 | return 1; | ||
578 | } | ||
579 | |||
580 | if (from) | ||
581 | dev_start = &from->dev; | ||
582 | dev = bus_find_device(dss_get_bus(), dev_start, NULL, match); | ||
583 | if (dev) | ||
584 | dssdev = to_dss_device(dev); | ||
585 | if (from) | ||
586 | put_device(&from->dev); | ||
587 | |||
588 | return dssdev; | ||
589 | } | ||
590 | EXPORT_SYMBOL(omap_dss_get_next_device); | ||
591 | |||
592 | struct omap_dss_device *omap_dss_find_device(void *data, | ||
593 | int (*match)(struct omap_dss_device *dssdev, void *data)) | ||
594 | { | ||
595 | struct omap_dss_device *dssdev = NULL; | ||
596 | |||
597 | while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) { | ||
598 | if (match(dssdev, data)) | ||
599 | return dssdev; | ||
600 | } | ||
601 | |||
602 | return NULL; | ||
603 | } | ||
604 | EXPORT_SYMBOL(omap_dss_find_device); | ||
605 | |||
606 | int omap_dss_start_device(struct omap_dss_device *dssdev) | ||
607 | { | ||
608 | if (!dssdev->driver) { | ||
609 | DSSDBG("no driver\n"); | ||
610 | return -ENODEV; | ||
611 | } | ||
612 | |||
613 | if (!try_module_get(dssdev->dev.driver->owner)) { | ||
614 | return -ENODEV; | ||
615 | } | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | EXPORT_SYMBOL(omap_dss_start_device); | ||
620 | |||
621 | void omap_dss_stop_device(struct omap_dss_device *dssdev) | ||
622 | { | ||
623 | module_put(dssdev->dev.driver->owner); | ||
624 | } | ||
625 | EXPORT_SYMBOL(omap_dss_stop_device); | ||
626 | |||