drm/i915/display: Restructure output format computation for better expandability

Couples the decission between RGB and YCbCr420 mode and the check if the
port clock can archive the required frequency. Other checks and
configuration steps that where previously done in between can also be done
before or after.

This allows for are cleaner implementation of retrying different color
encodings.

A slight change in behaviour occurs with this patch: If YCbCr420 is not
allowed but display is YCbCr420 only it no longer fails, but just prints
an error and tries to fallback on RGB.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210510133349.14491-3-wse@tuxedocomputers.com
This commit is contained in:
Werner Sembach 2021-05-10 15:33:48 +02:00 committed by Ville Syrjälä
parent eacba74d4d
commit 84d95f77f4
1 changed files with 35 additions and 31 deletions

View File

@ -2002,29 +2002,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
static int
intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_connector *connector = conn_state->connector;
struct drm_i915_private *i915 = to_i915(connector->dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
return 0;
if (!connector->ycbcr_420_allowed) {
drm_err(&i915->drm,
"Platform doesn't support YCBCR420 output\n");
return -EINVAL;
}
crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
return intel_pch_panel_fitting(crtc_state, conn_state);
}
static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int clock)
@ -2131,6 +2108,31 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_connector *connector = conn_state->connector;
struct drm_i915_private *i915 = to_i915(connector->dev);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int ret;
bool ycbcr_420_only;
ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, adjusted_mode);
if (connector->ycbcr_420_allowed && ycbcr_420_only) {
crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
} else {
if (!connector->ycbcr_420_allowed && ycbcr_420_only)
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->output_format = INTEL_OUTPUT_FORMAT_RGB;
}
ret = intel_hdmi_compute_clock(encoder, crtc_state);
return ret;
}
int intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
@ -2155,23 +2157,25 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
pipe_config->pixel_multiplier = 2;
ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state);
if (ret)
return ret;
pipe_config->limited_color_range =
intel_hdmi_limited_color_range(pipe_config, conn_state);
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
pipe_config->has_pch_encoder = true;
pipe_config->has_audio =
intel_hdmi_has_audio(encoder, pipe_config, conn_state);
ret = intel_hdmi_compute_clock(encoder, pipe_config);
ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state);
if (ret)
return ret;
if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
ret = intel_pch_panel_fitting(pipe_config, conn_state);
if (ret)
return ret;
}
pipe_config->limited_color_range =
intel_hdmi_limited_color_range(pipe_config, conn_state);
if (conn_state->picture_aspect_ratio)
adjusted_mode->picture_aspect_ratio =
conn_state->picture_aspect_ratio;