@@ -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 driver. 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 so that this driver can be bound independently. Changelog v3: - none Changelog v2: - none 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(-)