diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_bios.c | 442 |
1 files changed, 251 insertions, 191 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index e86e6ed2d3bf..b99907c656bb 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -451,13 +451,23 @@ parse_lfp_backlight(struct drm_i915_private *i915, } i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI; - if (bdb->version >= 191 && - get_blocksize(backlight_data) >= sizeof(*backlight_data)) { - const struct lfp_backlight_control_method *method; + if (bdb->version >= 191) { + size_t exp_size; - method = &backlight_data->backlight_control[panel_type]; - i915->vbt.backlight.type = method->type; - i915->vbt.backlight.controller = method->controller; + if (bdb->version >= 236) + exp_size = sizeof(struct bdb_lfp_backlight_data); + else if (bdb->version >= 234) + exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234; + else + exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191; + + if (get_blocksize(backlight_data) >= exp_size) { + const struct lfp_backlight_control_method *method; + + method = &backlight_data->backlight_control[panel_type]; + i915->vbt.backlight.type = method->type; + i915->vbt.backlight.controller = method->controller; + } } i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; @@ -483,6 +493,9 @@ parse_lfp_backlight(struct drm_i915_private *i915, level = 255; } i915->vbt.backlight.min_brightness = min_level; + + i915->vbt.backlight.brightness_precision_bits = + backlight_data->brightness_precision_bits[panel_type]; } else { level = backlight_data->level[panel_type]; i915->vbt.backlight.min_brightness = entry->min_brightness; @@ -1501,39 +1514,130 @@ static u8 translate_iboost(u8 val) return mapping[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 */ +}; + +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, +}; + +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, +}; + +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, +}; + +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, +}; + +static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) +{ + const u8 *ddc_pin_map; + int n_entries; + + if (IS_ALDERLAKE_S(i915)) { + ddc_pin_map = adls_ddc_pin_map; + n_entries = ARRAY_SIZE(adls_ddc_pin_map); + } else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) { + return vbt_pin; + } else if (IS_ROCKETLAKE(i915) && INTEL_PCH_TYPE(i915) == PCH_TGP) { + ddc_pin_map = rkl_pch_tgp_ddc_pin_map; + n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map); + } else if (HAS_PCH_TGP(i915) && DISPLAY_VER(i915) == 9) { + ddc_pin_map = gen9bc_tgp_ddc_pin_map; + n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map); + } else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) { + ddc_pin_map = icp_ddc_pin_map; + n_entries = ARRAY_SIZE(icp_ddc_pin_map); + } else if (HAS_PCH_CNP(i915)) { + ddc_pin_map = cnp_ddc_pin_map; + n_entries = ARRAY_SIZE(cnp_ddc_pin_map); + } else { + /* Assuming direct map */ + return vbt_pin; + } + + if (vbt_pin < n_entries && ddc_pin_map[vbt_pin] != 0) + return ddc_pin_map[vbt_pin]; + + drm_dbg_kms(&i915->drm, + "Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n", + vbt_pin); + return 0; +} + static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin) { - const struct ddi_vbt_port_info *info; + const struct intel_bios_encoder_data *devdata; enum port port; if (!ddc_pin) return PORT_NONE; for_each_port(port) { - info = &i915->vbt.ddi_port_info[port]; + devdata = i915->vbt.ports[port]; - if (info->devdata && ddc_pin == info->alternate_ddc_pin) + if (devdata && ddc_pin == devdata->child.ddc_pin) return port; } return PORT_NONE; } -static void sanitize_ddc_pin(struct drm_i915_private *i915, +static void sanitize_ddc_pin(struct intel_bios_encoder_data *devdata, enum port port) { - struct ddi_vbt_port_info *info = &i915->vbt.ddi_port_info[port]; + struct drm_i915_private *i915 = devdata->i915; struct child_device_config *child; + u8 mapped_ddc_pin; enum port p; - p = get_port_by_ddc_pin(i915, info->alternate_ddc_pin); + if (!devdata->child.ddc_pin) + return; + + mapped_ddc_pin = map_ddc_pin(i915, devdata->child.ddc_pin); + if (!intel_gmbus_is_valid_pin(i915, mapped_ddc_pin)) { + drm_dbg_kms(&i915->drm, + "Port %c has invalid DDC pin %d, " + "sticking to defaults\n", + port_name(port), mapped_ddc_pin); + devdata->child.ddc_pin = 0; + return; + } + + p = get_port_by_ddc_pin(i915, devdata->child.ddc_pin); if (p == PORT_NONE) return; drm_dbg_kms(&i915->drm, "port %c trying to use the same DDC pin (0x%x) as port %c, " "disabling port %c DVI/HDMI support\n", - port_name(port), info->alternate_ddc_pin, + port_name(port), mapped_ddc_pin, port_name(p), port_name(p)); /* @@ -1545,48 +1649,47 @@ static void sanitize_ddc_pin(struct drm_i915_private *i915, * there are real machines (eg. Asrock B250M-HDV) where VBT has both * port A and port E with the same AUX ch and we must pick port E :( */ - info = &i915->vbt.ddi_port_info[p]; - child = &info->devdata->child; + child = &i915->vbt.ports[p]->child; child->device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING; child->device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; - info->alternate_ddc_pin = 0; + child->ddc_pin = 0; } static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch) { - const struct ddi_vbt_port_info *info; + const struct intel_bios_encoder_data *devdata; enum port port; if (!aux_ch) return PORT_NONE; for_each_port(port) { - info = &i915->vbt.ddi_port_info[port]; + devdata = i915->vbt.ports[port]; - if (info->devdata && aux_ch == info->alternate_aux_channel) + if (devdata && aux_ch == devdata->child.aux_channel) return port; } return PORT_NONE; } -static void sanitize_aux_ch(struct drm_i915_private *i915, +static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, enum port port) { - struct ddi_vbt_port_info *info = &i915->vbt.ddi_port_info[port]; + struct drm_i915_private *i915 = devdata->i915; struct child_device_config *child; enum port p; - p = get_port_by_aux_ch(i915, info->alternate_aux_channel); + p = get_port_by_aux_ch(i915, devdata->child.aux_channel); if (p == PORT_NONE) return; drm_dbg_kms(&i915->drm, "port %c trying to use the same AUX CH (0x%x) as port %c, " "disabling port %c DP support\n", - port_name(port), info->alternate_aux_channel, + port_name(port), devdata->child.aux_channel, port_name(p), port_name(p)); /* @@ -1598,88 +1701,10 @@ static void sanitize_aux_ch(struct drm_i915_private *i915, * there are real machines (eg. Asrock B250M-HDV) where VBT has both * port A and port E with the same AUX ch and we must pick port E :( */ - info = &i915->vbt.ddi_port_info[p]; - child = &info->devdata->child; + child = &i915->vbt.ports[p]->child; child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; - info->alternate_aux_channel = 0; -} - -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 */ -}; - -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, -}; - -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, -}; - -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, -}; - -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, -}; - -static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) -{ - const u8 *ddc_pin_map; - int n_entries; - - if (IS_ALDERLAKE_S(i915)) { - ddc_pin_map = adls_ddc_pin_map; - n_entries = ARRAY_SIZE(adls_ddc_pin_map); - } else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) { - return vbt_pin; - } else if (IS_ROCKETLAKE(i915) && INTEL_PCH_TYPE(i915) == PCH_TGP) { - ddc_pin_map = rkl_pch_tgp_ddc_pin_map; - n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map); - } else if (HAS_PCH_TGP(i915) && DISPLAY_VER(i915) == 9) { - ddc_pin_map = gen9bc_tgp_ddc_pin_map; - n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map); - } else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) { - ddc_pin_map = icp_ddc_pin_map; - n_entries = ARRAY_SIZE(icp_ddc_pin_map); - } else if (HAS_PCH_CNP(i915)) { - ddc_pin_map = cnp_ddc_pin_map; - n_entries = ARRAY_SIZE(cnp_ddc_pin_map); - } else { - /* Assuming direct map */ - return vbt_pin; - } - - if (vbt_pin < n_entries && ddc_pin_map[vbt_pin] != 0) - return ddc_pin_map[vbt_pin]; - - drm_dbg_kms(&i915->drm, - "Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n", - vbt_pin); - return 0; + child->aux_channel = 0; } static enum port __dvo_port_to_port(int n_ports, int n_dvo, @@ -1815,6 +1840,17 @@ static int parse_bdb_216_dp_max_link_rate(const int vbt_max_link_rate) } } +static int _intel_bios_dp_max_link_rate(const struct intel_bios_encoder_data *devdata) +{ + if (!devdata || devdata->i915->vbt.version < 216) + return 0; + + if (devdata->i915->vbt.version >= 230) + return parse_bdb_230_dp_max_link_rate(devdata->child.dp_max_link_rate); + else + return parse_bdb_216_dp_max_link_rate(devdata->child.dp_max_link_rate); +} + static void sanitize_device_type(struct intel_bios_encoder_data *devdata, enum port port) { @@ -1868,6 +1904,76 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata) devdata->child.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR; } +static int _intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata) +{ + if (!devdata || devdata->i915->vbt.version < 158) + return -1; + + return devdata->child.hdmi_level_shifter_value; +} + +static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devdata) +{ + if (!devdata || devdata->i915->vbt.version < 204) + return 0; + + switch (devdata->child.hdmi_max_data_rate) { + default: + MISSING_CASE(devdata->child.hdmi_max_data_rate); + fallthrough; + case HDMI_MAX_DATA_RATE_PLATFORM: + return 0; + case HDMI_MAX_DATA_RATE_297: + return 297000; + case HDMI_MAX_DATA_RATE_165: + return 165000; + } +} + +static enum port get_edp_port(struct drm_i915_private *i915) +{ + const struct intel_bios_encoder_data *devdata; + enum port port; + + for_each_port(port) { + devdata = i915->vbt.ports[port]; + + if (devdata && intel_bios_encoder_supports_edp(devdata)) + return port; + } + + return PORT_NONE; +} + +/* + * FIXME: The power sequencer and backlight code currently do not support more + * than one set registers, at least not on anything other than VLV/CHV. It will + * clobber the registers. As a temporary workaround, gracefully prevent more + * than one eDP from being registered. + */ +static void sanitize_dual_edp(struct intel_bios_encoder_data *devdata, + enum port port) +{ + struct drm_i915_private *i915 = devdata->i915; + struct child_device_config *child = &devdata->child; + enum port p; + + /* CHV might not clobber PPS registers. */ + if (IS_CHERRYVIEW(i915)) + return; + + p = get_edp_port(i915); + if (p == PORT_NONE) + return; + + drm_dbg_kms(&i915->drm, "both ports %c and %c configured as eDP, " + "disabling port %c eDP\n", port_name(p), port_name(port), + port_name(port)); + + child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; + child->device_type &= ~DEVICE_TYPE_INTERNAL_CONNECTOR; +} + static bool is_port_valid(struct drm_i915_private *i915, enum port port) { /* @@ -1885,9 +1991,8 @@ static void parse_ddi_port(struct drm_i915_private *i915, struct intel_bios_encoder_data *devdata) { const struct child_device_config *child = &devdata->child; - struct ddi_vbt_port_info *info; bool is_dvi, is_hdmi, is_dp, is_edp, is_crt, supports_typec_usb, supports_tbt; - int dp_boost_level, hdmi_boost_level; + int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; enum port port; port = dvo_port_to_port(i915, child->dvo_port); @@ -1901,9 +2006,7 @@ static void parse_ddi_port(struct drm_i915_private *i915, return; } - info = &i915->vbt.ddi_port_info[port]; - - if (info->devdata) { + if (i915->vbt.ports[port]) { drm_dbg_kms(&i915->drm, "More than one child device for port %c in VBT, using the first.\n", port_name(port)); @@ -1928,62 +2031,27 @@ static void parse_ddi_port(struct drm_i915_private *i915, supports_typec_usb, supports_tbt, devdata->dsc != NULL); - if (is_dvi) { - u8 ddc_pin; + if (is_edp) + sanitize_dual_edp(devdata, port); - ddc_pin = map_ddc_pin(i915, child->ddc_pin); - if (intel_gmbus_is_valid_pin(i915, ddc_pin)) { - info->alternate_ddc_pin = ddc_pin; - sanitize_ddc_pin(i915, port); - } else { - drm_dbg_kms(&i915->drm, - "Port %c has invalid DDC pin %d, " - "sticking to defaults\n", - port_name(port), ddc_pin); - } - } - - if (is_dp) { - info->alternate_aux_channel = child->aux_channel; + if (is_dvi) + sanitize_ddc_pin(devdata, port); - sanitize_aux_ch(i915, port); - } + if (is_dp) + sanitize_aux_ch(devdata, port); - if (i915->vbt.version >= 158) { - /* The VBT HDMI level shift values match the table we have. */ - u8 hdmi_level_shift = child->hdmi_level_shifter_value; + hdmi_level_shift = _intel_bios_hdmi_level_shift(devdata); + if (hdmi_level_shift >= 0) { drm_dbg_kms(&i915->drm, "Port %c VBT HDMI level shift: %d\n", - port_name(port), - hdmi_level_shift); - info->hdmi_level_shift = hdmi_level_shift; - info->hdmi_level_shift_set = true; + port_name(port), hdmi_level_shift); } - if (i915->vbt.version >= 204) { - int max_tmds_clock; - - switch (child->hdmi_max_data_rate) { - default: - MISSING_CASE(child->hdmi_max_data_rate); - fallthrough; - case HDMI_MAX_DATA_RATE_PLATFORM: - max_tmds_clock = 0; - break; - case HDMI_MAX_DATA_RATE_297: - max_tmds_clock = 297000; - break; - case HDMI_MAX_DATA_RATE_165: - max_tmds_clock = 165000; - break; - } - - if (max_tmds_clock) - drm_dbg_kms(&i915->drm, - "Port %c VBT HDMI max TMDS clock: %d kHz\n", - port_name(port), max_tmds_clock); - info->max_tmds_clock = max_tmds_clock; - } + max_tmds_clock = _intel_bios_max_tmds_clock(devdata); + if (max_tmds_clock) + drm_dbg_kms(&i915->drm, + "Port %c VBT HDMI max TMDS clock: %d kHz\n", + port_name(port), max_tmds_clock); /* I_boost config for SKL and above */ dp_boost_level = intel_bios_encoder_dp_boost_level(devdata); @@ -1998,19 +2066,13 @@ static void parse_ddi_port(struct drm_i915_private *i915, "Port %c VBT HDMI boost level: %d\n", port_name(port), hdmi_boost_level); - /* DP max link rate for GLK+ */ - if (i915->vbt.version >= 216) { - if (i915->vbt.version >= 230) - info->dp_max_link_rate = parse_bdb_230_dp_max_link_rate(child->dp_max_link_rate); - else - info->dp_max_link_rate = parse_bdb_216_dp_max_link_rate(child->dp_max_link_rate); - + dp_max_link_rate = _intel_bios_dp_max_link_rate(devdata); + if (dp_max_link_rate) drm_dbg_kms(&i915->drm, "Port %c VBT DP max link rate: %d\n", - port_name(port), info->dp_max_link_rate); - } + port_name(port), dp_max_link_rate); - info->devdata = devdata; + i915->vbt.ports[port] = devdata; } static void parse_ddi_ports(struct drm_i915_private *i915) @@ -2548,12 +2610,8 @@ bool intel_bios_is_port_present(struct drm_i915_private *i915, enum port port) [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, }; - if (HAS_DDI(i915)) { - const struct ddi_vbt_port_info *port_info = - &i915->vbt.ddi_port_info[port]; - - return port_info->devdata; - } + if (HAS_DDI(i915)) + return i915->vbt.ports[port]; /* FIXME maybe deal with port A as well? */ if (drm_WARN_ON(&i915->drm, @@ -2804,8 +2862,7 @@ bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915, enum port port) { - const struct intel_bios_encoder_data *devdata = - i915->vbt.ddi_port_info[port].devdata; + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[port]; if (drm_WARN_ON_ONCE(&i915->drm, !IS_GEMINILAKE(i915) && !IS_BROXTON(i915))) @@ -2825,8 +2882,7 @@ bool intel_bios_is_lspcon_present(const struct drm_i915_private *i915, enum port port) { - const struct intel_bios_encoder_data *devdata = - i915->vbt.ddi_port_info[port].devdata; + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[port]; return HAS_LSPCON(i915) && devdata && devdata->child.lspcon; } @@ -2842,8 +2898,7 @@ bool intel_bios_is_lane_reversal_needed(const struct drm_i915_private *i915, enum port port) { - const struct intel_bios_encoder_data *devdata = - i915->vbt.ddi_port_info[port].devdata; + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[port]; return devdata && devdata->child.lane_reversal; } @@ -2851,11 +2906,10 @@ intel_bios_is_lane_reversal_needed(const struct drm_i915_private *i915, enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, enum port port) { - const struct ddi_vbt_port_info *info = - &i915->vbt.ddi_port_info[port]; + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[port]; enum aux_ch aux_ch; - if (!info->alternate_aux_channel) { + if (!devdata || !devdata->child.aux_channel) { aux_ch = (enum aux_ch)port; drm_dbg_kms(&i915->drm, @@ -2871,7 +2925,7 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, * ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E * map to DDI A,TC1,TC2,TC3,TC4 respectively. */ - switch (info->alternate_aux_channel) { + switch (devdata->child.aux_channel) { case DP_AUX_A: aux_ch = AUX_CH_A; break; @@ -2932,7 +2986,7 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, aux_ch = AUX_CH_I; break; default: - MISSING_CASE(info->alternate_aux_channel); + MISSING_CASE(devdata->child.aux_channel); aux_ch = AUX_CH_A; break; } @@ -2946,17 +3000,18 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, int intel_bios_max_tmds_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[encoder->port]; - return i915->vbt.ddi_port_info[encoder->port].max_tmds_clock; + return _intel_bios_max_tmds_clock(devdata); } +/* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */ int intel_bios_hdmi_level_shift(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - const struct ddi_vbt_port_info *info = - &i915->vbt.ddi_port_info[encoder->port]; + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[encoder->port]; - return info->hdmi_level_shift_set ? info->hdmi_level_shift : -1; + return _intel_bios_hdmi_level_shift(devdata); } int intel_bios_encoder_dp_boost_level(const struct intel_bios_encoder_data *devdata) @@ -2978,15 +3033,20 @@ int intel_bios_encoder_hdmi_boost_level(const struct intel_bios_encoder_data *de int intel_bios_dp_max_link_rate(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[encoder->port]; - return i915->vbt.ddi_port_info[encoder->port].dp_max_link_rate; + return _intel_bios_dp_max_link_rate(devdata); } int intel_bios_alternate_ddc_pin(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); + const struct intel_bios_encoder_data *devdata = i915->vbt.ports[encoder->port]; + + if (!devdata || !devdata->child.ddc_pin) + return 0; - return i915->vbt.ddi_port_info[encoder->port].alternate_ddc_pin; + return map_ddc_pin(i915, devdata->child.ddc_pin); } bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata) @@ -3002,5 +3062,5 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda const struct intel_bios_encoder_data * intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port) { - return i915->vbt.ddi_port_info[port].devdata; + return i915->vbt.ports[port]; } |