blob: b32d9852f34c556b97d961b1c20a36b907edb24c [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 Chehab4ac97912005-11-08 21:37:43 -08006 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
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#include <linux/video_decoder.h>
29
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080030#include "em28xx.h"
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080031#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080032
33/* ----------------------------------------------------------- */
34
35static unsigned int i2c_scan = 0;
36module_param(i2c_scan, int, 0444);
37MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
38
39static unsigned int i2c_debug = 0;
40module_param(i2c_debug, int, 0644);
41MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
42
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080043#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080044 printk(fmt , ##args); } while (0)
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -080045#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
46 printk(KERN_DEBUG "%s at %s: " fmt, \
47 dev->name, __FUNCTION__ , ##args); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080048
49/*
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080050 * em2800_i2c_send_max4()
51 * send up to 4 bytes to the i2c device
52 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080053static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080054 char *buf, int len)
55{
56 int ret;
57 int write_timeout;
58 unsigned char b2[6];
59 BUG_ON(len < 1 || len > 4);
60 b2[5] = 0x80 + len - 1;
61 b2[4] = addr;
62 b2[3] = buf[0];
63 if (len > 1)
64 b2[2] = buf[1];
65 if (len > 2)
66 b2[1] = buf[2];
67 if (len > 3)
68 b2[0] = buf[3];
69
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080070 ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080071 if (ret != 2 + len) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080072 em28xx_warn("writting to i2c device failed (error=%i)\n", ret);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080073 return -EIO;
74 }
75 for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
76 write_timeout -= 5) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080077 ret = dev->em28xx_read_reg(dev, 0x05);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080078 if (ret == 0x80 + len - 1)
79 return len;
80 mdelay(5);
81 }
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080082 em28xx_warn("i2c write timed out\n");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080083 return -EIO;
84}
85
86/*
87 * em2800_i2c_send_bytes()
88 */
89static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
90 short len)
91{
92 char *bufPtr = buf;
93 int ret;
94 int wrcount = 0;
95 int count;
96 int maxLen = 4;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080097 struct em28xx *dev = (struct em28xx *)data;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080098 while (len > 0) {
99 count = (len > maxLen) ? maxLen : len;
100 ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
101 if (ret > 0) {
102 len -= count;
103 bufPtr += count;
104 wrcount += count;
105 } else
106 return (ret < 0) ? ret : -EFAULT;
107 }
108 return wrcount;
109}
110
111/*
112 * em2800_i2c_check_for_device()
113 * check if there is a i2c_device at the supplied address
114 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800115static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800116{
117 char msg;
118 int ret;
119 int write_timeout;
120 msg = addr;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800121 ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800122 if (ret < 0) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800123 em28xx_warn("setting i2c device address failed (error=%i)\n",
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800124 ret);
125 return ret;
126 }
127 msg = 0x84;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800128 ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800129 if (ret < 0) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800130 em28xx_warn("preparing i2c read failed (error=%i)\n", ret);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800131 return ret;
132 }
133 for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
134 write_timeout -= 5) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800135 unsigned msg = dev->em28xx_read_reg(dev, 0x5);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800136 if (msg == 0x94)
137 return -ENODEV;
138 else if (msg == 0x84)
139 return 0;
140 mdelay(5);
141 }
142 return -ENODEV;
143}
144
145/*
146 * em2800_i2c_recv_bytes()
147 * read from the i2c device
148 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800149static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800150 char *buf, int len)
151{
152 int ret;
153 /* check for the device and set i2c read address */
154 ret = em2800_i2c_check_for_device(dev, addr);
155 if (ret) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800156 em28xx_warn
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800157 ("preparing read at i2c address 0x%x failed (error=%i)\n",
158 addr, ret);
159 return ret;
160 }
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800161 ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800162 if (ret < 0) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800163 em28xx_warn("reading from i2c device at 0x%x failed (error=%i)",
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800164 addr, ret);
165 return ret;
166 }
167 return ret;
168}
169
170/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800171 * em28xx_i2c_send_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800172 * untested for more than 4 bytes
173 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800174static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800175 short len, int stop)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800176{
177 int wrcount = 0;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800178 struct em28xx *dev = (struct em28xx *)data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800179
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800180 wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800181
182 return wrcount;
183}
184
185/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800186 * em28xx_i2c_recv_bytes()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800187 * read a byte from the i2c device
188 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800189static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800190 char *buf, int len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800191{
192 int ret;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800193 ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800194 if (ret < 0) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800195 em28xx_warn("reading i2c device failed (error=%i)\n", ret);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800196 return ret;
197 }
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800198 if (dev->em28xx_read_reg(dev, 0x5) != 0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800199 return -ENODEV;
200 return ret;
201}
202
203/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800204 * em28xx_i2c_check_for_device()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800205 * check if there is a i2c_device at the supplied address
206 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800207static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800208{
209 char msg;
210 int ret;
211 msg = addr;
212
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800213 ret = dev->em28xx_read_reg_req(dev, 2, addr);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800214 if (ret < 0) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800215 em28xx_warn("reading from i2c device failed (error=%i)\n", ret);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800216 return ret;
217 }
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800218 if (dev->em28xx_read_reg(dev, 0x5) != 0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800219 return -ENODEV;
220 return 0;
221}
222
223/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800224 * em28xx_i2c_xfer()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800225 * the main i2c transfer function
226 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800227static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800228 struct i2c_msg msgs[], int num)
229{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800230 struct em28xx *dev = i2c_adap->algo_data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800231 int addr, rc, i, byte;
232
233 if (num <= 0)
234 return 0;
235 for (i = 0; i < num; i++) {
236 addr = msgs[i].addr << 1;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800237 dprintk2(2,"%s %s addr=%x len=%d:",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800238 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
239 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
240 if (!msgs[i].len) { /* no len: check only for device presence */
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800241 if (dev->is_em2800)
242 rc = em2800_i2c_check_for_device(dev, addr);
243 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800244 rc = em28xx_i2c_check_for_device(dev, addr);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800245 if (rc < 0) {
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800246 dprintk2(2," no device\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800247 return rc;
248 }
249
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800250 } else if (msgs[i].flags & I2C_M_RD) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800251 /* read bytes */
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800252 if (dev->is_em2800)
253 rc = em2800_i2c_recv_bytes(dev, addr,
254 msgs[i].buf,
255 msgs[i].len);
256 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800257 rc = em28xx_i2c_recv_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800258 msgs[i].buf,
259 msgs[i].len);
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800260 if (i2c_debug>=2) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800261 for (byte = 0; byte < msgs[i].len; byte++) {
262 printk(" %02x", msgs[i].buf[byte]);
263 }
264 }
265 } else {
266 /* write bytes */
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800267 if (i2c_debug>=2) {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800268 for (byte = 0; byte < msgs[i].len; byte++)
269 printk(" %02x", msgs[i].buf[byte]);
270 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800271 if (dev->is_em2800)
272 rc = em2800_i2c_send_bytes(dev, addr,
273 msgs[i].buf,
274 msgs[i].len);
275 else
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800276 rc = em28xx_i2c_send_bytes(dev, addr,
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800277 msgs[i].buf,
278 msgs[i].len,
279 i == num - 1);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800280 if (rc < 0)
281 goto err;
282 }
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800283 if (i2c_debug>=2)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800284 printk("\n");
285 }
286
287 return num;
288 err:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800289 dprintk2(2," ERROR: %i\n", rc);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800290 return rc;
291}
292
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800293static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800294{
295 unsigned char buf, *p = eedata;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800296 struct em28xx_eeprom *em_eeprom = (void *)eedata;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800297 int i, err, size = len, block;
298
299 dev->i2c_client.addr = 0xa0 >> 1;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800300
301 /* Check if board has eeprom */
302 err = i2c_master_recv(&dev->i2c_client, &buf, 0);
303 if (err < 0)
304 return -1;
305
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800306 buf = 0;
307 if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
308 printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
309 dev->name, err);
310 return -1;
311 }
312 while (size > 0) {
313 if (size > 16)
314 block = 16;
315 else
316 block = size;
317
318 if (block !=
319 (err = i2c_master_recv(&dev->i2c_client, p, block))) {
320 printk(KERN_WARNING
321 "%s: i2c eeprom read error (err=%d)\n",
322 dev->name, err);
323 return -1;
324 }
325 size -= block;
326 p += block;
327 }
328 for (i = 0; i < len; i++) {
329 if (0 == (i % 16))
330 printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
331 printk(" %02x", eedata[i]);
332 if (15 == (i % 16))
333 printk("\n");
334 }
335
336 printk(KERN_INFO "EEPROM ID= 0x%08x\n", em_eeprom->id);
337 printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID,
338 em_eeprom->product_ID);
339
340 switch (em_eeprom->chip_conf >> 4 & 0x3) {
341 case 0:
342 printk(KERN_INFO "No audio on board.\n");
343 break;
344 case 1:
345 printk(KERN_INFO "AC97 audio (5 sample rates)\n");
346 break;
347 case 2:
348 printk(KERN_INFO "I2S audio, sample rate=32k\n");
349 break;
350 case 3:
351 printk(KERN_INFO "I2S audio, 3 sample rates\n");
352 break;
353 }
354
355 if (em_eeprom->chip_conf & 1 << 3)
356 printk(KERN_INFO "USB Remote wakeup capable\n");
357
358 if (em_eeprom->chip_conf & 1 << 2)
359 printk(KERN_INFO "USB Self power capable\n");
360
361 switch (em_eeprom->chip_conf & 0x3) {
362 case 0:
363 printk(KERN_INFO "500mA max power\n");
364 break;
365 case 1:
366 printk(KERN_INFO "400mA max power\n");
367 break;
368 case 2:
369 printk(KERN_INFO "300mA max power\n");
370 break;
371 case 3:
372 printk(KERN_INFO "200mA max power\n");
373 break;
374 }
Mauro Carvalho Chehab91cad0f2005-11-08 21:38:13 -0800375 printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
376 em_eeprom->string_idx_table,em_eeprom->string1,
377 em_eeprom->string2,em_eeprom->string3);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800378
379 return 0;
380}
381
382/* ----------------------------------------------------------- */
383
384/*
385 * algo_control()
386 */
387static int algo_control(struct i2c_adapter *adapter,
388 unsigned int cmd, unsigned long arg)
389{
390 return 0;
391}
392
393/*
394 * functionality()
395 */
396static u32 functionality(struct i2c_adapter *adap)
397{
398 return I2C_FUNC_SMBUS_EMUL;
399}
400
401#ifndef I2C_PEC
402static void inc_use(struct i2c_adapter *adap)
403{
404 MOD_INC_USE_COUNT;
405}
406
407static void dec_use(struct i2c_adapter *adap)
408{
409 MOD_DEC_USE_COUNT;
410}
411#endif
412
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800413static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800414{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800415 struct em28xx *dev = client->adapter->algo_data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800416 struct tuner_setup tun_setup;
417
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800418 if (dev->has_tuner) {
419 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
420 tun_setup.type = dev->tuner_type;
421 tun_setup.addr = dev->tuner_addr;
422
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800423 em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800424 }
Nickolay V. Shmyrevfd35a6b2005-11-08 21:37:09 -0800425
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800426 return (0);
427}
428
429/*
430 * attach_inform()
431 * gets called when a device attaches to the i2c bus
432 * does some basic configuration
433 */
434static int attach_inform(struct i2c_client *client)
435{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800436 struct em28xx *dev = client->adapter->algo_data;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800437
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800438 switch (client->addr << 1) {
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800439 case 0x86:
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800440 em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf);
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800441 break;
Markus Rechberger30556b22005-11-08 21:38:05 -0800442 case 0x42:
443 dprintk1(1,"attach_inform: saa7114 detected.\n");
444 break;
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800445 case 0x4a:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800446 dprintk1(1,"attach_inform: saa7113 detected.\n");
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800447 break;
448 case 0xa0:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800449 dprintk1(1,"attach_inform: eeprom detected.\n");
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800450 break;
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800451 case 0x60:
452 case 0x8e:
453 {
454 struct IR_i2c *ir = i2c_get_clientdata(client);
455 dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800456 em28xx_set_ir(dev,ir);
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800457 break;
458 }
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800459 case 0x80:
460 case 0x88:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800461 dprintk1(1,"attach_inform: msp34xx detected.\n");
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800462 break;
463 case 0xb8:
464 case 0xba:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800465 dprintk1(1,"attach_inform: tvp5150 detected.\n");
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800466 break;
467 default:
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -0800468 dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
Markus Rechbergera9ae9fb2005-11-08 21:37:20 -0800469 dev->tuner_addr = client->addr;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800470 em28xx_set_tuner(-1, client);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800471 }
472
473 return 0;
474}
475
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800476static struct i2c_algorithm em28xx_algo = {
477 .master_xfer = em28xx_i2c_xfer,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800478 .algo_control = algo_control,
479 .functionality = functionality,
480};
481
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800482static struct i2c_adapter em28xx_adap_template = {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800483#ifdef I2C_PEC
484 .owner = THIS_MODULE,
485#else
486 .inc_use = inc_use,
487 .dec_use = dec_use,
488#endif
489#ifdef I2C_CLASS_TV_ANALOG
490 .class = I2C_CLASS_TV_ANALOG,
491#endif
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800492 .name = "em28xx",
493 .id = I2C_HW_B_EM28XX,
494 .algo = &em28xx_algo,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800495 .client_register = attach_inform,
496};
497
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800498static struct i2c_client em28xx_client_template = {
499 .name = "em28xx internal",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800500 .flags = I2C_CLIENT_ALLOW_USE,
501};
502
503/* ----------------------------------------------------------- */
504
505/*
506 * i2c_devs
507 * incomplete list of known devices
508 */
509static char *i2c_devs[128] = {
510 [0x4a >> 1] = "saa7113h",
511 [0x60 >> 1] = "remote IR sensor",
Markus Rechbergerda45a2a2005-11-08 21:37:31 -0800512 [0x8e >> 1] = "remote IR sensor",
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800513 [0x86 >> 1] = "tda9887",
514 [0x80 >> 1] = "msp34xx",
515 [0x88 >> 1] = "msp34xx",
516 [0xa0 >> 1] = "eeprom",
517 [0xb8 >> 1] = "tvp5150a",
518 [0xba >> 1] = "tvp5150a",
519 [0xc0 >> 1] = "tuner (analog)",
520 [0xc2 >> 1] = "tuner (analog)",
521 [0xc4 >> 1] = "tuner (analog)",
522 [0xc6 >> 1] = "tuner (analog)",
523};
524
525/*
526 * do_i2c_scan()
527 * check i2c address range for devices
528 */
529static void do_i2c_scan(char *name, struct i2c_client *c)
530{
531 unsigned char buf;
532 int i, rc;
533
534 for (i = 0; i < 128; i++) {
535 c->addr = i;
536 rc = i2c_master_recv(c, &buf, 0);
537 if (rc < 0)
538 continue;
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800539 printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800540 i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
541 }
542}
543
544/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800545 * em28xx_i2c_call_clients()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800546 * send commands to all attached i2c devices
547 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800548void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800549{
550 BUG_ON(NULL == dev->i2c_adap.algo_data);
551 i2c_clients_command(&dev->i2c_adap, cmd, arg);
552}
553
554/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800555 * em28xx_i2c_register()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800556 * register i2c bus
557 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800558int em28xx_i2c_register(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800559{
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800560 BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
561 BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
562 dev->i2c_adap = em28xx_adap_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800563 dev->i2c_adap.dev.parent = &dev->udev->dev;
564 strcpy(dev->i2c_adap.name, dev->name);
565 dev->i2c_adap.algo_data = dev;
566 i2c_add_adapter(&dev->i2c_adap);
567
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800568 dev->i2c_client = em28xx_client_template;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800569 dev->i2c_client.adapter = &dev->i2c_adap;
570
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800571 em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800572
573 if (i2c_scan)
574 do_i2c_scan(dev->name, &dev->i2c_client);
575 return 0;
576}
577
578/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800579 * em28xx_i2c_unregister()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800580 * unregister i2c_bus
581 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800582int em28xx_i2c_unregister(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800583{
584 i2c_del_adapter(&dev->i2c_adap);
585 return 0;
586}