imx-drm: convert to componentised device support
[deliverable/linux.git] / drivers / staging / imx-drm / imx-drm-core.c
index 7f14ed0400729cd8f0ccf3ad306014052d6ebb66..82b0337096b073803c456240f949af34d6424e4f 100644 (file)
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/component.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <drm/drmP.h>
@@ -90,6 +90,8 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 {
        struct imx_drm_device *imxdrm = drm->dev_private;
 
+       component_unbind_all(drm->dev, drm);
+
        imx_drm_device_put();
 
        drm_vblank_cleanup(drm);
@@ -111,32 +113,30 @@ struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
        return NULL;
 }
 
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
                u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
        struct imx_drm_crtc_helper_funcs *helper;
        struct imx_drm_crtc *imx_crtc;
 
-       imx_crtc = imx_drm_find_crtc(crtc);
+       imx_crtc = imx_drm_find_crtc(encoder->crtc);
        if (!imx_crtc)
                return -EINVAL;
 
        helper = &imx_crtc->imx_drm_helper_funcs;
        if (helper->set_interface_pix_fmt)
-               return helper->set_interface_pix_fmt(crtc,
-                               encoder_type, interface_pix_fmt,
+               return helper->set_interface_pix_fmt(encoder->crtc,
+                               encoder->encoder_type, interface_pix_fmt,
                                hsync_pin, vsync_pin);
        return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
 
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
-               u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
 {
-       return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
-                                             interface_pix_fmt, 2, 3);
+       return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format);
 
 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
 {
@@ -373,11 +373,8 @@ static void imx_drm_connector_unregister(
 }
 
 /*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
  */
 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 {
@@ -430,8 +427,15 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 
        platform_set_drvdata(drm->platformdev, drm);
        mutex_unlock(&imxdrm->mutex);
+
+       /* Now try and bind all our sub-components */
+       ret = component_bind_all(drm->dev, drm);
+       if (ret)
+               goto err_relock;
        return 0;
 
+err_relock:
+       mutex_lock(&imxdrm->mutex);
 err_vblank:
        drm_vblank_cleanup(drm);
 err_kms:
@@ -811,6 +815,70 @@ static struct drm_driver imx_drm_driver = {
        .patchlevel             = 0,
 };
 
+static int compare_parent_of(struct device *dev, void *data)
+{
+       struct of_phandle_args *args = data;
+       return dev->parent && dev->parent->of_node == args->np;
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+       return dev->of_node == data;
+}
+
+static int imx_drm_add_components(struct device *master, struct master *m)
+{
+       struct device_node *np = master->of_node;
+       unsigned i;
+       int ret;
+
+       for (i = 0; ; i++) {
+               struct of_phandle_args args;
+
+               ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+                                                      i, &args);
+               if (ret)
+                       break;
+
+               ret = component_master_add_child(m, compare_parent_of, &args);
+               of_node_put(args.np);
+
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; ; i++) {
+               struct device_node *node;
+
+               node = of_parse_phandle(np, "connectors", i);
+               if (!node)
+                       break;
+
+               ret = component_master_add_child(m, compare_of, node);
+               of_node_put(node);
+
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int imx_drm_bind(struct device *dev)
+{
+       return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
+
+static void imx_drm_unbind(struct device *dev)
+{
+       drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops imx_drm_ops = {
+       .add_components = imx_drm_add_components,
+       .bind = imx_drm_bind,
+       .unbind = imx_drm_unbind,
+};
+
 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
        int ret;
@@ -821,27 +889,31 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
 
        imx_drm_device->dev = &pdev->dev;
 
-       return drm_platform_init(&imx_drm_driver, pdev);
+       return component_master_add(&pdev->dev, &imx_drm_ops);
 }
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
 {
-       drm_put_dev(platform_get_drvdata(pdev));
-
+       component_master_del(&pdev->dev, &imx_drm_ops);
        return 0;
 }
 
+static const struct of_device_id imx_drm_dt_ids[] = {
+       { .compatible = "fsl,imx-drm", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
 static struct platform_driver imx_drm_pdrv = {
        .probe          = imx_drm_platform_probe,
        .remove         = imx_drm_platform_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "imx-drm",
+               .of_match_table = imx_drm_dt_ids,
        },
 };
 
-static struct platform_device *imx_drm_pdev;
-
 static int __init imx_drm_init(void)
 {
        int ret;
@@ -854,12 +926,6 @@ static int __init imx_drm_init(void)
        INIT_LIST_HEAD(&imx_drm_device->connector_list);
        INIT_LIST_HEAD(&imx_drm_device->encoder_list);
 
-       imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
-       if (IS_ERR(imx_drm_pdev)) {
-               ret = PTR_ERR(imx_drm_pdev);
-               goto err_pdev;
-       }
-
        ret = platform_driver_register(&imx_drm_pdrv);
        if (ret)
                goto err_pdrv;
@@ -867,8 +933,6 @@ static int __init imx_drm_init(void)
        return 0;
 
 err_pdrv:
-       platform_device_unregister(imx_drm_pdev);
-err_pdev:
        kfree(imx_drm_device);
 
        return ret;
@@ -876,7 +940,6 @@ err_pdev:
 
 static void __exit imx_drm_exit(void)
 {
-       platform_device_unregister(imx_drm_pdev);
        platform_driver_unregister(&imx_drm_pdrv);
 
        kfree(imx_drm_device);
This page took 0.041749 seconds and 5 git commands to generate.