Commit 56185b90 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/dp: Duplicate native HDMI TMDS clock limit handling for DP HDMI DFPs

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: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220322120015.28074-11-ville.syrjala@linux.intel.comReviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
parent 632f8535
...@@ -843,10 +843,14 @@ static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp) ...@@ -843,10 +843,14 @@ static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp)
static enum drm_mode_status static enum drm_mode_status
intel_dp_tmds_clock_valid(struct intel_dp *intel_dp, 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; 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); tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
min_tmds_clock = intel_dp->dfp.min_tmds_clock; min_tmds_clock = intel_dp->dfp.min_tmds_clock;
...@@ -898,7 +902,7 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, ...@@ -898,7 +902,7 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */ /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
status = intel_dp_tmds_clock_valid(intel_dp, target_clock, status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
8, ycbcr_420_only); 8, ycbcr_420_only, true);
if (status != MODE_OK) { if (status != MODE_OK) {
if (ycbcr_420_only || if (ycbcr_420_only ||
...@@ -907,7 +911,7 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, ...@@ -907,7 +911,7 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
return status; return status;
status = intel_dp_tmds_clock_valid(intel_dp, target_clock, status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
8, true); 8, true, true);
if (status != MODE_OK) if (status != MODE_OK)
return status; return status;
} }
...@@ -1156,7 +1160,7 @@ static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp, ...@@ -1156,7 +1160,7 @@ static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp,
static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp, static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state, 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); bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state);
int clock = crtc_state->hw.adjusted_mode.crtc_clock; int clock = crtc_state->hw.adjusted_mode.crtc_clock;
...@@ -1168,10 +1172,19 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp, ...@@ -1168,10 +1172,19 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
*/ */
bpc = max(bpc, 8); 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) { for (; bpc >= 8; bpc -= 2) {
if (intel_hdmi_bpc_possible(crtc_state, bpc, if (intel_hdmi_bpc_possible(crtc_state, bpc,
intel_dp->has_hdmi_sink, ycbcr420_output) && 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; return bpc;
} }
...@@ -1179,7 +1192,8 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp, ...@@ -1179,7 +1192,8 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
} }
static int intel_dp_max_bpp(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 drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_connector *intel_connector = intel_dp->attached_connector; struct intel_connector *intel_connector = intel_dp->attached_connector;
...@@ -1193,7 +1207,8 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp, ...@@ -1193,7 +1207,8 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
if (intel_dp->dfp.min_tmds_clock) { if (intel_dp->dfp.min_tmds_clock) {
int max_hdmi_bpc; 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) if (max_hdmi_bpc < 0)
return 0; return 0;
...@@ -1512,7 +1527,8 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, ...@@ -1512,7 +1527,8 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
static int static int
intel_dp_compute_link_config(struct intel_encoder *encoder, intel_dp_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config, 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 drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
...@@ -1530,7 +1546,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, ...@@ -1530,7 +1546,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
limits.max_lane_count = intel_dp_max_lane_count(intel_dp); limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format); 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) { if (intel_dp->use_max_params) {
/* /*
...@@ -1901,7 +1917,8 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder, ...@@ -1901,7 +1917,8 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder,
static int static int
intel_dp_compute_output_format(struct intel_encoder *encoder, intel_dp_compute_output_format(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state, 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 drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
...@@ -1921,7 +1938,8 @@ intel_dp_compute_output_format(struct intel_encoder *encoder, ...@@ -1921,7 +1938,8 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB; 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 (ret) {
if (intel_dp_is_ycbcr420(intel_dp, crtc_state) || if (intel_dp_is_ycbcr420(intel_dp, crtc_state) ||
!connector->base.ycbcr_420_allowed || !connector->base.ycbcr_420_allowed ||
...@@ -1929,7 +1947,8 @@ intel_dp_compute_output_format(struct intel_encoder *encoder, ...@@ -1929,7 +1947,8 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
return ret; return ret;
crtc_state->output_format = intel_dp_output_format(connector, true); 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; return ret;
...@@ -1973,7 +1992,13 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -1973,7 +1992,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (intel_dp_hdisplay_bad(dev_priv, adjusted_mode->crtc_hdisplay)) if (intel_dp_hdisplay_bad(dev_priv, adjusted_mode->crtc_hdisplay))
return -EINVAL; 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) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment