diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 37 | 
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index df648cb4c29..864417cffe9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -479,6 +479,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  	uint16_t address = algo_data->address;  	uint8_t msg[5];  	uint8_t reply[2]; +	unsigned retry;  	int msg_bytes;  	int reply_bytes;  	int ret; @@ -513,14 +514,33 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  		break;  	} -	for (;;) { -	  ret = intel_dp_aux_ch(intel_dp, -				msg, msg_bytes, -				reply, reply_bytes); +	for (retry = 0; retry < 5; retry++) { +		ret = intel_dp_aux_ch(intel_dp, +				      msg, msg_bytes, +				      reply, reply_bytes);  		if (ret < 0) {  			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);  			return ret;  		} + +		switch (reply[0] & AUX_NATIVE_REPLY_MASK) { +		case AUX_NATIVE_REPLY_ACK: +			/* I2C-over-AUX Reply field is only valid +			 * when paired with AUX ACK. +			 */ +			break; +		case AUX_NATIVE_REPLY_NACK: +			DRM_DEBUG_KMS("aux_ch native nack\n"); +			return -EREMOTEIO; +		case AUX_NATIVE_REPLY_DEFER: +			udelay(100); +			continue; +		default: +			DRM_ERROR("aux_ch invalid native reply 0x%02x\n", +				  reply[0]); +			return -EREMOTEIO; +		} +  		switch (reply[0] & AUX_I2C_REPLY_MASK) {  		case AUX_I2C_REPLY_ACK:  			if (mode == MODE_I2C_READ) { @@ -528,17 +548,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  			}  			return reply_bytes - 1;  		case AUX_I2C_REPLY_NACK: -			DRM_DEBUG_KMS("aux_ch nack\n"); +			DRM_DEBUG_KMS("aux_i2c nack\n");  			return -EREMOTEIO;  		case AUX_I2C_REPLY_DEFER: -			DRM_DEBUG_KMS("aux_ch defer\n"); +			DRM_DEBUG_KMS("aux_i2c defer\n");  			udelay(100);  			break;  		default: -			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); +			DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);  			return -EREMOTEIO;  		}  	} + +	DRM_ERROR("too many retries, giving up\n"); +	return -EREMOTEIO;  }  static int  |