2014-04-02 23:06 GMT+09:00, Andrzej Hajda a.hajda@samsung.com:
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@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel