static enum drm_mode_status
intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
- int clock, int bpc, bool ycbcr420_output,
+ int clock, int bpc,
+ enum intel_output_format sink_format,
bool respect_downstream_limits)
{
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, sink_format);
min_tmds_clock = intel_dp->dfp.min_tmds_clock;
max_tmds_clock = intel_dp_max_tmds_clock(intel_dp);
const struct drm_display_info *info = &connector->base.display_info;
enum drm_mode_status status;
bool ycbcr_420_only;
+ enum intel_output_format sink_format;
/* If PCON supports FRL MODE, check FRL bandwidth constraints */
if (intel_dp->dfp.pcon_max_frl_bw) {
ycbcr_420_only = drm_mode_is_420_only(info, mode);
+ if (ycbcr_420_only)
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ else
+ sink_format = INTEL_OUTPUT_FORMAT_RGB;
+
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
- 8, ycbcr_420_only, true);
+ 8, sink_format, true);
if (status != MODE_OK) {
- if (ycbcr_420_only ||
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, mode))
return status;
-
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
- 8, true, true);
+ 8, sink_format, true);
if (status != MODE_OK)
return status;
}
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
}
-static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state)
-{
- return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
- (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
- intel_dp->dfp.ycbcr_444_to_420);
-}
-
static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
int bpc, bool respect_downstream_limits)
{
- bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state);
int clock = crtc_state->hw.adjusted_mode.crtc_clock;
/*
for (; bpc >= 8; bpc -= 2) {
if (intel_hdmi_bpc_possible(crtc_state, bpc,
- intel_dp->has_hdmi_sink, ycbcr420_output) &&
- intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output,
+ intel_dp->has_hdmi_sink) &&
+ intel_dp_tmds_clock_valid(intel_dp, clock, bpc, crtc_state->sink_format,
respect_downstream_limits) == MODE_OK)
return bpc;
}
return MODE_OK;
}
-int intel_hdmi_tmds_clock(int clock, int bpc, bool ycbcr420_output)
+int intel_hdmi_tmds_clock(int clock, int bpc,
+ enum intel_output_format sink_format)
{
/* YCBCR420 TMDS rate requirement is half the pixel clock */
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
clock /= 2;
/*
}
static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
- int bpc, bool has_hdmi_sink, bool ycbcr420_output)
+ int bpc, bool has_hdmi_sink,
+ enum intel_output_format sink_format)
{
const struct drm_display_info *info = &connector->display_info;
const struct drm_hdmi_info *hdmi = &info->hdmi;
if (!has_hdmi_sink)
return false;
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
else
return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36;
if (!has_hdmi_sink)
return false;
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
else
return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30;
static enum drm_mode_status
intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
- bool has_hdmi_sink, bool ycbcr420_output)
+ bool has_hdmi_sink,
+ enum intel_output_format sink_format)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
* least one color depth is accepted.
*/
for (bpc = 12; bpc >= 8; bpc -= 2) {
- int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+ int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, sink_format);
if (!intel_hdmi_source_bpc_possible(i915, bpc))
continue;
- if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output))
+ if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, sink_format))
continue;
status = hdmi_port_clock_valid(hdmi, tmds_clock, true, has_hdmi_sink);
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;
+ enum intel_output_format sink_format;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
clock *= 2;
ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode);
- status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, ycbcr_420_only);
+ if (ycbcr_420_only)
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ else
+ sink_format = INTEL_OUTPUT_FORMAT_RGB;
+
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
if (status != MODE_OK) {
if (ycbcr_420_only ||
!connector->ycbcr_420_allowed ||
!drm_mode_is_420_also(&connector->display_info, mode))
return status;
- status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, true);
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
if (status != MODE_OK)
return status;
}
}
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
- int bpc, bool has_hdmi_sink, bool ycbcr420_output)
+ int bpc, bool has_hdmi_sink)
{
struct drm_atomic_state *state = crtc_state->uapi.state;
struct drm_connector_state *connector_state;
if (connector_state->crtc != crtc_state->uapi.crtc)
continue;
- if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output))
+ if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink,
+ crtc_state->sink_format))
return false;
}
adjusted_mode->crtc_hblank_start) % 8 == 2)
return false;
- return intel_hdmi_bpc_possible(crtc_state, bpc, crtc_state->has_hdmi_sink,
- intel_hdmi_is_ycbcr420(crtc_state));
+ return intel_hdmi_bpc_possible(crtc_state, bpc, crtc_state->has_hdmi_sink);
}
static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
int clock, bool respect_downstream_limits)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- bool ycbcr420_output = intel_hdmi_is_ycbcr420(crtc_state);
int bpc;
/*
bpc = 8;
for (; bpc >= 8; bpc -= 2) {
- int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+ int tmds_clock = intel_hdmi_tmds_clock(clock, bpc,
+ crtc_state->sink_format);
if (hdmi_bpc_possible(crtc_state, bpc) &&
hdmi_port_clock_valid(intel_hdmi, tmds_clock,
return bpc;
crtc_state->port_clock =
- intel_hdmi_tmds_clock(clock, bpc, intel_hdmi_is_ycbcr420(crtc_state));
+ intel_hdmi_tmds_clock(clock, bpc, crtc_state->sink_format);
/*
* pipe_bpp could already be below 8bpc due to