diff options
author | Inki Dae <inki.dae@samsung.com> | 2014-05-09 09:25:20 +0400 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-06-01 21:07:04 +0400 |
commit | f37cd5e8098441af6447a87574fbb78eb5b4f9bf (patch) | |
tree | c1fc99c2d61e3ea0f91b5d336328690d390fb192 /drivers/gpu/drm/exynos/exynos_drm_fimd.c | |
parent | 121692eb0895c5c16f29f3b2141d2913021584ac (diff) | |
download | linux-f37cd5e8098441af6447a87574fbb78eb5b4f9bf.tar.xz |
drm/exynos: add component framework support
This patch adds component framework support to resolve
the probe order issue.
Until now, exynos drm had used codes specific to exynos drm
to resolve that issue so with this patch, the specific codes
are removed.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 83 |
1 files changed, 68 insertions, 15 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 99ae79e09e82..d1a282c3b062 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -19,10 +19,12 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pm_runtime.h> +#include <linux/component.h> #include <video/of_display_timing.h> #include <video/of_videomode.h> #include <video/samsung_fimd.h> +#include <drm/drm_panel.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h" @@ -186,12 +188,14 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr) } static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, - struct drm_device *drm_dev, int pipe) + struct drm_device *drm_dev) { struct fimd_context *ctx = mgr->ctx; + struct exynos_drm_private *priv; + priv = drm_dev->dev_private; - ctx->drm_dev = drm_dev; - ctx->pipe = pipe; + mgr->drm_dev = ctx->drm_dev = drm_dev; + mgr->pipe = ctx->pipe = priv->pipe++; /* * enable drm irq mode. @@ -832,8 +836,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) } static struct exynos_drm_manager_ops fimd_manager_ops = { - .initialize = fimd_mgr_initialize, - .remove = fimd_mgr_remove, .dpms = fimd_dpms, .mode_fixup = fimd_mode_fixup, .mode_set = fimd_mode_set, @@ -878,10 +880,12 @@ out: return IRQ_HANDLED; } -static int fimd_probe(struct platform_device *pdev) +static int fimd_bind(struct device *dev, struct device *master, void *data) { - struct device *dev = &pdev->dev; + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm_dev = data; struct fimd_context *ctx; + struct device_node *dn; struct resource *res; int win; int ret = -EINVAL; @@ -939,11 +943,19 @@ static int fimd_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &fimd_manager); fimd_manager.ctx = ctx; - exynos_drm_manager_register(&fimd_manager); + fimd_mgr_initialize(&fimd_manager, drm_dev); - exynos_dpi_probe(ctx->dev); + exynos_drm_crtc_create(&fimd_manager); - pm_runtime_enable(dev); + dn = exynos_dpi_of_find_panel_node(&pdev->dev); + if (dn) { + /* + * It should be called after exynos_drm_crtc_create call + * because exynos_dpi_probe call will try to find same lcd + * type of manager to setup possible_crtcs. + */ + exynos_dpi_probe(drm_dev, dev); + } for (win = 0; win < WINDOWS_NR; win++) fimd_clear_win(ctx, win); @@ -951,18 +963,59 @@ static int fimd_probe(struct platform_device *pdev) return 0; } -static int fimd_remove(struct platform_device *pdev) +static void fimd_unbind(struct device *dev, struct device *master, + void *data) { - struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); + struct exynos_drm_manager *mgr = dev_get_drvdata(dev); + struct drm_crtc *crtc = mgr->crtc; + struct device_node *dn; + + fimd_dpms(mgr, DRM_MODE_DPMS_OFF); - exynos_dpi_remove(&pdev->dev); + dn = exynos_dpi_of_find_panel_node(dev); + if (dn) + exynos_dpi_remove(mgr->drm_dev, dev); - exynos_drm_manager_unregister(&fimd_manager); + fimd_mgr_remove(mgr); - fimd_dpms(mgr, DRM_MODE_DPMS_OFF); + crtc->funcs->destroy(crtc); +} + +static const struct component_ops fimd_component_ops = { + .bind = fimd_bind, + .unbind = fimd_unbind, +}; + +static int fimd_probe(struct platform_device *pdev) +{ + struct device_node *dn; + + /* Check if fimd node has port node. */ + dn = exynos_dpi_of_find_panel_node(&pdev->dev); + if (dn) { + struct drm_panel *panel; + + /* + * Do not bind if there is the port node but a drm_panel + * isn't added to panel_list yet. + * In this case, fimd_probe will be called by defered probe + * again after the drm_panel is added to panel_list. + */ + panel = of_drm_find_panel(dn); + if (!panel) + return -EPROBE_DEFER; + } + + pm_runtime_enable(&pdev->dev); + + return exynos_drm_component_add(&pdev->dev, &fimd_component_ops); +} +static int fimd_remove(struct platform_device *pdev) +{ pm_runtime_disable(&pdev->dev); + exynos_drm_component_del(&pdev->dev, &fimd_component_ops); return 0; } |