2014-04-02 23:06 GMT+09:00, Andrzej Hajda <a.hajda@xxxxxxxxxxx>: > On 04/01/2014 02:37 PM, Inki Dae wrote: >> This patch adds super device support to bind sub drivers >> using device tree. >> >> For this, you should add a super device node to each machine dt files >> like belows, >> >> In case of using MIPI-DSI, >> display-subsystem { >> compatible = "samsung,exynos-display-subsystem"; >> ports = <&fimd>, <&dsi>; >> }; >> >> In case of using DisplayPort, >> display-subsystem { >> compatible = "samsung,exynos-display-subsystem"; >> ports = <&fimd>, <&dp>; >> }; >> >> In case of using Parallel panel, >> display-subsystem { >> compatible = "samsung,exynos-display-subsystem"; >> ports = <&fimd>; >> }; >> >> And if you don't add connector device node to ports property, >> default parallel panel driver, exynos_drm_dpi module, will be used. >> >> ports property can have the following device nodes, >> fimd, mixer, Image Enhancer, MIPI-DSI, eDP, LVDS Bridge, or HDMI >> >> With this patch, we can resolve the probing order issue without >> some global lists. So this patch also removes the unnecessary lists and >> stuff related to these lists. >> > > (...) > >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> index 40fd6cc..7ebfe15 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" >> @@ -144,12 +146,14 @@ static inline struct fimd_driver_data >> *drm_fimd_get_driver_data( >> } >> >> 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. >> @@ -803,8 +807,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, >> @@ -849,9 +851,10 @@ 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 resource *res; >> int win; >> @@ -910,11 +913,16 @@ 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); >> + /* >> + * 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); >> @@ -922,18 +930,56 @@ 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; >> + >> + fimd_dpms(mgr, DRM_MODE_DPMS_OFF); >> >> - exynos_dpi_remove(&pdev->dev); >> + 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; >> + } > > Wouldn't be better to leave it in exynos_dpi_probe? It should be called > in fimd_probe. It can return ERR_PTR(-EPROBE_DEFER) if the panel is > missing, NULL if there are no parallel bindings otherwise it will return > &exynos_dpi_display. fimd_bind will run exynos_drm_create_enc_conn on > returned pointer. In this case > in fimd_unbind connector and encoder should be removed and in > fimd_remove, exynos_dpi_remove should be conditionally called. > That was what I tried to do but cannot do it because of below issues, exynos_drm_crtc_create and exynos_dpi_probe functions need fimd_manager with *drm_device* but fimd_probe cannot get drm_device object. I am typing on my smart phone because of ugly outlook so It is not easy to comment enough. :( Thinks, Inki Dae > Regards > Andrzej > >> + >> + pm_runtime_enable(&pdev->dev); >> + >> + return component_add(&pdev->dev, &fimd_component_ops); >> +} >> + >> +static int fimd_remove(struct platform_device *pdev) >> +{ >> pm_runtime_disable(&pdev->dev); >> >> + component_del(&pdev->dev, &fimd_component_ops); >> return 0; >> } >> > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel