Commit c805ec7e authored by Philipp Zabel's avatar Philipp Zabel

drm/imx: dw_hdmi-imx: move initialization into probe

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: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 9dbb70fd
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <drm/bridge/dw_hdmi.h> #include <drm/bridge/dw_hdmi.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_encoder.h> #include <drm/drm_encoder.h>
#include <drm/drm_of.h> #include <drm/drm_of.h>
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
struct imx_hdmi { struct imx_hdmi {
struct device *dev; struct device *dev;
struct drm_encoder encoder; struct drm_encoder encoder;
struct drm_bridge *bridge;
struct dw_hdmi *hdmi; struct dw_hdmi *hdmi;
struct regmap *regmap; struct regmap *regmap;
}; };
...@@ -98,19 +100,6 @@ static const struct dw_hdmi_phy_config imx_phy_config[] = { ...@@ -98,19 +100,6 @@ static const struct dw_hdmi_phy_config imx_phy_config[] = {
{ ~0UL, 0x0000, 0x0000, 0x0000} { ~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) static void dw_hdmi_imx_encoder_enable(struct drm_encoder *encoder)
{ {
struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder); struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder);
...@@ -195,65 +184,34 @@ MODULE_DEVICE_TABLE(of, dw_hdmi_imx_dt_ids); ...@@ -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, static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
void *data) 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_device *drm = data;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct imx_hdmi *hdmi; struct imx_hdmi *hdmi;
int ret; int ret;
if (!pdev->dev.of_node)
return -ENODEV;
hdmi = dev_get_drvdata(dev); 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; encoder = &hdmi->encoder;
ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node); ret = imx_drm_encoder_parse_of(drm, encoder, dev->of_node);
if (ret) if (ret)
return 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_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); return drm_bridge_attach(encoder, hdmi->bridge, NULL, 0);
/*
* 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);
} }
static const struct component_ops dw_hdmi_imx_ops = { static const struct component_ops dw_hdmi_imx_ops = {
.bind = dw_hdmi_imx_bind, .bind = dw_hdmi_imx_bind,
.unbind = dw_hdmi_imx_unbind,
}; };
static int dw_hdmi_imx_probe(struct platform_device *pdev) 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; struct imx_hdmi *hdmi;
hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
...@@ -261,13 +219,33 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev) ...@@ -261,13 +219,33 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, hdmi); 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); return component_add(&pdev->dev, &dw_hdmi_imx_ops);
} }
static int dw_hdmi_imx_remove(struct platform_device *pdev) 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); component_del(&pdev->dev, &dw_hdmi_imx_ops);
dw_hdmi_remove(hdmi->hdmi);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment