Messages in this thread | | | Date | Mon, 18 Dec 2023 13:49:52 +0100 | Subject | Re: [PATCH v2 19/27] drm/rockchip: inno_hdmi: Move tmds rate to connector state subclass | From | Alex Bee <> |
| |
Am 18.12.23 um 11:06 schrieb Maxime Ripard: > Hi, > > On Sat, Dec 16, 2023 at 05:26:30PM +0100, Alex Bee wrote: >> 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@gmail.com> >> --- >> 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); > I still think my patch is better there. > > There's two places that use the inno_hdmi.tmds_rate field: the two > callers of inno_hdmi_i2c_init(). One is at bind time and needs to > initialise it with a sane default since we don't have a mode set yet, > the other is to update the internal clock rate while we have a mode set. That’s, unfortunately, not fully true: inno_hdmi_set_pwr_mode not only called at mode_set-time, but also in inno_hdmi_reset which is called in the bind path (where we do not have a mode). That’s the point why I thought extracting this in function makes sense. Otherwise I would have to pass the tmds_rate to inno_hdmi_set_pwr_mode (also for the LOWER_PWR-case where I don't need it) or do that whole fallback-if-no-mode thing in inno_hdmi_set_pwr_mode directly. Neither would make the code easier to follow. Being able to use it in inno_hdmi_i2c_init also is a nice gimmick. I agree, having it in the custom connector state is not strictly required, but I'd really like to keep the wrapping function.
Alex
> Since there's a single "modeset" user, there's no need to store it in > the state structure at all: it can be a local variable. > > And in the bind function, you're not going to use the state structure > either since there's no state, and it's just a default that has no > relation to the modeset code at all. > > Your function on the other end tries to reconcile and handle the two. > But there's no reason to, it just makes the code harder to follow. Just > pass the parent rate you want to init with as an argument and it's easy > to read and maintain. > > Maxime
| |