From: Werner Sembach <wse@xxxxxxxxxxxxxxxxxxx> This commit implements the "preferred color format" drm property for the Intel GPU driver. Signed-off-by: Werner Sembach <wse@xxxxxxxxxxxxxxxxxxx> Co-developed-by: Andri Yngvason <andri@xxxxxxxxxxx> Signed-off-by: Andri Yngvason <andri@xxxxxxxxxxx> Tested-by: Andri Yngvason <andri@xxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_dp.c | 16 ++++++++++------ drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++++ drivers/gpu/drm/i915/display/intel_hdmi.c | 12 +++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c40fe8a847614..f241798660d0b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2698,21 +2698,23 @@ intel_dp_compute_output_format(struct intel_encoder *encoder, struct intel_connector *connector = intel_dp->attached_connector; const struct drm_display_info *info = &connector->base.display_info; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - bool ycbcr_420_only; + bool ycbcr_420_output; int ret; - ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); + ycbcr_420_output = drm_mode_is_420_only(info, adjusted_mode) || + (conn_state->preferred_color_format == DRM_COLOR_FORMAT_YCBCR420 && + drm_mode_is_420_also(&connector->base.display_info, adjusted_mode)); - if (ycbcr_420_only && !connector->base.ycbcr_420_allowed) { + crtc_state->sink_format = ycbcr_420_output ? INTEL_OUTPUT_FORMAT_YCBCR420 : + INTEL_OUTPUT_FORMAT_RGB; + + if (ycbcr_420_output && !connector->base.ycbcr_420_allowed) { drm_dbg_kms(&i915->drm, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB; - } else { - crtc_state->sink_format = intel_dp_sink_format(connector, adjusted_mode); } crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format); - ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state, respect_downstream_limits); if (ret) { @@ -5912,9 +5914,11 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_broadcast_rgb_property(connector); if (HAS_GMCH(dev_priv)) { drm_connector_attach_max_bpc_property(connector, 6, 10); + drm_connector_attach_preferred_color_format_property(connector); drm_connector_attach_active_color_format_property(connector); } else if (DISPLAY_VER(dev_priv) >= 5) { drm_connector_attach_max_bpc_property(connector, 6, 12); + drm_connector_attach_preferred_color_format_property(connector); drm_connector_attach_active_color_format_property(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index e7574ca0604e6..4a850eb9b8d4d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1210,6 +1210,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n", connector->name, connector->base.id); + connector->preferred_color_format_property = + intel_dp->attached_connector->base.preferred_color_format_property; + if (connector->preferred_color_format_property) + drm_connector_attach_preferred_color_format_property(connector); + connector->active_color_format_property = intel_dp->attached_connector->base.active_color_format_property; if (connector->active_color_format_property) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index ce0221f90de92..3030589d245d7 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2214,19 +2214,24 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct drm_display_info *info = &connector->base.display_info; struct drm_i915_private *i915 = to_i915(connector->base.dev); - bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); + bool ycbcr_420_output; int ret; + ycbcr_420_output = drm_mode_is_420_only(info, adjusted_mode) || + (conn_state->preferred_color_format == DRM_COLOR_FORMAT_YCBCR420 && + drm_mode_is_420_also(&connector->base.display_info, adjusted_mode)); + crtc_state->sink_format = - intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_only); + intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_output); - if (ycbcr_420_only && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) { + if (ycbcr_420_output && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) { drm_dbg_kms(&i915->drm, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB; } crtc_state->output_format = intel_hdmi_output_format(crtc_state); + ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); if (ret) { if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 || @@ -2613,6 +2618,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c if (!HAS_GMCH(dev_priv)) { drm_connector_attach_max_bpc_property(connector, 8, 12); + drm_connector_attach_preferred_color_format_property(connector); drm_connector_attach_active_color_format_property(connector); } } -- 2.43.0