Message ID | 20250320-cdns-dsi-impro-v1-3-725277c5f43b@ideasonboard.com |
---|---|
State | New |
Headers | show |
Series | drm/bridge: cdns-dsi: Make it work a bit better | expand |
On Thu, Mar 20, 2025 at 05:59:58PM +0200, Tomi Valkeinen wrote: > At the moment the driver just sets the clock rate with clk_set_rate(), > and if the resulting rate is not the same as requested, prints a debug > print, but nothing else. > > Add mode_fixup(), in which the clk_round_rate() is used to get the > "rounded" rate, and set that to the adjusted_mode. > > In practice, with the current K3 SoCs, the display PLL is capable of > producing very exact clocks, so most likely the rounded rate is the same > as the original one. > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > drivers/gpu/drm/tidss/tidss_crtc.c | 22 ++++++++++++++++++++++ > drivers/gpu/drm/tidss/tidss_dispc.c | 6 ++++++ > drivers/gpu/drm/tidss/tidss_dispc.h | 2 ++ > 3 files changed, 30 insertions(+) > > diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c > index 1604eca265ef..b3338dac25bc 100644 > --- a/drivers/gpu/drm/tidss/tidss_crtc.c > +++ b/drivers/gpu/drm/tidss/tidss_crtc.c > @@ -309,7 +309,29 @@ enum drm_mode_status tidss_crtc_mode_valid(struct drm_crtc *crtc, > return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode); > } > > +static bool tidss_crtc_mode_fixup(struct drm_crtc *crtc, > + const struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > + struct tidss_crtc *tcrtc = to_tidss_crtc(crtc); > + struct drm_device *ddev = crtc->dev; > + struct tidss_device *tidss = to_tidss(ddev); > + long rate; > + > + rate = dispc_vp_round_clk_rate(tidss->dispc, tcrtc->hw_videoport, > + adjusted_mode->clock * 1000); > + if (rate < 0) > + return false; > + > + adjusted_mode->clock = rate / 1000; > + > + drm_mode_set_crtcinfo(adjusted_mode, 0); > + > + return true; > +} mode_fixup is deprecated in favor of atomic_check. If you can't use it for some reason, it should be documented one way or another. Maxime
diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index 1604eca265ef..b3338dac25bc 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -309,7 +309,29 @@ enum drm_mode_status tidss_crtc_mode_valid(struct drm_crtc *crtc, return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode); } +static bool tidss_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct tidss_crtc *tcrtc = to_tidss_crtc(crtc); + struct drm_device *ddev = crtc->dev; + struct tidss_device *tidss = to_tidss(ddev); + long rate; + + rate = dispc_vp_round_clk_rate(tidss->dispc, tcrtc->hw_videoport, + adjusted_mode->clock * 1000); + if (rate < 0) + return false; + + adjusted_mode->clock = rate / 1000; + + drm_mode_set_crtcinfo(adjusted_mode, 0); + + return true; +} + static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = { + .mode_fixup = tidss_crtc_mode_fixup, .atomic_check = tidss_crtc_atomic_check, .atomic_flush = tidss_crtc_atomic_flush, .atomic_enable = tidss_crtc_atomic_enable, diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index a5107f2732b1..3930fb7f03c2 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -1318,6 +1318,12 @@ unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate) return (unsigned int)(abs(((rr - r) * 100) / r)); } +long dispc_vp_round_clk_rate(struct dispc_device *dispc, u32 hw_videoport, + unsigned long rate) +{ + return clk_round_rate(dispc->vp_clk[hw_videoport], rate); +} + int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport, unsigned long rate) { diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h index c31b477a18b0..d4c335e918fb 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.h +++ b/drivers/gpu/drm/tidss/tidss_dispc.h @@ -120,6 +120,8 @@ enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc, const struct drm_display_mode *mode); int dispc_vp_enable_clk(struct dispc_device *dispc, u32 hw_videoport); void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport); +long dispc_vp_round_clk_rate(struct dispc_device *dispc, u32 hw_videoport, + unsigned long rate); int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport, unsigned long rate); void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
At the moment the driver just sets the clock rate with clk_set_rate(), and if the resulting rate is not the same as requested, prints a debug print, but nothing else. Add mode_fixup(), in which the clk_round_rate() is used to get the "rounded" rate, and set that to the adjusted_mode. In practice, with the current K3 SoCs, the display PLL is capable of producing very exact clocks, so most likely the rounded rate is the same as the original one. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- drivers/gpu/drm/tidss/tidss_crtc.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/tidss/tidss_dispc.c | 6 ++++++ drivers/gpu/drm/tidss/tidss_dispc.h | 2 ++ 3 files changed, 30 insertions(+)