Commit 596d92d5 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab Committed by Linus Torvalds

[PATCH] v4l: 767: included support for em2800

- Included support for em2800.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2b5200a7
0 -> Terratec Cinergy 250 USB [0ccd:0036] 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
1 -> Pinnacle PCTV USB 2 [2304:0208] 1 -> Unknown EM2820/2840 video grabber (em2820/em2840) [eb1a:2820]
2 -> Hauppauge WinTV USB 2 [2040:4200] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
3 -> MSI VOX USB 2.0 [eb1a:2820] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200]
5 -> MSI VOX USB 2.0 (em2820/em2840)
6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800)
/* /*
em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it> Ludovico Cavedon <cavedon@sssup.it>
...@@ -35,14 +35,43 @@ ...@@ -35,14 +35,43 @@
#include "em2820.h" #include "em2820.h"
enum em2820_board_entry {
EM2820_BOARD_TERRATEC_CINERGY_250,
EM2820_BOARD_PINNACLE_USB_2,
EM2820_BOARD_HAUPPAUGE_WINTV_USB_2,
EM2820_BOARD_MSI_VOX_USB_2
};
struct em2820_board em2820_boards[] = { struct em2820_board em2820_boards[] = {
[EM2800_BOARD_UNKNOWN] = {
.name = "Unknown EM2800 video grabber",
.is_em2800 = 1,
.vchannels = 2,
.norm = VIDEO_MODE_PAL,
.tda9887_conf = TDA9887_PRESENT,
.has_tuner = 1,
.decoder = EM2820_SAA7113,
.input = {{
.type = EM2820_VMUX_COMPOSITE1,
.vmux = 0,
.amux = 1,
},{
.type = EM2820_VMUX_SVIDEO,
.vmux = 9,
.amux = 1,
}},
},
[EM2820_BOARD_UNKNOWN] = {
.name = "Unknown EM2820/2840 video grabber",
.is_em2800 = 0,
.vchannels = 2,
.norm = VIDEO_MODE_PAL,
.tda9887_conf = TDA9887_PRESENT,
.has_tuner = 1,
.decoder = EM2820_SAA7113,
.input = {{
.type = EM2820_VMUX_COMPOSITE1,
.vmux = 0,
.amux = 1,
},{
.type = EM2820_VMUX_SVIDEO,
.vmux = 9,
.amux = 1,
}},
},
[EM2820_BOARD_TERRATEC_CINERGY_250] = { [EM2820_BOARD_TERRATEC_CINERGY_250] = {
.name = "Terratec Cinergy 250 USB", .name = "Terratec Cinergy 250 USB",
.vchannels = 3, .vchannels = 3,
...@@ -129,17 +158,88 @@ struct em2820_board em2820_boards[] = { ...@@ -129,17 +158,88 @@ struct em2820_board em2820_boards[] = {
.amux = 1, .amux = 1,
}}, }},
}, },
{ } /* Terminating entry */ [EM2800_BOARD_TERRATEC_CINERGY_200] = {
.name = "Terratec Cinergy 200 USB",
.chip_id = 0x4,
.is_em2800 = 1,
.vchannels = 3,
.norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
.has_tuner = 1,
.decoder = EM2820_SAA7113,
.input = {{
.type = EM2820_VMUX_TELEVISION,
.vmux = 2,
.amux = 0,
},{
.type = EM2820_VMUX_COMPOSITE1,
.vmux = 0,
.amux = 1,
},{
.type = EM2820_VMUX_SVIDEO,
.vmux = 9,
.amux = 1,
}},
},
[EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
.name = "Leadtek Winfast USB II",
.chip_id = 0x2,
.is_em2800 = 1,
.vchannels = 3,
.norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tda9887_conf = TDA9887_PRESENT,
.has_tuner = 1,
.decoder = EM2820_SAA7113,
.input = {{
.type = EM2820_VMUX_TELEVISION,
.vmux = 2,
.amux = 0,
},{
.type = EM2820_VMUX_COMPOSITE1,
.vmux = 0,
.amux = 1,
},{
.type = EM2820_VMUX_SVIDEO,
.vmux = 9,
.amux = 1,
}},
},
[EM2800_BOARD_KWORLD_USB2800] = {
.name = "Kworld USB2800",
.chip_id = 0x7,
.is_em2800 = 1,
.vchannels = 3,
.norm = VIDEO_MODE_PAL,
.tuner_type = TUNER_PHILIPS_ATSC,
.tda9887_conf = TDA9887_PRESENT,
.has_tuner = 1,
.decoder = EM2820_SAA7113,
.input = {{
.type = EM2820_VMUX_TELEVISION,
.vmux = 2,
.amux = 0,
},{
.type = EM2820_VMUX_COMPOSITE1,
.vmux = 0,
.amux = 1,
},{
.type = EM2820_VMUX_SVIDEO,
.vmux = 9,
.amux = 1,
}},
},
}; };
const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards);
/* table of devices that work with this driver */ /* table of devices that work with this driver */
struct usb_device_id em2820_id_table [] = { struct usb_device_id em2820_id_table [] = {
/* Terratec Cinerhy 200 USB: em2800 nor supported, at the moment */ { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN },
/* { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_TERRATEC_CINERGY_200 }, */ { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN },
{ USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
{ USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
{ USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
{ USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 },
{ }, { },
}; };
...@@ -163,6 +263,7 @@ void em2820_card_setup(struct em2820 *dev) ...@@ -163,6 +263,7 @@ void em2820_card_setup(struct em2820 *dev)
} }
EXPORT_SYMBOL(em2820_boards); EXPORT_SYMBOL(em2820_boards);
EXPORT_SYMBOL(em2820_bcount);
EXPORT_SYMBOL(em2820_id_table); EXPORT_SYMBOL(em2820_id_table);
MODULE_DEVICE_TABLE (usb, em2820_id_table); MODULE_DEVICE_TABLE (usb, em2820_id_table);
/* /*
em2820-core.c - driver for Empia EM2820/2840 USB video capture devices em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it> Ludovico Cavedon <cavedon@sssup.it>
...@@ -562,6 +562,11 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, ...@@ -562,6 +562,11 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev,
void *fieldstart, *startwrite, *startread; void *fieldstart, *startwrite, *startread;
int linesdone, currlinedone, offset, lencopy,remain; int linesdone, currlinedone, offset, lencopy,remain;
if(dev->frame_size != (*f)->buf.length){
em2820_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
return;
}
if ((*f)->fieldbytesused + len > dev->field_size) if ((*f)->fieldbytesused + len > dev->field_size)
len =dev->field_size - (*f)->fieldbytesused; len =dev->field_size - (*f)->fieldbytesused;
remain = len; remain = len;
...@@ -780,6 +785,11 @@ int em2820_set_alternate(struct em2820 *dev) ...@@ -780,6 +785,11 @@ int em2820_set_alternate(struct em2820 *dev)
dev->alt = alt; dev->alt = alt;
if (dev->alt == 0) { if (dev->alt == 0) {
int i; int i;
if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */
for(i=0;i< EM2820_MAX_ALT; i++)
if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt])
dev->alt=i;
}else{
unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */
em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); em2820_coredbg("minimum isoc packet size: %u", min_pkt_size);
dev->alt = 7; dev->alt = 7;
...@@ -788,6 +798,7 @@ int em2820_set_alternate(struct em2820 *dev) ...@@ -788,6 +798,7 @@ int em2820_set_alternate(struct em2820 *dev)
dev->alt = i; dev->alt = i;
break; break;
} }
}
} }
if (dev->alt != prev_alt) { if (dev->alt != prev_alt) {
......
/* /*
em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it> Ludovico Cavedon <cavedon@sssup.it>
...@@ -29,11 +29,6 @@ ...@@ -29,11 +29,6 @@
#include <media/tuner.h> #include <media/tuner.h>
#include <linux/video_decoder.h> #include <linux/video_decoder.h>
/* To be moved to compat.h */
#if !defined(I2C_HW_B_EM2820)
#define I2C_HW_B_EM2820 0x99
#endif
#include "em2820.h" #include "em2820.h"
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
...@@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); ...@@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
printk(fmt , ##args); } while (0) printk(fmt , ##args); } while (0)
/* /*
* i2c_send_bytes() * em2800_i2c_send_max4()
* send up to 4 bytes to the i2c device
*/
static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr,
char *buf, int len)
{
int ret;
int write_timeout;
unsigned char b2[6];
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];
ret = dev->em2820_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
if (ret != 2 + len) {
em2820_warn("writting to i2c device failed (error=%i)\n", ret);
return -EIO;
}
for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
write_timeout -= 5) {
ret = dev->em2820_read_reg(dev, 0x05);
if (ret == 0x80 + len - 1)
return len;
mdelay(5);
}
em2820_warn("i2c write timed out\n");
return -EIO;
}
/*
* em2800_i2c_send_bytes()
*/
static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
short len)
{
char *bufPtr = buf;
int ret;
int wrcount = 0;
int count;
int maxLen = 4;
struct em2820 *dev = (struct em2820 *)data;
while (len > 0) {
count = (len > maxLen) ? maxLen : len;
ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
if (ret > 0) {
len -= count;
bufPtr += count;
wrcount += count;
} else
return (ret < 0) ? ret : -EFAULT;
}
return wrcount;
}
/*
* em2800_i2c_check_for_device()
* check if there is a i2c_device at the supplied address
*/
static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr)
{
char msg;
int ret;
int write_timeout;
msg = addr;
ret = dev->em2820_write_regs(dev, 0x04, &msg, 1);
if (ret < 0) {
em2820_warn("setting i2c device address failed (error=%i)\n",
ret);
return ret;
}
msg = 0x84;
ret = dev->em2820_write_regs(dev, 0x05, &msg, 1);
if (ret < 0) {
em2820_warn("preparing i2c read failed (error=%i)\n", ret);
return ret;
}
for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
write_timeout -= 5) {
unsigned msg = dev->em2820_read_reg(dev, 0x5);
if (msg == 0x94)
return -ENODEV;
else if (msg == 0x84)
return 0;
mdelay(5);
}
return -ENODEV;
}
/*
* em2800_i2c_recv_bytes()
* read from the i2c device
*/
static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr,
char *buf, int len)
{
int ret;
/* check for the device and set i2c read address */
ret = em2800_i2c_check_for_device(dev, addr);
if (ret) {
em2820_warn
("preparing read at i2c address 0x%x failed (error=%i)\n",
addr, ret);
return ret;
}
ret = dev->em2820_read_reg_req_len(dev, 0x0, 0x3, buf, len);
if (ret < 0) {
em2820_warn("reading from i2c device at 0x%x failed (error=%i)",
addr, ret);
return ret;
}
return ret;
}
/*
* em2820_i2c_send_bytes()
* untested for more than 4 bytes * untested for more than 4 bytes
*/ */
static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf,
int stop) short len, int stop)
{ {
int wrcount = 0; int wrcount = 0;
struct em2820 *dev = (struct em2820 *)data; struct em2820 *dev = (struct em2820 *)data;
...@@ -71,11 +187,11 @@ static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, ...@@ -71,11 +187,11 @@ static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len,
} }
/* /*
* i2c_recv_byte() * em2820_i2c_recv_bytes()
* read a byte from the i2c device * read a byte from the i2c device
*/ */
static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr,
int len) char *buf, int len)
{ {
int ret; int ret;
ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len);
...@@ -89,10 +205,10 @@ static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, ...@@ -89,10 +205,10 @@ static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf,
} }
/* /*
* i2c_check_for_device() * em2820_i2c_check_for_device()
* check if there is a i2c_device at the supplied address * check if there is a i2c_device at the supplied address
*/ */
static int i2c_check_for_device(struct em2820 *dev, unsigned char addr) static int em2820_i2c_check_for_device(struct em2820 *dev, unsigned char addr)
{ {
char msg; char msg;
int ret; int ret;
...@@ -126,18 +242,25 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -126,18 +242,25 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap,
(msgs[i].flags & I2C_M_RD) ? "read" : "write", (msgs[i].flags & I2C_M_RD) ? "read" : "write",
i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
if (!msgs[i].len) { /* no len: check only for device presence */ if (!msgs[i].len) { /* no len: check only for device presence */
rc = i2c_check_for_device(dev, addr); if (dev->is_em2800)
rc = em2800_i2c_check_for_device(dev, addr);
else
rc = em2820_i2c_check_for_device(dev, addr);
if (rc < 0) { if (rc < 0) {
dprintk2(" no device\n"); dprintk2(" no device\n");
return rc; return rc;
} }
} } else if (msgs[i].flags & I2C_M_RD) {
if (msgs[i].flags & I2C_M_RD) {
/* read bytes */ /* read bytes */
if (dev->is_em2800)
rc = i2c_recv_bytes(dev, addr, msgs[i].buf, rc = em2800_i2c_recv_bytes(dev, addr,
msgs[i].len); msgs[i].buf,
msgs[i].len);
else
rc = em2820_i2c_recv_bytes(dev, addr,
msgs[i].buf,
msgs[i].len);
if (i2c_debug) { if (i2c_debug) {
for (byte = 0; byte < msgs[i].len; byte++) { for (byte = 0; byte < msgs[i].len; byte++) {
printk(" %02x", msgs[i].buf[byte]); printk(" %02x", msgs[i].buf[byte]);
...@@ -149,8 +272,15 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -149,8 +272,15 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap,
for (byte = 0; byte < msgs[i].len; byte++) for (byte = 0; byte < msgs[i].len; byte++)
printk(" %02x", msgs[i].buf[byte]); printk(" %02x", msgs[i].buf[byte]);
} }
rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, if (dev->is_em2800)
i == num - 1); rc = em2800_i2c_send_bytes(dev, addr,
msgs[i].buf,
msgs[i].len);
else
rc = em2820_i2c_send_bytes(dev, addr,
msgs[i].buf,
msgs[i].len,
i == num - 1);
if (rc < 0) if (rc < 0)
goto err; goto err;
} }
...@@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) ...@@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len)
int i, err, size = len, block; int i, err, size = len, block;
dev->i2c_client.addr = 0xa0 >> 1; dev->i2c_client.addr = 0xa0 >> 1;
/* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0)
return -1;
buf = 0; buf = 0;
if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
...@@ -389,7 +525,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) ...@@ -389,7 +525,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
rc = i2c_master_recv(c, &buf, 0); rc = i2c_master_recv(c, &buf, 0);
if (rc < 0) if (rc < 0)
continue; continue;
printk(KERN_INFO "%s: found device @ 0x%x [%s]", name, printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name,
i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
} }
} }
......
/* /*
em2820-video.c - driver for Empia EM2820/2840 USB video capture devices em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it> Ludovico Cavedon <cavedon@sssup.it>
...@@ -50,6 +50,11 @@ MODULE_AUTHOR(DRIVER_AUTHOR); ...@@ -50,6 +50,11 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned int card[] = {[0 ... (EM2820_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card,"card type");
static int tuner = -1; static int tuner = -1;
module_param(tuner, int, 0444); module_param(tuner, int, 0444);
MODULE_PARM_DESC(tuner, "tuner type"); MODULE_PARM_DESC(tuner, "tuner type");
...@@ -1081,7 +1086,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, ...@@ -1081,7 +1086,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp,
struct v4l2_cropcap *cc = arg; struct v4l2_cropcap *cc = arg;
if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return EINVAL; return -EINVAL;
cc->bounds.left = 0; cc->bounds.left = 0;
cc->bounds.top = 0; cc->bounds.top = 0;
cc->bounds.width = dev->width; cc->bounds.width = dev->width;
...@@ -1520,21 +1525,12 @@ static struct file_operations em2820_v4l_fops = { ...@@ -1520,21 +1525,12 @@ static struct file_operations em2820_v4l_fops = {
static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
int minor, int model) int minor, int model)
{ {
struct em2820 *dev; struct em2820 *dev = *devhandle;
int retval = -ENOMEM; int retval = -ENOMEM;
int errCode, i; int errCode, i;
unsigned int maxh, maxw; unsigned int maxh, maxw;
struct usb_interface *uif; struct usb_interface *uif;
/* allocate memory for our device state and initialize it */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em2820_err(DRIVER_NAME ": out of memory!\n");
return -ENOMEM;
}
memset(dev, 0x00, sizeof(*dev));
snprintf(dev->name, 29, "em2820 #%d", minor);
dev->udev = udev; dev->udev = udev;
dev->model = model; dev->model = model;
init_MUTEX(&dev->lock); init_MUTEX(&dev->lock);
...@@ -1545,6 +1541,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, ...@@ -1545,6 +1541,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
dev->em2820_read_reg_req_len = em2820_read_reg_req_len; dev->em2820_read_reg_req_len = em2820_read_reg_req_len;
dev->em2820_write_regs_req = em2820_write_regs_req; dev->em2820_write_regs_req = em2820_write_regs_req;
dev->em2820_read_reg_req = em2820_read_reg_req; dev->em2820_read_reg_req = em2820_read_reg_req;
dev->is_em2800 = em2820_boards[model].is_em2800;
dev->has_tuner = em2820_boards[model].has_tuner; dev->has_tuner = em2820_boards[model].has_tuner;
dev->has_msp34xx = em2820_boards[model].has_msp34xx; dev->has_msp34xx = em2820_boards[model].has_msp34xx;
dev->tda9887_conf = em2820_boards[model].tda9887_conf; dev->tda9887_conf = em2820_boards[model].tda9887_conf;
...@@ -1595,7 +1592,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, ...@@ -1595,7 +1592,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
/* compute alternate max packet sizes */ /* compute alternate max packet sizes */
uif = dev->udev->actconfig->interface[0]; uif = dev->udev->actconfig->interface[0];
dev->alt_max_pkt_size[0] = 0; dev->alt_max_pkt_size[0] = 0;
for (i = 1; i <= EM2820_MAX_ALT; i++) { for (i = 1; i <= EM2820_MAX_ALT && i < uif->num_altsetting ; i++) {
u16 tmp = u16 tmp =
le16_to_cpu(uif->altsetting[i].endpoint[1].desc. le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
wMaxPacketSize); wMaxPacketSize);
...@@ -1688,7 +1685,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, ...@@ -1688,7 +1685,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
em2820_info("V4L2 device registered as /dev/video%d\n", em2820_info("V4L2 device registered as /dev/video%d\n",
dev->vdev->minor); dev->vdev->minor);
*devhandle = dev;
return 0; return 0;
} }
...@@ -1703,27 +1699,68 @@ static int em2820_usb_probe(struct usb_interface *interface, ...@@ -1703,27 +1699,68 @@ static int em2820_usb_probe(struct usb_interface *interface,
struct usb_device *udev; struct usb_device *udev;
struct em2820 *dev = NULL; struct em2820 *dev = NULL;
int retval = -ENODEV; int retval = -ENODEV;
int model,i,nr;
udev = usb_get_dev(interface_to_usbdev(interface)); udev = usb_get_dev(interface_to_usbdev(interface));
endpoint = &interface->cur_altsetting->endpoint[1].desc; endpoint = &interface->cur_altsetting->endpoint[1].desc;
/* Don't register audio interfaces */
if (interface->altsetting[1].desc.bInterfaceClass == USB_CLASS_AUDIO)
return -ENODEV;
/* check if the the device has the iso in endpoint at the correct place */ /* check if the the device has the iso in endpoint at the correct place */
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_ISOC) { USB_ENDPOINT_XFER_ISOC) {
/* em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); */ em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
return -ENODEV; return -ENODEV;
} }
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
/* em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); */ em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
return -ENODEV; return -ENODEV;
} }
model=id->driver_info;
nr=interface->minor;
if (nr>EM2820_MAXBOARDS) {
printk ("em2820: Supports only %i em28xx boards.\n",EM2820_MAXBOARDS);
return -ENOMEM;
}
/* allocate memory for our device state and initialize it */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em2820_err(DRIVER_NAME ": out of memory!\n");
return -ENOMEM;
}
memset(dev, 0, sizeof(*dev));
snprintf(dev->name, 29, "em2820 #%d", nr);
if ((card[nr]>=0)&&(card[nr]<em2820_bcount))
model=card[nr];
if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) {
printk( "%s: Your board has no eeprom inside it and thus can't\n"
"%s: be autodetected. Please pass card=<n> insmod option to\n"
"%s: workaround that. Redirect complaints to the vendor of\n"
"%s: the TV card. Best regards,\n"
"%s: -- tux\n",
dev->name,dev->name,dev->name,dev->name,dev->name);
printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
dev->name);
for (i = 0; i < em2820_bcount; i++) {
printk("%s: card=%d -> %s\n",
dev->name, i, em2820_boards[i].name);
}
}
/* allocate device struct */ /* allocate device struct */
retval = em2820_init_dev(&dev, udev, interface->minor, id->driver_info); retval = em2820_init_dev(&dev, udev, nr, model);
if (retval) if (retval)
return retval; return retval;
em2820_info("Found %s\n", em2820_boards[id->driver_info].name); em2820_info("Found %s\n", em2820_boards[model].name);
/* save our data pointer in this interface device */ /* save our data pointer in this interface device */
usb_set_intfdata(interface, dev); usb_set_intfdata(interface, dev);
......
/* /*
em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it> Ludovico Cavedon <cavedon@sssup.it>
...@@ -28,6 +28,23 @@ ...@@ -28,6 +28,23 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/i2c.h> #include <linux/i2c.h>
/* Boards supported by driver */
#define EM2800_BOARD_UNKNOWN 0
#define EM2820_BOARD_UNKNOWN 1
#define EM2820_BOARD_TERRATEC_CINERGY_250 2
#define EM2820_BOARD_PINNACLE_USB_2 3
#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
#define EM2820_BOARD_MSI_VOX_USB_2 5
#define EM2800_BOARD_TERRATEC_CINERGY_200 6
#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
#define EM2800_BOARD_KWORLD_USB2800 8
#define UNSET -1
/* maximum number of em28xx boards */
#define EM2820_MAXBOARDS 1 /*FIXME: should be bigger */
/* maximum number of frames that can be queued */ /* maximum number of frames that can be queued */
#define EM2820_NUM_FRAMES 5 #define EM2820_NUM_FRAMES 5
/* number of frames that get used for v4l2_read() */ /* number of frames that get used for v4l2_read() */
...@@ -79,6 +96,9 @@ ...@@ -79,6 +96,9 @@
/* time to wait when stopping the isoc transfer */ /* time to wait when stopping the isoc transfer */
#define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) #define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS)
/* time in msecs to wait for i2c writes to finish */
#define EM2800_I2C_WRITE_TIMEOUT 20
/* the various frame states */ /* the various frame states */
enum em2820_frame_state { enum em2820_frame_state {
F_UNUSED = 0, F_UNUSED = 0,
...@@ -145,12 +165,13 @@ enum em2820_decoder { ...@@ -145,12 +165,13 @@ enum em2820_decoder {
struct em2820_board { struct em2820_board {
char *name; char *name;
unsigned char chip_id;
int vchannels; int vchannels;
int norm; int norm;
int tuner_type; int tuner_type;
/* i2c flags */ /* i2c flags */
unsigned int is_em2800;
unsigned int tda9887_conf; unsigned int tda9887_conf;
unsigned int has_tuner:1; unsigned int has_tuner:1;
...@@ -195,6 +216,7 @@ struct em2820 { ...@@ -195,6 +216,7 @@ struct em2820 {
/* generic device properties */ /* generic device properties */
char name[30]; /* name (including minor) of the device */ char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */ int model; /* index in the device_data struct */
unsigned int is_em2800;
int video_inputs; /* number of video inputs */ int video_inputs; /* number of video inputs */
unsigned int has_tuner:1; unsigned int has_tuner:1;
unsigned int has_msp34xx:1; unsigned int has_msp34xx:1;
...@@ -304,11 +326,14 @@ void em2820_uninit_isoc(struct em2820 *dev); ...@@ -304,11 +326,14 @@ void em2820_uninit_isoc(struct em2820 *dev);
int em2820_set_alternate(struct em2820 *dev); int em2820_set_alternate(struct em2820 *dev);
/* Provided by em2820-cards.c */ /* Provided by em2820-cards.c */
extern int em2800_variant_detect(struct usb_device* udev,int model);
extern void em2820_card_setup(struct em2820 *dev); extern void em2820_card_setup(struct em2820 *dev);
extern struct em2820_board em2820_boards[]; extern struct em2820_board em2820_boards[];
extern struct usb_device_id em2820_id_table[]; extern struct usb_device_id em2820_id_table[];
extern const unsigned int em2820_bcount;
/* em2820 registers */ /* em2820 registers */
#define CHIPID_REG 0x0a
#define USBSUSP_REG 0x0c /* */ #define USBSUSP_REG 0x0c /* */
#define AUDIOSRC_REG 0x0e #define AUDIOSRC_REG 0x0e
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment