From 89f12139652efe1b90b24484eb2ed70cd797e84b Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 26 Apr 2024 17:48:06 +0100
Subject: [PATCH 1071/1085] drm/vc4: Fixup mode for 7inch panel on DSI0

The TC358762 bridge and panel decodes the mode differently on
DSI0 to DSI1 for no obvious reason, and results in a shift off
the screen.
Whilst it would be possible to change the compatible used for
the panel, that then messes up Pi5.

As it appears to be restricted to vc4 DSI0, fix up the mode
in vc4_dsi.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 drivers/gpu/drm/vc4/vc4_dsi.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -866,6 +866,7 @@ static bool vc4_dsi_bridge_mode_fixup(st
 	unsigned long pixel_clock_hz = mode->clock * 1000;
 	unsigned long pll_clock = pixel_clock_hz * dsi->divider;
 	int divider;
+	u16 htotal;
 
 	/* Find what divider gets us a faster clock than the requested
 	 * pixel clock.
@@ -882,12 +883,27 @@ static bool vc4_dsi_bridge_mode_fixup(st
 	pixel_clock_hz = pll_clock / dsi->divider;
 
 	adjusted_mode->clock = pixel_clock_hz / 1000;
+	htotal = mode->htotal;
+
+	if (dsi->variant->port == 0 && mode->clock == 30000 &&
+	    mode->hdisplay == 800 && mode->htotal == (800 + 59 + 2 + 45) &&
+	    mode->vdisplay == 480 && mode->vtotal == (480 + 7 + 2 + 22)) {
+		/*
+		 * Raspberry Pi 7" panel via TC358762 seems to have an issue on
+		 * DSI0 that it doesn't actually follow the vertical timing that
+		 * is otherwise identical to that produced on DSI1.
+		 * Fixup the mode.
+		 */
+		htotal = 800 + 59 + 2 + 47;
+		adjusted_mode->vtotal = 480 + 7 + 2 + 45;
+		adjusted_mode->crtc_vtotal = 480 + 7 + 2 + 45;
+	}
 
 	/* Given the new pixel clock, adjust HFP to keep vrefresh the same. */
-	adjusted_mode->htotal = adjusted_mode->clock * mode->htotal /
+	adjusted_mode->htotal = adjusted_mode->clock * htotal /
 				mode->clock;
-	adjusted_mode->hsync_end += adjusted_mode->htotal - mode->htotal;
-	adjusted_mode->hsync_start += adjusted_mode->htotal - mode->htotal;
+	adjusted_mode->hsync_end += adjusted_mode->htotal - htotal;
+	adjusted_mode->hsync_start += adjusted_mode->htotal - htotal;
 
 	return true;
 }
