@@ -608,19 +608,12 @@ static int exynos_drm_init(void)
if (IS_ERR(exynos_drm_pdev))
return PTR_ERR(exynos_drm_pdev);
- ret = exynos_drm_probe_vidi();
- if (ret < 0)
- goto err_unregister_pd;
-
ret = platform_driver_register(&exynos_drm_platform_driver);
if (ret)
- goto err_remove_vidi;
+ goto err_unregister_pd;
return 0;
-err_remove_vidi:
- exynos_drm_remove_vidi();
-
err_unregister_pd:
platform_device_unregister(exynos_drm_pdev);
@@ -630,9 +623,6 @@ err_unregister_pd:
static void exynos_drm_exit(void)
{
platform_driver_unregister(&exynos_drm_platform_driver);
-
- exynos_drm_remove_vidi();
-
platform_device_unregister(exynos_drm_pdev);
}
@@ -310,14 +310,6 @@ exynos_dpi_probe(struct device *dev) { return NULL; }
static inline int exynos_dpi_remove(struct device *dev) { return 0; }
#endif
-#ifdef CONFIG_DRM_EXYNOS_VIDI
-int exynos_drm_probe_vidi(void);
-void exynos_drm_remove_vidi(void);
-#else
-static inline int exynos_drm_probe_vidi(void) { return 0; }
-static inline void exynos_drm_remove_vidi(void) {}
-#endif
-
/* This function creates a encoder and a connector, and initializes them. */
int exynos_drm_create_enc_conn(struct drm_device *dev,
struct exynos_drm_display *display);
@@ -333,5 +325,4 @@ extern int exynos_drm_non_kms_register(unsigned int device_type);
extern void exynos_drm_non_kms_unregister(unsigned int device_type);
extern struct platform_driver exynos_drm_common_hdmi_driver;
-extern struct platform_driver vidi_driver;
#endif
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/component.h>
#include <drm/exynos_drm.h>
@@ -48,10 +49,10 @@ struct vidi_win_data {
struct vidi_context {
struct drm_device *drm_dev;
+ struct platform_device *pdev;
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;
@@ -561,14 +562,13 @@ static struct exynos_drm_display vidi_display = {
.ops = &vidi_display_ops,
};
-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 exynos_drm_manager *mgr = get_vidi_mgr(dev);
- struct vidi_context *ctx = mgr->ctx;
- struct drm_crtc *crtc = ctx->crtc;
+ struct drm_crtc *crtc = vidi_manager.crtc;
+ struct drm_device *drm_dev = data;
int ret;
- vidi_mgr_initialize(mgr, drm_dev);
+ vidi_mgr_initialize(&vidi_manager, drm_dev);
ret = exynos_drm_crtc_create(&vidi_manager);
if (ret) {
@@ -586,20 +586,42 @@ 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;
+ ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
+ vidi_manager.type);
+ if (ret)
+ return ret;
+
+ ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
+ vidi_display.type);
+ if (ret)
+ goto err_del_crtc_component;
+
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
+ if (!ctx) {
+ ret = -ENOMEM;
+ goto err_del_conn_component;
+ }
ctx->default_win = 0;
INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
+ ctx->pdev = pdev;
vidi_manager.ctx = ctx;
vidi_display.ctx = ctx;
@@ -607,23 +629,21 @@ static int vidi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &vidi_manager);
- 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);
+ if (ret < 0)
DRM_INFO("failed to create connection sysfs.\n");
- }
- return 0;
+ ret = component_add(&pdev->dev, &vidi_component_ops);
+ if (ret)
+ goto err_del_conn_component;
+
+ return ret;
+
+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)
@@ -638,6 +658,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;
}
@@ -650,7 +674,7 @@ struct platform_driver vidi_driver = {
},
};
-int exynos_drm_probe_vidi(void)
+static int exynos_drm_vidi_init(void)
{
struct platform_device *pdev;
int ret;
@@ -668,12 +692,13 @@ int exynos_drm_probe_vidi(void)
return ret;
}
-void exynos_drm_remove_vidi(void)
+void exynos_drm_vidi_exit(void)
{
struct vidi_context *ctx = vidi_manager.ctx;
- struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct platform_device *pdev = to_platform_device(subdrv->dev);
platform_driver_unregister(&vidi_driver);
- platform_device_unregister(pdev);
+ platform_device_unregister(ctx->pdev);
}
+
+module_init(exynos_drm_vidi_init);
+module_exit(exynos_drm_vidi_exit);
This patch makes vidi driver to be independent module. For this, it removes register codes to vidi driver from exynos_drm_drv module and adds module_init/exit for vidi driver so that this driver can be called independently. In addition, this patch adds component support to vidi driver, which is required for modularity. Signed-off-by: Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 12 +---- drivers/gpu/drm/exynos/exynos_drm_drv.h | 9 ---- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 81 +++++++++++++++++++----------- 3 files changed, 54 insertions(+), 48 deletions(-)