Messages in this thread Patch in this message | | | Date | Mon, 14 Aug 2023 13:04:47 +0300 | Subject | Re: [PATCH 11/11] drm/bridge: tc358768: Add DRM_BRIDGE_ATTACH_NO_CONNECTOR support | From | Tomi Valkeinen <> |
| |
On 13/08/2023 20:11, Maxim Schwalm wrote: > On 04.08.23 12:44, Tomi Valkeinen wrote: >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> >> --- >> drivers/gpu/drm/bridge/tc358768.c | 64 +++++++++++++++++++++++++++------------ >> 1 file changed, 45 insertions(+), 19 deletions(-) >> >> diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c >> index ea19de5509ed..a567f136ddc7 100644 >> --- a/drivers/gpu/drm/bridge/tc358768.c >> +++ b/drivers/gpu/drm/bridge/tc358768.c >> @@ -131,8 +131,17 @@ static const char * const tc358768_supplies[] = { >> >> struct tc358768_dsi_output { >> struct mipi_dsi_device *dev; >> + >> + /* Legacy field if DRM_BRIDGE_ATTACH_NO_CONNECTOR is not used */ >> struct drm_panel *panel; >> - struct drm_bridge *bridge; >> + >> + /* >> + * If DRM_BRIDGE_ATTACH_NO_CONNECTOR is not used and a panel is attached >> + * to tc358768, 'next_bridge' contains the bridge the driver created >> + * with drm_panel_bridge_add_typed(). Otherwise 'next_bridge' contains >> + * the next bridge the driver found. >> + */ >> + struct drm_bridge *next_bridge; >> }; >> >> struct tc358768_priv { >> @@ -391,8 +400,6 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host, >> struct mipi_dsi_device *dev) >> { >> struct tc358768_priv *priv = dsi_host_to_tc358768(host); >> - struct drm_bridge *bridge; >> - struct drm_panel *panel; >> struct device_node *ep; >> int ret; >> >> @@ -420,21 +427,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host, >> return -ENOTSUPP; >> } >> >> - ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0, &panel, >> - &bridge); >> - if (ret) >> - return ret; >> - >> - if (panel) { >> - bridge = drm_panel_bridge_add_typed(panel, >> - DRM_MODE_CONNECTOR_DSI); >> - if (IS_ERR(bridge)) >> - return PTR_ERR(bridge); >> - } >> - >> priv->output.dev = dev; >> - priv->output.bridge = bridge; >> - priv->output.panel = panel; >> >> priv->dsi_lanes = dev->lanes; >> priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format); >> @@ -463,7 +456,7 @@ static int tc358768_dsi_host_detach(struct mipi_dsi_host *host, >> >> drm_bridge_remove(&priv->bridge); >> if (priv->output.panel) >> - drm_panel_bridge_remove(priv->output.bridge); >> + drm_panel_bridge_remove(priv->output.next_bridge); >> >> return 0; >> } >> @@ -544,7 +537,40 @@ static int tc358768_bridge_attach(struct drm_bridge *bridge, >> return -ENOTSUPP; >> } >> >> - return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge, >> + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { >> + struct device_node *node; >> + >> + /* Get the next bridge, connected to port@1. */ >> + node = of_graph_get_remote_node(priv->dev->of_node, 1, -1); >> + if (!node) >> + return -ENODEV; >> + >> + priv->output.next_bridge = of_drm_find_bridge(node); >> + of_node_put(node); >> + if (!priv->output.next_bridge) >> + return -EPROBE_DEFER; >> + } else { >> + struct drm_bridge *bridge; >> + struct drm_panel *panel; >> + int ret; >> + >> + ret = drm_of_find_panel_or_bridge(priv->dev->of_node, 1, 0, >> + &panel, &bridge); >> + if (ret) >> + return ret; >> + >> + if (panel) { >> + bridge = drm_panel_bridge_add_typed(panel, >> + DRM_MODE_CONNECTOR_DSI); >> + if (IS_ERR(bridge)) >> + return PTR_ERR(bridge); >> + } >> + >> + priv->output.next_bridge = bridge; >> + priv->output.panel = panel; >> + } >> + >> + return drm_bridge_attach(bridge->encoder, priv->output.next_bridge, bridge, >> flags); >> } >> >> > This patch unfortunately breaks the display output on the Asus TF700T: > > [drm:drm_bridge_attach] *ERROR* failed to attach bridge /i2c-mux/i2c@1/dsi@7 to encoder LVDS-59: -517 > tegra-dc 54200000.dc: failed to initialize RGB output: -517 > drm drm: failed to initialize 54200000.dc: -517 > ------------[ cut here ]------------ > WARNING: CPU: 3 PID: 69 at lib/refcount.c:28 tegra_dc_init+0x24/0x5fc > refcount_t: underflow; use-after-free. > Modules linked in: elants_i2c panel_simple tc358768 atkbd vivaldi_fmap > CPU: 3 PID: 69 Comm: kworker/u8:6 Not tainted 6.5.0-rc2-postmarketos-grate #95 > Hardware name: NVIDIA Tegra SoC (Flattened Device Tree) > Workqueue: events_unbound deferred_probe_work_func > unwind_backtrace from show_stack+0x10/0x14 > show_stack from dump_stack_lvl+0x40/0x4c > dump_stack_lvl from __warn+0x94/0xc0 > __warn from warn_slowpath_fmt+0x118/0x16c > warn_slowpath_fmt from tegra_dc_init+0x24/0x5fc > tegra_dc_init from host1x_device_init+0x84/0x15c > host1x_device_init from host1x_drm_probe+0xd8/0x3c4 > host1x_drm_probe from really_probe+0xc8/0x2dc > really_probe from __driver_probe_device+0x88/0x19c > __driver_probe_device from driver_probe_device+0x30/0x104 > driver_probe_device from __device_attach_driver+0x94/0x108 > __device_attach_driver from bus_for_each_drv+0x80/0xb8 > bus_for_each_drv from __device_attach+0xa0/0x190 > __device_attach from bus_probe_device+0x88/0x8c > bus_probe_device from deferred_probe_work_func+0x78/0xa4 > deferred_probe_work_func from process_one_work+0x208/0x420 > process_one_work from worker_thread+0x54/0x550 > worker_thread from kthread+0xdc/0xf8 > kthread from ret_from_fork+0x14/0x2c > Exception stack(0xcf9c5fb0 to 0xcf9c5ff8) > 5fa0: 00000000 00000000 00000000 00000000 > 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 > 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 > ---[ end trace 0000000000000000 ]---
Hi Maxim,
Can you try the attached patch (on top of the series)? If it helps, I'll refresh the series with the fix.
Tomi From c13c691bd8826b978325575be9a87f577b83b86b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Date: Mon, 14 Aug 2023 13:02:23 +0300 Subject: [PATCH] drm/bridge: tc358768: fix 'Add DRM_BRIDGE_ATTACH_NO_CONNECTOR support'
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- drivers/gpu/drm/bridge/tc358768.c | 56 +++++++++++++------------------ 1 file changed, 24 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 82ea4d9a814a..9705ce1bd028 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -455,8 +455,6 @@ static int tc358768_dsi_host_detach(struct mipi_dsi_host *host, struct tc358768_priv *priv = dsi_host_to_tc358768(host); drm_bridge_remove(&priv->bridge); - if (priv->output.panel) - drm_panel_bridge_remove(priv->output.next_bridge); return 0; } @@ -531,49 +529,42 @@ static int tc358768_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct tc358768_priv *priv = bridge_to_tc358768(bridge); + struct drm_bridge *next_bridge; + struct drm_panel *panel; + int ret; if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) { dev_err(priv->dev, "needs atomic updates support\n"); return -ENOTSUPP; } - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - struct device_node *node; - - /* Get the next bridge, connected to port@1. */ - node = of_graph_get_remote_node(priv->dev->of_node, 1, -1); - if (!node) - return -ENODEV; - - priv->output.next_bridge = of_drm_find_bridge(node); - of_node_put(node); - if (!priv->output.next_bridge) - return -EPROBE_DEFER; - } else { - struct drm_bridge *bridge; - struct drm_panel *panel; - int ret; - - ret = drm_of_find_panel_or_bridge(priv->dev->of_node, 1, 0, - &panel, &bridge); - if (ret) - return ret; - - if (panel) { - bridge = drm_panel_bridge_add_typed(panel, - DRM_MODE_CONNECTOR_DSI); - if (IS_ERR(bridge)) - return PTR_ERR(bridge); - } + ret = drm_of_find_panel_or_bridge(priv->dev->of_node, 1, -1, &panel, + &next_bridge); + if (ret) + return ret; - priv->output.next_bridge = bridge; - priv->output.panel = panel; + if (panel) { + next_bridge = drm_panel_bridge_add_typed(panel, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(next_bridge)) + return PTR_ERR(next_bridge); } + priv->output.next_bridge = next_bridge; + priv->output.panel = panel; + return drm_bridge_attach(bridge->encoder, priv->output.next_bridge, bridge, flags); } +void tc358768_bridge_detach(struct drm_bridge *bridge) +{ + struct tc358768_priv *priv = bridge_to_tc358768(bridge); + + if (priv->output.panel) + drm_panel_bridge_remove(priv->output.next_bridge); +} + static enum drm_mode_status tc358768_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, @@ -1156,6 +1147,7 @@ tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge, static const struct drm_bridge_funcs tc358768_bridge_funcs = { .attach = tc358768_bridge_attach, + .detach = tc358768_bridge_detach, .mode_valid = tc358768_bridge_mode_valid, .pre_enable = tc358768_bridge_pre_enable, .enable = tc358768_bridge_enable, -- 2.34.1
| |