]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
drm: xilinx: drv: Use component framework
authorHyun Kwon <hyun.kwon@xilinx.com>
Thu, 2 Feb 2017 19:00:56 +0000 (00:30 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 3 Feb 2017 09:41:23 +0000 (10:41 +0100)
Add support for the component framework for additional encoders.
Encoder / connector drivers with component framework will work
with Xilin DRM.

Signed-off-by: Hyun Kwon <hyun.kwon@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Hyun Kwon <hyunk@xilinx.com
drivers/gpu/drm/xilinx/xilinx_drm_drv.c

index 4c38954263c3b1ee85a9e709a45ae17970f280f5..23f60de87bc2cab44da0c8bee5de579130839707 100644 (file)
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
+#include <linux/component.h>
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/of_graph.h>
 #include <linux/platform_device.h>
 
 #include "xilinx_drm_connector.h"
@@ -267,14 +269,40 @@ unsigned int xilinx_drm_format_depth(uint32_t drm_format)
        return 0;
 }
 
+static int xilinx_drm_bind(struct device *dev)
+{
+       struct xilinx_drm_private *private = dev_get_drvdata(dev);
+       struct drm_device *drm = private->drm;
+
+       return component_bind_all(dev, drm);
+}
+
+static void xilinx_drm_unbind(struct device *dev)
+{
+       dev_set_drvdata(dev, NULL);
+}
+
+static const struct component_master_ops xilinx_drm_ops = {
+       .bind   = xilinx_drm_bind,
+       .unbind = xilinx_drm_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+       struct device_node *np = data;
+
+       return dev->of_node == np;
+}
+
 /* load xilinx drm */
 static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
 {
        struct xilinx_drm_private *private;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct device_node *encoder_node;
+       struct device_node *encoder_node, *ep = NULL, *remote;
        struct platform_device *pdev = drm->platformdev;
+       struct component_match *match = NULL;
        unsigned int bpp, align, i = 0;
        int ret;
 
@@ -312,6 +340,23 @@ static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
                i++;
        }
 
+       while (1) {
+               ep = of_graph_get_next_endpoint(drm->dev->of_node, ep);
+               if (!ep)
+                       break;
+
+               of_node_put(ep);
+               remote = of_graph_get_remote_port_parent(ep);
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
+                       continue;
+               }
+
+               component_match_add(drm->dev, &match, compare_of, remote);
+               of_node_put(remote);
+               i++;
+       }
+
        if (i == 0) {
                DRM_ERROR("failed to get an encoder slave node\n");
                return -ENODEV;
@@ -320,7 +365,7 @@ static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
        ret = drm_vblank_init(drm, 1);
        if (ret) {
                dev_err(&pdev->dev, "failed to initialize vblank\n");
-               goto err_out;
+               goto err_master;
        }
 
        /* enable irq to enable vblank feature */
@@ -347,10 +392,19 @@ static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
 
        platform_set_drvdata(pdev, private);
 
+       if (match) {
+               ret = component_master_add_with_match(drm->dev,
+                                                     &xilinx_drm_ops, match);
+               if (ret)
+                       goto err_fb;
+       }
+
        return 0;
 
 err_fb:
        drm_vblank_cleanup(drm);
+err_master:
+       component_master_del(drm->dev, &xilinx_drm_ops);
 err_out:
        drm_mode_config_cleanup(drm);
        if (ret == -EPROBE_DEFER)
@@ -364,11 +418,9 @@ static int xilinx_drm_unload(struct drm_device *drm)
        struct xilinx_drm_private *private = drm->dev_private;
 
        drm_vblank_cleanup(drm);
-
+       component_master_del(drm->dev, &xilinx_drm_ops);
        drm_kms_helper_poll_fini(drm);
-
        xilinx_drm_fb_fini(private->fb);
-
        drm_mode_config_cleanup(drm);
 
        return 0;