Skip to content

Commit

Permalink
drm/imx: dw_hdmi-imx: move initialization into probe
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Daniel Vetter <[email protected]>
  • Loading branch information
pH5 committed Jan 4, 2021
1 parent 9dbb70f commit c805ec7
Showing 1 changed file with 26 additions and 48 deletions.
74 changes: 26 additions & 48 deletions drivers/gpu/drm/imx/dw_hdmi-imx.c
Original file line number Diff line number Diff line change
@@ -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,79 +184,68 @@ 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);
if (!hdmi)
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;
}

0 comments on commit c805ec7

Please sign in to comment.