Commit 32c2bc89 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Fix type1 DVI DP dual mode adapter heuristic for modern platforms

Looks like we never updated intel_bios_is_port_dp_dual_mode() when
the VBT port mapping became erratic on modern platforms. This
is causing us to look up the wrong child device and thus throwing
the heuristic off (ie. we might end looking at a child device for
a genuine DP++ port when we were supposed to look at one for a
native HDMI port).

Fix it up by not using the outdated port_mapping[] in
intel_bios_is_port_dp_dual_mode() and rely on
intel_bios_encoder_data_lookup() instead.

Cc: stable@vger.kernel.org
Tested-by: default avatarRandy Dunlap <rdunlap@infradead.org>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4138Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211025142147.23897-1-ville.syrjala@linux.intel.comReviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
parent 4c3d0053
...@@ -1707,6 +1707,39 @@ static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, ...@@ -1707,6 +1707,39 @@ static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata,
child->aux_channel = 0; child->aux_channel = 0;
} }
static u8 dvo_port_type(u8 dvo_port)
{
switch (dvo_port) {
case DVO_PORT_HDMIA:
case DVO_PORT_HDMIB:
case DVO_PORT_HDMIC:
case DVO_PORT_HDMID:
case DVO_PORT_HDMIE:
case DVO_PORT_HDMIF:
case DVO_PORT_HDMIG:
case DVO_PORT_HDMIH:
case DVO_PORT_HDMII:
return DVO_PORT_HDMIA;
case DVO_PORT_DPA:
case DVO_PORT_DPB:
case DVO_PORT_DPC:
case DVO_PORT_DPD:
case DVO_PORT_DPE:
case DVO_PORT_DPF:
case DVO_PORT_DPG:
case DVO_PORT_DPH:
case DVO_PORT_DPI:
return DVO_PORT_DPA;
case DVO_PORT_MIPIA:
case DVO_PORT_MIPIB:
case DVO_PORT_MIPIC:
case DVO_PORT_MIPID:
return DVO_PORT_MIPIA;
default:
return dvo_port;
}
}
static enum port __dvo_port_to_port(int n_ports, int n_dvo, static enum port __dvo_port_to_port(int n_ports, int n_dvo,
const int port_mapping[][3], u8 dvo_port) const int port_mapping[][3], u8 dvo_port)
{ {
...@@ -2623,7 +2656,24 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port) ...@@ -2623,7 +2656,24 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port)
return false; return false;
} }
static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, static bool child_dev_is_dp_dual_mode(const struct child_device_config *child)
{
if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) !=
(DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS))
return false;
if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA)
return true;
/* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */
if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA &&
child->aux_channel != 0)
return true;
return false;
}
bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915,
enum port port) enum port port)
{ {
static const struct { static const struct {
...@@ -2639,32 +2689,23 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, ...@@ -2639,32 +2689,23 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child,
[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
[PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, },
}; };
const struct intel_bios_encoder_data *devdata;
if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) if (HAS_DDI(i915)) {
return false; const struct intel_bios_encoder_data *devdata;
if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) !=
(DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS))
return false;
if (child->dvo_port == port_mapping[port].dp) devdata = intel_bios_encoder_data_lookup(i915, port);
return true;
/* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ return devdata && child_dev_is_dp_dual_mode(&devdata->child);
if (child->dvo_port == port_mapping[port].hdmi && }
child->aux_channel != 0)
return true;
if (port == PORT_A || port >= ARRAY_SIZE(port_mapping))
return false; 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;
list_for_each_entry(devdata, &i915->vbt.display_devices, node) { list_for_each_entry(devdata, &i915->vbt.display_devices, node) {
if (child_dev_is_dp_dual_mode(&devdata->child, port)) if ((devdata->child.dvo_port == port_mapping[port].dp ||
devdata->child.dvo_port == port_mapping[port].hdmi) &&
child_dev_is_dp_dual_mode(&devdata->child))
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment