Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  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/* ----------------------------------------------------------- */
 36
 37static unsigned int i2c_debug;
 38module_param(i2c_debug, int, 0644);
 39MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 40
 41#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
 42			printk(KERN_DEBUG "%s at %s: " fmt, \
 43			dev->name, __func__, ##args); } while (0)
 44
 45static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
 46				__u8 reg, char *buf, int len)
 47{
 48	int rc;
 49	unsigned int tsleep;
 50	unsigned int i2c_packet_limit = 16;
 51
 52	if (dev->dev_type == TM6010)
 53		i2c_packet_limit = 64;
 54
 55	if (!buf)
 56		return -1;
 57
 58	if (len < 1 || len > i2c_packet_limit) {
 59		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
 60			len, i2c_packet_limit);
 61		return -1;
 62	}
 63
 64	/* capture mutex */
 65	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
 66		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
 67		addr | reg << 8, 0, buf, len);
 68
 69	if (rc < 0) {
 70		/* release mutex */
 71		return rc;
 72	}
 73
 74	/* Calculate delay time, 14000us for 64 bytes */
 75	tsleep = ((len * 200) + 200 + 1000) / 1000;
 76	msleep(tsleep);
 77
 78	/* release mutex */
 79	return rc;
 80}
 81
 82/* Generic read - doesn't work fine with 16bit registers */
 83static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
 84				__u8 reg, char *buf, int len)
 85{
 86	int rc;
 87	u8 b[2];
 88	unsigned int i2c_packet_limit = 16;
 89
 90	if (dev->dev_type == TM6010)
 91		i2c_packet_limit = 64;
 92
 93	if (!buf)
 94		return -1;
 95
 96	if (len < 1 || len > i2c_packet_limit) {
 97		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
 98			len, i2c_packet_limit);
 99		return -1;
100	}
101
102	/* capture mutex */
103	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
104		/*
105		 * Workaround an I2C bug when reading from zl10353
106		 */
107		reg -= 1;
108		len += 1;
109
110		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
111			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
112
113		*buf = b[1];
114	} else {
115		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
116			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
117	}
118
119	/* release mutex */
120	return rc;
121}
122
123/*
124 * read from a 16bit register
125 * for example xc2028, xc3028 or xc3028L
126 */
127static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
128				  __u16 reg, char *buf, int len)
129{
130	int rc;
131	unsigned char ureg;
132
133	if (!buf || len != 2)
134		return -1;
135
136	/* capture mutex */
137	if (dev->dev_type == TM6010) {
138		ureg = reg & 0xFF;
139		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
140			USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
141			addr | (reg & 0xFF00), 0, &ureg, 1);
142
143		if (rc < 0) {
144			/* release mutex */
145			return rc;
146		}
147
148		msleep(1400 / 1000);
149		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
150			USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
151			reg, 0, buf, len);
152	} else {
153		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
154			USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
155			addr, reg, buf, len);
156	}
157
158	/* release mutex */
159	return rc;
160}
161
162static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
163			   struct i2c_msg msgs[], int num)
164{
165	struct tm6000_core *dev = i2c_adap->algo_data;
166	int addr, rc, i, byte;
167
168	if (num <= 0)
169		return 0;
170	for (i = 0; i < num; i++) {
171		addr = (msgs[i].addr << 1) & 0xff;
172		i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
173			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
174			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
175		if (msgs[i].flags & I2C_M_RD) {
176			/* read request without preceding register selection */
177			/*
178			 * The TM6000 only supports a read transaction
179			 * immediately after a 1 or 2 byte write to select
180			 * a register.  We cannot fulfil this request.
181			 */
182			i2c_dprintk(2, " read without preceding write not"
183				       " supported");
184			rc = -EOPNOTSUPP;
185			goto err;
186		} else if (i + 1 < num && msgs[i].len <= 2 &&
187			   (msgs[i + 1].flags & I2C_M_RD) &&
188			   msgs[i].addr == msgs[i + 1].addr) {
189			/* 1 or 2 byte write followed by a read */
190			if (i2c_debug >= 2)
191				for (byte = 0; byte < msgs[i].len; byte++)
192					printk(" %02x", msgs[i].buf[byte]);
193			i2c_dprintk(2, "; joined to read %s len=%d:",
194				    i == num - 2 ? "stop" : "nonstop",
195				    msgs[i + 1].len);
196
197			if (msgs[i].len == 2) {
198				rc = tm6000_i2c_recv_regs16(dev, addr,
199					msgs[i].buf[0] << 8 | msgs[i].buf[1],
200					msgs[i + 1].buf, msgs[i + 1].len);
201			} else {
202				rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
203					msgs[i + 1].buf, msgs[i + 1].len);
204			}
205
206			i++;
207
208			if (addr == dev->tuner_addr << 1) {
209				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
210				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
211			}
212			if (i2c_debug >= 2)
213				for (byte = 0; byte < msgs[i].len; byte++)
214					printk(" %02x", msgs[i].buf[byte]);
215		} else {
216			/* write bytes */
217			if (i2c_debug >= 2)
218				for (byte = 0; byte < msgs[i].len; byte++)
219					printk(" %02x", msgs[i].buf[byte]);
220			rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
221				msgs[i].buf + 1, msgs[i].len - 1);
222
223			if (addr == dev->tuner_addr  << 1) {
224				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
225				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
226			}
227		}
228		if (i2c_debug >= 2)
229			printk("\n");
230		if (rc < 0)
231			goto err;
232	}
233
234	return num;
235err:
236	i2c_dprintk(2, " ERROR: %i\n", rc);
237	return rc;
238}
239
240static int tm6000_i2c_eeprom(struct tm6000_core *dev)
241{
242	int i, rc;
243	unsigned char *p = dev->eedata;
244	unsigned char bytes[17];
245
246	dev->i2c_client.addr = 0xa0 >> 1;
247	dev->eedata_size = 0;
248
249	bytes[16] = '\0';
250	for (i = 0; i < sizeof(dev->eedata); ) {
251		*p = i;
252		rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
253		if (rc < 1) {
254			if (p == dev->eedata)
255				goto noeeprom;
256			else {
257				printk(KERN_WARNING
258				"%s: i2c eeprom read error (err=%d)\n",
259				dev->name, rc);
260			}
261			return -EINVAL;
262		}
263		dev->eedata_size++;
264		p++;
265		if (0 == (i % 16))
266			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
267		printk(" %02x", dev->eedata[i]);
268		if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
269			bytes[i%16] = dev->eedata[i];
270		else
271			bytes[i%16] = '.';
272
273		i++;
274
275		if (0 == (i % 16)) {
276			bytes[16] = '\0';
277			printk("  %s\n", bytes);
278		}
279	}
280	if (0 != (i%16)) {
281		bytes[i%16] = '\0';
282		for (i %= 16; i < 16; i++)
283			printk("   ");
284		printk("  %s\n", bytes);
285	}
286
287	return 0;
288
289noeeprom:
290	printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
291	       dev->name, rc);
292	return -EINVAL;
293}
294
295/* ----------------------------------------------------------- */
296
297/*
298 * functionality()
299 */
300static u32 functionality(struct i2c_adapter *adap)
301{
302	return I2C_FUNC_SMBUS_EMUL;
303}
304
305static const struct i2c_algorithm tm6000_algo = {
306	.master_xfer   = tm6000_i2c_xfer,
307	.functionality = functionality,
308};
309
310/* ----------------------------------------------------------- */
311
312/*
313 * tm6000_i2c_register()
314 * register i2c bus
315 */
316int tm6000_i2c_register(struct tm6000_core *dev)
317{
318	int rc;
319
320	dev->i2c_adap.owner = THIS_MODULE;
321	dev->i2c_adap.algo = &tm6000_algo;
322	dev->i2c_adap.dev.parent = &dev->udev->dev;
323	strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
324	dev->i2c_adap.algo_data = dev;
325	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
326	rc = i2c_add_adapter(&dev->i2c_adap);
327	if (rc)
328		return rc;
329
330	dev->i2c_client.adapter = &dev->i2c_adap;
331	strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
332	tm6000_i2c_eeprom(dev);
333
334	return 0;
335}
336
337/*
338 * tm6000_i2c_unregister()
339 * unregister i2c_bus
340 */
341int tm6000_i2c_unregister(struct tm6000_core *dev)
342{
343	i2c_del_adapter(&dev->i2c_adap);
344	return 0;
345}