On Mon, May 16, 2016 at 2:47 PM, Maxime Ripard maxime.ripard@free-electrons.com wrote:
Our RGB bus can be either connected to a bridge or a panel. While the panel support was already there, the bridge was not.
Fix that.
Signed-off-by: Maxime Ripard maxime.ripard@free-electrons.com
For bridge support the only thing you need is to set drm_encoder->bridge. Why do you need to hand-roll your own bridge support? That pretty muchmeans you'll do it slightly differently (e.g. you don't bother with a lot of the calls), which will make sharing bridge drivers ever so harder. And also reviewing code, since using shared code but slightly differently is really confusing. -Daniel
drivers/gpu/drm/sun4i/sun4i_drv.c | 4 +-- drivers/gpu/drm/sun4i/sun4i_rgb.c | 56 +++++++++++++++++++++++++++----------- drivers/gpu/drm/sun4i/sun4i_tcon.c | 48 ++++++++++++++++++++++++++++---- drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + 4 files changed, 86 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 257d2b4f3645..1f9e00db747d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -268,8 +268,8 @@ static int sun4i_drv_add_endpoints(struct device *dev, }
/*
* If the node is our TCON, the first port is used for our
* panel, and will not be part of the
* If the node is our TCON, the first port is used for
* panel or bridges, and will not be part of the * component framework. */ if (sun4i_drv_node_is_tcon(node)) {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index b46d2c15dc95..c3c611b08269 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -161,7 +161,12 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Enabling RGB output\n");
drm_panel_enable(tcon->panel);
if (!IS_ERR(tcon->panel))
drm_panel_enable(tcon->panel);
if (!IS_ERR(tcon->bridge))
drm_bridge_enable(tcon->bridge);
sun4i_tcon_channel_enable(tcon, 0);
}
@@ -174,7 +179,12 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) DRM_DEBUG_DRIVER("Disabling RGB output\n");
sun4i_tcon_channel_disable(tcon, 0);
drm_panel_disable(tcon->panel);
if (!IS_ERR(tcon->bridge))
drm_bridge_disable(tcon->bridge);
if (!IS_ERR(tcon->panel))
drm_panel_disable(tcon->panel);
}
static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, @@ -216,10 +226,6 @@ int sun4i_rgb_init(struct drm_device *drm) struct sun4i_rgb *rgb; int ret;
/* If we don't have a panel, there's no point in going on */
if (IS_ERR(tcon->panel))
return -ENODEV;
rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL); if (!rgb) return -ENOMEM;
@@ -240,19 +246,37 @@ int sun4i_rgb_init(struct drm_device *drm) /* The RGB encoder can only work with the TCON channel 0 */ rgb->encoder.possible_crtcs = BIT(0);
drm_connector_helper_add(&rgb->connector,
&sun4i_rgb_con_helper_funcs);
ret = drm_connector_init(drm, &rgb->connector,
&sun4i_rgb_con_funcs,
DRM_MODE_CONNECTOR_Unknown);
if (ret) {
dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
goto err_cleanup_connector;
if (!IS_ERR(tcon->panel)) {
drm_connector_helper_add(&rgb->connector,
&sun4i_rgb_con_helper_funcs);
ret = drm_connector_init(drm, &rgb->connector,
&sun4i_rgb_con_funcs,
DRM_MODE_CONNECTOR_Unknown);
if (ret) {
dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
goto err_cleanup_connector;
}
drm_mode_connector_attach_encoder(&rgb->connector,
&rgb->encoder);
ret = drm_panel_attach(tcon->panel, &rgb->connector);
if (ret) {
dev_err(drm->dev, "Couldn't attach our panel\n");
goto err_cleanup_connector;
} }
drm_mode_connector_attach_encoder(&rgb->connector, &rgb->encoder);
if (!IS_ERR(tcon->bridge)) {
rgb->encoder.bridge = tcon->bridge;
tcon->bridge->encoder = &rgb->encoder;
drm_panel_attach(tcon->panel, &rgb->connector);
ret = drm_bridge_attach(drm, tcon->bridge);
if (ret) {
dev_err(drm->dev, "Couldn't attach our bridge\n");
goto err_cleanup_connector;
}
} return 0;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index eed6a9e8d9a6..4618d98913b4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -432,6 +432,40 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node) return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER); }
+static struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node) +{
struct device_node *port, *remote, *child;
struct device_node *end_node = NULL;
/* Inputs are listed first, then outputs */
port = of_graph_get_port_by_id(node, 1);
/*
* Our first output is the RGB interface where the panel will
* be connected.
*/
for_each_child_of_node(port, child) {
u32 reg;
of_property_read_u32(child, "reg", ®);
if (reg == 0)
end_node = child;
}
if (!end_node) {
DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
return ERR_PTR(-ENODEV);
}
remote = of_graph_get_remote_port_parent(end_node);
if (!remote) {
DRM_DEBUG_DRIVER("Enable to parse remote node\n");
return ERR_PTR(-EINVAL);
}
return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
+}
static int sun4i_tcon_bind(struct device *dev, struct device *master, void *data) { @@ -485,8 +519,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, }
tcon->panel = sun4i_tcon_find_panel(dev->of_node);
if (IS_ERR(tcon->panel)) {
dev_info(dev, "No panel found... RGB output disabled\n");
tcon->bridge = sun4i_tcon_find_bridge(dev->of_node);
if (IS_ERR(tcon->panel) && IS_ERR(tcon->bridge)) {
dev_info(dev, "No panel or bridge found... RGB output disabled\n"); return 0; }
@@ -515,19 +550,22 @@ static struct component_ops sun4i_tcon_ops = { static int sun4i_tcon_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node;
struct drm_bridge *bridge; struct drm_panel *panel; /*
* The panel is not ready.
* Neither the bridge or the panel is ready. * Defer the probe. */ panel = sun4i_tcon_find_panel(node);
bridge = sun4i_tcon_find_bridge(node); /* * If we don't have a panel endpoint, just go on */
if (PTR_ERR(panel) == -EPROBE_DEFER) {
DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
(PTR_ERR(bridge) == -EPROBE_DEFER)) {
DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n"); return -EPROBE_DEFER; }
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 0e0b11db401b..31069027d7fb 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -162,6 +162,7 @@ struct sun4i_tcon { /* Platform adjustments */ bool has_mux;
struct drm_bridge *bridge; struct drm_panel *panel;
};
-- 2.8.2
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel