[v7,02/12] drm: bridge: panel: Implement drmm_of_dsi_get_bridge helper

Message ID 20230329131615.1328366-3-jagan@amarulasolutions.com
State New
Headers show
Series
  • drm: sun4i: Convert Allwinner DSI to bridge
Related show

Commit Message

Jagan Teki March 29, 2023, 1:16 p.m. UTC
Implement a DRM-managed action helper that returns the next DSI bridge
in the chain.

Unlike general bridge return helper drmm_of_get_bridge, this helper
uses the dsi specific panel_or_bridge helper to find the next DSI
device in the pipeline.

Helper lookup a given downstream DSI device that has been added via
child or OF-graph port or ports node.

Upstream DSI looks for downstream devices using drm pointer, port and
endpoint number. Downstream devices added via child node don't affect
the port and endpoint number arguments.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v7:
- new patch

 drivers/gpu/drm/bridge/panel.c | 34 ++++++++++++++++++++++++++++++++++
 include/drm/drm_bridge.h       | 10 ++++++++++
 2 files changed, 44 insertions(+)

Comments

Maxime Ripard March 29, 2023, 3:03 p.m. UTC | #1
On Wed, Mar 29, 2023 at 06:46:08PM +0530, Jagan Teki wrote:
> Implement a DRM-managed action helper that returns the next DSI bridge
> in the chain.
> 
> Unlike general bridge return helper drmm_of_get_bridge, this helper
> uses the dsi specific panel_or_bridge helper to find the next DSI
> device in the pipeline.
> 
> Helper lookup a given downstream DSI device that has been added via
> child or OF-graph port or ports node.
> 
> Upstream DSI looks for downstream devices using drm pointer, port and
> endpoint number. Downstream devices added via child node don't affect
> the port and endpoint number arguments.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

If you intend to use it with the sun4i driver, then don't. The sun4i
driver is barely using drm-managed resources, so chances are all its
resources will be freed by the time this action will run.

Maxime
Jagan Teki March 29, 2023, 3:26 p.m. UTC | #2
On Wed, Mar 29, 2023 at 8:33 PM Maxime Ripard <maxime@cerno.tech> wrote:
>
> On Wed, Mar 29, 2023 at 06:46:08PM +0530, Jagan Teki wrote:
> > Implement a DRM-managed action helper that returns the next DSI bridge
> > in the chain.
> >
> > Unlike general bridge return helper drmm_of_get_bridge, this helper
> > uses the dsi specific panel_or_bridge helper to find the next DSI
> > device in the pipeline.
> >
> > Helper lookup a given downstream DSI device that has been added via
> > child or OF-graph port or ports node.
> >
> > Upstream DSI looks for downstream devices using drm pointer, port and
> > endpoint number. Downstream devices added via child node don't affect
> > the port and endpoint number arguments.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>
> If you intend to use it with the sun4i driver, then don't. The sun4i
> driver is barely using drm-managed resources, so chances are all its
> resources will be freed by the time this action will run.

Any idea how to check all resources will be freed before this
DRM-managed action helper runs? I did test the panel insertion and
removal at runtime and I can see that the action helper
(drmm_drm_panel_bridge_release) is triggered at removal time.

Here is the log for it.
# insmod panel-bananapi-s070wv20-icn6211.ko
[   11.411894] sun4i-drm display-engine: bound
1e00000.display-frontend (ops 0xc0951eb4)
[   11.420253] sun4i-drm display-engine: bound 1e60000.display-backend
(ops 0xc0951620)
[   11.428128] sun4i-drm display-engine: bound 1e70000.drc (ops 0xc0951150)
[   11.435574] sun4i-drm display-engine: No panel or bridge found...
RGB output disabled
[   11.443484] sun4i-drm display-engine: bound 1c0c000.lcd-controller
(ops 0xc094fdb0)
[   11.451264] sun4i-drm display-engine: bound 1ca0000.dsi (ops 0xc0952f04)
[   11.462479] [drm] Initialized sun4i-drm 1.0.0 20150629 for
display-engine on minor 1
[   11.963246] Console: switching to colour frame buffer device 100x30
[   12.046329] sun4i-drm display-engine: [drm] fb0: sun4i-drmdrmfb
frame buffer device
[   12.082641] sun6i-mipi-dsi 1ca0000.dsi: Attached device s070wv20-ct16-icn62
# rmmod panel-bananapi-s070wv20-icn6211.ko
[   16.306388] Console: switching to colour dummy device 80x30
[   16.466963] drmm_drm_panel_bridge_release: In

Thanks,
Jagan.
Maxime Ripard March 29, 2023, 4:08 p.m. UTC | #3
On Wed, Mar 29, 2023 at 08:56:29PM +0530, Jagan Teki wrote:
> On Wed, Mar 29, 2023 at 8:33 PM Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > On Wed, Mar 29, 2023 at 06:46:08PM +0530, Jagan Teki wrote:
> > > Implement a DRM-managed action helper that returns the next DSI bridge
> > > in the chain.
> > >
> > > Unlike general bridge return helper drmm_of_get_bridge, this helper
> > > uses the dsi specific panel_or_bridge helper to find the next DSI
> > > device in the pipeline.
> > >
> > > Helper lookup a given downstream DSI device that has been added via
> > > child or OF-graph port or ports node.
> > >
> > > Upstream DSI looks for downstream devices using drm pointer, port and
> > > endpoint number. Downstream devices added via child node don't affect
> > > the port and endpoint number arguments.
> > >
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> >
> > If you intend to use it with the sun4i driver, then don't. The sun4i
> > driver is barely using drm-managed resources, so chances are all its
> > resources will be freed by the time this action will run.
> 
> Any idea how to check all resources will be freed before this
> DRM-managed action helper runs? I did test the panel insertion and
> removal at runtime and I can see that the action helper
> (drmm_drm_panel_bridge_release) is triggered at removal time.
> 
> Here is the log for it.
> # insmod panel-bananapi-s070wv20-icn6211.ko
> [   11.411894] sun4i-drm display-engine: bound
> 1e00000.display-frontend (ops 0xc0951eb4)
> [   11.420253] sun4i-drm display-engine: bound 1e60000.display-backend
> (ops 0xc0951620)
> [   11.428128] sun4i-drm display-engine: bound 1e70000.drc (ops 0xc0951150)
> [   11.435574] sun4i-drm display-engine: No panel or bridge found...
> RGB output disabled
> [   11.443484] sun4i-drm display-engine: bound 1c0c000.lcd-controller
> (ops 0xc094fdb0)
> [   11.451264] sun4i-drm display-engine: bound 1ca0000.dsi (ops 0xc0952f04)
> [   11.462479] [drm] Initialized sun4i-drm 1.0.0 20150629 for
> display-engine on minor 1
> [   11.963246] Console: switching to colour frame buffer device 100x30
> [   12.046329] sun4i-drm display-engine: [drm] fb0: sun4i-drmdrmfb
> frame buffer device
> [   12.082641] sun6i-mipi-dsi 1ca0000.dsi: Attached device s070wv20-ct16-icn62
> # rmmod panel-bananapi-s070wv20-icn6211.ko
> [   16.306388] Console: switching to colour dummy device 80x30
> [   16.466963] drmm_drm_panel_bridge_release: In

Enable KASAN, unload the DSI controller module or unbind its device,
and watch things go boom :)

Maxime

Patch

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index d4b112911a99..d047c7d9551d 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -501,4 +501,38 @@  struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
 }
 EXPORT_SYMBOL(drmm_of_get_bridge);
 
+/**
+ * drmm_of_dsi_get_bridge - Return next DSI bridge in the chain
+ * @drm: device to tie the bridge lifetime to
+ * @np: device tree node containing DSI output ports
+ * @port: port in the device tree node
+ * @endpoint: endpoint in the device tree node
+ *
+ * Given a DT node's port and endpoint number, finds the connected node
+ * and returns the associated DSI bridge if any, or creates and returns
+ * a DSI panel bridge instance if a panel is connected.
+ *
+ * Returns a drmm managed pointer to the DSI bridge if successful, or
+ * an error pointer otherwise.
+ */
+struct drm_bridge *drmm_of_dsi_get_bridge(struct drm_device *drm,
+					  struct device_node *np,
+					  u32 port, u32 endpoint)
+{
+	struct drm_bridge *bridge;
+	struct drm_panel *panel;
+	int ret;
+
+	ret = drm_of_dsi_find_panel_or_bridge(np, port, endpoint,
+					      &panel, &bridge);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (panel)
+		bridge = drmm_panel_bridge_add(drm, panel);
+
+	return bridge;
+}
+EXPORT_SYMBOL(drmm_of_dsi_get_bridge);
+
 #endif
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 42f86327b40a..a1a31704b917 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -931,6 +931,9 @@  struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node
 					  u32 port, u32 endpoint);
 struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, struct device_node *node,
 					  u32 port, u32 endpoint);
+struct drm_bridge *drmm_of_dsi_get_bridge(struct drm_device *drm,
+					  struct device_node *node,
+					  u32 port, u32 endpoint);
 #else
 static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
 							struct device_node *node,
@@ -947,6 +950,13 @@  static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
 {
 	return ERR_PTR(-ENODEV);
 }
+
+static inline struct drm_bridge *drmm_of_dsi_get_bridge(struct drm_device *drm,
+							struct device_node *node,
+							u32 port, u32 endpoint)
+{
+	return ERR_PTR(-ENODEV);
+}
 #endif
 
 #endif