On Tue, May 21, 2024 at 12:13:42PM +0200, Maxime Ripard wrote: > A lot of HDMI drivers have some variation of the formula to calculate > the TMDS character rate from a mode, but few of them actually take all > parameters into account. > > Let's create a helper to provide that rate taking all parameters into > account. > > Reviewed-by: Dave Stevenson <dave.stevenson@xxxxxxxxxxxxxxx> > Signed-off-by: Maxime Ripard <mripard@xxxxxxxxxx> > --- > drivers/gpu/drm/display/drm_hdmi_helper.c | 57 +++++++++++++++++++++++++++++++ > include/drm/display/drm_hdmi_helper.h | 4 +++ > 2 files changed, 61 insertions(+) > > diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c > index faf5e9efa7d3..679eb3e81393 100644 > --- a/drivers/gpu/drm/display/drm_hdmi_helper.c > +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c > @@ -193,5 +193,62 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame, > } > > frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA; > } > EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type); > + > +/** > + * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate > + * @mode: Display mode to compute the clock for > + * @bpc: Bits per character > + * @fmt: Output Pixel Format used > + * > + * Returns the TMDS Character Rate for a given mode, bpc count and output format. > + * > + * RETURNS: > + * The TMDS Character Rate, in Hertz, or 0 on error. > + */ > +unsigned long long > +drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode, > + unsigned int bpc, enum hdmi_colorspace fmt) > +{ > + unsigned long long clock = mode->clock * 1000ULL; > + unsigned int vic = drm_match_cea_mode(mode); > + > + /* > + * CTA-861-G Spec, section 5.4 - Color Coding and Quantization > + * mandates that VIC 1 always uses 8 bpc. > + */ > + if (vic == 1 && bpc != 8) > + return 0; > + > + if (fmt == HDMI_COLORSPACE_YUV422) { > + /* > + * HDMI 1.4b Spec, section 6.2.3 - Pixel Encoding Requirements This is probably 6.2.4, but it doesn't specify that it is 36-bit _only_. > + * specifies that YUV422 is 36-bit only. > + */ > + if (bpc != 12) > + return 0; 6.5.1 allows using less than 12 bits (If fewer than 12 bits are used...). So I think it would be more correct to allow less than 12 bpc, but we'd still have to use 8 for the matter of the calculating the clock. > + > + /* > + * HDMI 1.0 Spec, section 6.5 - Pixel Encoding > + * specifies that YUV422 requires two 12-bits components per > + * pixel clock, which is equivalent in our calculation to three > + * 8-bits components > + */ > + bpc = 8; > + } > + > + /* > + * HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding > + * specifies that YUV420 encoding is carried at a TMDS Character Rate > + * equal to half the pixel clock rate. > + */ > + if (fmt == HDMI_COLORSPACE_YUV420) > + clock = clock / 2; > + > + if (mode->flags & DRM_MODE_FLAG_DBLCLK) > + clock = clock * 2; > + > + return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8); > +} > +EXPORT_SYMBOL(drm_hdmi_compute_mode_clock); > diff --git a/include/drm/display/drm_hdmi_helper.h b/include/drm/display/drm_hdmi_helper.h > index 76d234826e22..57e3b18c15ec 100644 > --- a/include/drm/display/drm_hdmi_helper.h > +++ b/include/drm/display/drm_hdmi_helper.h > @@ -22,6 +22,10 @@ drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, > const struct drm_connector_state *conn_state); > > void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame, > const struct drm_connector_state *conn_state); > > +unsigned long long > +drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode, > + unsigned int bpc, enum hdmi_colorspace fmt); > + > #endif > > -- > 2.45.0 > -- With best wishes Dmitry