drm/i915: DP->HDMI TMDS clock limits vs. deep color
Account for the TMDS clock limits declared by the DFP when determining what color depth we're going to use. v2: Drop the reference to DP++ dongle since it's not handled here Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-17-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
04e18e01b3
commit
bc7ca6a647
|
@ -1977,18 +1977,69 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
|
|||
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
|
||||
}
|
||||
|
||||
static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420;
|
||||
}
|
||||
|
||||
static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state, int bpc)
|
||||
{
|
||||
int clock = crtc_state->hw.adjusted_mode.crtc_clock * bpc / 8;
|
||||
|
||||
if (intel_dp_hdmi_ycbcr420(intel_dp, crtc_state))
|
||||
clock /= 2;
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
||||
static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state, int bpc)
|
||||
{
|
||||
int tmds_clock = intel_dp_hdmi_tmds_clock(intel_dp, crtc_state, bpc);
|
||||
|
||||
if (intel_dp->dfp.min_tmds_clock &&
|
||||
tmds_clock < intel_dp->dfp.min_tmds_clock)
|
||||
return false;
|
||||
|
||||
if (intel_dp->dfp.max_tmds_clock &&
|
||||
tmds_clock > intel_dp->dfp.max_tmds_clock)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
int bpc)
|
||||
{
|
||||
bool has_hdmi_sink = intel_dp->has_hdmi_sink;
|
||||
|
||||
return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) &&
|
||||
intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
|
||||
}
|
||||
|
||||
static int intel_dp_max_bpp(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
int bpp;
|
||||
int bpp, bpc;
|
||||
|
||||
bpp = pipe_config->pipe_bpp;
|
||||
bpc = crtc_state->pipe_bpp / 3;
|
||||
|
||||
if (intel_dp->dfp.max_bpc)
|
||||
bpp = min(bpp, 3 * intel_dp->dfp.max_bpc);
|
||||
bpc = min_t(int, bpc, intel_dp->dfp.max_bpc);
|
||||
|
||||
if (intel_dp->dfp.min_tmds_clock) {
|
||||
for (; bpc >= 10; bpc -= 2) {
|
||||
if (intel_dp_hdmi_deep_color_possible(intel_dp, crtc_state, bpc))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bpp = bpc * 3;
|
||||
if (intel_dp_is_edp(intel_dp)) {
|
||||
/* Get bpp from vbt only for panels that dont have bpp in edid */
|
||||
if (intel_connector->base.display_info.bpc == 0 &&
|
||||
|
@ -2310,7 +2361,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
|||
limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
|
||||
|
||||
limits.min_bpp = intel_dp_min_bpp(pipe_config);
|
||||
limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
|
||||
limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp)) {
|
||||
/*
|
||||
|
|
|
@ -2277,35 +2277,18 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
|
|||
return intel_mode_valid_max_plane_size(dev_priv, mode);
|
||||
}
|
||||
|
||||
static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
int bpc)
|
||||
bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
int bpc, bool has_hdmi_sink)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct drm_atomic_state *state = crtc_state->uapi.state;
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_connector *connector;
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
int i;
|
||||
|
||||
if (HAS_GMCH(dev_priv))
|
||||
return false;
|
||||
|
||||
if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
|
||||
return false;
|
||||
|
||||
if (crtc_state->pipe_bpp < bpc * 3)
|
||||
return false;
|
||||
|
||||
if (!crtc_state->has_hdmi_sink)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* HDMI deep color affects the clocks, so it's only possible
|
||||
* when not cloning with other encoder types.
|
||||
*/
|
||||
if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI)
|
||||
if (!has_hdmi_sink)
|
||||
return false;
|
||||
|
||||
for_each_new_connector_in_state(state, connector, connector_state, i) {
|
||||
|
@ -2333,6 +2316,30 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
int bpc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
to_i915(crtc_state->uapi.crtc->dev);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
|
||||
if (HAS_GMCH(dev_priv))
|
||||
return false;
|
||||
|
||||
if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* HDMI deep color affects the clocks, so it's only possible
|
||||
* when not cloning with other encoder types.
|
||||
*/
|
||||
if (crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI))
|
||||
return false;
|
||||
|
||||
/* Display Wa_1405510057:icl,ehl */
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
|
||||
bpc == 10 && IS_GEN(dev_priv, 11) &&
|
||||
|
@ -2340,7 +2347,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
|||
adjusted_mode->crtc_hblank_start) % 8 == 2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return intel_hdmi_deep_color_possible(crtc_state, bpc,
|
||||
crtc_state->has_hdmi_sink);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -48,5 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder,
|
|||
union hdmi_infoframe *frame);
|
||||
bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
int bpc, bool has_hdmi_sink);
|
||||
|
||||
#endif /* __INTEL_HDMI_H__ */
|
||||
|
|
Loading…
Reference in New Issue