drm/imx: dw_hdmi-imx: move initialization into probe
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 10 Dec 2020 15:38:32 +0000 (16:38 +0100)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 4 Jan 2021 11:59:33 +0000 (12:59 +0100)
Parts of the initialization that do not require the drm device can be
done once during probe instead of possibly multiple times during bind.
The bind function only creates the encoder and attaches the bridge.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/imx/dw_hdmi-imx.c

index d07b39b..bbd0a0c 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_of.h>
@@ -25,6 +26,7 @@
 struct imx_hdmi {
        struct device *dev;
        struct drm_encoder encoder;
+       struct drm_bridge *bridge;
        struct dw_hdmi *hdmi;
        struct regmap *regmap;
 };
@@ -98,19 +100,6 @@ static const struct dw_hdmi_phy_config imx_phy_config[] = {
        { ~0UL,      0x0000, 0x0000, 0x0000}
 };
 
-static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi)
-{
-       struct device_node *np = hdmi->dev->of_node;
-
-       hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
-       if (IS_ERR(hdmi->regmap)) {
-               dev_err(hdmi->dev, "Unable to get gpr\n");
-               return PTR_ERR(hdmi->regmap);
-       }
-
-       return 0;
-}
-
 static void dw_hdmi_imx_encoder_enable(struct drm_encoder *encoder)
 {
        struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder);
@@ -195,65 +184,34 @@ MODULE_DEVICE_TABLE(of, dw_hdmi_imx_dt_ids);
 static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
                            void *data)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       const struct dw_hdmi_plat_data *plat_data;
-       const struct of_device_id *match;
        struct drm_device *drm = data;
        struct drm_encoder *encoder;
        struct imx_hdmi *hdmi;
        int ret;
 
-       if (!pdev->dev.of_node)
-               return -ENODEV;
-
        hdmi = dev_get_drvdata(dev);
-       memset(hdmi, 0, sizeof(*hdmi));
+       memset(&hdmi->encoder, 0, sizeof(hdmi->encoder));
 
-       match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node);
-       plat_data = match->data;
-       hdmi->dev = &pdev->dev;
        encoder = &hdmi->encoder;
 
        ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node);
        if (ret)
                return ret;
 
-       ret = dw_hdmi_imx_parse_dt(hdmi);
-       if (ret < 0)
-               return ret;
-
        drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
        drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-       hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
-
-       /*
-        * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
-        * which would have called the encoder cleanup.  Do it manually.
-        */
-       if (IS_ERR(hdmi->hdmi)) {
-               ret = PTR_ERR(hdmi->hdmi);
-               drm_encoder_cleanup(encoder);
-       }
-
-       return ret;
-}
-
-static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
-                              void *data)
-{
-       struct imx_hdmi *hdmi = dev_get_drvdata(dev);
-
-       dw_hdmi_unbind(hdmi->hdmi);
+       return drm_bridge_attach(encoder, hdmi->bridge, NULL, 0);
 }
 
 static const struct component_ops dw_hdmi_imx_ops = {
        .bind   = dw_hdmi_imx_bind,
-       .unbind = dw_hdmi_imx_unbind,
 };
 
 static int dw_hdmi_imx_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match = of_match_node(dw_hdmi_imx_dt_ids, np);
        struct imx_hdmi *hdmi;
 
        hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
@@ -261,13 +219,33 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        platform_set_drvdata(pdev, hdmi);
+       hdmi->dev = &pdev->dev;
+
+       hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+       if (IS_ERR(hdmi->regmap)) {
+               dev_err(hdmi->dev, "Unable to get gpr\n");
+               return PTR_ERR(hdmi->regmap);
+       }
+
+       hdmi->hdmi = dw_hdmi_probe(pdev, match->data);
+       if (IS_ERR(hdmi->hdmi))
+               return PTR_ERR(hdmi->hdmi);
+
+       hdmi->bridge = of_drm_find_bridge(np);
+       if (!hdmi->bridge) {
+               dev_err(hdmi->dev, "Unable to find bridge\n");
+               return -ENODEV;
+       }
 
        return component_add(&pdev->dev, &dw_hdmi_imx_ops);
 }
 
 static int dw_hdmi_imx_remove(struct platform_device *pdev)
 {
+       struct imx_hdmi *hdmi = platform_get_drvdata(pdev);
+
        component_del(&pdev->dev, &dw_hdmi_imx_ops);
+       dw_hdmi_remove(hdmi->hdmi);
 
        return 0;
 }