drm/exynos: vidi: add component support
authorInki Dae <inki.dae@samsung.com>
Mon, 24 Nov 2014 05:55:41 +0000 (14:55 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 25 Nov 2014 02:58:37 +0000 (11:58 +0900)
This patch adds component support for vidi driver.

vidi driver is a kms driver so it doesn't need to be registered
to exynos_drm_subdrv_list. For this, it changes for the component
framework to be used for vidi driver.

This patch fixes below error also,

# echo 1 > /sys/devices/platform/exynos-drm-vidi/connection
[   55.618529] ------------[ cut here ]------------
[   55.621960] WARNING: CPU: 0 PID: 1397 at drivers/gpu/drm/drm_irq.c:1203 exynos_drm_crtc_dpms+0x88/0x17c()
[   55.631268] Modules linked in:
[   55.634278] CPU: 0 PID: 1397 Comm: sh Not tainted 3.18.0-rc2-146253-g31449d7 #1154
[   55.641885] [<c0014400>] (unwind_backtrace) from [<c0011570>] (show_stack+0x10/0x14)
[   55.649597] [<c0011570>] (show_stack) from [<c04764f4>] (dump_stack+0x84/0xc4)
[   55.656802] [<c04764f4>] (dump_stack) from [<c00218b8>] (warn_slowpath_common+0x6c/0x88)
[   55.664866] [<c00218b8>] (warn_slowpath_common) from [<c0021970>] (warn_slowpath_null+0x1c/0x24)
[   55.673632] [<c0021970>] (warn_slowpath_null) from [<c027a780>] (exynos_drm_crtc_dpms+0x88/0x17c)
[   55.682482] [<c027a780>] (exynos_drm_crtc_dpms) from [<c027a910>] (exynos_drm_crtc_commit+0x14/0x44)
[   55.691622] [<c027a910>] (exynos_drm_crtc_commit) from [<c025521c>] (drm_crtc_helper_set_mode+0x3d0/0x51c)
[   55.701233] [<c025521c>] (drm_crtc_helper_set_mode) from [<c0255d68>] (drm_crtc_helper_set_config+0x87c/0x9dc)
[   55.711230] [<c0255d68>] (drm_crtc_helper_set_config) from [<c026afa8>] (drm_mode_set_config_internal+0x58/0xd4)
[   55.721380] [<c026afa8>] (drm_mode_set_config_internal) from [<c025c208>] (restore_fbdev_mode+0xcc/0xec)
[   55.730834] [<c025c208>] (restore_fbdev_mode) from [<c025c244>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x1c/0x30)
[   55.741424] [<c025c244>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c025e0a8>] (drm_fb_helper_set_par+0x1c/0x60)
[   55.752271] [<c025e0a8>] (drm_fb_helper_set_par) from [<c025e174>] (drm_fb_helper_hotplug_event+0x88/0xc4)
[   55.761906] [<c025e174>] (drm_fb_helper_hotplug_event) from [<c02571c4>] (drm_helper_hpd_irq_event+0xc8/0x134)
[   55.771898] [<c02571c4>] (drm_helper_hpd_irq_event) from [<c028e27c>] (vidi_store_connection+0x90/0xc8)
[   55.781268] [<c028e27c>] (vidi_store_connection) from [<c0125f80>] (kernfs_fop_write+0xc0/0x180)
[   55.790045] [<c0125f80>] (kernfs_fop_write) from [<c00cdf60>] (vfs_write+0xa0/0x1ac)
[   55.797757] [<c00cdf60>] (vfs_write) from [<c00ce468>] (SyS_write+0x44/0x9c)
[   55.804790] [<c00ce468>] (SyS_write) from [<c000e6a0>] (ret_fast_syscall+0x0/0x30)
[   55.812328] ---[ end trace 3c0fe4386702d4dd ]---

This issue occurs when modeset to vidi is tried in case that drm_vblank_init
is called prior to crtc creation of vidi driver. In this case, crtc number
of vidi is invalid so any requests with the crtc number will fail.
This patch guarantees drm_vblank_init to be called after all kms drivers
are ready by using component framework.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_vidi.c

index 3b6fdd61458475687e2a763761fba2f5d202f47a..45899fb63272723003837d1e6f338a7b2afa3d87 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/component.h>
 
 #include <drm/exynos_drm.h>
 
@@ -48,11 +49,11 @@ struct vidi_win_data {
 struct vidi_context {
        struct exynos_drm_manager       manager;
        struct exynos_drm_display       display;
+       struct platform_device          *pdev;
        struct drm_device               *drm_dev;
        struct drm_crtc                 *crtc;
        struct drm_encoder              *encoder;
        struct drm_connector            connector;
-       struct exynos_drm_subdrv        subdrv;
        struct vidi_win_data            win_data[WINDOWS_NR];
        struct edid                     *raw_edid;
        unsigned int                    clkdiv;
@@ -560,9 +561,10 @@ static struct exynos_drm_display_ops vidi_display_ops = {
        .create_connector = vidi_create_connector,
 };
 
-static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+static int vidi_bind(struct device *dev, struct device *master, void *data)
 {
        struct vidi_context *ctx = dev_get_drvdata(dev);
+       struct drm_device *drm_dev = data;
        struct drm_crtc *crtc = ctx->crtc;
        int ret;
 
@@ -584,9 +586,18 @@ static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
        return 0;
 }
 
+
+static void vidi_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops vidi_component_ops = {
+       .bind   = vidi_bind,
+       .unbind = vidi_unbind,
+};
+
 static int vidi_probe(struct platform_device *pdev)
 {
-       struct exynos_drm_subdrv *subdrv;
        struct vidi_context *ctx;
        int ret;
 
@@ -599,6 +610,17 @@ static int vidi_probe(struct platform_device *pdev)
        ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI;
        ctx->display.ops = &vidi_display_ops;
        ctx->default_win = 0;
+       ctx->pdev = pdev;
+
+       ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
+                                       ctx->manager.type);
+       if (ret)
+               return ret;
+
+       ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
+                                       ctx->display.type);
+       if (ret)
+               goto err_del_crtc_component;
 
        INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
 
@@ -606,23 +628,26 @@ static int vidi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ctx);
 
-       subdrv = &ctx->subdrv;
-       subdrv->dev = &pdev->dev;
-       subdrv->probe = vidi_subdrv_probe;
-
-       ret = exynos_drm_subdrv_register(subdrv);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to register drm vidi device\n");
-               return ret;
-       }
-
        ret = device_create_file(&pdev->dev, &dev_attr_connection);
        if (ret < 0) {
-               exynos_drm_subdrv_unregister(subdrv);
-               DRM_INFO("failed to create connection sysfs.\n");
+               DRM_ERROR("failed to create connection sysfs.\n");
+               goto err_del_conn_component;
        }
 
-       return 0;
+       ret = component_add(&pdev->dev, &vidi_component_ops);
+       if (ret)
+               goto err_remove_file;
+
+       return ret;
+
+err_remove_file:
+       device_remove_file(&pdev->dev, &dev_attr_connection);
+err_del_conn_component:
+       exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
+err_del_crtc_component:
+       exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
+
+       return ret;
 }
 
 static int vidi_remove(struct platform_device *pdev)
@@ -636,6 +661,10 @@ static int vidi_remove(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       component_del(&pdev->dev, &vidi_component_ops);
+       exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
+       exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
+
        return 0;
 }