Skip to content

Commit 3f5f155

Browse files
committed
drm/i915: Fix DDC probe for passive adapters
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 <eugeni.dodonov@intel.com> 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 <chris@chris-wilson.co.uk> 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 <tprevite@gmail.com>. [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 <tprevite@gmail.com> Cc: stable@vger.kernel.org Tested-by: Oliver Grafe <oliver.grafe@ge.com> (v2) Tested-by: Jim Bride <jim.bride@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
1 parent 8ce7da4 commit 3f5f155

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
@@ -435,7 +435,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
435435
struct intel_gmbus,
436436
adapter);
437437
struct drm_i915_private *dev_priv = bus->dev_priv;
438-
int i, reg_offset;
438+
int i = 0, inc, try = 0, reg_offset;
439439
int ret = 0;
440440

441441
intel_aux_display_runtime_get(dev_priv);
@@ -448,12 +448,14 @@ gmbus_xfer(struct i2c_adapter *adapter,
448448

449449
reg_offset = dev_priv->gpio_mmio_base;
450450

451+
retry:
451452
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
452453

453-
for (i = 0; i < num; i++) {
454+
for (; i < num; i += inc) {
455+
inc = 1;
454456
if (gmbus_is_index_read(msgs, i, num)) {
455457
ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
456-
i += 1; /* set i to the index of the read xfer */
458+
inc = 2; /* an index read is two msgs */
457459
} else if (msgs[i].flags & I2C_M_RD) {
458460
ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
459461
} else {
@@ -525,6 +527,18 @@ gmbus_xfer(struct i2c_adapter *adapter,
525527
adapter->name, msgs[i].addr,
526528
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
527529

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

530544
timeout:

0 commit comments

Comments
 (0)