mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	Deleted following upstreamed patches: bcm27xx: 950-0006-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch bcm27xx: 950-0420-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch bcm27xx: 950-0425-drm-vc4-A-present-but-empty-dmas-disables-audio.patch bcm27xx: 950-0432-vc4-drm-Avoid-full-hdmi-audio-fifo-writes.patch bcm27xx: 950-0433-vc4-drm-vc4_plane-Remove-subpixel-positioning-check.patch bcm27xx: 950-0435-drm-vc4-Correct-pixel-order-for-DSI0.patch bcm27xx: 950-0436-drm-vc4-Register-dsi0-as-the-correct-vc4-encoder-typ.patch bcm27xx: 950-0437-drm-vc4-Fix-dsi0-interrupt-support.patch bcm27xx: 950-0438-drm-vc4-Add-correct-stop-condition-to-vc4_dsi_encode.patch bcm27xx: 950-0443-drm-vc4-Fix-timings-for-interlaced-modes.patch bcm27xx: 950-0445-drm-vc4-Fix-margin-calculations-for-the-right-bottom.patch bcm27xx: 950-0475-drm-vc4-Reset-HDMI-MISC_CONTROL-register.patch bcm27xx: 950-0476-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch bcm27xx: 950-0477-drm-vc4-Correct-DSI-divider-calculations.patch bcm27xx: 950-0664-drm-vc4-dsi-Correct-max-divider-to-255-not-7.patch bcm53xx: 072-next-ARM_dts_BCM53015-add-mr26.patch mediatek: 920-linux-next-dts-mt7622-bpi-r64-fix-wps-button.patch Manually rebased following patches: bcm27xx: 950-0004-drm-vc4-hdmi-Remove-the-DDC-probing-for-status-detec.patch bcm27xx: 950-0700-net-phy-lan87xx-Decrease-phy-polling-rate.patch bcm27xx: 950-0711-drm-vc4-Rename-bridge-to-out_bridge.patch bcm27xx: 950-0713-drm-vc4-Remove-splitting-the-bridge-chain-from-the-d.patch bcm27xx: 950-0715-drm-vc4-Convert-vc4_dsi-to-using-a-bridge-instead-of.patch bcm27xx: 950-0787-vc4-drm-vc4_plane-Keep-fractional-source-coords-insi.patch bcm27xx: 950-0914-mmc-block-Don-t-do-single-sector-reads-during-recove.patch Runtime tested on turris-omnia and glinet-b1300. Tested-by: John Audia <therealgraysky@proton.me> [bcm2711/RPi4B, mt7622/RT3200] Signed-off-by: Petr Štetiar <ynezz@true.cz>
		
			
				
	
	
		
			265 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 3e6793632310f9991b75c3095a9795b6a8d1d859 Mon Sep 17 00:00:00 2001
 | 
						|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
Date: Wed, 15 Dec 2021 17:57:45 +0000
 | 
						|
Subject: [PATCH] drm/vc4: Convert vc4_dsi to using a bridge instead of
 | 
						|
 encoder.
 | 
						|
 | 
						|
Remove the encoder functions, and create a bridge attached to
 | 
						|
this dumb encoder which implements the same functionality.
 | 
						|
 | 
						|
As a bridge has state which an encoder doesn't, we need to
 | 
						|
add the state management functions as well.
 | 
						|
 | 
						|
As there is no bridge atomic_mode_set, move the initialisation
 | 
						|
code that was in mode_set into _pre_enable.
 | 
						|
The code to actually enable and disable sending video are split
 | 
						|
from the general control into _enable and _disable.
 | 
						|
 | 
						|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
---
 | 
						|
 drivers/gpu/drm/vc4/vc4_dsi.c | 124 ++++++++++++++++++++++++----------
 | 
						|
 1 file changed, 90 insertions(+), 34 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
 | 
						|
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
 | 
						|
@@ -554,6 +554,7 @@ struct vc4_dsi {
 | 
						|
 	struct mipi_dsi_host dsi_host;
 | 
						|
 	struct drm_encoder *encoder;
 | 
						|
 	struct drm_bridge *out_bridge;
 | 
						|
+	struct drm_bridge bridge;
 | 
						|
 
 | 
						|
 	void __iomem *regs;
 | 
						|
 
 | 
						|
@@ -655,6 +656,12 @@ to_vc4_dsi_encoder(struct drm_encoder *e
 | 
						|
 	return container_of(encoder, struct vc4_dsi_encoder, base.base);
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline struct vc4_dsi *
 | 
						|
+bridge_to_vc4_dsi(struct drm_bridge *bridge)
 | 
						|
+{
 | 
						|
+	return container_of(bridge, struct vc4_dsi, bridge);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static const struct debugfs_reg32 dsi0_regs[] = {
 | 
						|
 	VC4_REG32(DSI0_CTRL),
 | 
						|
 	VC4_REG32(DSI0_STAT),
 | 
						|
@@ -792,11 +799,21 @@ dsi_esc_timing(u32 ns)
 | 
						|
 	return DIV_ROUND_UP(ns, ESC_TIME_NS);
 | 
						|
 }
 | 
						|
 
 | 
						|
-static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
 | 
						|
-				    struct drm_atomic_state *state)
 | 
						|
+static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
 | 
						|
+				   struct drm_bridge_state *state)
 | 
						|
+{
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
+	u32 disp0_ctrl;
 | 
						|
+
 | 
						|
+	disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
 | 
						|
+	disp0_ctrl &= ~DSI_DISP0_ENABLE;
 | 
						|
+	DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
 | 
						|
+					struct drm_bridge_state *state)
 | 
						|
 {
 | 
						|
-	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 | 
						|
-	struct vc4_dsi *dsi = vc4_encoder->dsi;
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
 	struct device *dev = &dsi->pdev->dev;
 | 
						|
 
 | 
						|
 	vc4_dsi_ulps(dsi, true);
 | 
						|
@@ -821,12 +838,11 @@ static void vc4_dsi_encoder_disable(stru
 | 
						|
  * higher-than-expected clock rate to the panel, but that's what the
 | 
						|
  * firmware does too.
 | 
						|
  */
 | 
						|
-static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
 | 
						|
-				       const struct drm_display_mode *mode,
 | 
						|
-				       struct drm_display_mode *adjusted_mode)
 | 
						|
+static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
 | 
						|
+				      const struct drm_display_mode *mode,
 | 
						|
+				      struct drm_display_mode *adjusted_mode)
 | 
						|
 {
 | 
						|
-	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 | 
						|
-	struct vc4_dsi *dsi = vc4_encoder->dsi;
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
 	struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
 | 
						|
 	unsigned long parent_rate = clk_get_rate(phy_parent);
 | 
						|
 	unsigned long pixel_clock_hz = mode->clock * 1000;
 | 
						|
@@ -858,16 +874,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
 | 
						|
 	return true;
 | 
						|
 }
 | 
						|
 
 | 
						|
-static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
 | 
						|
-				     struct drm_crtc_state *crtc_state,
 | 
						|
-				     struct drm_connector_state *conn_state)
 | 
						|
+static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
 | 
						|
+				      struct drm_bridge_state *old_state)
 | 
						|
 {
 | 
						|
-	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 | 
						|
-	struct vc4_dsi *dsi = vc4_encoder->dsi;
 | 
						|
+	struct drm_atomic_state *state = old_state->base.state;
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
+	const struct drm_crtc_state *crtc_state;
 | 
						|
 	struct device *dev = &dsi->pdev->dev;
 | 
						|
 	const struct drm_display_mode *mode;
 | 
						|
+	struct drm_connector *connector;
 | 
						|
 	bool debug_dump_regs = false;
 | 
						|
 	unsigned long hs_clock;
 | 
						|
+	struct drm_crtc *crtc;
 | 
						|
 	u32 ui_ns;
 | 
						|
 	/* Minimum LP state duration in escape clock cycles. */
 | 
						|
 	u32 lpx = dsi_esc_timing(60);
 | 
						|
@@ -888,6 +906,14 @@ static void vc4_dsi_encoder_mode_set(str
 | 
						|
 		drm_print_regset32(&p, &dsi->regset);
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	/*
 | 
						|
+	 * Retrieve the CRTC adjusted mode. This requires a little dance to go
 | 
						|
+	 * from the bridge to the encoder, to the connector and to the CRTC.
 | 
						|
+	 */
 | 
						|
+	connector = drm_atomic_get_new_connector_for_encoder(state,
 | 
						|
+							     bridge->encoder);
 | 
						|
+	crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
 | 
						|
+	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 | 
						|
 	mode = &crtc_state->adjusted_mode;
 | 
						|
 
 | 
						|
 	pixel_clock_hz = mode->clock * 1000;
 | 
						|
@@ -1102,14 +1128,6 @@ static void vc4_dsi_encoder_mode_set(str
 | 
						|
 		       ~DSI_PORT_BIT(PHY_AFEC0_RESET));
 | 
						|
 
 | 
						|
 	vc4_dsi_ulps(dsi, false);
 | 
						|
-}
 | 
						|
-
 | 
						|
-static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
 | 
						|
-				   struct drm_atomic_state *state)
 | 
						|
-{
 | 
						|
-	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 | 
						|
-	struct vc4_dsi *dsi = vc4_encoder->dsi;
 | 
						|
-	bool debug_dump_regs = false;
 | 
						|
 
 | 
						|
 	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
 | 
						|
 		DSI_PORT_WRITE(DISP0_CTRL,
 | 
						|
@@ -1118,13 +1136,23 @@ static void vc4_dsi_encoder_enable(struc
 | 
						|
 			       VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) |
 | 
						|
 			       VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME,
 | 
						|
 					     DSI_DISP0_LP_STOP_CTRL) |
 | 
						|
-			       DSI_DISP0_ST_END |
 | 
						|
-			       DSI_DISP0_ENABLE);
 | 
						|
+			       DSI_DISP0_ST_END);
 | 
						|
 	} else {
 | 
						|
 		DSI_PORT_WRITE(DISP0_CTRL,
 | 
						|
-			       DSI_DISP0_COMMAND_MODE |
 | 
						|
-			       DSI_DISP0_ENABLE);
 | 
						|
+			       DSI_DISP0_COMMAND_MODE);
 | 
						|
 	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
 | 
						|
+				  struct drm_bridge_state *old_state)
 | 
						|
+{
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
+	bool debug_dump_regs = false;
 | 
						|
+	u32 disp0_ctrl;
 | 
						|
+
 | 
						|
+	disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
 | 
						|
+	disp0_ctrl |= DSI_DISP0_ENABLE;
 | 
						|
+	DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
 | 
						|
 
 | 
						|
 	if (debug_dump_regs) {
 | 
						|
 		struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
 | 
						|
@@ -1133,6 +1161,16 @@ static void vc4_dsi_encoder_enable(struc
 | 
						|
 	}
 | 
						|
 }
 | 
						|
 
 | 
						|
+static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
 | 
						|
+				 enum drm_bridge_attach_flags flags)
 | 
						|
+{
 | 
						|
+	struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
 | 
						|
+
 | 
						|
+	/* Attach the panel or bridge to the dsi bridge */
 | 
						|
+	return drm_bridge_attach(bridge->encoder, dsi->out_bridge,
 | 
						|
+				 &dsi->bridge, flags);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
 | 
						|
 				     const struct mipi_dsi_msg *msg)
 | 
						|
 {
 | 
						|
@@ -1309,6 +1347,7 @@ static int vc4_dsi_host_attach(struct mi
 | 
						|
 			       struct mipi_dsi_device *device)
 | 
						|
 {
 | 
						|
 	struct vc4_dsi *dsi = host_to_dsi(host);
 | 
						|
+	int ret;
 | 
						|
 
 | 
						|
 	dsi->lanes = device->lanes;
 | 
						|
 	dsi->channel = device->channel;
 | 
						|
@@ -1343,7 +1382,15 @@ static int vc4_dsi_host_attach(struct mi
 | 
						|
 		return 0;
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	return component_add(&dsi->pdev->dev, &vc4_dsi_ops);
 | 
						|
+	drm_bridge_add(&dsi->bridge);
 | 
						|
+
 | 
						|
+	ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops);
 | 
						|
+	if (ret) {
 | 
						|
+		drm_bridge_remove(&dsi->bridge);
 | 
						|
+		return ret;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
 static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
 | 
						|
@@ -1352,6 +1399,7 @@ static int vc4_dsi_host_detach(struct mi
 | 
						|
 	struct vc4_dsi *dsi = host_to_dsi(host);
 | 
						|
 
 | 
						|
 	component_del(&dsi->pdev->dev, &vc4_dsi_ops);
 | 
						|
+	drm_bridge_remove(&dsi->bridge);
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -1361,11 +1409,16 @@ static const struct mipi_dsi_host_ops vc
 | 
						|
 	.transfer = vc4_dsi_host_transfer,
 | 
						|
 };
 | 
						|
 
 | 
						|
-static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
 | 
						|
-	.atomic_disable = vc4_dsi_encoder_disable,
 | 
						|
-	.atomic_enable = vc4_dsi_encoder_enable,
 | 
						|
-	.mode_fixup = vc4_dsi_encoder_mode_fixup,
 | 
						|
-	.atomic_mode_set = vc4_dsi_encoder_mode_set,
 | 
						|
+static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
 | 
						|
+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
 | 
						|
+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
 | 
						|
+	.atomic_reset = drm_atomic_helper_bridge_reset,
 | 
						|
+	.atomic_pre_enable = vc4_dsi_bridge_pre_enable,
 | 
						|
+	.atomic_enable = vc4_dsi_bridge_enable,
 | 
						|
+	.atomic_disable = vc4_dsi_bridge_disable,
 | 
						|
+	.atomic_post_disable = vc4_dsi_bridge_post_disable,
 | 
						|
+	.attach = vc4_dsi_bridge_attach,
 | 
						|
+	.mode_fixup = vc4_dsi_bridge_mode_fixup,
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const struct vc4_dsi_variant bcm2711_dsi1_variant = {
 | 
						|
@@ -1692,9 +1745,8 @@ static int vc4_dsi_bind(struct device *d
 | 
						|
 		return ret;
 | 
						|
 
 | 
						|
 	drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
 | 
						|
-	drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
 | 
						|
 
 | 
						|
-	ret = drm_bridge_attach(dsi->encoder, dsi->out_bridge, NULL, 0);
 | 
						|
+	ret = drm_bridge_attach(dsi->encoder, &dsi->bridge, NULL, 0);
 | 
						|
 	if (ret)
 | 
						|
 		return ret;
 | 
						|
 
 | 
						|
@@ -1730,6 +1782,10 @@ static int vc4_dsi_dev_probe(struct plat
 | 
						|
 		return -ENOMEM;
 | 
						|
 	dev_set_drvdata(dev, dsi);
 | 
						|
 
 | 
						|
+	dsi->bridge.funcs = &vc4_dsi_bridge_funcs;
 | 
						|
+	dsi->bridge.of_node = dev->of_node;
 | 
						|
+	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 | 
						|
+
 | 
						|
 	dsi->pdev = pdev;
 | 
						|
 	dsi->dsi_host.ops = &vc4_dsi_host_ops;
 | 
						|
 	dsi->dsi_host.dev = dev;
 |