diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_bios.c | 251 |
1 files changed, 122 insertions, 129 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 75e69dffc5e9..34a397adbd6b 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2141,58 +2141,58 @@ static u8 translate_iboost(u8 val) static const u8 cnp_ddc_pin_map[] = { [0] = 0, /* N/A */ - [DDC_BUS_DDI_B] = GMBUS_PIN_1_BXT, - [DDC_BUS_DDI_C] = GMBUS_PIN_2_BXT, - [DDC_BUS_DDI_D] = GMBUS_PIN_4_CNP, /* sic */ - [DDC_BUS_DDI_F] = GMBUS_PIN_3_BXT, /* sic */ + [GMBUS_PIN_1_BXT] = DDC_BUS_DDI_B, + [GMBUS_PIN_2_BXT] = DDC_BUS_DDI_C, + [GMBUS_PIN_4_CNP] = DDC_BUS_DDI_D, /* sic */ + [GMBUS_PIN_3_BXT] = DDC_BUS_DDI_F, /* sic */ }; static const u8 icp_ddc_pin_map[] = { - [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT, - [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT, - [TGL_DDC_BUS_DDI_C] = GMBUS_PIN_3_BXT, - [ICL_DDC_BUS_PORT_1] = GMBUS_PIN_9_TC1_ICP, - [ICL_DDC_BUS_PORT_2] = GMBUS_PIN_10_TC2_ICP, - [ICL_DDC_BUS_PORT_3] = GMBUS_PIN_11_TC3_ICP, - [ICL_DDC_BUS_PORT_4] = GMBUS_PIN_12_TC4_ICP, - [TGL_DDC_BUS_PORT_5] = GMBUS_PIN_13_TC5_TGP, - [TGL_DDC_BUS_PORT_6] = GMBUS_PIN_14_TC6_TGP, + [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A, + [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B, + [GMBUS_PIN_3_BXT] = TGL_DDC_BUS_DDI_C, + [GMBUS_PIN_9_TC1_ICP] = ICL_DDC_BUS_PORT_1, + [GMBUS_PIN_10_TC2_ICP] = ICL_DDC_BUS_PORT_2, + [GMBUS_PIN_11_TC3_ICP] = ICL_DDC_BUS_PORT_3, + [GMBUS_PIN_12_TC4_ICP] = ICL_DDC_BUS_PORT_4, + [GMBUS_PIN_13_TC5_TGP] = TGL_DDC_BUS_PORT_5, + [GMBUS_PIN_14_TC6_TGP] = TGL_DDC_BUS_PORT_6, }; static const u8 rkl_pch_tgp_ddc_pin_map[] = { - [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT, - [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT, - [RKL_DDC_BUS_DDI_D] = GMBUS_PIN_9_TC1_ICP, - [RKL_DDC_BUS_DDI_E] = GMBUS_PIN_10_TC2_ICP, + [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A, + [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B, + [GMBUS_PIN_9_TC1_ICP] = RKL_DDC_BUS_DDI_D, + [GMBUS_PIN_10_TC2_ICP] = RKL_DDC_BUS_DDI_E, }; static const u8 adls_ddc_pin_map[] = { - [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT, - [ADLS_DDC_BUS_PORT_TC1] = GMBUS_PIN_9_TC1_ICP, - [ADLS_DDC_BUS_PORT_TC2] = GMBUS_PIN_10_TC2_ICP, - [ADLS_DDC_BUS_PORT_TC3] = GMBUS_PIN_11_TC3_ICP, - [ADLS_DDC_BUS_PORT_TC4] = GMBUS_PIN_12_TC4_ICP, + [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A, + [GMBUS_PIN_9_TC1_ICP] = ADLS_DDC_BUS_PORT_TC1, + [GMBUS_PIN_10_TC2_ICP] = ADLS_DDC_BUS_PORT_TC2, + [GMBUS_PIN_11_TC3_ICP] = ADLS_DDC_BUS_PORT_TC3, + [GMBUS_PIN_12_TC4_ICP] = ADLS_DDC_BUS_PORT_TC4, }; static const u8 gen9bc_tgp_ddc_pin_map[] = { - [DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT, - [DDC_BUS_DDI_C] = GMBUS_PIN_9_TC1_ICP, - [DDC_BUS_DDI_D] = GMBUS_PIN_10_TC2_ICP, + [GMBUS_PIN_2_BXT] = DDC_BUS_DDI_B, + [GMBUS_PIN_9_TC1_ICP] = DDC_BUS_DDI_C, + [GMBUS_PIN_10_TC2_ICP] = DDC_BUS_DDI_D, }; static const u8 adlp_ddc_pin_map[] = { - [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT, - [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT, - [ADLP_DDC_BUS_PORT_TC1] = GMBUS_PIN_9_TC1_ICP, - [ADLP_DDC_BUS_PORT_TC2] = GMBUS_PIN_10_TC2_ICP, - [ADLP_DDC_BUS_PORT_TC3] = GMBUS_PIN_11_TC3_ICP, - [ADLP_DDC_BUS_PORT_TC4] = GMBUS_PIN_12_TC4_ICP, + [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A, + [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B, + [GMBUS_PIN_9_TC1_ICP] = ADLP_DDC_BUS_PORT_TC1, + [GMBUS_PIN_10_TC2_ICP] = ADLP_DDC_BUS_PORT_TC2, + [GMBUS_PIN_11_TC3_ICP] = ADLP_DDC_BUS_PORT_TC3, + [GMBUS_PIN_12_TC4_ICP] = ADLP_DDC_BUS_PORT_TC4, }; static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) { const u8 *ddc_pin_map; - int n_entries; + int i, n_entries; if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) { ddc_pin_map = adlp_ddc_pin_map; @@ -2219,8 +2219,10 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) return vbt_pin; } - if (vbt_pin < n_entries && ddc_pin_map[vbt_pin] != 0) - return ddc_pin_map[vbt_pin]; + for (i = 0; i < n_entries; i++) { + if (ddc_pin_map[i] == vbt_pin) + return i; + } drm_dbg_kms(&i915->drm, "Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n", @@ -2675,8 +2677,9 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata, supports_tbt = intel_bios_encoder_supports_tbt(devdata); drm_dbg_kms(&i915->drm, - "Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d DSI:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n", + "Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d DSI:%d DP++:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n", port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp, is_dsi, + intel_bios_encoder_supports_dp_dual_mode(devdata), intel_bios_encoder_is_lspcon(devdata), supports_typec_usb, supports_tbt, devdata->dsc != NULL); @@ -3030,6 +3033,13 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return vbt; } +static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset) +{ + intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset); + + return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER); +} + static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) { u32 count, data, found, store = 0; @@ -3046,9 +3056,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) oprom_offset &= OROM_OFFSET_MASK; for (count = 0; count < oprom_size; count += 4) { - intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, oprom_offset + count); - data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER); - + data = intel_spi_read(&i915->uncore, oprom_offset + count); if (data == *((const u32 *)"$VBT")) { found = oprom_offset + count; break; @@ -3059,20 +3067,16 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) goto err_not_found; /* Get VBT size and allocate space for the VBT */ - intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found + - offsetof(struct vbt_header, vbt_size)); - vbt_size = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER); + vbt_size = intel_spi_read(&i915->uncore, + found + offsetof(struct vbt_header, vbt_size)); vbt_size &= 0xffff; vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL); if (!vbt) goto err_not_found; - for (count = 0; count < vbt_size; count += 4) { - intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found + count); - data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER); - *(vbt + store++) = data; - } + for (count = 0; count < vbt_size; count += 4) + *(vbt + store++) = intel_spi_read(&i915->uncore, found + count); if (!intel_bios_is_valid_vbt(vbt, vbt_size)) goto err_free_vbt; @@ -3424,7 +3428,7 @@ bool intel_bios_is_port_present(struct drm_i915_private *i915, enum port port) return false; } -static bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata) +bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata) { const struct child_device_config *child = &devdata->child; @@ -3443,15 +3447,6 @@ static bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_enc return false; } -bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, - enum port port) -{ - const struct intel_bios_encoder_data *devdata = - intel_bios_encoder_data_lookup(i915, port); - - return devdata && intel_bios_encoder_supports_dp_dual_mode(devdata); -} - /** * intel_bios_is_dsi_present - is DSI present in VBT * @i915: i915 device instance @@ -3578,84 +3573,82 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder, return false; } +static const u8 adlp_aux_ch_map[] = { + [AUX_CH_A] = DP_AUX_A, + [AUX_CH_B] = DP_AUX_B, + [AUX_CH_C] = DP_AUX_C, + [AUX_CH_D_XELPD] = DP_AUX_D, + [AUX_CH_E_XELPD] = DP_AUX_E, + [AUX_CH_USBC1] = DP_AUX_F, + [AUX_CH_USBC2] = DP_AUX_G, + [AUX_CH_USBC3] = DP_AUX_H, + [AUX_CH_USBC4] = DP_AUX_I, +}; + +/* + * ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E + * map to DDI A,TC1,TC2,TC3,TC4 respectively. + */ +static const u8 adls_aux_ch_map[] = { + [AUX_CH_A] = DP_AUX_A, + [AUX_CH_USBC1] = DP_AUX_B, + [AUX_CH_USBC2] = DP_AUX_C, + [AUX_CH_USBC3] = DP_AUX_D, + [AUX_CH_USBC4] = DP_AUX_E, +}; + +/* + * RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D + * map to DDI A,B,TC1,TC2 respectively. + */ +static const u8 rkl_aux_ch_map[] = { + [AUX_CH_A] = DP_AUX_A, + [AUX_CH_B] = DP_AUX_B, + [AUX_CH_USBC1] = DP_AUX_C, + [AUX_CH_USBC2] = DP_AUX_D, +}; + +static const u8 direct_aux_ch_map[] = { + [AUX_CH_A] = DP_AUX_A, + [AUX_CH_B] = DP_AUX_B, + [AUX_CH_C] = DP_AUX_C, + [AUX_CH_D] = DP_AUX_D, /* aka AUX_CH_USBC1 */ + [AUX_CH_E] = DP_AUX_E, /* aka AUX_CH_USBC2 */ + [AUX_CH_F] = DP_AUX_F, /* aka AUX_CH_USBC3 */ + [AUX_CH_G] = DP_AUX_G, /* aka AUX_CH_USBC4 */ + [AUX_CH_H] = DP_AUX_H, /* aka AUX_CH_USBC5 */ + [AUX_CH_I] = DP_AUX_I, /* aka AUX_CH_USBC6 */ +}; + static enum aux_ch map_aux_ch(struct drm_i915_private *i915, u8 aux_channel) { - enum aux_ch aux_ch; + const u8 *aux_ch_map; + int i, n_entries; - /* - * RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D - * map to DDI A,B,TC1,TC2 respectively. - * - * ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E - * map to DDI A,TC1,TC2,TC3,TC4 respectively. - */ - switch (aux_channel) { - case DP_AUX_A: - aux_ch = AUX_CH_A; - break; - case DP_AUX_B: - if (IS_ALDERLAKE_S(i915)) - aux_ch = AUX_CH_USBC1; - else - aux_ch = AUX_CH_B; - break; - case DP_AUX_C: - if (IS_ALDERLAKE_S(i915)) - aux_ch = AUX_CH_USBC2; - else if (IS_DG1(i915) || IS_ROCKETLAKE(i915)) - aux_ch = AUX_CH_USBC1; - else - aux_ch = AUX_CH_C; - break; - case DP_AUX_D: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_D_XELPD; - else if (IS_ALDERLAKE_S(i915)) - aux_ch = AUX_CH_USBC3; - else if (IS_DG1(i915) || IS_ROCKETLAKE(i915)) - aux_ch = AUX_CH_USBC2; - else - aux_ch = AUX_CH_D; - break; - case DP_AUX_E: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_E_XELPD; - else if (IS_ALDERLAKE_S(i915)) - aux_ch = AUX_CH_USBC4; - else - aux_ch = AUX_CH_E; - break; - case DP_AUX_F: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_USBC1; - else - aux_ch = AUX_CH_F; - break; - case DP_AUX_G: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_USBC2; - else - aux_ch = AUX_CH_G; - break; - case DP_AUX_H: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_USBC3; - else - aux_ch = AUX_CH_H; - break; - case DP_AUX_I: - if (DISPLAY_VER(i915) >= 13) - aux_ch = AUX_CH_USBC4; - else - aux_ch = AUX_CH_I; - break; - default: - MISSING_CASE(aux_channel); - aux_ch = AUX_CH_A; - break; + if (DISPLAY_VER(i915) >= 13) { + aux_ch_map = adlp_aux_ch_map; + n_entries = ARRAY_SIZE(adlp_aux_ch_map); + } else if (IS_ALDERLAKE_S(i915)) { + aux_ch_map = adls_aux_ch_map; + n_entries = ARRAY_SIZE(adls_aux_ch_map); + } else if (IS_DG1(i915) || IS_ROCKETLAKE(i915)) { + aux_ch_map = rkl_aux_ch_map; + n_entries = ARRAY_SIZE(rkl_aux_ch_map); + } else { + aux_ch_map = direct_aux_ch_map; + n_entries = ARRAY_SIZE(direct_aux_ch_map); + } + + for (i = 0; i < n_entries; i++) { + if (aux_ch_map[i] == aux_channel) + return i; } - return aux_ch; + drm_dbg_kms(&i915->drm, + "Ignoring alternate AUX CH: VBT claims AUX 0x%x, which is not valid for this platform\n", + aux_channel); + + return AUX_CH_NONE; } enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata) |