diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_i2c.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_i2c.c | 36 | 
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index deaf98cdca3..9c570fb15b8 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -27,8 +27,6 @@  #include "radeon.h"  #include "atom.h" -extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); -  #define TARGET_HW_I2C_CLOCK 50  /* these are a limitation of ProcessI2cChannelTransaction not the hw */ @@ -44,25 +42,35 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,  	PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;  	int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);  	unsigned char *base; -	u16 out; +	u16 out = cpu_to_le16(0); +	int r = 0;  	memset(&args, 0, sizeof(args)); +	mutex_lock(&chan->mutex); +  	base = (unsigned char *)rdev->mode_info.atom_context->scratch;  	if (flags & HW_I2C_WRITE) {  		if (num > ATOM_MAX_HW_I2C_WRITE) {  			DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); -			return -EINVAL; +			r = -EINVAL; +			goto done;  		} -		args.ucRegIndex = buf[0]; -		if (num > 1) -			memcpy(&out, &buf[1], num - 1); +		if (buf == NULL) +			args.ucRegIndex = 0; +		else +			args.ucRegIndex = buf[0]; +		if (num) +			num--; +		if (num) +			memcpy(&out, &buf[1], num);  		args.lpI2CDataOut = cpu_to_le16(out);  	} else {  		if (num > ATOM_MAX_HW_I2C_READ) {  			DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num); -			return -EINVAL; +			r = -EINVAL; +			goto done;  		}  		args.ucRegIndex = 0;  		args.lpI2CDataOut = 0; @@ -79,13 +87,17 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,  	/* error */  	if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {  		DRM_DEBUG_KMS("hw_i2c error\n"); -		return -EIO; +		r = -EIO; +		goto done;  	}  	if (!(flags & HW_I2C_WRITE))  		radeon_atom_copy_swap(buf, base, num, false); -	return 0; +done: +	mutex_unlock(&chan->mutex); + +	return r;  }  int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, @@ -94,14 +106,14 @@ int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,  	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);  	struct i2c_msg *p;  	int i, remaining, current_count, buffer_offset, max_bytes, ret; -	u8 buf = 0, flags; +	u8 flags;  	/* check for bus probe */  	p = &msgs[0];  	if ((num == 1) && (p->len == 0)) {  		ret = radeon_process_i2c_ch(i2c,  					    p->addr, HW_I2C_WRITE, -					    &buf, 1); +					    NULL, 0);  		if (ret)  			return ret;  		else  | 
