diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index d07b39b8afd21a0a7c43b45760d750bd1e4ae997..bbd0a0cd7c3d8cb28ed84046cc1342981393625d 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -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; }