> -----Original Message----- > From: Intel-gfx <intel-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx> On Behalf Of Ville Syrjala > Sent: Tuesday, March 22, 2022 5:30 PM > To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx > Subject: [PATCH v2 10/12] drm/i915/dp: Duplicate native HDMI TMDS > clock limit handling for DP HDMI DFPs > > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > With native HDMI we allow the user to override the mode with something that may > not respect the downstream (sink,dual-mode adapter) TMDS clock limits. Let's reuse > the same logic for DP HDMI DFPs so that behaviour is more or less uniform. Looks Good to me. Reviewed-by: Uma Shankar <uma.shankar@xxxxxxxxx> > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_dp.c | 51 ++++++++++++++++++------- > 1 file changed, 38 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c > b/drivers/gpu/drm/i915/display/intel_dp.c > index 3dbb68fa4e51..053853a3054e 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -870,10 +870,14 @@ static int intel_dp_max_tmds_clock(struct intel_dp > *intel_dp) > > static enum drm_mode_status > intel_dp_tmds_clock_valid(struct intel_dp *intel_dp, > - int clock, int bpc, bool ycbcr420_output) > + int clock, int bpc, bool ycbcr420_output, > + bool respect_downstream_limits) > { > int tmds_clock, min_tmds_clock, max_tmds_clock; > > + if (!respect_downstream_limits) > + return MODE_OK; > + > tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output); > > min_tmds_clock = intel_dp->dfp.min_tmds_clock; @@ -925,7 +929,7 @@ > intel_dp_mode_valid_downstream(struct intel_connector *connector, > > /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */ > status = intel_dp_tmds_clock_valid(intel_dp, target_clock, > - 8, ycbcr_420_only); > + 8, ycbcr_420_only, true); > > if (status != MODE_OK) { > if (ycbcr_420_only || > @@ -934,7 +938,7 @@ intel_dp_mode_valid_downstream(struct intel_connector > *connector, > return status; > > status = intel_dp_tmds_clock_valid(intel_dp, target_clock, > - 8, true); > + 8, true, true); > if (status != MODE_OK) > return status; > } > @@ -1183,7 +1187,7 @@ static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp, > > static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp, > const struct intel_crtc_state *crtc_state, > - int bpc) > + int bpc, bool respect_downstream_limits) > { > bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state); > int clock = crtc_state->hw.adjusted_mode.crtc_clock; > @@ -1195,10 +1199,19 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp > *intel_dp, > */ > bpc = max(bpc, 8); > > + /* > + * We will never exceed downstream TMDS clock limits while > + * attempting deep color. If the user insists on forcing an > + * out of spec mode they will have to be satisfied with 8bpc. > + */ > + if (!respect_downstream_limits) > + bpc = 8; > + > for (; bpc >= 8; bpc -= 2) { > if (intel_hdmi_bpc_possible(crtc_state, bpc, > intel_dp->has_hdmi_sink, > ycbcr420_output) && > - intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output) > == MODE_OK) > + intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output, > + respect_downstream_limits) == > MODE_OK) > return bpc; > } > > @@ -1206,7 +1219,8 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp > *intel_dp, } > > static int intel_dp_max_bpp(struct intel_dp *intel_dp, > - const struct intel_crtc_state *crtc_state) > + const struct intel_crtc_state *crtc_state, > + bool respect_downstream_limits) > { > struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); > struct intel_connector *intel_connector = intel_dp->attached_connector; > @@ -1220,7 +1234,8 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp, > if (intel_dp->dfp.min_tmds_clock) { > int max_hdmi_bpc; > > - max_hdmi_bpc = intel_dp_hdmi_compute_bpc(intel_dp, crtc_state, > bpc); > + max_hdmi_bpc = intel_dp_hdmi_compute_bpc(intel_dp, crtc_state, > bpc, > + > respect_downstream_limits); > if (max_hdmi_bpc < 0) > return 0; > > @@ -1539,7 +1554,8 @@ static int intel_dp_dsc_compute_config(struct intel_dp > *intel_dp, static int intel_dp_compute_link_config(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config, > - struct drm_connector_state *conn_state) > + struct drm_connector_state *conn_state, > + bool respect_downstream_limits) > { > struct drm_i915_private *i915 = to_i915(encoder->base.dev); > struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); > @@ -1556,7 +1572,7 @@ intel_dp_compute_link_config(struct intel_encoder > *encoder, > limits.max_lane_count = intel_dp_max_lane_count(intel_dp); > > limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format); > - limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config); > + limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config, > +respect_downstream_limits); > > if (intel_dp->use_max_params) { > /* > @@ -1850,7 +1866,8 @@ static bool intel_dp_has_audio(struct intel_encoder > *encoder, static int intel_dp_compute_output_format(struct intel_encoder > *encoder, > struct intel_crtc_state *crtc_state, > - struct drm_connector_state *conn_state) > + struct drm_connector_state *conn_state, > + bool respect_downstream_limits) > { > struct drm_i915_private *i915 = to_i915(encoder->base.dev); > struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1870,7 +1887,8 > @@ intel_dp_compute_output_format(struct intel_encoder *encoder, > crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB; > } > > - ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state); > + ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state, > + respect_downstream_limits); > if (ret) { > if (intel_dp_is_ycbcr420(intel_dp, crtc_state) || > !connector->base.ycbcr_420_allowed || @@ -1878,7 +1896,8 > @@ intel_dp_compute_output_format(struct intel_encoder *encoder, > return ret; > > crtc_state->output_format = intel_dp_output_format(connector, > true); > - ret = intel_dp_compute_link_config(encoder, crtc_state, > conn_state); > + ret = intel_dp_compute_link_config(encoder, crtc_state, > conn_state, > + respect_downstream_limits); > } > > return ret; > @@ -1922,7 +1941,13 @@ intel_dp_compute_config(struct intel_encoder > *encoder, > if (intel_dp_hdisplay_bad(dev_priv, adjusted_mode->crtc_hdisplay)) > return -EINVAL; > > - ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state); > + /* > + * Try to respect downstream TMDS clock limits first, if > + * that fails assume the user might know something we don't. > + */ > + ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, > true); > + if (ret) > + ret = intel_dp_compute_output_format(encoder, pipe_config, > +conn_state, false); > if (ret) > return ret; > > -- > 2.34.1