aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2011-03-02 11:23:52 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 18:23:48 -0400
commitb443ac5a2836532af2315a4acb95c7a2cf721cbd (patch)
tree1313a4d282f79b8fe4f1eaeda25aa3653cd0e57a /drivers/media
parent53a5fd4dede974ba9727cda430e6714293be5e71 (diff)
[media] hdpvr: i2c master enhancements
Make the hdpvr's i2c master implementation more closely mirror that of the pvrusb2 driver. Currently makes no significant difference in IR reception behavior with ir-kbd-i2c (i.e., it still sucks). Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/hdpvr/hdpvr-i2c.c67
1 files changed, 50 insertions, 17 deletions
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
index e53fa55d56a1..3e0658768135 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -62,15 +62,25 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
62} 62}
63 63
64static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, 64static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
65 unsigned char addr, char *data, int len) 65 unsigned char addr, char *wdata, int wlen,
66 char *data, int len)
66{ 67{
67 int ret; 68 int ret;
68 69
69 if (len > sizeof(dev->i2c_buf)) 70 if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
70 return -EINVAL; 71 return -EINVAL;
71 72
72 ret = usb_control_msg(dev->udev, 73 if (wlen) {
73 usb_rcvctrlpipe(dev->udev, 0), 74 memcpy(&dev->i2c_buf, wdata, wlen);
75 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
76 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
77 (bus << 8) | addr, 0, &dev->i2c_buf,
78 wlen, 1000);
79 if (ret < 0)
80 return ret;
81 }
82
83 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
74 REQTYPE_I2C_READ, CTRL_READ_REQUEST, 84 REQTYPE_I2C_READ, CTRL_READ_REQUEST,
75 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); 85 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
76 86
@@ -92,16 +102,14 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
92 return -EINVAL; 102 return -EINVAL;
93 103
94 memcpy(&dev->i2c_buf, data, len); 104 memcpy(&dev->i2c_buf, data, len);
95 ret = usb_control_msg(dev->udev, 105 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
96 usb_sndctrlpipe(dev->udev, 0),
97 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, 106 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
98 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); 107 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
99 108
100 if (ret < 0) 109 if (ret < 0)
101 return ret; 110 return ret;
102 111
103 ret = usb_control_msg(dev->udev, 112 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
104 usb_rcvctrlpipe(dev->udev, 0),
105 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, 113 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
106 0, 0, &dev->i2c_buf, 2, 1000); 114 0, 0, &dev->i2c_buf, 2, 1000);
107 115
@@ -117,24 +125,49 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
117 int num) 125 int num)
118{ 126{
119 struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); 127 struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
120 int retval = 0, i, addr; 128 int retval = 0, addr;
121 129
122 if (num <= 0) 130 if (num <= 0)
123 return 0; 131 return 0;
124 132
125 mutex_lock(&dev->i2c_mutex); 133 mutex_lock(&dev->i2c_mutex);
126 134
127 for (i = 0; i < num && !retval; i++) { 135 addr = msgs[0].addr << 1;
128 addr = msgs[i].addr << 1;
129 136
130 if (msgs[i].flags & I2C_M_RD) 137 if (num == 1) {
131 retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, 138 if (msgs[0].flags & I2C_M_RD)
132 msgs[i].len); 139 retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
140 msgs[0].buf, msgs[0].len);
133 else 141 else
134 retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, 142 retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
135 msgs[i].len); 143 msgs[0].len);
144 } else if (num == 2) {
145 if (msgs[0].addr != msgs[1].addr) {
146 v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
147 "with conflicting target addresses\n");
148 retval = -EINVAL;
149 goto out;
150 }
151
152 if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
153 v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
154 "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
155 msgs[1].flags & I2C_M_RD);
156 retval = -EINVAL;
157 goto out;
158 }
159
160 /*
161 * Write followed by atomic read is the only complex xfer that
162 * we actually support here.
163 */
164 retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
165 msgs[1].buf, msgs[1].len);
166 } else {
167 v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
136 } 168 }
137 169
170out:
138 mutex_unlock(&dev->i2c_mutex); 171 mutex_unlock(&dev->i2c_mutex);
139 172
140 return retval ? retval : num; 173 return retval ? retval : num;
@@ -162,7 +195,7 @@ static int hdpvr_activate_ir(struct hdpvr_device *dev)
162 195
163 mutex_lock(&dev->i2c_mutex); 196 mutex_lock(&dev->i2c_mutex);
164 197
165 hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); 198 hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
166 199
167 buffer[0] = 0; 200 buffer[0] = 0;
168 buffer[1] = 0x8; 201 buffer[1] = 0x8;