diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 79ebb58afcb28..98da94ab3e244 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1900,6 +1900,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, int clock = mode->clock; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); + bool ycbcr_420_only; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -1916,12 +1917,22 @@ intel_hdmi_mode_valid(struct drm_connector *connector, clock *= 2; } - if (drm_mode_is_420_only(&connector->display_info, mode)) + ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode); + if (ycbcr_420_only) clock /= 2; status = intel_hdmi_mode_clock_valid(hdmi, clock, has_hdmi_sink); - if (status != MODE_OK) - return status; + if (status != MODE_OK) { + if (ycbcr_420_only || + !connector->ycbcr_420_allowed || + !drm_mode_is_420_also(&connector->display_info, mode)) + return status; + + clock /= 2; + status = intel_hdmi_mode_clock_valid(hdmi, clock, has_hdmi_sink); + if (status != MODE_OK) + return status; + } return intel_mode_valid_max_plane_size(dev_priv, mode, false); } @@ -2129,6 +2140,14 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, } ret = intel_hdmi_compute_clock(encoder, crtc_state); + if (ret) { + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 && + connector->ycbcr_420_allowed && + drm_mode_is_420_also(&connector->display_info, adjusted_mode)) { + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; + ret = intel_hdmi_compute_clock(encoder, crtc_state); + } + } return ret; }