diff options
author | Jani Nikula <jani.nikula@intel.com> | 2015-12-01 09:29:26 -0500 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2015-12-02 06:29:41 -0500 |
commit | bffce907d64042b5683ed3076e839d0249606264 (patch) | |
tree | 6bda4975b36467d0f4460f824ff201751e9eb7b2 | |
parent | 0aeb904888f52f48ca0cc7dfec2c2f540d2a762a (diff) |
drm/i915: abstract i2c bit banging fallback in gmbus xfer
Choose between i2c bit banging and gmbus in a new higher level function,
and let the i2c core retry the first time we fall back to bit banging.
The i2c core imposes a timeout on -EAGAIN, but it defaults to 1 second,
and shouldn't be a problem for us.
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1448980166-23055-2-git-send-email-jani.nikula@intel.com
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index ccb522c176bd..e26e22a72e3b 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -472,9 +472,7 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs) | |||
472 | } | 472 | } |
473 | 473 | ||
474 | static int | 474 | static int |
475 | gmbus_xfer(struct i2c_adapter *adapter, | 475 | do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) |
476 | struct i2c_msg *msgs, | ||
477 | int num) | ||
478 | { | 476 | { |
479 | struct intel_gmbus *bus = container_of(adapter, | 477 | struct intel_gmbus *bus = container_of(adapter, |
480 | struct intel_gmbus, | 478 | struct intel_gmbus, |
@@ -483,14 +481,6 @@ gmbus_xfer(struct i2c_adapter *adapter, | |||
483 | int i = 0, inc, try = 0; | 481 | int i = 0, inc, try = 0; |
484 | int ret = 0; | 482 | int ret = 0; |
485 | 483 | ||
486 | intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); | ||
487 | mutex_lock(&dev_priv->gmbus_mutex); | ||
488 | |||
489 | if (bus->force_bit) { | ||
490 | ret = i2c_bit_algo.master_xfer(adapter, msgs, num); | ||
491 | goto out; | ||
492 | } | ||
493 | |||
494 | retry: | 484 | retry: |
495 | I915_WRITE(GMBUS0, bus->reg0); | 485 | I915_WRITE(GMBUS0, bus->reg0); |
496 | 486 | ||
@@ -585,13 +575,34 @@ timeout: | |||
585 | bus->adapter.name, bus->reg0 & 0xff); | 575 | bus->adapter.name, bus->reg0 & 0xff); |
586 | I915_WRITE(GMBUS0, 0); | 576 | I915_WRITE(GMBUS0, 0); |
587 | 577 | ||
588 | /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ | 578 | /* |
579 | * Hardware may not support GMBUS over these pins? Try GPIO bitbanging | ||
580 | * instead. Use EAGAIN to have i2c core retry. | ||
581 | */ | ||
589 | bus->force_bit = 1; | 582 | bus->force_bit = 1; |
590 | ret = i2c_bit_algo.master_xfer(adapter, msgs, num); | 583 | ret = -EAGAIN; |
591 | 584 | ||
592 | out: | 585 | out: |
593 | mutex_unlock(&dev_priv->gmbus_mutex); | 586 | return ret; |
587 | } | ||
588 | |||
589 | static int | ||
590 | gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) | ||
591 | { | ||
592 | struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus, | ||
593 | adapter); | ||
594 | struct drm_i915_private *dev_priv = bus->dev_priv; | ||
595 | int ret; | ||
596 | |||
597 | intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); | ||
598 | mutex_lock(&dev_priv->gmbus_mutex); | ||
599 | |||
600 | if (bus->force_bit) | ||
601 | ret = i2c_bit_algo.master_xfer(adapter, msgs, num); | ||
602 | else | ||
603 | ret = do_gmbus_xfer(adapter, msgs, num); | ||
594 | 604 | ||
605 | mutex_unlock(&dev_priv->gmbus_mutex); | ||
595 | intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); | 606 | intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); |
596 | 607 | ||
597 | return ret; | 608 | return ret; |