diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 215 |
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; |
