aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-i2c.c
diff options
context:
space:
mode:
authorakpm@osdl.org <akpm@osdl.org>2005-11-09 00:37:07 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:15 -0500
commita6c2ba283565dbc9f055dcb2ecba1971460bb535 (patch)
treefd262f8af5bffc99753ff861be85574616113467 /drivers/media/video/em28xx/em28xx-i2c.c
parent4b017415fc9ab63f7c0e49aced5e403c18d55659 (diff)
[PATCH] v4l: 716: support for em28xx board family
- Added support for em28xx board family Signed-off-by: Ludovico Cavedon <cavedon@sssup.it> Signed-off-by: Markus Rechberger <mrechberger@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-i2c.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
new file mode 100644
index 000000000000..95f80a7615bd
--- /dev/null
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -0,0 +1,443 @@
1/*
2 em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices
3
4 Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
5 Ludovico Cavedon <cavedon@sssup.it>
6 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
7
8 Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/usb.h>
28#include <linux/i2c.h>
29#include <linux/videodev.h>
30#include <media/tuner.h>
31#include <linux/video_decoder.h>
32
33/* To be moved to compat.h */
34#if !defined(I2C_HW_B_EM2820)
35#define I2C_HW_B_EM2820 I2C_HW_B_BT848
36#endif
37
38#include "em2820.h"
39
40/* ----------------------------------------------------------- */
41
42static unsigned int i2c_scan = 0;
43module_param(i2c_scan, int, 0444);
44MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
45
46static unsigned int i2c_debug = 0;
47module_param(i2c_debug, int, 0644);
48MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
49
50#define dprintk(fmt, args...) if (i2c_debug) do {\
51 printk(KERN_DEBUG "%s: %s: " fmt "\n",\
52 dev->name, __FUNCTION__ , ##args); } while (0)
53#define dprintk1(fmt, args...) if (i2c_debug) do{ \
54 printk(KERN_DEBUG "%s: %s: " fmt, \
55 dev->name, __FUNCTION__ , ##args); } while (0)
56#define dprintk2(fmt, args...) if (i2c_debug) do {\
57 printk(fmt , ##args); } while (0)
58
59/*
60 * i2c_send_bytes()
61 * untested for more than 4 bytes
62 */
63static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len,
64 int stop)
65{
66 int wrcount = 0;
67 struct em2820 *dev = (struct em2820 *)data;
68
69 wrcount = dev->em2820_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
70
71 return wrcount;
72}
73
74/*
75 * i2c_recv_byte()
76 * read a byte from the i2c device
77 */
78static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf,
79 int len)
80{
81 int ret;
82 ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len);
83 if (ret < 0) {
84 em2820_warn("reading i2c device failed (error=%i)\n", ret);
85 return ret;
86 }
87 if (dev->em2820_read_reg(dev, 0x5) != 0)
88 return -ENODEV;
89 return ret;
90}
91
92/*
93 * i2c_check_for_device()
94 * check if there is a i2c_device at the supplied address
95 */
96static int i2c_check_for_device(struct em2820 *dev, unsigned char addr)
97{
98 char msg;
99 int ret;
100 msg = addr;
101
102 ret = dev->em2820_read_reg_req(dev, 2, addr);
103 if (ret < 0) {
104 em2820_warn("reading from i2c device failed (error=%i)\n", ret);
105 return ret;
106 }
107 if (dev->em2820_read_reg(dev, 0x5) != 0)
108 return -ENODEV;
109 return 0;
110}
111
112/*
113 * em2820_i2c_xfer()
114 * the main i2c transfer function
115 */
116static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap,
117 struct i2c_msg msgs[], int num)
118{
119 struct em2820 *dev = i2c_adap->algo_data;
120 int addr, rc, i, byte;
121
122 if (num <= 0)
123 return 0;
124 for (i = 0; i < num; i++) {
125 addr = msgs[i].addr << 1;
126 dprintk1("%s %s addr=%x len=%d:",
127 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
128 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
129 if (!msgs[i].len) { /* no len: check only for device presence */
130 rc = i2c_check_for_device(dev, addr);
131 if (rc < 0) {
132 dprintk2(" no device\n");
133 return rc;
134 }
135
136 }
137 if (msgs[i].flags & I2C_M_RD) {
138 /* read bytes */
139
140 rc = i2c_recv_bytes(dev, addr, msgs[i].buf,
141 msgs[i].len);
142 if (i2c_debug) {
143 for (byte = 0; byte < msgs[i].len; byte++) {
144 printk(" %02x", msgs[i].buf[byte]);
145 }
146 }
147 } else {
148 /* write bytes */
149 if (i2c_debug) {
150 for (byte = 0; byte < msgs[i].len; byte++)
151 printk(" %02x", msgs[i].buf[byte]);
152 }
153 rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len,
154 i == num - 1);
155 if (rc < 0)
156 goto err;
157 }
158 if (i2c_debug)
159 printk("\n");
160 }
161
162 return num;
163 err:
164 dprintk2(" ERROR: %i\n", rc);
165 return rc;
166}
167
168static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len)
169{
170 unsigned char buf, *p = eedata;
171 struct em2820_eeprom *em_eeprom = (void *)eedata;
172 int i, err, size = len, block;
173
174 dev->i2c_client.addr = 0xa0 >> 1;
175 buf = 0;
176 if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
177 printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
178 dev->name, err);
179 return -1;
180 }
181 while (size > 0) {
182 if (size > 16)
183 block = 16;
184 else
185 block = size;
186
187 if (block !=
188 (err = i2c_master_recv(&dev->i2c_client, p, block))) {
189 printk(KERN_WARNING
190 "%s: i2c eeprom read error (err=%d)\n",
191 dev->name, err);
192 return -1;
193 }
194 size -= block;
195 p += block;
196 }
197 for (i = 0; i < len; i++) {
198 if (0 == (i % 16))
199 printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
200 printk(" %02x", eedata[i]);
201 if (15 == (i % 16))
202 printk("\n");
203 }
204
205 printk(KERN_INFO "EEPROM ID= 0x%08x\n", em_eeprom->id);
206 printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID,
207 em_eeprom->product_ID);
208
209 switch (em_eeprom->chip_conf >> 4 & 0x3) {
210 case 0:
211 printk(KERN_INFO "No audio on board.\n");
212 break;
213 case 1:
214 printk(KERN_INFO "AC97 audio (5 sample rates)\n");
215 break;
216 case 2:
217 printk(KERN_INFO "I2S audio, sample rate=32k\n");
218 break;
219 case 3:
220 printk(KERN_INFO "I2S audio, 3 sample rates\n");
221 break;
222 }
223
224 if (em_eeprom->chip_conf & 1 << 3)
225 printk(KERN_INFO "USB Remote wakeup capable\n");
226
227 if (em_eeprom->chip_conf & 1 << 2)
228 printk(KERN_INFO "USB Self power capable\n");
229
230 switch (em_eeprom->chip_conf & 0x3) {
231 case 0:
232 printk(KERN_INFO "500mA max power\n");
233 break;
234 case 1:
235 printk(KERN_INFO "400mA max power\n");
236 break;
237 case 2:
238 printk(KERN_INFO "300mA max power\n");
239 break;
240 case 3:
241 printk(KERN_INFO "200mA max power\n");
242 break;
243 }
244
245 return 0;
246}
247
248/* ----------------------------------------------------------- */
249
250/*
251 * algo_control()
252 */
253static int algo_control(struct i2c_adapter *adapter,
254 unsigned int cmd, unsigned long arg)
255{
256 return 0;
257}
258
259/*
260 * functionality()
261 */
262static u32 functionality(struct i2c_adapter *adap)
263{
264 return I2C_FUNC_SMBUS_EMUL;
265}
266
267#ifndef I2C_PEC
268static void inc_use(struct i2c_adapter *adap)
269{
270 MOD_INC_USE_COUNT;
271}
272
273static void dec_use(struct i2c_adapter *adap)
274{
275 MOD_DEC_USE_COUNT;
276}
277#endif
278
279static int em2820_set_tuner(int check_eeprom, struct i2c_client *client)
280{
281 struct em2820 *dev = client->adapter->algo_data;
282
283 struct tuner_setup tun_setup;
284
285 /* tuner */
286 if (dev->has_tuner) {
287 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
288 tun_setup.type = dev->tuner_type;
289 tun_setup.addr = dev->tuner_addr;
290
291 em2820_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
292 }
293 return (0);
294}
295
296/*
297 * attach_inform()
298 * gets called when a device attaches to the i2c bus
299 * does some basic configuration
300 */
301static int attach_inform(struct i2c_client *client)
302{
303 struct em2820 *dev = client->adapter->algo_data;
304
305 dprintk("address %x", client->addr << 1);
306 switch (client->addr << 1) {
307 case 0x68:
308 em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf);
309 break;
310 case 0x4a:
311 dprintk1("attach_inform: saa7113 detected.\n");
312 break;
313 case 0xa0:
314 dprintk1("attach_inform: eeprom detected.\n");
315 break;
316 case 0x80:
317 case 0x88:
318 dprintk1("attach_inform: msp34xx detected.\n");
319 break;
320 case 0xb8:
321 case 0xba:
322 dprintk1("attach_inform: tvp5150 detected.\n");
323 break;
324 default:
325 dev->tuner_addr = client->addr;
326 em2820_set_tuner(-1, client);
327 }
328
329 return 0;
330}
331
332static struct i2c_algorithm em2820_algo = {
333 .name = "em2820",
334 .id = I2C_HW_B_EM2820,
335 .master_xfer = em2820_i2c_xfer,
336 .algo_control = algo_control,
337 .functionality = functionality,
338};
339
340static struct i2c_adapter em2820_adap_template = {
341#ifdef I2C_PEC
342 .owner = THIS_MODULE,
343#else
344 .inc_use = inc_use,
345 .dec_use = dec_use,
346#endif
347#ifdef I2C_CLASS_TV_ANALOG
348 .class = I2C_CLASS_TV_ANALOG,
349#endif
350 .name = "em2820",
351 .id = I2C_HW_B_EM2820,
352 .algo = &em2820_algo,
353 .client_register = attach_inform,
354};
355
356static struct i2c_client em2820_client_template = {
357 .name = "em2820 internal",
358 .flags = I2C_CLIENT_ALLOW_USE,
359};
360
361/* ----------------------------------------------------------- */
362
363/*
364 * i2c_devs
365 * incomplete list of known devices
366 */
367static char *i2c_devs[128] = {
368 [0x4a >> 1] = "saa7113h",
369 [0x60 >> 1] = "remote IR sensor",
370 [0x86 >> 1] = "tda9887",
371 [0x80 >> 1] = "msp34xx",
372 [0x88 >> 1] = "msp34xx",
373 [0xa0 >> 1] = "eeprom",
374 [0xb8 >> 1] = "tvp5150a",
375 [0xba >> 1] = "tvp5150a",
376 [0xc0 >> 1] = "tuner (analog)",
377 [0xc2 >> 1] = "tuner (analog)",
378 [0xc4 >> 1] = "tuner (analog)",
379 [0xc6 >> 1] = "tuner (analog)",
380};
381
382/*
383 * do_i2c_scan()
384 * check i2c address range for devices
385 */
386static void do_i2c_scan(char *name, struct i2c_client *c)
387{
388 unsigned char buf;
389 int i, rc;
390
391 for (i = 0; i < 128; i++) {
392 c->addr = i;
393 rc = i2c_master_recv(c, &buf, 0);
394 if (rc < 0)
395 continue;
396 printk(KERN_INFO "%s: found device @ 0x%x [%s]", name,
397 i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
398 }
399}
400
401/*
402 * em2820_i2c_call_clients()
403 * send commands to all attached i2c devices
404 */
405void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg)
406{
407 BUG_ON(NULL == dev->i2c_adap.algo_data);
408 i2c_clients_command(&dev->i2c_adap, cmd, arg);
409}
410
411/*
412 * em2820_i2c_register()
413 * register i2c bus
414 */
415int em2820_i2c_register(struct em2820 *dev)
416{
417 BUG_ON(!dev->em2820_write_regs || !dev->em2820_read_reg);
418 BUG_ON(!dev->em2820_write_regs_req || !dev->em2820_read_reg_req);
419 dev->i2c_adap = em2820_adap_template;
420 dev->i2c_adap.dev.parent = &dev->udev->dev;
421 strcpy(dev->i2c_adap.name, dev->name);
422 dev->i2c_adap.algo_data = dev;
423 i2c_add_adapter(&dev->i2c_adap);
424
425 dev->i2c_client = em2820_client_template;
426 dev->i2c_client.adapter = &dev->i2c_adap;
427
428 em2820_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
429
430 if (i2c_scan)
431 do_i2c_scan(dev->name, &dev->i2c_client);
432 return 0;
433}
434
435/*
436 * em2820_i2c_unregister()
437 * unregister i2c_bus
438 */
439int em2820_i2c_unregister(struct em2820 *dev)
440{
441 i2c_del_adapter(&dev->i2c_adap);
442 return 0;
443}