[Intel-gfx] [PATCH v2 10/12] drm/i915/dp: Duplicate native HDMI TMDS clock limit handling for DP HDMI DFPs
Ville Syrjala
ville.syrjala at linux.intel.com
Tue Mar 22 12:00:13 UTC 2022
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
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.
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
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
More information about the Intel-gfx
mailing list