[PATCH v2 19/27] drm/rockchip: inno_hdmi: Move tmds rate to connector state subclass

From: Alex Bee
Date: Sat Dec 16 2023 - 11:32:49 EST


Similar to the othter members of inno_hdmi_connector_state the tmds_rate is
not a property of the device, but of the connector state. Move it to
inno_hdmi_connector_state and make it a long to comply with the clock
framework. To get arround the issue of not having the connector state when
inno_hdmi_i2c_init is called in the bind path, getting the tmds rate is
wrapped in function which returns the fallback rate if the connector
doesn't have a state yet.

Signed-off-by: Alex Bee <knaerzche@xxxxxxxxx>
---
changes in v2:
- new patch

drivers/gpu/drm/rockchip/inno_hdmi.c | 36 +++++++++++++++++++---------
1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index f9bfae1e97a2..6799d24501b8 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -47,14 +47,13 @@ struct inno_hdmi {

struct inno_hdmi_i2c *i2c;
struct i2c_adapter *ddc;
-
- unsigned int tmds_rate;
};

struct inno_hdmi_connector_state {
struct drm_connector_state base;
unsigned int enc_out_format;
unsigned int colorimetry;
+ unsigned long tmds_rate;
};

static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
@@ -133,11 +132,33 @@ static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
hdmi_writeb(hdmi, offset, temp);
}

+static unsigned long inno_hdmi_tmds_rate(struct inno_hdmi *hdmi)
+{
+ struct drm_connector *connector = &hdmi->connector;
+ struct drm_connector_state *conn_state = connector->state;
+ struct inno_hdmi_connector_state *inno_conn_state;
+
+ if (conn_state) {
+ inno_conn_state = to_inno_hdmi_conn_state(conn_state);
+ return inno_conn_state->tmds_rate;
+ }
+
+ /*
+ * When IP controller haven't configured to an accurate video
+ * timing, then the TMDS clock source would be switched to
+ * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
+ * and reconfigure the DDC clock.
+ */
+
+ return clk_get_rate(hdmi->pclk);
+}
+
static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
{
int ddc_bus_freq;
+ unsigned long tmds_rate = inno_hdmi_tmds_rate(hdmi);

- ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
+ ddc_bus_freq = (tmds_rate >> 2) / HDMI_SCL_RATE;

hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
@@ -431,7 +452,7 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
* DCLK_LCDC, so we need to init the TMDS rate to mode pixel
* clock rate, and reconfigure the DDC clock.
*/
- hdmi->tmds_rate = mode->clock * 1000;
+ inno_conn_state->tmds_rate = mode->clock * 1000;
inno_hdmi_i2c_init(hdmi);

/* Unmute video and audio output */
@@ -823,13 +844,6 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
goto err_disable_clk;
}

- /*
- * When IP controller haven't configured to an accurate video
- * timing, then the TMDS clock source would be switched to
- * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
- * and reconfigure the DDC clock.
- */
- hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
inno_hdmi_i2c_init(hdmi);

ret = inno_hdmi_register(drm, hdmi);
--
2.43.0