Hi Maxime,
Thank you for the patch.
On Thu, Jul 30, 2020 at 11:35:02AM +0200, Maxime Ripard wrote:
The current code to parse the DT, deal with the older device trees, and register either the RGB or LVDS output has so far grown organically into the bind function and has become quite hard to extend properly.
Let's move it into a single function that grabs all the resources it needs and registers the proper panel output.
Signed-off-by: Maxime Ripard maxime@cerno.tech
drivers/gpu/drm/sun4i/sun4i_tcon.c | 139 +++++++++++++++--------------- 1 file changed, 70 insertions(+), 69 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 2a5a9903c4c6..d03ad75f9900 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -875,6 +875,75 @@ static int sun4i_tcon_init_regmap(struct device *dev, return 0; }
+static int sun4i_tcon_register_panel(struct drm_device *drm,
struct sun4i_tcon *tcon)
+{
- struct device_node *companion;
- struct device_node *remote;
- struct device *dev = tcon->dev;
- bool has_lvds_alt;
- bool has_lvds_rst;
- int ret;
- /*
* If we have an LVDS panel connected to the TCON, we should
* just probe the LVDS connector. Otherwise, let's just register
* an RGB panel.
*/
- remote = of_graph_get_remote_node(dev->of_node, 1, 0);
- if (!tcon->quirks->supports_lvds ||
!of_device_is_compatible(remote, "panel-lvds"))
This isn't very nice :-S Not a candidate for a fix in this patch, but something that should be addressed in the future. As Chen-Yu mentioned, there are LVDS panels supported by the panel-simple driver.
return sun4i_rgb_init(drm, tcon);
- /*
* This can only be made optional since we've had DT
* nodes without the LVDS reset properties.
*
* If the property is missing, just disable LVDS, and
* print a warning.
*/
- tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
- if (IS_ERR(tcon->lvds_rst)) {
dev_err(dev, "Couldn't get our reset line\n");
return PTR_ERR(tcon->lvds_rst);
- } else if (tcon->lvds_rst) {
has_lvds_rst = true;
reset_control_reset(tcon->lvds_rst);
- } else {
has_lvds_rst = false;
- }
- /*
* This can only be made optional since we've had DT
* nodes without the LVDS reset properties.
Shouldn't this mention clock, not reset ?
*
* If the property is missing, just disable LVDS, and
* print a warning.
*/
- if (tcon->quirks->has_lvds_alt) {
tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
if (IS_ERR(tcon->lvds_pll)) {
if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
has_lvds_alt = false;
} else {
dev_err(dev, "Couldn't get the LVDS PLL\n");
return PTR_ERR(tcon->lvds_pll);
}
} else {
has_lvds_alt = true;
}
- }
- if (!has_lvds_rst ||
(tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
dev_warn(dev, "LVDS output disabled\n");
Would it make sense to move this to the has_lvds_rst = false and has_lvds_alt = false code sections about ? You could then print which property is missing.
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
return -ENODEV;
- }
- return sun4i_lvds_init(drm, tcon);
+}
/*
- On SoCs with the old display pipeline design (Display Engine 1.0),
- the TCON is always tied to just one backend. Hence we can traverse
@@ -1122,10 +1191,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, struct drm_device *drm = data; struct sun4i_drv *drv = drm->dev_private; struct sunxi_engine *engine;
struct device_node *remote; struct sun4i_tcon *tcon; struct reset_control *edp_rstc;
bool has_lvds_rst, has_lvds_alt, can_lvds; int ret;
engine = sun4i_tcon_find_engine(drv, dev->of_node);
@@ -1170,58 +1237,6 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, return ret; }
- if (tcon->quirks->supports_lvds) {
/*
* This can only be made optional since we've had DT
* nodes without the LVDS reset properties.
*
* If the property is missing, just disable LVDS, and
* print a warning.
*/
tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
if (IS_ERR(tcon->lvds_rst)) {
dev_err(dev, "Couldn't get our reset line\n");
return PTR_ERR(tcon->lvds_rst);
} else if (tcon->lvds_rst) {
has_lvds_rst = true;
reset_control_reset(tcon->lvds_rst);
} else {
has_lvds_rst = false;
}
/*
* This can only be made optional since we've had DT
* nodes without the LVDS reset properties.
*
* If the property is missing, just disable LVDS, and
* print a warning.
*/
if (tcon->quirks->has_lvds_alt) {
tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
if (IS_ERR(tcon->lvds_pll)) {
if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
has_lvds_alt = false;
} else {
dev_err(dev, "Couldn't get the LVDS PLL\n");
return PTR_ERR(tcon->lvds_pll);
}
} else {
has_lvds_alt = true;
}
}
if (!has_lvds_rst ||
(tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
dev_warn(dev, "LVDS output disabled\n");
can_lvds = false;
} else {
can_lvds = true;
}
- } else {
can_lvds = false;
- }
- ret = sun4i_tcon_init_clocks(dev, tcon); if (ret) { dev_err(dev, "Couldn't init our TCON clocks\n");
@@ -1256,21 +1271,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, }
if (tcon->quirks->has_channel_0) {
/*
* If we have an LVDS panel connected to the TCON, we should
* just probe the LVDS connector. Otherwise, just probe RGB as
* we used to.
*/
remote = of_graph_get_remote_node(dev->of_node, 1, 0);
if (of_device_is_compatible(remote, "panel-lvds"))
if (can_lvds)
ret = sun4i_lvds_init(drm, tcon);
else
ret = -EINVAL;
else
ret = sun4i_rgb_init(drm, tcon);
of_node_put(remote);
if (ret < 0) goto err_free_dotclock; }ret = sun4i_tcon_register_panel(drm, tcon);