From af3f381a59c10f6bd49d86a5ff2325b6ebeb79e9 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 27 Apr 2020 19:07:50 +0100
Subject: [PATCH] vc4_hdmi: BCM2835 requires a fixed hsm clock for CEC
 to work

Signed-off-by: popcornmix <popcornmix@gmail.com>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 32 ++++++++++++++++++++++++++------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
 2 files changed, 29 insertions(+), 6 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -580,12 +580,7 @@ static void vc4_hdmi_encoder_enable(stru
 		return;
 	}
 
-	/*
-	 * The HSM rate needs to be slightly greater than the pixel clock, with
-	 * a minimum of 108MHz.
-	 * Use 101% as this is what the firmware uses.
-	 */
-	hsm_rate = max_t(unsigned long, 108000000, (pixel_rate / 100) * 101);
+	hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate);
 	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
@@ -753,6 +748,28 @@ static u32 vc5_hdmi_get_hsm_clock(struct
 	return 108000000;
 }
 
+static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate)
+{
+	/*
+	 * This is the rate that is set by the firmware.  The number
+	 * needs to be a bit higher than the pixel clock rate
+	 * (generally 148.5Mhz).
+	 */
+
+	return 163682864;
+}
+
+static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate)
+{
+	/*
+	 * The HSM rate needs to be slightly greater than the pixel clock, with
+	 * a minimum of 108MHz.
+	 * Use 101% as this is what the firmware uses.
+	 */
+
+	return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101);
+}
+
 static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 {
 	int i;
@@ -1749,6 +1766,7 @@ static const struct vc4_hdmi_variant bcm
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
 	.get_hsm_clock		= vc4_hdmi_get_hsm_clock,
+	.calc_hsm_clock		= vc4_hdmi_calc_hsm_clock,
 	.channel_map		= vc4_hdmi_channel_map,
 };
 
@@ -1773,6 +1791,7 @@ static const struct vc4_hdmi_variant bcm
 	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
 	.get_hsm_clock		= vc5_hdmi_get_hsm_clock,
+	.calc_hsm_clock		= vc5_hdmi_calc_hsm_clock,
 	.channel_map		= vc5_hdmi_channel_map,
 };
 
@@ -1797,6 +1816,7 @@ static const struct vc4_hdmi_variant bcm
 	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
 	.get_hsm_clock		= vc5_hdmi_get_hsm_clock,
+	.calc_hsm_clock		= vc5_hdmi_calc_hsm_clock,
 	.channel_map		= vc5_hdmi_channel_map,
 };
 
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -92,6 +92,9 @@ struct vc4_hdmi_variant {
 	/* Callback to get hsm clock */
 	u32 (*get_hsm_clock)(struct vc4_hdmi *vc4_hdmi);
 
+	/* Callback to get hsm clock */
+	u32 (*calc_hsm_clock)(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate);
+
 	/* Callback to get channel map */
 	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
 };
