diff mbox

[v3,15/20] drm: bridge: dw-hdmi: Handle overflow workaround based on device version

Message ID 20170117082910.27023-16-laurent.pinchart+renesas@ideasonboard.com (mailing list archive)
State Accepted
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Laurent Pinchart Jan. 17, 2017, 8:29 a.m. UTC
Use the device version queried at runtime instead of the device type
provided through platform data to handle the overflow workaround. This
will make support of other SoCs integrating the same HDMI TX controller
version easier.

Among the supported platforms only i.MX6DL and i.MX6Q have been
identified as needing the workaround. Disabling it on Rockchip RK3288
(which integrates a v2.00a controller) didn't produce any error or
artifact.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 46 ++++++++++++++++++++++++++++------------
 1 file changed, 33 insertions(+), 13 deletions(-)

Comments

Eugeniu Rosca Aug. 20, 2017, 4:37 p.m. UTC | #1
Hello Laurent, Jose,

As you might know, Renesas uses the same Synopsis Designware HDMI
transmitter IP in the Rcar Gen3 SoCs. There are v4.9+ patches present
in [1] to enable support for this.

Why I reply in this specific thread is because I am having a trial
attempt to rebase the RCAR-specific v4.9+ dw-hdmi patches on top of
a more recent kernel, which already contains mainline commit [2],
being proposed as part of this patch series.

Based on [3], it looks like that the `dw_hdmi_clear_overflow()`
workaround, formerly implemented for IMX6, is still used on Rcar3.

Current patch (integrated in upstream as commit [2]) assumes that
the workaround is only needed for the older v1.30a and v1.31a IP
implementations. Given much newer HDMI controller contained in RCAR3
(kernel reports v2.01a) and given it's you who witnessed the
original issue, I wonder what is the easiest way to check if the
problem fixed by the workaround still occurs on the Renesas SoC?
I have plenty of Salvator-X and ULCB boards, so HW is not a problem.

Your feedback is much appreciated.

Best regards,
Eugeniu.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-bsp.git/
[2] mainline commit be41fc55f1aa ("drm: bridge: dw-hdmi: Handle overflow workaround based on device version")
[3] https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-bsp.git/commit/?h=8fdb115e6e1f
diff mbox

Patch

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 730a7558d4d4..f4faa14213e5 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -117,8 +117,10 @@  struct dw_hdmi {
 	struct drm_connector connector;
 	struct drm_bridge bridge;
 
-	struct platform_device *audio;
 	enum dw_hdmi_devtype dev_type;
+	unsigned int version;
+
+	struct platform_device *audio;
 	struct device *dev;
 	struct clk *isfr_clk;
 	struct clk *iahb_clk;
@@ -1323,19 +1325,38 @@  static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
 /* Workaround to clear the overflow condition */
 static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
 {
-	int count;
+	unsigned int count;
+	unsigned int i;
 	u8 val;
 
-	/* TMDS software reset */
-	hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+	/*
+	 * Under some circumstances the Frame Composer arithmetic unit can miss
+	 * an FC register write due to being busy processing the previous one.
+	 * The issue can be worked around by issuing a TMDS software reset and
+	 * then write one of the FC registers several times.
+	 *
+	 * The number of iterations matters and depends on the HDMI TX revision
+	 * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
+	 * i.MX6DL (v1.31a) have been identified as needing the workaround, with
+	 * 4 and 1 iterations respectively.
+	 */
 
-	val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
-	if (hdmi->dev_type == IMX6DL_HDMI) {
-		hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+	switch (hdmi->version) {
+	case 0x130a:
+		count = 4;
+		break;
+	case 0x131a:
+		count = 1;
+		break;
+	default:
 		return;
 	}
 
-	for (count = 0; count < 4; count++)
+	/* TMDS software reset */
+	hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+
+	val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
+	for (i = 0; i < count; i++)
 		hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
 }
 
@@ -1832,7 +1853,6 @@  __dw_hdmi_probe(struct platform_device *pdev,
 	int irq;
 	int ret;
 	u32 val = 1;
-	u16 version;
 	u8 prod_id0;
 	u8 prod_id1;
 	u8 config0;
@@ -1917,21 +1937,21 @@  __dw_hdmi_probe(struct platform_device *pdev,
 	}
 
 	/* Product and revision IDs */
-	version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
-		| (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
+	hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
+		      | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
 	prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
 	prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
 
 	if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
 	    (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
 		dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
-			version, prod_id0, prod_id1);
+			hdmi->version, prod_id0, prod_id1);
 		ret = -ENODEV;
 		goto err_iahb;
 	}
 
 	dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
-		 version >> 12, version & 0xfff,
+		 hdmi->version >> 12, hdmi->version & 0xfff,
 		 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
 
 	initialize_hdmi_ih_mutes(hdmi);