Commit f1477219 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Remove the 8bpc shackles from DP MST

Allow DP MST to output any color depth. This means deep color as
well as falling back to 6bpc if we would otherwise require too
much bandwidth.

TODO: We should probably extend bw_contstrained scheme to force
all streams on the link to 6bpc if we can't fit the new stream(s)
otherwise.

v2: Use a proper for-loop (Jani)
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com> #v1
Link: https://patchwork.freedesktop.org/patch/msgid/20190326142556.21176-3-ville.syrjala@linux.intel.com
parent 765bdb0b
...@@ -1723,12 +1723,6 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, ...@@ -1723,12 +1723,6 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
} }
} }
struct link_config_limits {
int min_clock, max_clock;
int min_lane_count, max_lane_count;
int min_bpp, max_bpp;
};
static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp, static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
const struct intel_crtc_state *pipe_config) const struct intel_crtc_state *pipe_config)
{ {
...@@ -1791,7 +1785,7 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp, ...@@ -1791,7 +1785,7 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
} }
/* Adjust link config limits based on compliance test requests. */ /* Adjust link config limits based on compliance test requests. */
static void void
intel_dp_adjust_compliance_config(struct intel_dp *intel_dp, intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config, struct intel_crtc_state *pipe_config,
struct link_config_limits *limits) struct link_config_limits *limits)
......
...@@ -29,41 +29,78 @@ ...@@ -29,41 +29,78 @@
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
{
struct drm_atomic_state *state = crtc_state->base.state;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
struct intel_dp *intel_dp = &intel_mst->primary->dp;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode =
&crtc_state->base.adjusted_mode;
void *port = connector->port;
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL;
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_clock;
for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
crtc_state->pipe_bpp = bpp;
crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
crtc_state->pipe_bpp);
slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr,
port, crtc_state->pbn);
if (slots == -EDEADLK)
return slots;
if (slots >= 0)
break;
}
if (slots < 0) {
DRM_DEBUG_KMS("failed finding vcpi slots:%d\n", slots);
return slots;
}
intel_link_compute_m_n(crtc_state->pipe_bpp,
crtc_state->lane_count,
adjusted_mode->crtc_clock,
crtc_state->port_clock,
&crtc_state->dp_m_n,
constant_n);
crtc_state->dp_m_n.tu = slots;
return 0;
}
static int intel_dp_mst_compute_config(struct intel_encoder *encoder, static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config, struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state) struct drm_connector_state *conn_state)
{ {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_mst->primary->dp;
struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_connector *connector =
struct drm_connector *connector = conn_state->connector; to_intel_connector(conn_state->connector);
struct intel_digital_connector_state *intel_conn_state = struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state); to_intel_digital_connector_state(conn_state);
void *port = to_intel_connector(connector)->port; const struct drm_display_mode *adjusted_mode =
struct drm_atomic_state *state = pipe_config->base.state; &pipe_config->base.adjusted_mode;
struct drm_crtc *crtc = pipe_config->base.crtc; void *port = connector->port;
struct drm_crtc_state *old_crtc_state = struct link_config_limits limits;
drm_atomic_get_old_crtc_state(state, crtc); int ret;
int bpp;
int lane_count, slots =
to_intel_crtc_state(old_crtc_state)->dp_m_n.tu;
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int mst_pbn;
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
DP_DPCD_QUIRK_CONSTANT_N);
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL; return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false; pipe_config->has_pch_encoder = false;
bpp = 24;
if (intel_dp->compliance.test_data.bpc) {
bpp = intel_dp->compliance.test_data.bpc * 3;
DRM_DEBUG_KMS("Setting pipe bpp to %d\n",
bpp);
}
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
pipe_config->has_audio = pipe_config->has_audio =
...@@ -76,36 +113,25 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, ...@@ -76,36 +113,25 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
* for MST we always configure max link bw - the spec doesn't * for MST we always configure max link bw - the spec doesn't
* seem to suggest we should do otherwise. * seem to suggest we should do otherwise.
*/ */
lane_count = intel_dp_max_lane_count(intel_dp); limits.min_clock =
limits.max_clock = intel_dp_max_link_rate(intel_dp);
pipe_config->lane_count = lane_count; limits.min_lane_count =
limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
pipe_config->pipe_bpp = bpp; limits.min_bpp = 6 * 3;
limits.max_bpp = pipe_config->pipe_bpp;
pipe_config->port_clock = intel_dp_max_link_rate(intel_dp); intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
conn_state, &limits);
if (ret)
return ret;
pipe_config->limited_color_range = pipe_config->limited_color_range =
intel_dp_limited_color_range(pipe_config, conn_state); intel_dp_limited_color_range(pipe_config, conn_state);
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
pipe_config->pbn = mst_pbn;
slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, port,
mst_pbn);
if (slots < 0) {
DRM_DEBUG_KMS("failed finding vcpi slots:%d\n",
slots);
return slots;
}
intel_link_compute_m_n(bpp, lane_count,
adjusted_mode->crtc_clock,
pipe_config->port_clock,
&pipe_config->dp_m_n,
constant_n);
pipe_config->dp_m_n.tu = slots;
if (IS_GEN9_LP(dev_priv)) if (IS_GEN9_LP(dev_priv))
pipe_config->lane_lat_optim_mask = pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
...@@ -389,7 +415,6 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, ...@@ -389,7 +415,6 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port; struct intel_dp *intel_dp = intel_connector->mst_port;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
int bpp = 24; /* MST uses fixed bpp */
int max_rate, mode_rate, max_lanes, max_link_clock; int max_rate, mode_rate, max_lanes, max_link_clock;
if (drm_connector_is_unregistered(connector)) if (drm_connector_is_unregistered(connector))
...@@ -402,7 +427,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, ...@@ -402,7 +427,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
max_lanes = intel_dp_max_lane_count(intel_dp); max_lanes = intel_dp_max_lane_count(intel_dp);
max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
mode_rate = intel_dp_link_required(mode->clock, bpp); mode_rate = intel_dp_link_required(mode->clock, 18);
/* TODO - validate mode against available PBN for link */ /* TODO - validate mode against available PBN for link */
if (mode->clock < 10000) if (mode->clock < 10000)
......
...@@ -1908,6 +1908,14 @@ void intel_csr_ucode_suspend(struct drm_i915_private *); ...@@ -1908,6 +1908,14 @@ void intel_csr_ucode_suspend(struct drm_i915_private *);
void intel_csr_ucode_resume(struct drm_i915_private *); void intel_csr_ucode_resume(struct drm_i915_private *);
/* intel_dp.c */ /* intel_dp.c */
struct link_config_limits {
int min_clock, max_clock;
int min_lane_count, max_lane_count;
int min_bpp, max_bpp;
};
void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits);
bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state); const struct drm_connector_state *conn_state);
bool intel_dp_port_enabled(struct drm_i915_private *dev_priv, bool intel_dp_port_enabled(struct drm_i915_private *dev_priv,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment