blob: ebe1ec626892149519bbcd05c1710dad70e5fb81 [file] [log] [blame]
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001/*
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08002 em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08003
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08004 Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
5 Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -03006 Mauro Carvalho Chehab <mchehab@infradead.org>
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08007 Sascha Sommer <saschasommer@freenet.de>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/usb.h>
27#include <linux/i2c.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080028
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080029#include "em28xx.h"
Mauro Carvalho Chehab6c362c82007-10-29 23:36:12 -030030#include "tuner-xc2028.h"
Michael Krufky5e453dc2006-01-09 15:32:31 -020031#include <media/v4l2-common.h>
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080032#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080033
34/* ----------------------------------------------------------- */
35
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030036static unsigned int i2c_scan;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080037module_param(i2c_scan, int, 0444);
38MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
39
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030040static unsigned int i2c_debug;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080041module_param(i2c_debug, int, 0644);
42MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
43
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080044/*
Frank Schaeferf5ae3712013-01-03 14:27:02 -030045 * em2800_i2c_send_bytes()
46 * send up to 4 bytes to the em2800 i2c device
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080047 */
Frank Schaeferf5ae3712013-01-03 14:27:02 -030048static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080049{
50 int ret;
51 int write_timeout;
Frank Schaefera6bad042012-12-16 14:23:27 -030052 u8 b2[6];
Frank Schaeferf5ae3712013-01-03 14:27:02 -030053
54 if (len < 1 || len > 4)
55 return -EOPNOTSUPP;
56
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080057 BUG_ON(len < 1 || len > 4);
58 b2[5] = 0x80 + len - 1;
59 b2[4] = addr;
60 b2[3] = buf[0];
61 if (len > 1)
62 b2[2] = buf[1];
63 if (len > 2)
64 b2[1] = buf[2];
65 if (len > 3)
66 b2[0] = buf[3];
67
Frank Schaefer2fcc82d2013-01-03 14:27:03 -030068 /* trigger write */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080069 ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080070 if (ret != 2 + len) {
Frank Schaefer45f04e82013-01-03 14:27:05 -030071 em28xx_warn("failed to trigger write to i2c address 0x%x "
72 "(error=%i)\n", addr, ret);
73 return (ret < 0) ? ret : -EIO;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080074 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -030075 /* wait for completion */
76 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080077 write_timeout -= 5) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080078 ret = dev->em28xx_read_reg(dev, 0x05);
Frank Schaefer45f04e82013-01-03 14:27:05 -030079 if (ret == 0x80 + len - 1) {
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080080 return len;
Frank Schaefer45f04e82013-01-03 14:27:05 -030081 } else if (ret == 0x94 + len - 1) {
82 return -ENODEV;
83 } else if (ret < 0) {
84 em28xx_warn("failed to get i2c transfer status from "
85 "bridge register (error=%i)\n", ret);
86 return ret;
87 }
Markus Rechbergere8e41da2006-02-07 06:49:11 -020088 msleep(5);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080089 }
Frank Schaefer45f04e82013-01-03 14:27:05 -030090 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080091 return -EIO;
92}
93
94/*
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080095 * em2800_i2c_recv_bytes()
Frank Schaefer2fcc82d2013-01-03 14:27:03 -030096 * read up to 4 bytes from the em2800 i2c device
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080097 */
Frank Schaefera6bad042012-12-16 14:23:27 -030098static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080099{
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300100 u8 buf2[4];
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800101 int ret;
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300102 int read_timeout;
103 int i;
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300104
105 if (len < 1 || len > 4)
106 return -EOPNOTSUPP;
107
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300108 /* trigger read */
109 buf2[1] = 0x84 + len - 1;
110 buf2[0] = addr;
111 ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
112 if (ret != 2) {
113 em28xx_warn("failed to trigger read from i2c address 0x%x "
114 "(error=%i)\n", addr, ret);
115 return (ret < 0) ? ret : -EIO;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800116 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300117
118 /* wait for completion */
119 for (read_timeout = EM2800_I2C_XFER_TIMEOUT; read_timeout > 0;
120 read_timeout -= 5) {
121 ret = dev->em28xx_read_reg(dev, 0x05);
122 if (ret == 0x84 + len - 1) {
123 break;
124 } else if (ret == 0x94 + len - 1) {
125 return -ENODEV;
126 } else if (ret < 0) {
127 em28xx_warn("failed to get i2c transfer status from "
128 "bridge register (error=%i)\n", ret);
129 return ret;
130 }
131 msleep(5);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800132 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300133 if (ret != 0x84 + len - 1)
134 em28xx_warn("read from i2c device at 0x%x timed out\n", addr);
135
136 /* get the received message */
137 ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
138 if (ret != len) {
139 em28xx_warn("reading from i2c device at 0x%x failed: "
140 "couldn't get the received message from the bridge "
141 "(error=%i)\n", addr, ret);
142 return (ret < 0) ? ret : -EIO;
143 }
144 for (i = 0; i < len; i++)
145 buf[i] = buf2[len - 1 - i];
146
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800147 return ret;
148}
149
150/*
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300151 * em2800_i2c_check_for_device()
152 * check if there is an i2c device at the supplied address
153 */
154static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
155{
156 u8 buf;
157 int ret;
158
159 ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
160 if (ret == 1)
161 return 0;
162 return (ret < 0) ? ret : -EIO;
163}
164
165/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800166 * em28xx_i2c_send_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800167 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300168static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
169 u16 len, int stop)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800170{
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300171 int write_timeout, ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800172
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300173 if (len < 1 || len > 64)
174 return -EOPNOTSUPP;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300175 /* NOTE: limited by the USB ctrl message constraints
176 * Zero length reads always succeed, even if no device is connected */
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300177
Frank Schaefer45f04e82013-01-03 14:27:05 -0300178 /* Write to i2c device */
179 ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
180 if (ret != len) {
181 if (ret < 0) {
182 em28xx_warn("writing to i2c device at 0x%x failed "
183 "(error=%i)\n", addr, ret);
184 return ret;
185 } else {
186 em28xx_warn("%i bytes write to i2c device at 0x%x "
187 "requested, but %i bytes written\n",
188 len, addr, ret);
189 return -EIO;
190 }
191 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800192
Frank Schaefer45f04e82013-01-03 14:27:05 -0300193 /* Check success of the i2c operation */
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300194 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300195 write_timeout -= 5) {
196 ret = dev->em28xx_read_reg(dev, 0x05);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300197 if (ret == 0) { /* success */
198 return len;
199 } else if (ret == 0x10) {
200 return -ENODEV;
201 } else if (ret < 0) {
202 em28xx_warn("failed to read i2c transfer status from "
203 "bridge (error=%i)\n", ret);
204 return ret;
205 }
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300206 msleep(5);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300207 /* NOTE: do we really have to wait for success ?
208 Never seen anything else than 0x00 or 0x10
209 (even with high payload) ... */
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300210 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300211 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
212 return -EIO;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800213}
214
215/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800216 * em28xx_i2c_recv_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800217 * read a byte from the i2c device
218 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300219static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800220{
221 int ret;
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300222
223 if (len < 1 || len > 64)
224 return -EOPNOTSUPP;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300225 /* NOTE: limited by the USB ctrl message constraints
226 * Zero length reads always succeed, even if no device is connected */
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300227
Frank Schaefer45f04e82013-01-03 14:27:05 -0300228 /* Read data from i2c device */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800229 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300230 if (ret != len) {
231 if (ret < 0) {
232 em28xx_warn("reading from i2c device at 0x%x failed "
233 "(error=%i)\n", addr, ret);
234 return ret;
235 } else {
236 em28xx_warn("%i bytes requested from i2c device at "
237 "0x%x, but %i bytes received\n",
238 len, addr, ret);
239 return -EIO;
240 }
241 }
242
243 /* Check success of the i2c operation */
244 ret = dev->em28xx_read_reg(dev, 0x05);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800245 if (ret < 0) {
Frank Schaefer45f04e82013-01-03 14:27:05 -0300246 em28xx_warn("failed to read i2c transfer status from "
247 "bridge (error=%i)\n", ret);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800248 return ret;
249 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300250 if (ret > 0) {
251 if (ret == 0x10) {
252 return -ENODEV;
253 } else {
254 em28xx_warn("unknown i2c error (status=%i)\n", ret);
255 return -EIO;
256 }
257 }
258 return len;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800259}
260
261/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800262 * em28xx_i2c_check_for_device()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800263 * check if there is a i2c_device at the supplied address
264 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300265static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800266{
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800267 int ret;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300268 u8 buf;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800269
Frank Schaefer45f04e82013-01-03 14:27:05 -0300270 ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
271 if (ret == 1)
272 return 0;
273 return (ret < 0) ? ret : -EIO;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800274}
275
276/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800277 * em28xx_i2c_xfer()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800278 * the main i2c transfer function
279 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800280static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800281 struct i2c_msg msgs[], int num)
282{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800283 struct em28xx *dev = i2c_adap->algo_data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800284 int addr, rc, i, byte;
285
286 if (num <= 0)
287 return 0;
288 for (i = 0; i < num; i++) {
289 addr = msgs[i].addr << 1;
Frank Schaeferd7a80ea2013-03-03 15:37:35 -0300290 if (i2c_debug >= 2)
291 printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
292 dev->name, __func__ ,
293 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
294 i == num - 1 ? "stop" : "nonstop",
295 addr, msgs[i].len);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300296 if (!msgs[i].len) { /* no len: check only for device presence */
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300297 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800298 rc = em2800_i2c_check_for_device(dev, addr);
299 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800300 rc = em28xx_i2c_check_for_device(dev, addr);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300301 if (rc == -ENODEV) {
302 if (i2c_debug >= 2)
303 printk(" no device\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800304 return rc;
305 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800306 } else if (msgs[i].flags & I2C_M_RD) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800307 /* read bytes */
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300308 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800309 rc = em2800_i2c_recv_bytes(dev, addr,
310 msgs[i].buf,
311 msgs[i].len);
312 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800313 rc = em28xx_i2c_recv_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800314 msgs[i].buf,
315 msgs[i].len);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300316 if (i2c_debug >= 2) {
317 for (byte = 0; byte < msgs[i].len; byte++)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800318 printk(" %02x", msgs[i].buf[byte]);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800319 }
320 } else {
321 /* write bytes */
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300322 if (i2c_debug >= 2) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800323 for (byte = 0; byte < msgs[i].len; byte++)
324 printk(" %02x", msgs[i].buf[byte]);
325 }
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300326 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800327 rc = em2800_i2c_send_bytes(dev, addr,
328 msgs[i].buf,
329 msgs[i].len);
330 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800331 rc = em28xx_i2c_send_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800332 msgs[i].buf,
333 msgs[i].len,
334 i == num - 1);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800335 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300336 if (rc < 0) {
337 if (i2c_debug >= 2)
338 printk(" ERROR: %i\n", rc);
339 return rc;
340 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300341 if (i2c_debug >= 2)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800342 printk("\n");
343 }
344
345 return num;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800346}
347
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -0300348/* based on linux/sunrpc/svcauth.h and linux/hash.h
349 * The original hash function returns a different value, if arch is x86_64
350 * or i386.
351 */
352static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
353{
354 unsigned long hash = 0;
355 unsigned long l = 0;
356 int len = 0;
357 unsigned char c;
358 do {
359 if (len == length) {
360 c = (char)len;
361 len = -1;
362 } else
363 c = *buf++;
364 l = (l << 8) | c;
365 len++;
366 if ((len & (32 / 8 - 1)) == 0)
367 hash = ((hash^l) * 0x9e370001UL);
368 } while (len);
369
370 return (hash >> (32 - bits)) & 0xffffffffUL;
371}
372
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800373static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800374{
375 unsigned char buf, *p = eedata;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800376 struct em28xx_eeprom *em_eeprom = (void *)eedata;
Frank Schaefer90271962013-01-03 14:27:06 -0300377 int i, err, size = len, block, block_max;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800378
Mauro Carvalho Chehabfec528b2011-07-03 21:05:06 -0300379 if (dev->chip_id == CHIP_ID_EM2874 ||
380 dev->chip_id == CHIP_ID_EM28174 ||
381 dev->chip_id == CHIP_ID_EM2884) {
Devin Heitmuellera527c9f2008-11-12 02:05:10 -0300382 /* Empia switched to a 16-bit addressable eeprom in newer
383 devices. While we could certainly write a routine to read
384 the eeprom, there is nothing of use in there that cannot be
385 accessed through registers, and there is the risk that we
386 could corrupt the eeprom (since a 16-bit read call is
387 interpreted as a write call by 8-bit eeproms).
388 */
389 return 0;
390 }
391
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800392 dev->i2c_client.addr = 0xa0 >> 1;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800393
394 /* Check if board has eeprom */
395 err = i2c_master_recv(&dev->i2c_client, &buf, 0);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300396 if (err < 0) {
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300397 em28xx_info("board has no eeprom\n");
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300398 memset(eedata, 0, len);
399 return -ENODEV;
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300400 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800401
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800402 buf = 0;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300403
404 err = i2c_master_send(&dev->i2c_client, &buf, 1);
405 if (err != 1) {
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300406 em28xx_errdev("failed to read eeprom (err=%d)\n", err);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300407 return err;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800408 }
Frank Schaefer90271962013-01-03 14:27:06 -0300409
410 if (dev->board.is_em2800)
411 block_max = 4;
412 else
413 block_max = 64;
414
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800415 while (size > 0) {
Frank Schaefer90271962013-01-03 14:27:06 -0300416 if (size > block_max)
417 block = block_max;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800418 else
419 block = size;
420
421 if (block !=
422 (err = i2c_master_recv(&dev->i2c_client, p, block))) {
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300423 em28xx_errdev("i2c eeprom read error (err=%d)\n", err);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300424 return err;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800425 }
426 size -= block;
427 p += block;
428 }
429 for (i = 0; i < len; i++) {
430 if (0 == (i % 16))
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300431 em28xx_info("i2c eeprom %02x:", i);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800432 printk(" %02x", eedata[i]);
433 if (15 == (i % 16))
434 printk("\n");
435 }
436
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -0300437 if (em_eeprom->id == 0x9567eb1a)
438 dev->hash = em28xx_hash_mem(eedata, len, 32);
439
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300440 em28xx_info("EEPROM ID = 0x%08x, EEPROM hash = 0x%08lx\n",
441 em_eeprom->id, dev->hash);
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300442
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300443 em28xx_info("EEPROM info:\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800444
445 switch (em_eeprom->chip_conf >> 4 & 0x3) {
446 case 0:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300447 em28xx_info("\tNo audio on board.\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800448 break;
449 case 1:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300450 em28xx_info("\tAC97 audio (5 sample rates)\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800451 break;
452 case 2:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300453 em28xx_info("\tI2S audio, sample rate=32k\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800454 break;
455 case 3:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300456 em28xx_info("\tI2S audio, 3 sample rates\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800457 break;
458 }
459
460 if (em_eeprom->chip_conf & 1 << 3)
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300461 em28xx_info("\tUSB Remote wakeup capable\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800462
463 if (em_eeprom->chip_conf & 1 << 2)
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300464 em28xx_info("\tUSB Self power capable\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800465
466 switch (em_eeprom->chip_conf & 0x3) {
467 case 0:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300468 em28xx_info("\t500mA max power\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800469 break;
470 case 1:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300471 em28xx_info("\t400mA max power\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800472 break;
473 case 2:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300474 em28xx_info("\t300mA max power\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800475 break;
476 case 3:
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300477 em28xx_info("\t200mA max power\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800478 break;
479 }
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300480 em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
481 em_eeprom->string_idx_table,
482 em_eeprom->string1,
483 em_eeprom->string2,
484 em_eeprom->string3);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800485
486 return 0;
487}
488
489/* ----------------------------------------------------------- */
490
491/*
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800492 * functionality()
493 */
494static u32 functionality(struct i2c_adapter *adap)
495{
Frank Schaefereaf33c42013-01-03 14:27:04 -0300496 struct em28xx *dev = adap->algo_data;
497 u32 func_flags = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
498 if (dev->board.is_em2800)
499 func_flags &= ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
500 return func_flags;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800501}
502
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800503static struct i2c_algorithm em28xx_algo = {
504 .master_xfer = em28xx_i2c_xfer,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800505 .functionality = functionality,
506};
507
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800508static struct i2c_adapter em28xx_adap_template = {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800509 .owner = THIS_MODULE,
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800510 .name = "em28xx",
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800511 .algo = &em28xx_algo,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800512};
513
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800514static struct i2c_client em28xx_client_template = {
515 .name = "em28xx internal",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800516};
517
518/* ----------------------------------------------------------- */
519
520/*
521 * i2c_devs
522 * incomplete list of known devices
523 */
524static char *i2c_devs[128] = {
Frank Schaefer0b3966e2013-01-13 10:15:08 -0300525 [0x3e >> 1] = "remote IR sensor",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800526 [0x4a >> 1] = "saa7113h",
Martin Blumenstingl729841e2012-06-12 18:19:27 -0300527 [0x52 >> 1] = "drxk",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800528 [0x60 >> 1] = "remote IR sensor",
Markus Rechbergerda45a2a2005-11-08 21:37:31 -0800529 [0x8e >> 1] = "remote IR sensor",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800530 [0x86 >> 1] = "tda9887",
531 [0x80 >> 1] = "msp34xx",
532 [0x88 >> 1] = "msp34xx",
533 [0xa0 >> 1] = "eeprom",
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -0300534 [0xb0 >> 1] = "tda9874",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800535 [0xb8 >> 1] = "tvp5150a",
Mauro Carvalho Chehab791a08f2009-07-03 15:36:18 -0300536 [0xba >> 1] = "webcam sensor or tvp5150a",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800537 [0xc0 >> 1] = "tuner (analog)",
538 [0xc2 >> 1] = "tuner (analog)",
539 [0xc4 >> 1] = "tuner (analog)",
540 [0xc6 >> 1] = "tuner (analog)",
541};
542
543/*
544 * do_i2c_scan()
545 * check i2c address range for devices
546 */
Sascha Sommerfad7b952007-11-04 08:06:48 -0300547void em28xx_do_i2c_scan(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800548{
Sascha Sommerfad7b952007-11-04 08:06:48 -0300549 u8 i2c_devicelist[128];
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800550 unsigned char buf;
551 int i, rc;
552
Sascha Sommerfad7b952007-11-04 08:06:48 -0300553 memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
554
Mauro Carvalho Chehab53c4e952007-03-29 08:42:30 -0300555 for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
Sascha Sommerfad7b952007-11-04 08:06:48 -0300556 dev->i2c_client.addr = i;
557 rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800558 if (rc < 0)
559 continue;
Sascha Sommerfad7b952007-11-04 08:06:48 -0300560 i2c_devicelist[i] = i;
Frank Schaefer12d7ce12013-03-03 15:37:34 -0300561 em28xx_info("found i2c device @ 0x%x [%s]\n",
562 i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800563 }
Sascha Sommerfad7b952007-11-04 08:06:48 -0300564
565 dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
566 ARRAY_SIZE(i2c_devicelist), 32);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800567}
568
569/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800570 * em28xx_i2c_register()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800571 * register i2c bus
572 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800573int em28xx_i2c_register(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800574{
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300575 int retval;
576
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800577 BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
578 BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
579 dev->i2c_adap = em28xx_adap_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800580 dev->i2c_adap.dev.parent = &dev->udev->dev;
581 strcpy(dev->i2c_adap.name, dev->name);
582 dev->i2c_adap.algo_data = dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -0300583 i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300584
585 retval = i2c_add_adapter(&dev->i2c_adap);
586 if (retval < 0) {
587 em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
588 __func__, retval);
589 return retval;
590 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800591
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800592 dev->i2c_client = em28xx_client_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800593 dev->i2c_client.adapter = &dev->i2c_adap;
594
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300595 retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300596 if ((retval < 0) && (retval != -ENODEV)) {
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300597 em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
598 __func__, retval);
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300599
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300600 return retval;
601 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800602
603 if (i2c_scan)
Sascha Sommerfad7b952007-11-04 08:06:48 -0300604 em28xx_do_i2c_scan(dev);
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300605
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800606 return 0;
607}
608
609/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800610 * em28xx_i2c_unregister()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800611 * unregister i2c_bus
612 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800613int em28xx_i2c_unregister(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800614{
615 i2c_del_adapter(&dev->i2c_adap);
616 return 0;
617}