forked from Minki/linux
drm/i915: Restore GMBUS operation after a failed bit-banging fallback
When the GMBUS based i2c transfer times out, we try to fall back to bit-banging and retry the operation that way. However if the bit-banging attempt also fails, we should probably go back to the GMBUS method for the next attempt. Maybe there simply wasn't anyone one the bus at this time. There's also a bit of a mess going on with the force_bit handling. It's supposed to be a ref count actually, and it is as far as intel_gmbus_force_bit() is concerned. But it's treated as just a flag by the timeout based bit-banging fallback. I suppose that's fine since we should never end up in the timeout fallback case if force_bit was already non-zero. However now that we want to restore things back to where they were after the bit-banging attempt failed, we're going to have to do things a bit differently to avoid clobbering the force_bit count as set up by intel_gmbus_force_bit(). So let's dedicate the high bit as a flag for the low level timeout based fallback and treat the rest of the bits as a ref count just as before. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1457366220-29409-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:
parent
ade754ec11
commit
3e4d44e0fa
@ -996,6 +996,7 @@ struct intel_fbc_work;
|
|||||||
|
|
||||||
struct intel_gmbus {
|
struct intel_gmbus {
|
||||||
struct i2c_adapter adapter;
|
struct i2c_adapter adapter;
|
||||||
|
#define GMBUS_FORCE_BIT_RETRY (1U << 31)
|
||||||
u32 force_bit;
|
u32 force_bit;
|
||||||
u32 reg0;
|
u32 reg0;
|
||||||
i915_reg_t gpio_reg;
|
i915_reg_t gpio_reg;
|
||||||
|
@ -579,7 +579,6 @@ timeout:
|
|||||||
* Hardware may not support GMBUS over these pins? Try GPIO bitbanging
|
* Hardware may not support GMBUS over these pins? Try GPIO bitbanging
|
||||||
* instead. Use EAGAIN to have i2c core retry.
|
* instead. Use EAGAIN to have i2c core retry.
|
||||||
*/
|
*/
|
||||||
bus->force_bit = 1;
|
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -597,10 +596,15 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
|||||||
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
|
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
mutex_lock(&dev_priv->gmbus_mutex);
|
mutex_lock(&dev_priv->gmbus_mutex);
|
||||||
|
|
||||||
if (bus->force_bit)
|
if (bus->force_bit) {
|
||||||
ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
|
ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
|
||||||
else
|
if (ret < 0)
|
||||||
|
bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
|
||||||
|
} else {
|
||||||
ret = do_gmbus_xfer(adapter, msgs, num);
|
ret = do_gmbus_xfer(adapter, msgs, num);
|
||||||
|
if (ret == -EAGAIN)
|
||||||
|
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||||
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
|
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
|
||||||
|
Loading…
Reference in New Issue
Block a user