blob: f784b516ae1cf5180f7f20affafc0979e37ebc07 [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
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030044#define dprintk2(lvl, fmt, args...) \
45do { \
46 if (i2c_debug >= lvl) { \
47 printk(KERN_DEBUG "%s at %s: " fmt, \
48 dev->name, __func__ , ##args); \
49 } \
50} while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080051
52/*
Frank Schaeferf5ae3712013-01-03 14:27:02 -030053 * em2800_i2c_send_bytes()
54 * send up to 4 bytes to the em2800 i2c device
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080055 */
Frank Schaeferf5ae3712013-01-03 14:27:02 -030056static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080057{
58 int ret;
59 int write_timeout;
Frank Schaefera6bad042012-12-16 14:23:27 -030060 u8 b2[6];
Frank Schaeferf5ae3712013-01-03 14:27:02 -030061
62 if (len < 1 || len > 4)
63 return -EOPNOTSUPP;
64
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080065 BUG_ON(len < 1 || len > 4);
66 b2[5] = 0x80 + len - 1;
67 b2[4] = addr;
68 b2[3] = buf[0];
69 if (len > 1)
70 b2[2] = buf[1];
71 if (len > 2)
72 b2[1] = buf[2];
73 if (len > 3)
74 b2[0] = buf[3];
75
Frank Schaefer2fcc82d2013-01-03 14:27:03 -030076 /* trigger write */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080077 ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080078 if (ret != 2 + len) {
Frank Schaefer45f04e82013-01-03 14:27:05 -030079 em28xx_warn("failed to trigger write to i2c address 0x%x "
80 "(error=%i)\n", addr, ret);
81 return (ret < 0) ? ret : -EIO;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080082 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -030083 /* wait for completion */
84 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080085 write_timeout -= 5) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080086 ret = dev->em28xx_read_reg(dev, 0x05);
Frank Schaefer45f04e82013-01-03 14:27:05 -030087 if (ret == 0x80 + len - 1) {
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080088 return len;
Frank Schaefer45f04e82013-01-03 14:27:05 -030089 } else if (ret == 0x94 + len - 1) {
90 return -ENODEV;
91 } else if (ret < 0) {
92 em28xx_warn("failed to get i2c transfer status from "
93 "bridge register (error=%i)\n", ret);
94 return ret;
95 }
Markus Rechbergere8e41da2006-02-07 06:49:11 -020096 msleep(5);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080097 }
Frank Schaefer45f04e82013-01-03 14:27:05 -030098 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080099 return -EIO;
100}
101
102/*
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800103 * em2800_i2c_recv_bytes()
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300104 * read up to 4 bytes from the em2800 i2c device
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800105 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300106static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800107{
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300108 u8 buf2[4];
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800109 int ret;
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300110 int read_timeout;
111 int i;
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300112
113 if (len < 1 || len > 4)
114 return -EOPNOTSUPP;
115
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300116 /* trigger read */
117 buf2[1] = 0x84 + len - 1;
118 buf2[0] = addr;
119 ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
120 if (ret != 2) {
121 em28xx_warn("failed to trigger read from i2c address 0x%x "
122 "(error=%i)\n", addr, ret);
123 return (ret < 0) ? ret : -EIO;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800124 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300125
126 /* wait for completion */
127 for (read_timeout = EM2800_I2C_XFER_TIMEOUT; read_timeout > 0;
128 read_timeout -= 5) {
129 ret = dev->em28xx_read_reg(dev, 0x05);
130 if (ret == 0x84 + len - 1) {
131 break;
132 } else if (ret == 0x94 + len - 1) {
133 return -ENODEV;
134 } else if (ret < 0) {
135 em28xx_warn("failed to get i2c transfer status from "
136 "bridge register (error=%i)\n", ret);
137 return ret;
138 }
139 msleep(5);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800140 }
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300141 if (ret != 0x84 + len - 1)
142 em28xx_warn("read from i2c device at 0x%x timed out\n", addr);
143
144 /* get the received message */
145 ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
146 if (ret != len) {
147 em28xx_warn("reading from i2c device at 0x%x failed: "
148 "couldn't get the received message from the bridge "
149 "(error=%i)\n", addr, ret);
150 return (ret < 0) ? ret : -EIO;
151 }
152 for (i = 0; i < len; i++)
153 buf[i] = buf2[len - 1 - i];
154
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800155 return ret;
156}
157
158/*
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300159 * em2800_i2c_check_for_device()
160 * check if there is an i2c device at the supplied address
161 */
162static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
163{
164 u8 buf;
165 int ret;
166
167 ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
168 if (ret == 1)
169 return 0;
170 return (ret < 0) ? ret : -EIO;
171}
172
173/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800174 * em28xx_i2c_send_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800175 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300176static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
177 u16 len, int stop)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800178{
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300179 int write_timeout, ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800180
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300181 if (len < 1 || len > 64)
182 return -EOPNOTSUPP;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300183 /* NOTE: limited by the USB ctrl message constraints
184 * Zero length reads always succeed, even if no device is connected */
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300185
Frank Schaefer45f04e82013-01-03 14:27:05 -0300186 /* Write to i2c device */
187 ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
188 if (ret != len) {
189 if (ret < 0) {
190 em28xx_warn("writing to i2c device at 0x%x failed "
191 "(error=%i)\n", addr, ret);
192 return ret;
193 } else {
194 em28xx_warn("%i bytes write to i2c device at 0x%x "
195 "requested, but %i bytes written\n",
196 len, addr, ret);
197 return -EIO;
198 }
199 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800200
Frank Schaefer45f04e82013-01-03 14:27:05 -0300201 /* Check success of the i2c operation */
Frank Schaefer2fcc82d2013-01-03 14:27:03 -0300202 for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300203 write_timeout -= 5) {
204 ret = dev->em28xx_read_reg(dev, 0x05);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300205 if (ret == 0) { /* success */
206 return len;
207 } else if (ret == 0x10) {
208 return -ENODEV;
209 } else if (ret < 0) {
210 em28xx_warn("failed to read i2c transfer status from "
211 "bridge (error=%i)\n", ret);
212 return ret;
213 }
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300214 msleep(5);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300215 /* NOTE: do we really have to wait for success ?
216 Never seen anything else than 0x00 or 0x10
217 (even with high payload) ... */
Mauro Carvalho Chehabbbc70e62011-07-09 19:36:11 -0300218 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300219 em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
220 return -EIO;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800221}
222
223/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800224 * em28xx_i2c_recv_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800225 * read a byte from the i2c device
226 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300227static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800228{
229 int ret;
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300230
231 if (len < 1 || len > 64)
232 return -EOPNOTSUPP;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300233 /* NOTE: limited by the USB ctrl message constraints
234 * Zero length reads always succeed, even if no device is connected */
Frank Schaeferf5ae3712013-01-03 14:27:02 -0300235
Frank Schaefer45f04e82013-01-03 14:27:05 -0300236 /* Read data from i2c device */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800237 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300238 if (ret != len) {
239 if (ret < 0) {
240 em28xx_warn("reading from i2c device at 0x%x failed "
241 "(error=%i)\n", addr, ret);
242 return ret;
243 } else {
244 em28xx_warn("%i bytes requested from i2c device at "
245 "0x%x, but %i bytes received\n",
246 len, addr, ret);
247 return -EIO;
248 }
249 }
250
251 /* Check success of the i2c operation */
252 ret = dev->em28xx_read_reg(dev, 0x05);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800253 if (ret < 0) {
Frank Schaefer45f04e82013-01-03 14:27:05 -0300254 em28xx_warn("failed to read i2c transfer status from "
255 "bridge (error=%i)\n", ret);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800256 return ret;
257 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300258 if (ret > 0) {
259 if (ret == 0x10) {
260 return -ENODEV;
261 } else {
262 em28xx_warn("unknown i2c error (status=%i)\n", ret);
263 return -EIO;
264 }
265 }
266 return len;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800267}
268
269/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800270 * em28xx_i2c_check_for_device()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800271 * check if there is a i2c_device at the supplied address
272 */
Frank Schaefera6bad042012-12-16 14:23:27 -0300273static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800274{
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800275 int ret;
Frank Schaefer45f04e82013-01-03 14:27:05 -0300276 u8 buf;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800277
Frank Schaefer45f04e82013-01-03 14:27:05 -0300278 ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
279 if (ret == 1)
280 return 0;
281 return (ret < 0) ? ret : -EIO;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800282}
283
284/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800285 * em28xx_i2c_xfer()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800286 * the main i2c transfer function
287 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800288static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800289 struct i2c_msg msgs[], int num)
290{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800291 struct em28xx *dev = i2c_adap->algo_data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800292 int addr, rc, i, byte;
293
294 if (num <= 0)
295 return 0;
296 for (i = 0; i < num; i++) {
297 addr = msgs[i].addr << 1;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300298 dprintk2(2, "%s %s addr=%x len=%d:",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800299 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
300 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300301 if (!msgs[i].len) { /* no len: check only for device presence */
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300302 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800303 rc = em2800_i2c_check_for_device(dev, addr);
304 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800305 rc = em28xx_i2c_check_for_device(dev, addr);
Frank Schaefer45f04e82013-01-03 14:27:05 -0300306 if (rc == -ENODEV) {
307 if (i2c_debug >= 2)
308 printk(" no device\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800309 return rc;
310 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800311 } else if (msgs[i].flags & I2C_M_RD) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800312 /* read bytes */
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300313 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800314 rc = em2800_i2c_recv_bytes(dev, addr,
315 msgs[i].buf,
316 msgs[i].len);
317 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800318 rc = em28xx_i2c_recv_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800319 msgs[i].buf,
320 msgs[i].len);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300321 if (i2c_debug >= 2) {
322 for (byte = 0; byte < msgs[i].len; byte++)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800323 printk(" %02x", msgs[i].buf[byte]);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800324 }
325 } else {
326 /* write bytes */
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300327 if (i2c_debug >= 2) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800328 for (byte = 0; byte < msgs[i].len; byte++)
329 printk(" %02x", msgs[i].buf[byte]);
330 }
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -0300331 if (dev->board.is_em2800)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800332 rc = em2800_i2c_send_bytes(dev, addr,
333 msgs[i].buf,
334 msgs[i].len);
335 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800336 rc = em28xx_i2c_send_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800337 msgs[i].buf,
338 msgs[i].len,
339 i == num - 1);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800340 }
Frank Schaefer45f04e82013-01-03 14:27:05 -0300341 if (rc < 0) {
342 if (i2c_debug >= 2)
343 printk(" ERROR: %i\n", rc);
344 return rc;
345 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300346 if (i2c_debug >= 2)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800347 printk("\n");
348 }
349
350 return num;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800351}
352
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -0300353/* based on linux/sunrpc/svcauth.h and linux/hash.h
354 * The original hash function returns a different value, if arch is x86_64
355 * or i386.
356 */
357static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
358{
359 unsigned long hash = 0;
360 unsigned long l = 0;
361 int len = 0;
362 unsigned char c;
363 do {
364 if (len == length) {
365 c = (char)len;
366 len = -1;
367 } else
368 c = *buf++;
369 l = (l << 8) | c;
370 len++;
371 if ((len & (32 / 8 - 1)) == 0)
372 hash = ((hash^l) * 0x9e370001UL);
373 } while (len);
374
375 return (hash >> (32 - bits)) & 0xffffffffUL;
376}
377
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800378static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800379{
380 unsigned char buf, *p = eedata;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800381 struct em28xx_eeprom *em_eeprom = (void *)eedata;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800382 int i, err, size = len, block;
383
Mauro Carvalho Chehabfec528b2011-07-03 21:05:06 -0300384 if (dev->chip_id == CHIP_ID_EM2874 ||
385 dev->chip_id == CHIP_ID_EM28174 ||
386 dev->chip_id == CHIP_ID_EM2884) {
Devin Heitmuellera527c9f2008-11-12 02:05:10 -0300387 /* Empia switched to a 16-bit addressable eeprom in newer
388 devices. While we could certainly write a routine to read
389 the eeprom, there is nothing of use in there that cannot be
390 accessed through registers, and there is the risk that we
391 could corrupt the eeprom (since a 16-bit read call is
392 interpreted as a write call by 8-bit eeproms).
393 */
394 return 0;
395 }
396
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800397 dev->i2c_client.addr = 0xa0 >> 1;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800398
399 /* Check if board has eeprom */
400 err = i2c_master_recv(&dev->i2c_client, &buf, 0);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300401 if (err < 0) {
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300402 em28xx_errdev("board has no eeprom\n");
403 memset(eedata, 0, len);
404 return -ENODEV;
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300405 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800406
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800407 buf = 0;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300408
409 err = i2c_master_send(&dev->i2c_client, &buf, 1);
410 if (err != 1) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800411 printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
412 dev->name, err);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300413 return err;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800414 }
415 while (size > 0) {
416 if (size > 16)
417 block = 16;
418 else
419 block = size;
420
421 if (block !=
422 (err = i2c_master_recv(&dev->i2c_client, p, block))) {
423 printk(KERN_WARNING
424 "%s: i2c eeprom read error (err=%d)\n",
425 dev->name, err);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300426 return err;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800427 }
428 size -= block;
429 p += block;
430 }
431 for (i = 0; i < len; i++) {
432 if (0 == (i % 16))
433 printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
434 printk(" %02x", eedata[i]);
435 if (15 == (i % 16))
436 printk("\n");
437 }
438
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -0300439 if (em_eeprom->id == 0x9567eb1a)
440 dev->hash = em28xx_hash_mem(eedata, len, 32);
441
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300442 printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n",
443 dev->name, em_eeprom->id, dev->hash);
444
445 printk(KERN_INFO "%s: EEPROM info:\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800446
447 switch (em_eeprom->chip_conf >> 4 & 0x3) {
448 case 0:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300449 printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800450 break;
451 case 1:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300452 printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n",
453 dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800454 break;
455 case 2:
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300456 printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
457 dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800458 break;
459 case 3:
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300460 printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
461 dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800462 break;
463 }
464
465 if (em_eeprom->chip_conf & 1 << 3)
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300466 printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800467
468 if (em_eeprom->chip_conf & 1 << 2)
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300469 printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800470
471 switch (em_eeprom->chip_conf & 0x3) {
472 case 0:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300473 printk(KERN_INFO "%s:\t500mA max power\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800474 break;
475 case 1:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300476 printk(KERN_INFO "%s:\t400mA max power\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800477 break;
478 case 2:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300479 printk(KERN_INFO "%s:\t300mA max power\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800480 break;
481 case 3:
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300482 printk(KERN_INFO "%s:\t200mA max power\n", dev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800483 break;
484 }
Mauro Carvalho Chehab1bee0182008-11-25 10:06:21 -0300485 printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
486 dev->name,
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300487 em_eeprom->string_idx_table,
488 em_eeprom->string1,
489 em_eeprom->string2,
490 em_eeprom->string3);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800491
492 return 0;
493}
494
495/* ----------------------------------------------------------- */
496
497/*
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800498 * functionality()
499 */
500static u32 functionality(struct i2c_adapter *adap)
501{
Frank Schaefereaf33c42013-01-03 14:27:04 -0300502 struct em28xx *dev = adap->algo_data;
503 u32 func_flags = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
504 if (dev->board.is_em2800)
505 func_flags &= ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
506 return func_flags;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800507}
508
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800509static struct i2c_algorithm em28xx_algo = {
510 .master_xfer = em28xx_i2c_xfer,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800511 .functionality = functionality,
512};
513
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800514static struct i2c_adapter em28xx_adap_template = {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800515 .owner = THIS_MODULE,
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800516 .name = "em28xx",
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800517 .algo = &em28xx_algo,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800518};
519
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800520static struct i2c_client em28xx_client_template = {
521 .name = "em28xx internal",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800522};
523
524/* ----------------------------------------------------------- */
525
526/*
527 * i2c_devs
528 * incomplete list of known devices
529 */
530static char *i2c_devs[128] = {
531 [0x4a >> 1] = "saa7113h",
Martin Blumenstingl729841e2012-06-12 18:19:27 -0300532 [0x52 >> 1] = "drxk",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800533 [0x60 >> 1] = "remote IR sensor",
Markus Rechbergerda45a2a2005-11-08 21:37:31 -0800534 [0x8e >> 1] = "remote IR sensor",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800535 [0x86 >> 1] = "tda9887",
536 [0x80 >> 1] = "msp34xx",
537 [0x88 >> 1] = "msp34xx",
538 [0xa0 >> 1] = "eeprom",
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -0300539 [0xb0 >> 1] = "tda9874",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800540 [0xb8 >> 1] = "tvp5150a",
Mauro Carvalho Chehab791a08f2009-07-03 15:36:18 -0300541 [0xba >> 1] = "webcam sensor or tvp5150a",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800542 [0xc0 >> 1] = "tuner (analog)",
543 [0xc2 >> 1] = "tuner (analog)",
544 [0xc4 >> 1] = "tuner (analog)",
545 [0xc6 >> 1] = "tuner (analog)",
546};
547
548/*
549 * do_i2c_scan()
550 * check i2c address range for devices
551 */
Sascha Sommerfad7b952007-11-04 08:06:48 -0300552void em28xx_do_i2c_scan(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800553{
Sascha Sommerfad7b952007-11-04 08:06:48 -0300554 u8 i2c_devicelist[128];
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800555 unsigned char buf;
556 int i, rc;
557
Sascha Sommerfad7b952007-11-04 08:06:48 -0300558 memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
559
Mauro Carvalho Chehab53c4e952007-03-29 08:42:30 -0300560 for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
Sascha Sommerfad7b952007-11-04 08:06:48 -0300561 dev->i2c_client.addr = i;
562 rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800563 if (rc < 0)
564 continue;
Sascha Sommerfad7b952007-11-04 08:06:48 -0300565 i2c_devicelist[i] = i;
566 printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
567 dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800568 }
Sascha Sommerfad7b952007-11-04 08:06:48 -0300569
570 dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
571 ARRAY_SIZE(i2c_devicelist), 32);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800572}
573
574/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800575 * em28xx_i2c_register()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800576 * register i2c bus
577 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800578int em28xx_i2c_register(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800579{
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300580 int retval;
581
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800582 BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
583 BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
584 dev->i2c_adap = em28xx_adap_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800585 dev->i2c_adap.dev.parent = &dev->udev->dev;
586 strcpy(dev->i2c_adap.name, dev->name);
587 dev->i2c_adap.algo_data = dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -0300588 i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300589
590 retval = i2c_add_adapter(&dev->i2c_adap);
591 if (retval < 0) {
592 em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
593 __func__, retval);
594 return retval;
595 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800596
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800597 dev->i2c_client = em28xx_client_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800598 dev->i2c_client.adapter = &dev->i2c_adap;
599
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300600 retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300601 if ((retval < 0) && (retval != -ENODEV)) {
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300602 em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
603 __func__, retval);
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300604
Douglas Schilling Landgraff2a01a02008-09-08 03:27:20 -0300605 return retval;
606 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800607
608 if (i2c_scan)
Sascha Sommerfad7b952007-11-04 08:06:48 -0300609 em28xx_do_i2c_scan(dev);
Mauro Carvalho Chehabc41109f2008-11-15 23:44:14 -0300610
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800611 return 0;
612}
613
614/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800615 * em28xx_i2c_unregister()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800616 * unregister i2c_bus
617 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800618int em28xx_i2c_unregister(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800619{
620 i2c_del_adapter(&dev->i2c_adap);
621 return 0;
622}