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

[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
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
  0 -> Terratec Cinergy 250 USB                            [0ccd:0036]
  1 -> Pinnacle PCTV USB 2                                 [2304:0208]
  2 -> Hauppauge WinTV USB 2                               [2040:4200]
  3 -> MSI VOX USB 2.0                                     [eb1a:2820]
  0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
  1 -> Unknown EM2820/2840 video grabber        (em2820/em2840) [eb1a:2820]
  2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
  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)
+113 −12
Original line number Diff line number Diff line
/*
   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>
                      Ludovico Cavedon <cavedon@sssup.it>
@@ -35,14 +35,43 @@

#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[] = {
	[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] = {
		.name         = "Terratec Cinergy 250 USB",
		.vchannels    = 3,
@@ -129,17 +158,88 @@ struct em2820_board em2820_boards[] = {
			.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 */
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_TERRATEC_CINERGY_200 }, */
	{ USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN },
	{ USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN },
	{ USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
	{ 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(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 },
	{ },
};

@@ -163,6 +263,7 @@ void em2820_card_setup(struct em2820 *dev)
}

EXPORT_SYMBOL(em2820_boards);
EXPORT_SYMBOL(em2820_bcount);
EXPORT_SYMBOL(em2820_id_table);

MODULE_DEVICE_TABLE (usb, em2820_id_table);
+12 −1
Original line number Diff line number Diff line
/*
   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>
                      Ludovico Cavedon <cavedon@sssup.it>
@@ -562,6 +562,11 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev,
	void *fieldstart, *startwrite, *startread;
	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)
		len =dev->field_size - (*f)->fieldbytesused;
	remain = len;
@@ -780,6 +785,11 @@ int em2820_set_alternate(struct em2820 *dev)
	dev->alt = alt;
	if (dev->alt == 0) {
		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 */
		em2820_coredbg("minimum isoc packet size: %u", min_pkt_size);
		dev->alt = 7;
@@ -789,6 +799,7 @@ int em2820_set_alternate(struct em2820 *dev)
			break;
			}
		}
	}

	if (dev->alt != prev_alt) {
		dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+159 −23
Original line number Diff line number Diff line
/*
   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>
                      Ludovico Cavedon <cavedon@sssup.it>
@@ -29,11 +29,6 @@
#include <media/tuner.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"

/* ----------------------------------------------------------- */
@@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
			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
 */
static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len,
			  int stop)
static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf,
				 short len, int stop)
{
	int wrcount = 0;
	struct em2820 *dev = (struct em2820 *)data;
@@ -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
 */
static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf,
			  int len)
static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr,
				 char *buf, int len)
{
	int ret;
	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,
}

/*
 * i2c_check_for_device()
 * em2820_i2c_check_for_device()
 * 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;
	int ret;
@@ -126,17 +242,24 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap,
			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
		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) {
				dprintk2(" no device\n");
				return rc;
			}

		}
		if (msgs[i].flags & I2C_M_RD) {
		} else if (msgs[i].flags & I2C_M_RD) {
			/* read bytes */

			rc = i2c_recv_bytes(dev, addr, msgs[i].buf,
			if (dev->is_em2800)
				rc = em2800_i2c_recv_bytes(dev, addr,
							   msgs[i].buf,
							   msgs[i].len);
			else
				rc = em2820_i2c_recv_bytes(dev, addr,
							   msgs[i].buf,
							   msgs[i].len);
			if (i2c_debug) {
				for (byte = 0; byte < msgs[i].len; byte++) {
@@ -149,7 +272,14 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap,
				for (byte = 0; byte < msgs[i].len; byte++)
					printk(" %02x", msgs[i].buf[byte]);
			}
			rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len,
			if (dev->is_em2800)
				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)
				goto err;
@@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len)
	int i, err, size = len, block;

	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;
	if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
		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)
		rc = i2c_master_recv(c, &buf, 0);
		if (rc < 0)
			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] : "???");
	}
}
+55 −18
Original line number Diff line number Diff line
/*
   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>
                      Ludovico Cavedon <cavedon@sssup.it>
@@ -50,6 +50,11 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
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;
module_param(tuner, int, 0444);
MODULE_PARM_DESC(tuner, "tuner type");
@@ -1081,7 +1086,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp,
			struct v4l2_cropcap *cc = arg;

			if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
				return EINVAL;
				return -EINVAL;
			cc->bounds.left = 0;
			cc->bounds.top = 0;
			cc->bounds.width = dev->width;
@@ -1520,21 +1525,12 @@ static struct file_operations em2820_v4l_fops = {
static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
			   int minor, int model)
{
	struct em2820 *dev;
	struct em2820 *dev = *devhandle;
	int retval = -ENOMEM;
	int errCode, i;
	unsigned int maxh, maxw;
	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->model = model;
	init_MUTEX(&dev->lock);
@@ -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_write_regs_req = em2820_write_regs_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_msp34xx = em2820_boards[model].has_msp34xx;
	dev->tda9887_conf = em2820_boards[model].tda9887_conf;
@@ -1595,7 +1592,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev,
	/* compute alternate max packet sizes */
	uif = dev->udev->actconfig->interface[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 =
		    le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
				wMaxPacketSize);
@@ -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",
		    dev->vdev->minor);

	*devhandle = dev;
	return 0;
}

@@ -1703,27 +1699,68 @@ static int em2820_usb_probe(struct usb_interface *interface,
	struct usb_device *udev;
	struct em2820 *dev = NULL;
	int retval = -ENODEV;
	int model,i,nr;

	udev = usb_get_dev(interface_to_usbdev(interface));
	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 */
	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
	    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;
	}
	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;
	}

	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 */
	retval = em2820_init_dev(&dev, udev, interface->minor, id->driver_info);
	retval = em2820_init_dev(&dev, udev, nr, model);
	if (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 */
	usb_set_intfdata(interface, dev);
Loading