/*
em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab <mchehab@infradead.org>
Sascha Sommer <saschasommer@freenet.de>
Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "em28xx.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#include <linux/jiffies.h>
#include "tuner-xc2028.h"
#include <media/v4l2-common.h>
#include <media/tuner.h>
/* ----------------------------------------------------------- */
static unsigned int i2c_scan;
module_param(i2c_scan, int, 0444);
MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
static unsigned int i2c_debug;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)");
#define dprintk(level, fmt, arg...) do { \
if (i2c_debug > level) \
dev_printk(KERN_DEBUG, &dev->intf->dev, \
"i2c: %s: " fmt, __func__, ## arg); \
} while (0)
/*
* em2800_i2c_send_bytes()
* send up to 4 bytes to the em2800 i2c device
*/
static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
{
unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
int ret;
u8 b2[6];
if (len < 1 || len > 4)
return -EOPNOTSUPP;
BUG_ON(len < 1 || len > 4);
b2[5] = 0x80 + len - 1;
b2[4] = addr;
b2[3] = buf[0];
if (len > 1)
b2[2] = buf[1];
if (len > 2)
b2[1] = buf[2];
if (len > 3)
b2[0] = buf[3];
/* trigger write */
ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
if (ret != 2 + len) {
dev_warn(&dev->intf->dev,
"failed to trigger write to i2c address 0x%x (error=%i)\n",
addr, ret);
return (ret < 0) ? ret : -EIO;
}
/* wait for completion */
while (time_is_after_jiffies(timeout)) {
ret = dev->em28xx_read_reg(dev, 0x05);
if (ret == 0x80 + len - 1)
return len;
if (ret == 0x94 + len - 1) {
dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", ret);
return -ENXIO;
}
if (ret < 0) {
dev_warn(&dev->intf->dev,
"failed to get i2c transfer status from bridge register (error=%i)\n",
ret);
return ret;
}
msleep(5);
}
dprintk(0, "write to i2c device at 0x%x timed out\n", addr);
return -ETIMEDOUT;
}
/*
* em2800_i2c_recv_bytes()
* read up to 4 bytes from the em2800 i2c device
*/
static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
{
unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
u8 buf2[4];
int ret;
int i;
if (len < 1 || len > 4)
return -EOPNOTSUPP;
/* trigger read */
buf2[1] = 0x84 + len - 1;
buf2[0] = addr;
ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
if (ret != 2) {
dev_warn(&dev->intf->dev,
"failed to trigger read from i2c address 0x%x (error=%i)\n",
addr, ret);
return (ret < 0) ? ret : -EIO;
}
/* wait for completion */
while (time_is_after_jiffies(timeout)) {
ret = dev->em28xx_read_reg(dev, 0x05);
if (ret == 0x84