diff options
Diffstat (limited to 'drivers/video/omap2/dss/core.c')
-rw-r--r-- | drivers/video/omap2/dss/core.c | 255 |
1 files changed, 152 insertions, 103 deletions
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e8a120771ac6..72ded9cd2cb0 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -43,6 +43,8 @@ static struct { | |||
43 | 43 | ||
44 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
45 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
46 | |||
47 | const char *default_display_name; | ||
46 | } core; | 48 | } core; |
47 | 49 | ||
48 | static char *def_disp_name; | 50 | static char *def_disp_name; |
@@ -54,9 +56,6 @@ bool dss_debug; | |||
54 | module_param_named(debug, dss_debug, bool, 0644); | 56 | module_param_named(debug, dss_debug, bool, 0644); |
55 | #endif | 57 | #endif |
56 | 58 | ||
57 | static int omap_dss_register_device(struct omap_dss_device *); | ||
58 | static void omap_dss_unregister_device(struct omap_dss_device *); | ||
59 | |||
60 | /* REGULATORS */ | 59 | /* REGULATORS */ |
61 | 60 | ||
62 | struct regulator *dss_get_vdds_dsi(void) | 61 | struct regulator *dss_get_vdds_dsi(void) |
@@ -87,6 +86,51 @@ struct regulator *dss_get_vdds_sdi(void) | |||
87 | return reg; | 86 | return reg; |
88 | } | 87 | } |
89 | 88 | ||
89 | int dss_get_ctx_loss_count(struct device *dev) | ||
90 | { | ||
91 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
92 | int cnt; | ||
93 | |||
94 | if (!board_data->get_context_loss_count) | ||
95 | return -ENOENT; | ||
96 | |||
97 | cnt = board_data->get_context_loss_count(dev); | ||
98 | |||
99 | WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); | ||
100 | |||
101 | return cnt; | ||
102 | } | ||
103 | |||
104 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) | ||
105 | { | ||
106 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
107 | |||
108 | if (!board_data->dsi_enable_pads) | ||
109 | return -ENOENT; | ||
110 | |||
111 | return board_data->dsi_enable_pads(dsi_id, lane_mask); | ||
112 | } | ||
113 | |||
114 | void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask) | ||
115 | { | ||
116 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
117 | |||
118 | if (!board_data->dsi_enable_pads) | ||
119 | return; | ||
120 | |||
121 | return board_data->dsi_disable_pads(dsi_id, lane_mask); | ||
122 | } | ||
123 | |||
124 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput) | ||
125 | { | ||
126 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
127 | |||
128 | if (pdata->set_min_bus_tput) | ||
129 | return pdata->set_min_bus_tput(dev, tput); | ||
130 | else | ||
131 | return 0; | ||
132 | } | ||
133 | |||
90 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 134 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
91 | static int dss_debug_show(struct seq_file *s, void *unused) | 135 | static int dss_debug_show(struct seq_file *s, void *unused) |
92 | { | 136 | { |
@@ -121,34 +165,6 @@ static int dss_initialize_debugfs(void) | |||
121 | debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, | 165 | debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, |
122 | &dss_debug_dump_clocks, &dss_debug_fops); | 166 | &dss_debug_dump_clocks, &dss_debug_fops); |
123 | 167 | ||
124 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
125 | debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, | ||
126 | &dispc_dump_irqs, &dss_debug_fops); | ||
127 | #endif | ||
128 | |||
129 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) | ||
130 | dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); | ||
131 | #endif | ||
132 | |||
133 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, | ||
134 | &dss_dump_regs, &dss_debug_fops); | ||
135 | debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, | ||
136 | &dispc_dump_regs, &dss_debug_fops); | ||
137 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
138 | debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, | ||
139 | &rfbi_dump_regs, &dss_debug_fops); | ||
140 | #endif | ||
141 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
142 | dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); | ||
143 | #endif | ||
144 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | ||
146 | &venc_dump_regs, &dss_debug_fops); | ||
147 | #endif | ||
148 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
149 | debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, | ||
150 | &hdmi_dump_regs, &dss_debug_fops); | ||
151 | #endif | ||
152 | return 0; | 168 | return 0; |
153 | } | 169 | } |
154 | 170 | ||
@@ -157,6 +173,19 @@ static void dss_uninitialize_debugfs(void) | |||
157 | if (dss_debugfs_dir) | 173 | if (dss_debugfs_dir) |
158 | debugfs_remove_recursive(dss_debugfs_dir); | 174 | debugfs_remove_recursive(dss_debugfs_dir); |
159 | } | 175 | } |
176 | |||
177 | int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) | ||
178 | { | ||
179 | struct dentry *d; | ||
180 | |||
181 | d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, | ||
182 | write, &dss_debug_fops); | ||
183 | |||
184 | if (IS_ERR(d)) | ||
185 | return PTR_ERR(d); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
160 | #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ | 189 | #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ |
161 | static inline int dss_initialize_debugfs(void) | 190 | static inline int dss_initialize_debugfs(void) |
162 | { | 191 | { |
@@ -165,14 +194,18 @@ static inline int dss_initialize_debugfs(void) | |||
165 | static inline void dss_uninitialize_debugfs(void) | 194 | static inline void dss_uninitialize_debugfs(void) |
166 | { | 195 | { |
167 | } | 196 | } |
197 | static inline int dss_debugfs_create_file(const char *name, | ||
198 | void (*write)(struct seq_file *)) | ||
199 | { | ||
200 | return 0; | ||
201 | } | ||
168 | #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ | 202 | #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ |
169 | 203 | ||
170 | /* PLATFORM DEVICE */ | 204 | /* PLATFORM DEVICE */ |
171 | static int omap_dss_probe(struct platform_device *pdev) | 205 | static int __init omap_dss_probe(struct platform_device *pdev) |
172 | { | 206 | { |
173 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 207 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
174 | int r; | 208 | int r; |
175 | int i; | ||
176 | 209 | ||
177 | core.pdev = pdev; | 210 | core.pdev = pdev; |
178 | 211 | ||
@@ -187,28 +220,13 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
187 | if (r) | 220 | if (r) |
188 | goto err_debugfs; | 221 | goto err_debugfs; |
189 | 222 | ||
190 | for (i = 0; i < pdata->num_devices; ++i) { | 223 | if (def_disp_name) |
191 | struct omap_dss_device *dssdev = pdata->devices[i]; | 224 | core.default_display_name = def_disp_name; |
192 | 225 | else if (pdata->default_device) | |
193 | r = omap_dss_register_device(dssdev); | 226 | core.default_display_name = pdata->default_device->name; |
194 | if (r) { | ||
195 | DSSERR("device %d %s register failed %d\n", i, | ||
196 | dssdev->name ?: "unnamed", r); | ||
197 | |||
198 | while (--i >= 0) | ||
199 | omap_dss_unregister_device(pdata->devices[i]); | ||
200 | |||
201 | goto err_register; | ||
202 | } | ||
203 | |||
204 | if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) | ||
205 | pdata->default_device = dssdev; | ||
206 | } | ||
207 | 227 | ||
208 | return 0; | 228 | return 0; |
209 | 229 | ||
210 | err_register: | ||
211 | dss_uninitialize_debugfs(); | ||
212 | err_debugfs: | 230 | err_debugfs: |
213 | 231 | ||
214 | return r; | 232 | return r; |
@@ -216,17 +234,11 @@ err_debugfs: | |||
216 | 234 | ||
217 | static int omap_dss_remove(struct platform_device *pdev) | 235 | static int omap_dss_remove(struct platform_device *pdev) |
218 | { | 236 | { |
219 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
220 | int i; | ||
221 | |||
222 | dss_uninitialize_debugfs(); | 237 | dss_uninitialize_debugfs(); |
223 | 238 | ||
224 | dss_uninit_overlays(pdev); | 239 | dss_uninit_overlays(pdev); |
225 | dss_uninit_overlay_managers(pdev); | 240 | dss_uninit_overlay_managers(pdev); |
226 | 241 | ||
227 | for (i = 0; i < pdata->num_devices; ++i) | ||
228 | omap_dss_unregister_device(pdata->devices[i]); | ||
229 | |||
230 | return 0; | 242 | return 0; |
231 | } | 243 | } |
232 | 244 | ||
@@ -251,7 +263,6 @@ static int omap_dss_resume(struct platform_device *pdev) | |||
251 | } | 263 | } |
252 | 264 | ||
253 | static struct platform_driver omap_dss_driver = { | 265 | static struct platform_driver omap_dss_driver = { |
254 | .probe = omap_dss_probe, | ||
255 | .remove = omap_dss_remove, | 266 | .remove = omap_dss_remove, |
256 | .shutdown = omap_dss_shutdown, | 267 | .shutdown = omap_dss_shutdown, |
257 | .suspend = omap_dss_suspend, | 268 | .suspend = omap_dss_suspend, |
@@ -326,7 +337,6 @@ static int dss_driver_probe(struct device *dev) | |||
326 | int r; | 337 | int r; |
327 | struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); | 338 | struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); |
328 | struct omap_dss_device *dssdev = to_dss_device(dev); | 339 | struct omap_dss_device *dssdev = to_dss_device(dev); |
329 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
330 | bool force; | 340 | bool force; |
331 | 341 | ||
332 | DSSDBG("driver_probe: dev %s/%s, drv %s\n", | 342 | DSSDBG("driver_probe: dev %s/%s, drv %s\n", |
@@ -335,7 +345,8 @@ static int dss_driver_probe(struct device *dev) | |||
335 | 345 | ||
336 | dss_init_device(core.pdev, dssdev); | 346 | dss_init_device(core.pdev, dssdev); |
337 | 347 | ||
338 | force = pdata->default_device == dssdev; | 348 | force = core.default_display_name && |
349 | strcmp(core.default_display_name, dssdev->name) == 0; | ||
339 | dss_recheck_connections(dssdev, force); | 350 | dss_recheck_connections(dssdev, force); |
340 | 351 | ||
341 | r = dssdrv->probe(dssdev); | 352 | r = dssdrv->probe(dssdev); |
@@ -381,6 +392,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver) | |||
381 | if (dssdriver->get_recommended_bpp == NULL) | 392 | if (dssdriver->get_recommended_bpp == NULL) |
382 | dssdriver->get_recommended_bpp = | 393 | dssdriver->get_recommended_bpp = |
383 | omapdss_default_get_recommended_bpp; | 394 | omapdss_default_get_recommended_bpp; |
395 | if (dssdriver->get_timings == NULL) | ||
396 | dssdriver->get_timings = omapdss_default_get_timings; | ||
384 | 397 | ||
385 | return driver_register(&dssdriver->driver); | 398 | return driver_register(&dssdriver->driver); |
386 | } | 399 | } |
@@ -427,27 +440,38 @@ static void omap_dss_dev_release(struct device *dev) | |||
427 | reset_device(dev, 0); | 440 | reset_device(dev, 0); |
428 | } | 441 | } |
429 | 442 | ||
430 | static int omap_dss_register_device(struct omap_dss_device *dssdev) | 443 | int omap_dss_register_device(struct omap_dss_device *dssdev, |
444 | struct device *parent, int disp_num) | ||
431 | { | 445 | { |
432 | static int dev_num; | ||
433 | |||
434 | WARN_ON(!dssdev->driver_name); | 446 | WARN_ON(!dssdev->driver_name); |
435 | 447 | ||
436 | reset_device(&dssdev->dev, 1); | 448 | reset_device(&dssdev->dev, 1); |
437 | dssdev->dev.bus = &dss_bus_type; | 449 | dssdev->dev.bus = &dss_bus_type; |
438 | dssdev->dev.parent = &dss_bus; | 450 | dssdev->dev.parent = parent; |
439 | dssdev->dev.release = omap_dss_dev_release; | 451 | dssdev->dev.release = omap_dss_dev_release; |
440 | dev_set_name(&dssdev->dev, "display%d", dev_num++); | 452 | dev_set_name(&dssdev->dev, "display%d", disp_num); |
441 | return device_register(&dssdev->dev); | 453 | return device_register(&dssdev->dev); |
442 | } | 454 | } |
443 | 455 | ||
444 | static void omap_dss_unregister_device(struct omap_dss_device *dssdev) | 456 | void omap_dss_unregister_device(struct omap_dss_device *dssdev) |
445 | { | 457 | { |
446 | device_unregister(&dssdev->dev); | 458 | device_unregister(&dssdev->dev); |
447 | } | 459 | } |
448 | 460 | ||
461 | static int dss_unregister_dss_dev(struct device *dev, void *data) | ||
462 | { | ||
463 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
464 | omap_dss_unregister_device(dssdev); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | void omap_dss_unregister_child_devices(struct device *parent) | ||
469 | { | ||
470 | device_for_each_child(parent, NULL, dss_unregister_dss_dev); | ||
471 | } | ||
472 | |||
449 | /* BUS */ | 473 | /* BUS */ |
450 | static int omap_dss_bus_register(void) | 474 | static int __init omap_dss_bus_register(void) |
451 | { | 475 | { |
452 | int r; | 476 | int r; |
453 | 477 | ||
@@ -469,12 +493,56 @@ static int omap_dss_bus_register(void) | |||
469 | } | 493 | } |
470 | 494 | ||
471 | /* INIT */ | 495 | /* INIT */ |
496 | static int (*dss_output_drv_reg_funcs[])(void) __initdata = { | ||
497 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
498 | dpi_init_platform_driver, | ||
499 | #endif | ||
500 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
501 | sdi_init_platform_driver, | ||
502 | #endif | ||
503 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
504 | rfbi_init_platform_driver, | ||
505 | #endif | ||
506 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
507 | venc_init_platform_driver, | ||
508 | #endif | ||
509 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
510 | dsi_init_platform_driver, | ||
511 | #endif | ||
512 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
513 | hdmi_init_platform_driver, | ||
514 | #endif | ||
515 | }; | ||
516 | |||
517 | static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { | ||
518 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
519 | dpi_uninit_platform_driver, | ||
520 | #endif | ||
521 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
522 | sdi_uninit_platform_driver, | ||
523 | #endif | ||
524 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
525 | rfbi_uninit_platform_driver, | ||
526 | #endif | ||
527 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
528 | venc_uninit_platform_driver, | ||
529 | #endif | ||
530 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
531 | dsi_uninit_platform_driver, | ||
532 | #endif | ||
533 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
534 | hdmi_uninit_platform_driver, | ||
535 | #endif | ||
536 | }; | ||
537 | |||
538 | static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)]; | ||
472 | 539 | ||
473 | static int __init omap_dss_register_drivers(void) | 540 | static int __init omap_dss_register_drivers(void) |
474 | { | 541 | { |
475 | int r; | 542 | int r; |
543 | int i; | ||
476 | 544 | ||
477 | r = platform_driver_register(&omap_dss_driver); | 545 | r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); |
478 | if (r) | 546 | if (r) |
479 | return r; | 547 | return r; |
480 | 548 | ||
@@ -490,40 +558,18 @@ static int __init omap_dss_register_drivers(void) | |||
490 | goto err_dispc; | 558 | goto err_dispc; |
491 | } | 559 | } |
492 | 560 | ||
493 | r = rfbi_init_platform_driver(); | 561 | /* |
494 | if (r) { | 562 | * It's ok if the output-driver register fails. It happens, for example, |
495 | DSSERR("Failed to initialize rfbi platform driver\n"); | 563 | * when there is no output-device (e.g. SDI for OMAP4). |
496 | goto err_rfbi; | 564 | */ |
497 | } | 565 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { |
498 | 566 | r = dss_output_drv_reg_funcs[i](); | |
499 | r = venc_init_platform_driver(); | 567 | if (r == 0) |
500 | if (r) { | 568 | dss_output_drv_loaded[i] = true; |
501 | DSSERR("Failed to initialize venc platform driver\n"); | ||
502 | goto err_venc; | ||
503 | } | ||
504 | |||
505 | r = dsi_init_platform_driver(); | ||
506 | if (r) { | ||
507 | DSSERR("Failed to initialize DSI platform driver\n"); | ||
508 | goto err_dsi; | ||
509 | } | ||
510 | |||
511 | r = hdmi_init_platform_driver(); | ||
512 | if (r) { | ||
513 | DSSERR("Failed to initialize hdmi\n"); | ||
514 | goto err_hdmi; | ||
515 | } | 569 | } |
516 | 570 | ||
517 | return 0; | 571 | return 0; |
518 | 572 | ||
519 | err_hdmi: | ||
520 | dsi_uninit_platform_driver(); | ||
521 | err_dsi: | ||
522 | venc_uninit_platform_driver(); | ||
523 | err_venc: | ||
524 | rfbi_uninit_platform_driver(); | ||
525 | err_rfbi: | ||
526 | dispc_uninit_platform_driver(); | ||
527 | err_dispc: | 573 | err_dispc: |
528 | dss_uninit_platform_driver(); | 574 | dss_uninit_platform_driver(); |
529 | err_dss: | 575 | err_dss: |
@@ -534,10 +580,13 @@ err_dss: | |||
534 | 580 | ||
535 | static void __exit omap_dss_unregister_drivers(void) | 581 | static void __exit omap_dss_unregister_drivers(void) |
536 | { | 582 | { |
537 | hdmi_uninit_platform_driver(); | 583 | int i; |
538 | dsi_uninit_platform_driver(); | 584 | |
539 | venc_uninit_platform_driver(); | 585 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) { |
540 | rfbi_uninit_platform_driver(); | 586 | if (dss_output_drv_loaded[i]) |
587 | dss_output_drv_unreg_funcs[i](); | ||
588 | } | ||
589 | |||
541 | dispc_uninit_platform_driver(); | 590 | dispc_uninit_platform_driver(); |
542 | dss_uninit_platform_driver(); | 591 | dss_uninit_platform_driver(); |
543 | 592 | ||