@@ -1897,6 +1897,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;
@@ -1913,12 +1914,20 @@ 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);
}
@@ -2125,6 +2134,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;
}