aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc/tilcdc_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tilcdc/tilcdc_drv.c')
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c99
1 files changed, 73 insertions, 26 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 095fca91525c..0f283a3b932c 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -17,16 +17,17 @@
17 17
18/* LCDC DRM driver, based on da8xx-fb */ 18/* LCDC DRM driver, based on da8xx-fb */
19 19
20#include <linux/component.h>
21
20#include "tilcdc_drv.h" 22#include "tilcdc_drv.h"
21#include "tilcdc_regs.h" 23#include "tilcdc_regs.h"
22#include "tilcdc_tfp410.h" 24#include "tilcdc_tfp410.h"
23#include "tilcdc_slave.h"
24#include "tilcdc_panel.h" 25#include "tilcdc_panel.h"
26#include "tilcdc_external.h"
25 27
26#include "drm_fb_helper.h" 28#include "drm_fb_helper.h"
27 29
28static LIST_HEAD(module_list); 30static LIST_HEAD(module_list);
29static bool slave_probing;
30 31
31void tilcdc_module_init(struct tilcdc_module *mod, const char *name, 32void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
32 const struct tilcdc_module_ops *funcs) 33 const struct tilcdc_module_ops *funcs)
@@ -42,11 +43,6 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod)
42 list_del(&mod->list); 43 list_del(&mod->list);
43} 44}
44 45
45void tilcdc_slave_probedefer(bool defered)
46{
47 slave_probing = defered;
48}
49
50static struct of_device_id tilcdc_of_match[]; 46static struct of_device_id tilcdc_of_match[];
51 47
52static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, 48static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
@@ -80,13 +76,6 @@ static int modeset_init(struct drm_device *dev)
80 mod->funcs->modeset_init(mod, dev); 76 mod->funcs->modeset_init(mod, dev);
81 } 77 }
82 78
83 if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
84 /* oh nos! */
85 dev_err(dev->dev, "no encoders/connectors found\n");
86 drm_mode_config_cleanup(dev);
87 return -ENXIO;
88 }
89
90 dev->mode_config.min_width = 0; 79 dev->mode_config.min_width = 0;
91 dev->mode_config.min_height = 0; 80 dev->mode_config.min_height = 0;
92 dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc); 81 dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
@@ -121,6 +110,8 @@ static int tilcdc_unload(struct drm_device *dev)
121{ 110{
122 struct tilcdc_drm_private *priv = dev->dev_private; 111 struct tilcdc_drm_private *priv = dev->dev_private;
123 112
113 tilcdc_remove_external_encoders(dev);
114
124 drm_fbdev_cma_fini(priv->fbdev); 115 drm_fbdev_cma_fini(priv->fbdev);
125 drm_kms_helper_poll_fini(dev); 116 drm_kms_helper_poll_fini(dev);
126 drm_mode_config_cleanup(dev); 117 drm_mode_config_cleanup(dev);
@@ -171,6 +162,9 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
171 162
172 dev->dev_private = priv; 163 dev->dev_private = priv;
173 164
165 priv->is_componentized =
166 tilcdc_get_external_components(dev->dev, NULL) > 0;
167
174 priv->wq = alloc_ordered_workqueue("tilcdc", 0); 168 priv->wq = alloc_ordered_workqueue("tilcdc", 0);
175 if (!priv->wq) { 169 if (!priv->wq) {
176 ret = -ENOMEM; 170 ret = -ENOMEM;
@@ -233,6 +227,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
233 DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); 227 DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
234 228
235 pm_runtime_enable(dev->dev); 229 pm_runtime_enable(dev->dev);
230 pm_runtime_irq_safe(dev->dev);
236 231
237 /* Determine LCD IP Version */ 232 /* Determine LCD IP Version */
238 pm_runtime_get_sync(dev->dev); 233 pm_runtime_get_sync(dev->dev);
@@ -260,10 +255,28 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
260 goto fail_cpufreq_unregister; 255 goto fail_cpufreq_unregister;
261 } 256 }
262 257
258 platform_set_drvdata(pdev, dev);
259
260 if (priv->is_componentized) {
261 ret = component_bind_all(dev->dev, dev);
262 if (ret < 0)
263 goto fail_mode_config_cleanup;
264
265 ret = tilcdc_add_external_encoders(dev, &bpp);
266 if (ret < 0)
267 goto fail_component_cleanup;
268 }
269
270 if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
271 dev_err(dev->dev, "no encoders/connectors found\n");
272 ret = -ENXIO;
273 goto fail_external_cleanup;
274 }
275
263 ret = drm_vblank_init(dev, 1); 276 ret = drm_vblank_init(dev, 1);
264 if (ret < 0) { 277 if (ret < 0) {
265 dev_err(dev->dev, "failed to initialize vblank\n"); 278 dev_err(dev->dev, "failed to initialize vblank\n");
266 goto fail_mode_config_cleanup; 279 goto fail_external_cleanup;
267 } 280 }
268 281
269 pm_runtime_get_sync(dev->dev); 282 pm_runtime_get_sync(dev->dev);
@@ -274,9 +287,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
274 goto fail_vblank_cleanup; 287 goto fail_vblank_cleanup;
275 } 288 }
276 289
277 platform_set_drvdata(pdev, dev);
278
279
280 list_for_each_entry(mod, &module_list, list) { 290 list_for_each_entry(mod, &module_list, list) {
281 DBG("%s: preferred_bpp: %d", mod->name, mod->preferred_bpp); 291 DBG("%s: preferred_bpp: %d", mod->name, mod->preferred_bpp);
282 bpp = mod->preferred_bpp; 292 bpp = mod->preferred_bpp;
@@ -307,6 +317,13 @@ fail_vblank_cleanup:
307fail_mode_config_cleanup: 317fail_mode_config_cleanup:
308 drm_mode_config_cleanup(dev); 318 drm_mode_config_cleanup(dev);
309 319
320fail_component_cleanup:
321 if (priv->is_componentized)
322 component_unbind_all(dev->dev, dev);
323
324fail_external_cleanup:
325 tilcdc_remove_external_encoders(dev);
326
310fail_cpufreq_unregister: 327fail_cpufreq_unregister:
311 pm_runtime_disable(dev->dev); 328 pm_runtime_disable(dev->dev);
312#ifdef CONFIG_CPU_FREQ 329#ifdef CONFIG_CPU_FREQ
@@ -612,24 +629,56 @@ static const struct dev_pm_ops tilcdc_pm_ops = {
612 * Platform driver: 629 * Platform driver:
613 */ 630 */
614 631
632static int tilcdc_bind(struct device *dev)
633{
634 return drm_platform_init(&tilcdc_driver, to_platform_device(dev));
635}
636
637static void tilcdc_unbind(struct device *dev)
638{
639 drm_put_dev(dev_get_drvdata(dev));
640}
641
642static const struct component_master_ops tilcdc_comp_ops = {
643 .bind = tilcdc_bind,
644 .unbind = tilcdc_unbind,
645};
646
615static int tilcdc_pdev_probe(struct platform_device *pdev) 647static int tilcdc_pdev_probe(struct platform_device *pdev)
616{ 648{
649 struct component_match *match = NULL;
650 int ret;
651
617 /* bail out early if no DT data: */ 652 /* bail out early if no DT data: */
618 if (!pdev->dev.of_node) { 653 if (!pdev->dev.of_node) {
619 dev_err(&pdev->dev, "device-tree data is missing\n"); 654 dev_err(&pdev->dev, "device-tree data is missing\n");
620 return -ENXIO; 655 return -ENXIO;
621 } 656 }
622 657
623 /* defer probing if slave is in deferred probing */ 658 ret = tilcdc_get_external_components(&pdev->dev, &match);
624 if (slave_probing == true) 659 if (ret < 0)
625 return -EPROBE_DEFER; 660 return ret;
626 661 else if (ret == 0)
627 return drm_platform_init(&tilcdc_driver, pdev); 662 return drm_platform_init(&tilcdc_driver, pdev);
663 else
664 return component_master_add_with_match(&pdev->dev,
665 &tilcdc_comp_ops,
666 match);
628} 667}
629 668
630static int tilcdc_pdev_remove(struct platform_device *pdev) 669static int tilcdc_pdev_remove(struct platform_device *pdev)
631{ 670{
632 drm_put_dev(platform_get_drvdata(pdev)); 671 struct drm_device *ddev = dev_get_drvdata(&pdev->dev);
672 struct tilcdc_drm_private *priv = ddev->dev_private;
673
674 /* Check if a subcomponent has already triggered the unloading. */
675 if (!priv)
676 return 0;
677
678 if (priv->is_componentized)
679 component_master_del(&pdev->dev, &tilcdc_comp_ops);
680 else
681 drm_put_dev(platform_get_drvdata(pdev));
633 682
634 return 0; 683 return 0;
635} 684}
@@ -654,7 +703,6 @@ static int __init tilcdc_drm_init(void)
654{ 703{
655 DBG("init"); 704 DBG("init");
656 tilcdc_tfp410_init(); 705 tilcdc_tfp410_init();
657 tilcdc_slave_init();
658 tilcdc_panel_init(); 706 tilcdc_panel_init();
659 return platform_driver_register(&tilcdc_platform_driver); 707 return platform_driver_register(&tilcdc_platform_driver);
660} 708}
@@ -664,7 +712,6 @@ static void __exit tilcdc_drm_fini(void)
664 DBG("fini"); 712 DBG("fini");
665 platform_driver_unregister(&tilcdc_platform_driver); 713 platform_driver_unregister(&tilcdc_platform_driver);
666 tilcdc_panel_fini(); 714 tilcdc_panel_fini();
667 tilcdc_slave_fini();
668 tilcdc_tfp410_fini(); 715 tilcdc_tfp410_fini();
669} 716}
670 717