Skip to content

Commit 49d4648

Browse files
committed
drm/i915: Remove DDC pin sanitation
Stop with the VBT DDC pin sanitation, and instead just check that the appropriate DDC pin is still available when initializing a HDMI connector. The reason being that we want to start initializing ports in VBT order to deal with VBTs that declare child devices with seemingly conflicting ports. As the encoder initialization can fail for other reasons (at least for eDP+AUX) we can't know upfront which way the conflicts should be resolved. Note that the old way of sanitizing gave priority to the last port declared in the VBT, but now we sort of do the opposite by favoring the first encoder to successfully initialize. So far we're not aware of HDMI/DDC use cases where this would matter but for AUX CH (will be subject to a similar change) there are known cases where it matters. Also note that the old code fell back to the platform default DDC pin if the VBT pin was populated but invalid. That doesn't seem like such a great idea because the VBT might have later declared another port using that platform default pin, and so we might just be creating more DDC pin conflicts here. So lets not second guess the VBT and simply reject the entire HDMI encoder if the VBT DDC pin is invalid. v2: Pimp the commit message (Jani) Cc: Jani Nikula <[email protected]> Signed-off-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Jani Nikula <[email protected]>
1 parent 9856308 commit 49d4648

File tree

2 files changed

+59
-82
lines changed

2 files changed

+59
-82
lines changed

drivers/gpu/drm/i915/display/intel_bios.c

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,72 +2230,6 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
22302230
return 0;
22312231
}
22322232

2233-
static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin)
2234-
{
2235-
enum port port;
2236-
2237-
if (!ddc_pin)
2238-
return PORT_NONE;
2239-
2240-
for_each_port(port) {
2241-
const struct intel_bios_encoder_data *devdata =
2242-
i915->display.vbt.ports[port];
2243-
2244-
if (devdata && ddc_pin == devdata->child.ddc_pin)
2245-
return port;
2246-
}
2247-
2248-
return PORT_NONE;
2249-
}
2250-
2251-
static void sanitize_ddc_pin(struct intel_bios_encoder_data *devdata,
2252-
enum port port)
2253-
{
2254-
struct drm_i915_private *i915 = devdata->i915;
2255-
struct child_device_config *child;
2256-
u8 mapped_ddc_pin;
2257-
enum port p;
2258-
2259-
if (!devdata->child.ddc_pin)
2260-
return;
2261-
2262-
mapped_ddc_pin = map_ddc_pin(i915, devdata->child.ddc_pin);
2263-
if (!intel_gmbus_is_valid_pin(i915, mapped_ddc_pin)) {
2264-
drm_dbg_kms(&i915->drm,
2265-
"Port %c has invalid DDC pin %d, "
2266-
"sticking to defaults\n",
2267-
port_name(port), mapped_ddc_pin);
2268-
devdata->child.ddc_pin = 0;
2269-
return;
2270-
}
2271-
2272-
p = get_port_by_ddc_pin(i915, devdata->child.ddc_pin);
2273-
if (p == PORT_NONE)
2274-
return;
2275-
2276-
drm_dbg_kms(&i915->drm,
2277-
"port %c trying to use the same DDC pin (0x%x) as port %c, "
2278-
"disabling port %c DVI/HDMI support\n",
2279-
port_name(port), mapped_ddc_pin,
2280-
port_name(p), port_name(p));
2281-
2282-
/*
2283-
* If we have multiple ports supposedly sharing the pin, then dvi/hdmi
2284-
* couldn't exist on the shared port. Otherwise they share the same ddc
2285-
* pin and system couldn't communicate with them separately.
2286-
*
2287-
* Give inverse child device order the priority, last one wins. Yes,
2288-
* there are real machines (eg. Asrock B250M-HDV) where VBT has both
2289-
* port A and port E with the same AUX ch and we must pick port E :(
2290-
*/
2291-
child = &i915->display.vbt.ports[p]->child;
2292-
2293-
child->device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING;
2294-
child->device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT;
2295-
2296-
child->ddc_pin = 0;
2297-
}
2298-
22992233
static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch)
23002234
{
23012235
enum port port;
@@ -2754,9 +2688,6 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
27542688

27552689
sanitize_device_type(devdata, port);
27562690

2757-
if (intel_bios_encoder_supports_dvi(devdata))
2758-
sanitize_ddc_pin(devdata, port);
2759-
27602691
if (intel_bios_encoder_supports_dp(devdata))
27612692
sanitize_aux_ch(devdata, port);
27622693

drivers/gpu/drm/i915/display/intel_hdmi.c

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,21 +2880,12 @@ static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv,
28802880
return ddc_pin;
28812881
}
28822882

2883-
static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
2883+
static u8 intel_hdmi_default_ddc_pin(struct intel_encoder *encoder)
28842884
{
28852885
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
28862886
enum port port = encoder->port;
28872887
u8 ddc_pin;
28882888

2889-
ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata);
2890-
if (ddc_pin) {
2891-
drm_dbg_kms(&dev_priv->drm,
2892-
"[ENCODER:%d:%s] Using DDC pin 0x%x (VBT)\n",
2893-
encoder->base.base.id, encoder->base.name,
2894-
ddc_pin);
2895-
return ddc_pin;
2896-
}
2897-
28982889
if (IS_ALDERLAKE_S(dev_priv))
28992890
ddc_pin = adls_port_to_ddc_pin(dev_priv, port);
29002891
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
@@ -2916,10 +2907,62 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
29162907
else
29172908
ddc_pin = g4x_port_to_ddc_pin(dev_priv, port);
29182909

2919-
drm_dbg_kms(&dev_priv->drm,
2920-
"[ENCODER:%d:%s] Using DDC pin 0x%x (platform default)\n",
2910+
return ddc_pin;
2911+
}
2912+
2913+
static struct intel_encoder *
2914+
get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
2915+
{
2916+
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2917+
struct intel_encoder *other;
2918+
2919+
for_each_intel_encoder(&i915->drm, other) {
2920+
if (other == encoder)
2921+
continue;
2922+
2923+
if (!intel_encoder_is_dig_port(other))
2924+
continue;
2925+
2926+
if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin)
2927+
return other;
2928+
}
2929+
2930+
return NULL;
2931+
}
2932+
2933+
static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
2934+
{
2935+
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2936+
struct intel_encoder *other;
2937+
const char *source;
2938+
u8 ddc_pin;
2939+
2940+
ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata);
2941+
source = "VBT";
2942+
2943+
if (!ddc_pin) {
2944+
ddc_pin = intel_hdmi_default_ddc_pin(encoder);
2945+
source = "platform default";
2946+
}
2947+
2948+
if (!intel_gmbus_is_valid_pin(i915, ddc_pin)) {
2949+
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Invalid DDC pin %d\n",
2950+
encoder->base.base.id, encoder->base.name, ddc_pin);
2951+
return 0;
2952+
}
2953+
2954+
other = get_encoder_by_ddc_pin(encoder, ddc_pin);
2955+
if (other) {
2956+
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] DDC pin %d already claimed by [ENCODER:%d:%s]\n",
2957+
encoder->base.base.id, encoder->base.name, ddc_pin,
2958+
other->base.base.id, other->base.name);
2959+
return 0;
2960+
}
2961+
2962+
drm_dbg_kms(&i915->drm,
2963+
"[ENCODER:%d:%s] Using DDC pin 0x%x (%s)\n",
29212964
encoder->base.base.id, encoder->base.name,
2922-
ddc_pin);
2965+
ddc_pin, source);
29232966

29242967
return ddc_pin;
29252968
}
@@ -2990,6 +3033,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
29903033
return;
29913034

29923035
intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder);
3036+
if (!intel_hdmi->ddc_bus)
3037+
return;
3038+
29933039
ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
29943040

29953041
drm_connector_init_with_ddc(dev, connector,

0 commit comments

Comments
 (0)