Skip to content

Commit a0e4eef

Browse files
jnikulagregkh
authored andcommitted
drm/i915: Fix DDC probe for passive adapters
commit 3f5f155 upstream. Passive DP->DVI/HDMI dongles on DP++ ports show up to the system as HDMI devices, as they do not have a sink device in them to respond to any AUX traffic. When probing these dongles over the DDC, sometimes they will NAK the first attempt even though the transaction is valid and they support the DDC protocol. The retry loop inside of drm_do_probe_ddc_edid() would normally catch this case and try the transaction again, resulting in success. That, however, was thwarted by the fix for [1]: commit 9292f37 Author: Eugeni Dodonov <[email protected]> Date: Thu Jan 5 09:34:28 2012 -0200 drm: give up on edid retries when i2c bus is not responding This added code to exit immediately if the return code from the i2c_transfer function was -ENXIO in order to reduce the amount of time spent in waiting for unresponsive or disconnected devices. That was possible because the underlying i2c bit banging algorithm had retries of its own (which, of course, were part of the reason for the bug the commit fixes). Since its introduction in commit f899fc6 Author: Chris Wilson <[email protected]> Date: Tue Jul 20 15:44:45 2010 -0700 drm/i915: use GMBUS to manage i2c links we've been flipping back and forth enabling the GMBUS transfers, but we've settled since then. The GMBUS implementation does not do any retries, however, bailing out of the drm_do_probe_ddc_edid() retry loop on first encounter of -ENXIO. This, combined with Eugeni's commit, broke the retry on -ENXIO. Retry GMBUS once on -ENXIO on first message to mitigate the issues with passive adapters. This patch is based on the work, and commit message, by Todd Previte <[email protected]>. [1] https://bugs.freedesktop.org/show_bug.cgi?id=41059 v2: Don't retry if using bit banging. v3: Move retry within gmbux_xfer, retry only on first message. v4: Initialize GMBUS0 on retry (Ville). v5: Take index reads into account (Ville). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=85924 Cc: Todd Previte <[email protected]> Tested-by: Oliver Grafe <[email protected]> (v2) Tested-by: Jim Bride <[email protected]> Reviewed-by: Ville Syrjälä <[email protected]> Signed-off-by: Jani Nikula <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 57d5697 commit a0e4eef

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

drivers/gpu/drm/i915/intel_i2c.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
441441
struct intel_gmbus,
442442
adapter);
443443
struct drm_i915_private *dev_priv = bus->dev_priv;
444-
int i, reg_offset;
444+
int i = 0, inc, try = 0, reg_offset;
445445
int ret = 0;
446446

447447
mutex_lock(&dev_priv->gmbus_mutex);
@@ -453,12 +453,14 @@ gmbus_xfer(struct i2c_adapter *adapter,
453453

454454
reg_offset = dev_priv->gpio_mmio_base;
455455

456+
retry:
456457
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
457458

458-
for (i = 0; i < num; i++) {
459+
for (; i < num; i += inc) {
460+
inc = 1;
459461
if (gmbus_is_index_read(msgs, i, num)) {
460462
ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
461-
i += 1; /* set i to the index of the read xfer */
463+
inc = 2; /* an index read is two msgs */
462464
} else if (msgs[i].flags & I2C_M_RD) {
463465
ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
464466
} else {
@@ -530,6 +532,18 @@ gmbus_xfer(struct i2c_adapter *adapter,
530532
adapter->name, msgs[i].addr,
531533
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
532534

535+
/*
536+
* Passive adapters sometimes NAK the first probe. Retry the first
537+
* message once on -ENXIO for GMBUS transfers; the bit banging algorithm
538+
* has retries internally. See also the retry loop in
539+
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
540+
*/
541+
if (ret == -ENXIO && i == 0 && try++ == 0) {
542+
DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
543+
adapter->name);
544+
goto retry;
545+
}
546+
533547
goto out;
534548

535549
timeout:

0 commit comments

Comments
 (0)