summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c215
1 files changed, 143 insertions, 72 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 75070eb07d4b..80d95cec8f9d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -117,7 +117,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
}
static void intel_dp_unset_edid(struct intel_dp *intel_dp);
-static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
/* Is link rate UHBR and thus 128b/132b? */
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
@@ -673,23 +672,59 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915)
return 6144 * 8;
}
-static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
- u32 link_clock, u32 lane_count,
- u32 mode_clock, u32 mode_hdisplay,
- bool bigjoiner,
- u32 pipe_bpp)
+u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp)
{
- u32 bits_per_pixel, max_bpp_small_joiner_ram;
+ u32 bits_per_pixel = bpp;
int i;
+ /* Error out if the max bpp is less than smallest allowed valid bpp */
+ if (bits_per_pixel < valid_dsc_bpp[0]) {
+ drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n",
+ bits_per_pixel, valid_dsc_bpp[0]);
+ return 0;
+ }
+
+ /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
+ if (DISPLAY_VER(i915) >= 13) {
+ bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
+ } else {
+ /* Find the nearest match in the array of known BPPs from VESA */
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
+ if (bits_per_pixel < valid_dsc_bpp[i + 1])
+ break;
+ }
+ drm_dbg_kms(&i915->drm, "Set dsc bpp from %d to VESA %d\n",
+ bits_per_pixel, valid_dsc_bpp[i]);
+
+ bits_per_pixel = valid_dsc_bpp[i];
+ }
+
+ return bits_per_pixel;
+}
+
+u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
+ u32 link_clock, u32 lane_count,
+ u32 mode_clock, u32 mode_hdisplay,
+ bool bigjoiner,
+ u32 pipe_bpp,
+ u32 timeslots)
+{
+ u32 bits_per_pixel, max_bpp_small_joiner_ram;
+
/*
* Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
- * (LinkSymbolClock)* 8 * (TimeSlotsPerMTP)
- * for SST -> TimeSlotsPerMTP is 1,
- * for MST -> TimeSlotsPerMTP has to be calculated
+ * (LinkSymbolClock)* 8 * (TimeSlots / 64)
+ * for SST -> TimeSlots is 64(i.e all TimeSlots that are available)
+ * for MST -> TimeSlots has to be calculated, based on mode requirements
*/
- bits_per_pixel = (link_clock * lane_count * 8) /
- intel_dp_mode_to_fec_clock(mode_clock);
+ bits_per_pixel = DIV_ROUND_UP((link_clock * lane_count) * timeslots,
+ intel_dp_mode_to_fec_clock(mode_clock) * 8);
+
+ drm_dbg_kms(&i915->drm, "Max link bpp is %u for %u timeslots "
+ "total bw %u pixel clock %u\n",
+ bits_per_pixel, timeslots,
+ (link_clock * lane_count * 8),
+ intel_dp_mode_to_fec_clock(mode_clock));
/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) /
@@ -712,24 +747,7 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner);
}
- /* Error out if the max bpp is less than smallest allowed valid bpp */
- if (bits_per_pixel < valid_dsc_bpp[0]) {
- drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n",
- bits_per_pixel, valid_dsc_bpp[0]);
- return 0;
- }
-
- /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
- if (DISPLAY_VER(i915) >= 13) {
- bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
- } else {
- /* Find the nearest match in the array of known BPPs from VESA */
- for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
- if (bits_per_pixel < valid_dsc_bpp[i + 1])
- break;
- }
- bits_per_pixel = valid_dsc_bpp[i];
- }
+ bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
/*
* Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
@@ -738,9 +756,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
return bits_per_pixel << 4;
}
-static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
- int mode_clock, int mode_hdisplay,
- bool bigjoiner)
+u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+ int mode_clock, int mode_hdisplay,
+ bool bigjoiner)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 min_slice_count, i;
@@ -947,8 +965,8 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
return MODE_OK;
}
-static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
- int hdisplay, int clock)
+bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
+ int hdisplay, int clock)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -974,9 +992,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
enum drm_mode_status status;
bool dsc = false, bigjoiner = false;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
return MODE_H_ILLEGAL;
@@ -1013,7 +1028,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
* Output bpp is stored in 6.4 format so right shift by 4 to get the
* integer value since we support only integer values of bpp.
*/
- if (DISPLAY_VER(dev_priv) >= 10 &&
+ if (HAS_DSC(dev_priv) &&
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
/*
* TBD pass the connector BPC,
@@ -1035,7 +1050,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
target_clock,
mode->hdisplay,
bigjoiner,
- pipe_bpp) >> 4;
+ pipe_bpp, 64) >> 4;
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
target_clock,
@@ -1364,7 +1379,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
return -EINVAL;
}
-static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
+int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
int i, num_bpc;
@@ -1465,10 +1480,12 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
return drm_dsc_compute_rc_parameters(vdsc_cfg);
}
-static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *pipe_config,
- struct drm_connector_state *conn_state,
- struct link_config_limits *limits)
+int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state,
+ struct link_config_limits *limits,
+ int timeslots,
+ bool compute_pipe_bpp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
@@ -1483,7 +1500,10 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
if (!intel_dp_supports_dsc(intel_dp, pipe_config))
return -EINVAL;
- pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
+ if (compute_pipe_bpp)
+ pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
+ else
+ pipe_bpp = pipe_config->pipe_bpp;
if (intel_dp->force_dsc_bpc) {
pipe_bpp = intel_dp->force_dsc_bpc * 3;
@@ -1514,33 +1534,52 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
true);
} else {
- u16 dsc_max_output_bpp;
+ u16 dsc_max_output_bpp = 0;
u8 dsc_dp_slice_count;
- dsc_max_output_bpp =
- intel_dp_dsc_get_output_bpp(dev_priv,
- pipe_config->port_clock,
- pipe_config->lane_count,
- adjusted_mode->crtc_clock,
- adjusted_mode->crtc_hdisplay,
- pipe_config->bigjoiner_pipes,
- pipe_bpp);
+ if (compute_pipe_bpp) {
+ dsc_max_output_bpp =
+ intel_dp_dsc_get_output_bpp(dev_priv,
+ pipe_config->port_clock,
+ pipe_config->lane_count,
+ adjusted_mode->crtc_clock,
+ adjusted_mode->crtc_hdisplay,
+ pipe_config->bigjoiner_pipes,
+ pipe_bpp,
+ timeslots);
+ if (!dsc_max_output_bpp) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Compressed BPP not supported\n");
+ return -EINVAL;
+ }
+ }
dsc_dp_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
pipe_config->bigjoiner_pipes);
- if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
+ if (!dsc_dp_slice_count) {
drm_dbg_kms(&dev_priv->drm,
- "Compressed BPP/Slice Count not supported\n");
+ "Compressed Slice Count not supported\n");
return -EINVAL;
}
- pipe_config->dsc.compressed_bpp = min_t(u16,
- dsc_max_output_bpp >> 4,
- pipe_config->pipe_bpp);
+
+ /*
+ * compute pipe bpp is set to false for DP MST DSC case
+ * and compressed_bpp is calculated same time once
+ * vpci timeslots are allocated, because overall bpp
+ * calculation procedure is bit different for MST case.
+ */
+ if (compute_pipe_bpp) {
+ pipe_config->dsc.compressed_bpp = min_t(u16,
+ dsc_max_output_bpp >> 4,
+ pipe_config->pipe_bpp);
+ }
pipe_config->dsc.slice_count = dsc_dp_slice_count;
+ drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n",
+ pipe_config->dsc.compressed_bpp,
+ pipe_config->dsc.slice_count);
}
-
/*
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
* is greater than the maximum Cdclock and if slice count is even
@@ -1548,13 +1587,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
*/
if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_cdclk_freq ||
pipe_config->bigjoiner_pipes) {
- if (pipe_config->dsc.slice_count < 2) {
+ if (pipe_config->dsc.slice_count > 1) {
+ pipe_config->dsc.dsc_split = true;
+ } else {
drm_dbg_kms(&dev_priv->drm,
"Cannot split stream to use 2 VDSC instances\n");
return -EINVAL;
}
-
- pipe_config->dsc.dsc_split = true;
}
ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config);
@@ -1643,7 +1682,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
str_yes_no(ret), str_yes_no(joiner_needs_dsc),
str_yes_no(intel_dp->force_dsc_en));
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
- conn_state, &limits);
+ conn_state, &limits, 64, true);
if (ret < 0)
return ret;
}
@@ -2009,6 +2048,23 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
return ret;
}
+static void
+intel_dp_audio_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct drm_connector *connector = conn_state->connector;
+
+ pipe_config->sdp_split_enable =
+ intel_dp_has_audio(encoder, pipe_config, conn_state) &&
+ intel_dp_is_uhbr(pipe_config);
+
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDP split enable: %s\n",
+ connector->base.id, connector->name,
+ str_yes_no(pipe_config->sdp_split_enable));
+}
+
int
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
@@ -2036,7 +2092,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
- if (HAS_GMCH(dev_priv) &&
+ if (!connector->base.interlace_allowed &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return -EINVAL;
@@ -2092,6 +2148,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
adjusted_mode->crtc_clock /= n;
}
+ intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
+
intel_link_compute_m_n(output_bpp,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
@@ -2907,7 +2965,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
intel_dp_set_max_sink_lane_count(intel_dp);
/* Read the eDP DSC DPCD registers */
- if (DISPLAY_VER(dev_priv) >= 10)
+ if (HAS_DSC(dev_priv))
intel_dp_get_dsc_sink_cap(intel_dp);
/*
@@ -4633,7 +4691,7 @@ intel_dp_detect(struct drm_connector *connector,
}
/* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
- if (DISPLAY_VER(dev_priv) >= 11)
+ if (HAS_DSC(dev_priv))
intel_dp_get_dsc_sink_cap(intel_dp);
intel_dp_configure_mst(intel_dp);
@@ -5202,7 +5260,20 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
return false;
}
- intel_pps_init(intel_dp);
+ intel_bios_init_panel_early(dev_priv, &intel_connector->panel,
+ encoder->devdata);
+
+ if (!intel_pps_init(intel_dp)) {
+ drm_info(&dev_priv->drm,
+ "[ENCODER:%d:%s] unusable PPS, disabling eDP\n",
+ encoder->base.base.id, encoder->base.name);
+ /*
+ * The BIOS may have still enabled VDD on the PPS even
+ * though it's unusable. Make sure we turn it back off
+ * and to release the power domain references/etc.
+ */
+ goto out_vdd_off;
+ }
/* Cache DPCD and EDID for edp. */
has_dpcd = intel_edp_init_dpcd(intel_dp);
@@ -5237,8 +5308,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
intel_connector->edid = edid;
- intel_bios_init_panel(dev_priv, &intel_connector->panel,
- encoder->devdata, IS_ERR(edid) ? NULL : edid);
+ intel_bios_init_panel_late(dev_priv, &intel_connector->panel,
+ encoder->devdata, IS_ERR(edid) ? NULL : edid);
intel_panel_add_edid_fixed_modes(intel_connector, true);
@@ -5364,7 +5435,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
- if (!HAS_GMCH(dev_priv))
+ if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12)
connector->interlace_allowed = true;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;