• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/tm6000/
1/*
2   tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
3
4   Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
5
6   Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
7	- Fix SMBus Read Byte command
8
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 version 2
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/usb.h>
26#include <linux/i2c.h>
27
28#include "tm6000.h"
29#include "tm6000-regs.h"
30#include <media/v4l2-common.h>
31#include <media/tuner.h>
32#include "tuner-xc2028.h"
33
34
35#define I2C_HW_B_TM6000 I2C_HW_B_EM28XX
36/* ----------------------------------------------------------- */
37
38static unsigned int i2c_debug = 0;
39module_param(i2c_debug, int, 0644);
40MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
41
42#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
43			printk(KERN_DEBUG "%s at %s: " fmt, \
44			dev->name, __FUNCTION__ , ##args); } while (0)
45
46static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
47				__u8 reg, char *buf, int len)
48{
49	int rc;
50	unsigned int tsleep;
51	unsigned int i2c_packet_limit = 16;
52
53	if (dev->dev_type == TM6010)
54		i2c_packet_limit = 64;
55
56	if (!buf)
57		return -1;
58
59	if (len < 1 || len > i2c_packet_limit) {
60		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
61			len, i2c_packet_limit);
62		return -1;
63	}
64
65	/* capture mutex */
66	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
67		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
68		addr | reg << 8, 0, buf, len);
69
70	if (rc < 0) {
71		/* release mutex */
72		return rc;
73	}
74
75	/* Calculate delay time, 14000us for 64 bytes */
76	tsleep = ((len * 200) + 200 + 1000) / 1000;
77	msleep(tsleep);
78
79	/* release mutex */
80	return rc;
81}
82
83/* Generic read - doesn't work fine with 16bit registers */
84static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
85				__u8 reg, char *buf, int len)
86{
87	int rc;
88	u8 b[2];
89	unsigned int i2c_packet_limit = 16;
90
91	if (dev->dev_type == TM6010)
92		i2c_packet_limit = 64;
93
94	if (!buf)
95		return -1;
96
97	if (len < 1 || len > i2c_packet_limit) {
98		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
99			len, i2c_packet_limit);
100		return -1;
101	}
102
103	/* capture mutex */
104	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
105		reg -= 1;
106		len += 1;
107
108		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
109			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
110
111		*buf = b[1];
112	} else {
113		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
114			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
115	}
116
117	/* release mutex */
118	return rc;
119}
120
121/*
122 * read from a 16bit register
123 * for example xc2028, xc3028 or xc3028L
124 */
125static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
126				  __u16 reg, char *buf, int len)
127{
128	int rc;
129	unsigned char ureg;
130
131	if (!buf || len != 2)
132		return -1;
133
134	/* capture mutex */
135	if (dev->dev_type == TM6010) {
136		ureg = reg & 0xFF;
137		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
138			USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
139			addr | (reg & 0xFF00), 0, &ureg, 1);
140
141		if (rc < 0) {
142			/* release mutex */
143			return rc;
144		}
145
146		msleep(1400 / 1000);
147		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
148			USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
149			reg, 0, buf, len);
150	} else {
151		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
152			USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
153			addr, reg, buf, len);
154	}
155
156	/* release mutex */
157	return rc;
158}
159
160static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
161			   struct i2c_msg msgs[], int num)
162{
163	struct tm6000_core *dev = i2c_adap->algo_data;
164	int addr, rc, i, byte;
165
166	if (num <= 0)
167		return 0;
168	for (i = 0; i < num; i++) {
169		addr = (msgs[i].addr << 1) & 0xff;
170		i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
171			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
172			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
173		if (msgs[i].flags & I2C_M_RD) {
174			/* read request without preceding register selection */
175			/*
176			 * The TM6000 only supports a read transaction
177			 * immediately after a 1 or 2 byte write to select
178			 * a register.  We cannot fulfil this request.
179			 */
180			i2c_dprintk(2, " read without preceding write not"
181				       " supported");
182			rc = -EOPNOTSUPP;
183			goto err;
184		} else if (i + 1 < num && msgs[i].len <= 2 &&
185			   (msgs[i + 1].flags & I2C_M_RD) &&
186			   msgs[i].addr == msgs[i + 1].addr) {
187			/* 1 or 2 byte write followed by a read */
188			if (i2c_debug >= 2)
189				for (byte = 0; byte < msgs[i].len; byte++)
190					printk(" %02x", msgs[i].buf[byte]);
191			i2c_dprintk(2, "; joined to read %s len=%d:",
192				    i == num - 2 ? "stop" : "nonstop",
193				    msgs[i + 1].len);
194
195			if (msgs[i].len == 2) {
196				rc = tm6000_i2c_recv_regs16(dev, addr,
197					msgs[i].buf[0] << 8 | msgs[i].buf[1],
198					msgs[i + 1].buf, msgs[i + 1].len);
199			} else {
200				rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
201					msgs[i + 1].buf, msgs[i + 1].len);
202			}
203
204			i++;
205
206			if (addr == dev->tuner_addr << 1) {
207				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
208				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
209			}
210			if (i2c_debug >= 2)
211				for (byte = 0; byte < msgs[i].len; byte++)
212					printk(" %02x", msgs[i].buf[byte]);
213		} else {
214			/* write bytes */
215			if (i2c_debug >= 2)
216				for (byte = 0; byte < msgs[i].len; byte++)
217					printk(" %02x", msgs[i].buf[byte]);
218			rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
219				msgs[i].buf + 1, msgs[i].len - 1);
220
221			if (addr == dev->tuner_addr  << 1) {
222				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
223				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
224			}
225		}
226		if (i2c_debug >= 2)
227			printk("\n");
228		if (rc < 0)
229			goto err;
230	}
231
232	return num;
233err:
234	i2c_dprintk(2, " ERROR: %i\n", rc);
235	return rc;
236}
237
238static int tm6000_i2c_eeprom(struct tm6000_core *dev,
239			     unsigned char *eedata, int len)
240{
241	int i, rc;
242	unsigned char *p = eedata;
243	unsigned char bytes[17];
244
245	dev->i2c_client.addr = 0xa0 >> 1;
246
247	bytes[16] = '\0';
248	for (i = 0; i < len; ) {
249	*p = i;
250	rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
251		if (rc < 1) {
252			if (p == eedata)
253				goto noeeprom;
254			else {
255				printk(KERN_WARNING
256				"%s: i2c eeprom read error (err=%d)\n",
257				dev->name, rc);
258			}
259			return -1;
260		}
261		p++;
262		if (0 == (i % 16))
263			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
264		printk(" %02x", eedata[i]);
265		if ((eedata[i] >= ' ') && (eedata[i] <= 'z'))
266			bytes[i%16] = eedata[i];
267		else
268			bytes[i%16] = '.';
269
270		i++;
271
272		if (0 == (i % 16)) {
273			bytes[16] = '\0';
274			printk("  %s\n", bytes);
275		}
276	}
277	if (0 != (i%16)) {
278		bytes[i%16] = '\0';
279		for (i %= 16; i < 16; i++)
280			printk("   ");
281	}
282	printk("  %s\n", bytes);
283
284	return 0;
285
286noeeprom:
287	printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
288		       dev->name, rc);
289	return rc;
290}
291
292/* ----------------------------------------------------------- */
293
294/*
295 * functionality()
296 */
297static u32 functionality(struct i2c_adapter *adap)
298{
299	return I2C_FUNC_SMBUS_EMUL;
300}
301
302#define mass_write(addr, reg, data...)					\
303	{ static const u8 _val[] = data;				\
304	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,	\
305	REQ_16_SET_GET_I2C_WR1_RDN, (reg<<8)+addr, 0x00, (u8 *) _val,	\
306	ARRAY_SIZE(_val));						\
307	if (rc < 0) {							\
308		printk(KERN_ERR "Error on line %d: %d\n", __LINE__, rc);	\
309		return rc;						\
310	}								\
311	msleep(10);							\
312	}
313
314static struct i2c_algorithm tm6000_algo = {
315	.master_xfer   = tm6000_i2c_xfer,
316	.functionality = functionality,
317};
318
319static struct i2c_adapter tm6000_adap_template = {
320	.owner = THIS_MODULE,
321	.class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
322	.name = "tm6000",
323	.id = I2C_HW_B_TM6000,
324	.algo = &tm6000_algo,
325};
326
327static struct i2c_client tm6000_client_template = {
328	.name = "tm6000 internal",
329};
330
331/* ----------------------------------------------------------- */
332
333/*
334 * tm6000_i2c_register()
335 * register i2c bus
336 */
337int tm6000_i2c_register(struct tm6000_core *dev)
338{
339	unsigned char eedata[256];
340
341	dev->i2c_adap = tm6000_adap_template;
342	dev->i2c_adap.dev.parent = &dev->udev->dev;
343	strcpy(dev->i2c_adap.name, dev->name);
344	dev->i2c_adap.algo_data = dev;
345	i2c_add_adapter(&dev->i2c_adap);
346
347	dev->i2c_client = tm6000_client_template;
348	dev->i2c_client.adapter = &dev->i2c_adap;
349
350	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
351
352	tm6000_i2c_eeprom(dev, eedata, sizeof(eedata));
353
354	return 0;
355}
356
357/*
358 * tm6000_i2c_unregister()
359 * unregister i2c_bus
360 */
361int tm6000_i2c_unregister(struct tm6000_core *dev)
362{
363	i2c_del_adapter(&dev->i2c_adap);
364	return 0;
365}
366