diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_bios.c | 188 |
1 files changed, 43 insertions, 145 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 34a397adbd6b..858c959f7bab 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2230,122 +2230,6 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) return 0; } -static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin) -{ - enum port port; - - if (!ddc_pin) - return PORT_NONE; - - for_each_port(port) { - const struct intel_bios_encoder_data *devdata = - i915->display.vbt.ports[port]; - - if (devdata && ddc_pin == devdata->child.ddc_pin) - return port; - } - - return PORT_NONE; -} - -static void sanitize_ddc_pin(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child; - u8 mapped_ddc_pin; - enum port p; - - 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), mapped_ddc_pin, - port_name(p), port_name(p)); - - /* - * If we have multiple ports supposedly sharing the pin, then dvi/hdmi - * couldn't exist on the shared port. Otherwise they share the same ddc - * pin and system couldn't communicate with them separately. - * - * Give inverse child device order the priority, last one wins. Yes, - * 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 :( - */ - child = &i915->display.vbt.ports[p]->child; - - child->device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING; - child->device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; - - child->ddc_pin = 0; -} - -static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch) -{ - enum port port; - - if (!aux_ch) - return PORT_NONE; - - for_each_port(port) { - const struct intel_bios_encoder_data *devdata = - i915->display.vbt.ports[port]; - - if (devdata && aux_ch == devdata->child.aux_channel) - return port; - } - - return PORT_NONE; -} - -static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child; - enum port p; - - 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), devdata->child.aux_channel, - port_name(p), port_name(p)); - - /* - * If we have multiple ports supposedly sharing the aux channel, then DP - * couldn't exist on the shared port. Otherwise they share the same aux - * channel and system couldn't communicate with them separately. - * - * Give inverse child device order the priority, last one wins. Yes, - * 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 :( - */ - child = &i915->display.vbt.ports[p]->child; - - child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; - child->aux_channel = 0; -} - static u8 dvo_port_type(u8 dvo_port) { switch (dvo_port) { @@ -2490,6 +2374,19 @@ dsi_dvo_port_to_port(struct drm_i915_private *i915, u8 dvo_port) } } +enum port intel_bios_encoder_port(const struct intel_bios_encoder_data *devdata) +{ + struct drm_i915_private *i915 = devdata->i915; + const struct child_device_config *child = &devdata->child; + enum port port; + + port = dvo_port_to_port(i915, child->dvo_port); + if (port == PORT_NONE && DISPLAY_VER(i915) >= 11) + port = dsi_dvo_port_to_port(i915, child->dvo_port); + + return port; +} + static int parse_bdb_230_dp_max_link_rate(const int vbt_max_link_rate) { switch (vbt_max_link_rate) { @@ -2600,7 +2497,7 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata) devdata->child.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR; } -static bool +bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata) { return devdata->child.device_type & DEVICE_TYPE_MIPI_OUTPUT; @@ -2615,7 +2512,8 @@ intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata) /* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */ int intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata) { - if (!devdata || devdata->i915->display.vbt.version < 158) + if (!devdata || devdata->i915->display.vbt.version < 158 || + DISPLAY_VER(devdata->i915) >= 14) return -1; return devdata->child.hdmi_level_shifter_value; @@ -2658,13 +2556,17 @@ static bool is_port_valid(struct drm_i915_private *i915, enum port port) return true; } -static void print_ddi_port(const struct intel_bios_encoder_data *devdata, - enum port port) +static void print_ddi_port(const struct intel_bios_encoder_data *devdata) { struct drm_i915_private *i915 = devdata->i915; const struct child_device_config *child = &devdata->child; bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt; int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; + enum port port; + + port = intel_bios_encoder_port(devdata); + if (port == PORT_NONE) + return; is_dvi = intel_bios_encoder_supports_dvi(devdata); is_dp = intel_bios_encoder_supports_dp(devdata); @@ -2728,12 +2630,9 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata, static void parse_ddi_port(struct intel_bios_encoder_data *devdata) { struct drm_i915_private *i915 = devdata->i915; - const struct child_device_config *child = &devdata->child; enum port port; - port = dvo_port_to_port(i915, child->dvo_port); - if (port == PORT_NONE && DISPLAY_VER(i915) >= 11) - port = dsi_dvo_port_to_port(i915, child->dvo_port); + port = intel_bios_encoder_port(devdata); if (port == PORT_NONE) return; @@ -2744,22 +2643,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata) return; } - if (i915->display.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)); - return; - } - sanitize_device_type(devdata, port); - - if (intel_bios_encoder_supports_dvi(devdata)) - sanitize_ddc_pin(devdata, port); - - if (intel_bios_encoder_supports_dp(devdata)) - sanitize_aux_ch(devdata, port); - - i915->display.vbt.ports[port] = devdata; } static bool has_ddi_port_info(struct drm_i915_private *i915) @@ -2770,7 +2654,6 @@ static bool has_ddi_port_info(struct drm_i915_private *i915) static void parse_ddi_ports(struct drm_i915_private *i915) { struct intel_bios_encoder_data *devdata; - enum port port; if (!has_ddi_port_info(i915)) return; @@ -2778,10 +2661,8 @@ static void parse_ddi_ports(struct drm_i915_private *i915) list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) parse_ddi_port(devdata); - for_each_port(port) { - if (i915->display.vbt.ports[port]) - print_ddi_port(i915->display.vbt.ports[port], port); - } + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) + print_ddi_port(devdata); } static void @@ -3706,5 +3587,22 @@ bool intel_bios_encoder_hpd_invert(const struct intel_bios_encoder_data *devdata const struct intel_bios_encoder_data * intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port) { - return i915->display.vbt.ports[port]; + struct intel_bios_encoder_data *devdata; + + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) { + if (intel_bios_encoder_port(devdata) == port) + return devdata; + } + + return NULL; +} + +void intel_bios_for_each_encoder(struct drm_i915_private *i915, + void (*func)(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata)) +{ + struct intel_bios_encoder_data *devdata; + + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) + func(i915, devdata); } |