0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <drm/radeon_drm.h>
0027 #include "radeon.h"
0028 #include "atom.h"
0029
0030 #define TARGET_HW_I2C_CLOCK 50
0031
0032
0033 #define ATOM_MAX_HW_I2C_WRITE 3
0034 #define ATOM_MAX_HW_I2C_READ 255
0035
0036 static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
0037 u8 slave_addr, u8 flags,
0038 u8 *buf, int num)
0039 {
0040 struct drm_device *dev = chan->dev;
0041 struct radeon_device *rdev = dev->dev_private;
0042 PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
0043 int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
0044 unsigned char *base;
0045 u16 out = cpu_to_le16(0);
0046 int r = 0;
0047
0048 memset(&args, 0, sizeof(args));
0049
0050 mutex_lock(&chan->mutex);
0051 mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
0052
0053 base = (unsigned char *)rdev->mode_info.atom_context->scratch;
0054
0055 if (flags & HW_I2C_WRITE) {
0056 if (num > ATOM_MAX_HW_I2C_WRITE) {
0057 DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
0058 r = -EINVAL;
0059 goto done;
0060 }
0061 if (buf == NULL)
0062 args.ucRegIndex = 0;
0063 else
0064 args.ucRegIndex = buf[0];
0065 if (num)
0066 num--;
0067 if (num)
0068 memcpy(&out, &buf[1], num);
0069 args.lpI2CDataOut = cpu_to_le16(out);
0070 } else {
0071 args.ucRegIndex = 0;
0072 args.lpI2CDataOut = 0;
0073 }
0074
0075 args.ucFlag = flags;
0076 args.ucI2CSpeed = TARGET_HW_I2C_CLOCK;
0077 args.ucTransBytes = num;
0078 args.ucSlaveAddr = slave_addr << 1;
0079 args.ucLineNumber = chan->rec.i2c_id;
0080
0081 atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);
0082
0083
0084 if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
0085 DRM_DEBUG_KMS("hw_i2c error\n");
0086 r = -EIO;
0087 goto done;
0088 }
0089
0090 if (!(flags & HW_I2C_WRITE))
0091 radeon_atom_copy_swap(buf, base, num, false);
0092
0093 done:
0094 mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
0095 mutex_unlock(&chan->mutex);
0096
0097 return r;
0098 }
0099
0100 int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
0101 struct i2c_msg *msgs, int num)
0102 {
0103 struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
0104 struct i2c_msg *p;
0105 int i, remaining, current_count, buffer_offset, max_bytes, ret;
0106 u8 flags;
0107
0108
0109 p = &msgs[0];
0110 if ((num == 1) && (p->len == 0)) {
0111 ret = radeon_process_i2c_ch(i2c,
0112 p->addr, HW_I2C_WRITE,
0113 NULL, 0);
0114 if (ret)
0115 return ret;
0116 else
0117 return num;
0118 }
0119
0120 for (i = 0; i < num; i++) {
0121 p = &msgs[i];
0122 remaining = p->len;
0123 buffer_offset = 0;
0124
0125 if (p->flags & I2C_M_RD) {
0126 max_bytes = ATOM_MAX_HW_I2C_READ;
0127 flags = HW_I2C_READ;
0128 } else {
0129 max_bytes = ATOM_MAX_HW_I2C_WRITE;
0130 flags = HW_I2C_WRITE;
0131 }
0132 while (remaining) {
0133 if (remaining > max_bytes)
0134 current_count = max_bytes;
0135 else
0136 current_count = remaining;
0137 ret = radeon_process_i2c_ch(i2c,
0138 p->addr, flags,
0139 &p->buf[buffer_offset], current_count);
0140 if (ret)
0141 return ret;
0142 remaining -= current_count;
0143 buffer_offset += current_count;
0144 }
0145 }
0146
0147 return num;
0148 }
0149
0150 u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap)
0151 {
0152 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
0153 }
0154