diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 1a09f7933e49..be7554c483ad 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -3880,6 +3880,97 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda return devdata->display->vbt.version >= 209 && devdata->child.tbt; } +static bool +validate_vspeo(const struct intel_bios_encoder_data *devdata, bool has_dp) +{ + struct intel_ddi_buf_trans *vspeo; + + vspeo = devdata->vspeo; + if (!vspeo) + return false; + + if (!has_dp) + return false; + + return true; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, bool is_uhbr) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + int idx = is_uhbr ? 5 : 4; + size_t offset = 0; + int level; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 vswing = tables[offset]; + u32 pre_cursor = tables[offset + 1]; + u32 post_cursor = tables[offset + 2]; + + entries[level].snps.vswing = vswing; + entries[level].snps.pre_cursor = pre_cursor; + entries[level].snps.post_cursor = post_cursor; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool has_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int level, idx; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (has_edp) + idx = port_clock > 540000 ? 3 : 2; + else + idx = port_clock > 270000 ? 1 : 0; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 vswing = tables[offset]; + u32 pre_cursor = tables[offset + 1]; + u32 post_cursor = tables[offset + 2]; + + entries[level].snps.vswing = vswing; + entries[level].snps.pre_cursor = pre_cursor; + entries[level].snps.post_cursor = post_cursor; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata) { return devdata->display->vbt.version >= 264 && diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 7a50a272cd27..49acf8c405e2 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -73,6 +73,13 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder, const struct intel_bios_encoder_data * intel_bios_encoder_data_lookup(struct intel_display *display, enum port port); +const struct intel_ddi_buf_trans * +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, bool is_uhbr); +const struct intel_ddi_buf_trans * +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool has_edp); + bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_dvi(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_hdmi(const struct intel_bios_encoder_data *devdata); diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index f31283a0331b..92c0d0f933ab 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1784,6 +1784,36 @@ xe3plpd_get_lt_buf_trans(struct intel_encoder *encoder, return intel_get_buf_trans(&xe3plpd_lt_trans_dp14, n_entries); } +static const struct intel_ddi_buf_trans * +mtl_get_c10_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_edp, has_dp; + int port_clock; + + has_edp = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP); + has_dp = intel_crtc_has_dp_encoder(crtc_state); + port_clock = crtc_state->port_clock; + + return intel_bios_get_c10_vspeo(devdata, has_dp, port_clock, has_edp); +} + +static const struct intel_ddi_buf_trans * +mtl_get_c20_buf_trans_override(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + const struct intel_bios_encoder_data *devdata = encoder->devdata; + bool has_dp, is_uhbr; + + has_dp = intel_crtc_has_dp_encoder(crtc_state); + is_uhbr = intel_dp_is_uhbr(crtc_state); + + return intel_bios_get_c20_vspeo(devdata, has_dp, is_uhbr); +} + void intel_ddi_buf_trans_init(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); @@ -1791,10 +1821,13 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) if (HAS_LT_PHY(display)) { encoder->get_buf_trans = xe3plpd_get_lt_buf_trans; } else if (DISPLAY_VER(display) >= 14) { - if (intel_encoder_is_c10phy(encoder)) + if (intel_encoder_is_c10phy(encoder)) { encoder->get_buf_trans = mtl_get_c10_buf_trans; - else + encoder->get_buf_trans_override = mtl_get_c10_buf_trans_override; + } else { encoder->get_buf_trans = mtl_get_c20_buf_trans; + encoder->get_buf_trans_override = mtl_get_c20_buf_trans_override; + } } else if (display->platform.dg2) { encoder->get_buf_trans = dg2_get_snps_buf_trans; } else if (display->platform.alderlake_p) {