summary refs log tree commit diff
path: root/drivers/media
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-02-14 17:08:37 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:43:01 -0300
commit5811cf99df2e3c102055be3ea77508e56c9f77c6 (patch)
tree75be74b5072280edadeee2c1f6c42f5e961c208c /drivers/media
parent1a2670465ec94029e5df62e3decca9e2f7aea075 (diff)
downloadlinux-5811cf99df2e3c102055be3ea77508e56c9f77c6.tar.gz
V4L/DVB (10756): cx18: Slim down instance handling, build names from v4l2_device.name
Convert card instance handling to a lighter weight mechanism like ivtv.
Also convert name strings and debug messages to use v4l2_device.name.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/cx18/cx18-driver.c107
-rw-r--r--drivers/media/video/cx18/cx18-driver.h27
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c35
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c10
-rw-r--r--drivers/media/video/cx18/cx18-streams.c9
6 files changed, 71 insertions, 119 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 2a45bbc757e8..f69e688ab6f4 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -39,10 +39,6 @@
 
 #include <media/tveeprom.h>
 
-
-/* var to keep track of the number of array elements in use */
-int cx18_cards_active;
-
 /* If you have already X v4l cards, then set this to X. This way
    the device numbers stay matched. Example: you have a WinTV card
    without radio and a Compro H900 with. Normally this would give a
@@ -50,12 +46,6 @@ int cx18_cards_active;
    setting this to 1 you ensure that radio0 is now also radio1. */
 int cx18_first_minor;
 
-/* Master variable for all cx18 info */
-struct cx18 *cx18_cards[CX18_MAX_CARDS];
-
-/* Protects cx18_cards_active */
-DEFINE_SPINLOCK(cx18_cards_lock);
-
 /* add your revision and whatnot here */
 static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
 	{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
@@ -65,6 +55,8 @@ static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
 
+static atomic_t cx18_instance = ATOMIC_INIT(0);
+
 /* Parameter declarations */
 static int cardtype[CX18_MAX_CARDS];
 static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
@@ -491,9 +483,9 @@ static void cx18_process_options(struct cx18 *cx)
 		cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */
 	}
 
-	cx->options.cardtype = cardtype[cx->num];
-	cx->options.tuner = tuner[cx->num];
-	cx->options.radio = radio[cx->num];
+	cx->options.cardtype = cardtype[cx->instance];
+	cx->options.tuner = tuner[cx->instance];
+	cx->options.radio = radio[cx->instance];
 
 	cx->std = cx18_parse_std(cx);
 	if (cx->options.cardtype == -1) {
@@ -550,7 +542,7 @@ done:
 }
 
 /* Precondition: the cx18 structure has been memset to 0. Only
-   the dev and num fields have been filled in.
+   the dev and instance fields have been filled in.
    No assumptions on the card type may be made here (see cx18_init_struct2
    for that).
  */
@@ -567,7 +559,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
 	mutex_init(&cx->epu2apu_mb_lock);
 	mutex_init(&cx->epu2cpu_mb_lock);
 
-	cx->work_queue = create_singlethread_workqueue(cx->name);
+	cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
 	if (cx->work_queue == NULL) {
 		CX18_ERR("Unable to create work hander thread\n");
 		return -ENOMEM;
@@ -647,15 +639,16 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
 	CX18_DEBUG_INFO("Enabling pci device\n");
 
 	if (pci_enable_device(pci_dev)) {
-		CX18_ERR("Can't enable device %d!\n", cx->num);
+		CX18_ERR("Can't enable device %d!\n", cx->instance);
 		return -EIO;
 	}
 	if (pci_set_dma_mask(pci_dev, 0xffffffff)) {
-		CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
+		CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
 		return -EIO;
 	}
 	if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
-		CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
+		CX18_ERR("Cannot request encoder memory region, card %d\n",
+			 cx->instance);
 		return -EIO;
 	}
 
@@ -741,44 +734,42 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
 	u32 devtype;
 	struct cx18 *cx;
 
-	spin_lock(&cx18_cards_lock);
-
-	/* Make sure we've got a place for this card */
-	if (cx18_cards_active == CX18_MAX_CARDS) {
-		printk(KERN_ERR "cx18:  Maximum number of cards detected (%d).\n",
-			      cx18_cards_active);
-		spin_unlock(&cx18_cards_lock);
+	/* FIXME - module parameter arrays constrain max instances */
+	i = atomic_inc_return(&cx18_instance) - 1;
+	if (i >= CX18_MAX_CARDS) {
+		printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
+		       "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
 		return -ENOMEM;
 	}
 
 	cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-	if (!cx) {
-		spin_unlock(&cx18_cards_lock);
+	if (cx == NULL) {
+		printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
+		       i);
 		return -ENOMEM;
 	}
-	cx18_cards[cx18_cards_active] = cx;
-	cx->num = cx18_cards_active++;
-	snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
-	CX18_INFO("Initializing card #%d\n", cx->num);
-
-	spin_unlock(&cx18_cards_lock);
-
 	cx->pci_dev = pci_dev;
+	cx->instance = i;
+
 	retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
 	if (retval) {
-		CX18_ERR("Call to v4l2_device_register() failed\n");
-		goto err;
+		printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
+		       "\n", cx->instance);
+		kfree(cx);
+		return retval;
 	}
-	CX18_DEBUG_INFO("registered v4l2_device name: %s\n", cx->v4l2_dev.name);
+	snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
+		 cx->instance);
+	CX18_INFO("Initializing card %d\n", cx->instance);
 
 	cx18_process_options(cx);
 	if (cx->options.cardtype == -1) {
 		retval = -ENODEV;
-		goto unregister_v4l2;
+		goto err;
 	}
 	if (cx18_init_struct1(cx)) {
 		retval = -ENOMEM;
-		goto unregister_v4l2;
+		goto err;
 	}
 
 	CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
@@ -829,8 +820,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
 		goto free_map;
 	}
 
-	CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
-
 	if (cx->card->hw_all & CX18_HW_TVEEPROM) {
 		/* Based on the model number the cardtype may be changed.
 		   The PCI IDs are not always reliable. */
@@ -847,7 +836,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
 
 	/* Register IRQ */
 	retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
-			     IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
+			     IRQF_SHARED | IRQF_DISABLED,
+			     cx->v4l2_dev.name, (void *)cx);
 	if (retval) {
 		CX18_ERR("Failed to register irq %d\n", retval);
 		goto free_i2c;
@@ -933,8 +923,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
 		goto free_streams;
 	}
 
-	CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
-
+	CX18_INFO("Initialized card: %s\n", cx->card_name);
 	return 0;
 
 free_streams:
@@ -949,18 +938,13 @@ free_mem:
 	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 free_workqueue:
 	destroy_workqueue(cx->work_queue);
-unregister_v4l2:
-	v4l2_device_unregister(&cx->v4l2_dev);
 err:
 	if (retval == 0)
 		retval = -ENODEV;
 	CX18_ERR("Error %d on initialization\n", retval);
 
-	i = cx->num;
-	spin_lock(&cx18_cards_lock);
-	kfree(cx18_cards[i]);
-	cx18_cards[i] = NULL;
-	spin_unlock(&cx18_cards_lock);
+	v4l2_device_unregister(&cx->v4l2_dev);
+	kfree(cx);
 	return retval;
 }
 
@@ -1069,9 +1053,9 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx)
 static void cx18_remove(struct pci_dev *pci_dev)
 {
 	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-	struct cx18 *cx = container_of(v4l2_dev, struct cx18, v4l2_dev);
+	struct cx18 *cx = to_cx18(v4l2_dev);
 
-	CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+	CX18_DEBUG_INFO("Removing Card\n");
 
 	/* Stop all captures */
 	CX18_DEBUG_INFO("Stopping all streams\n");
@@ -1099,10 +1083,12 @@ static void cx18_remove(struct pci_dev *pci_dev)
 	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 
 	pci_disable_device(cx->pci_dev);
+	/* FIXME - we leak cx->vbi.sliced_mpeg_data[i] allocations */
 
-	v4l2_device_unregister(v4l2_dev);
+	CX18_INFO("Removed %s\n", cx->card_name);
 
-	CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+	v4l2_device_unregister(v4l2_dev);
+	kfree(cx);
 }
 
 /* define a pci_driver for card detection */
@@ -1117,8 +1103,6 @@ static int module_start(void)
 {
 	printk(KERN_INFO "cx18:  Start initialization, version %s\n", CX18_VERSION);
 
-	memset(cx18_cards, 0, sizeof(cx18_cards));
-
 	/* Validate parameters */
 	if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
 		printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
@@ -1141,16 +1125,7 @@ static int module_start(void)
 
 static void module_cleanup(void)
 {
-	int i;
-
 	pci_unregister_driver(&cx18_pci_driver);
-
-	for (i = 0; i < cx18_cards_active; i++) {
-		if (cx18_cards[i] == NULL)
-			continue;
-		kfree(cx18_cards[i]);
-	}
-
 }
 
 module_init(module_start);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 7fc914c521f7..def82bd1078a 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -144,12 +144,12 @@
 /* Flag to turn on high volume debugging */
 #define CX18_DBGFLG_HIGHVOL (1 << 8)
 
-/* NOTE: extra space before comma in 'cx->num , ## args' is required for
+/* NOTE: extra space before comma in 'fmt , ## args' is required for
    gcc-2.95, otherwise it won't compile. */
 #define CX18_DEBUG(x, type, fmt, args...) \
 	do { \
 		if ((x) & cx18_debug) \
-			printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
+			v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
 	} while (0)
 #define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
@@ -163,7 +163,7 @@
 #define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
 	do { \
 		if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
-			printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
+			v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
 	} while (0)
 #define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
@@ -175,9 +175,9 @@
 #define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
 
 /* Standard kernel messages */
-#define CX18_ERR(fmt, args...)      printk(KERN_ERR  "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_WARN(fmt, args...)     printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_INFO(fmt, args...)     printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_ERR(fmt, args...)      v4l2_err(&cx->v4l2_dev, fmt , ## args)
+#define CX18_WARN(fmt, args...)     v4l2_warn(&cx->v4l2_dev, fmt , ## args)
+#define CX18_INFO(fmt, args...)     v4l2_info(&cx->v4l2_dev, fmt , ## args)
 
 /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
 #define MPEG_FRAME_TYPE_IFRAME 1
@@ -445,8 +445,7 @@ struct cx18_i2c_algo_callback_data {
 
 /* Struct to hold info about cx18 cards */
 struct cx18 {
-	int num;		/* board number, -1 during init! */
-	char name[8];		/* board name for printk and interrupts (e.g. 'cx180') */
+	int instance;
 	struct pci_dev *pci_dev;
 	struct v4l2_device v4l2_dev;
 
@@ -455,8 +454,8 @@ struct cx18 {
 	const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
 	u8 is_50hz;
 	u8 is_60hz;
-	u8 is_out_50hz;
-	u8 is_out_60hz;
+	u8 is_out_50hz; /* FIXME - remove, we don't have an output decoder */
+	u8 is_out_60hz; /* FIXME - remove, we don't have an output decoder */
 	u8 nof_inputs;		/* number of video inputs */
 	u8 nof_audio_inputs;	/* number of audio inputs */
 	u16 buffer_id;		/* buffer ID counter */
@@ -547,11 +546,13 @@ struct cx18 {
 	v4l2_std_id tuner_std;	/* The norm of the tuner (fixed) */
 };
 
+static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx18, v4l2_dev);
+}
+
 /* Globals */
-extern struct cx18 *cx18_cards[];
-extern int cx18_cards_active;
 extern int cx18_first_minor;
-extern spinlock_t cx18_cards_lock;
 
 /*==============Prototypes==================*/
 
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 68dd50ac4bfe..757982ea3766 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -682,38 +682,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
 
 int cx18_v4l2_open(struct file *filp)
 {
-	int res, x, y = 0;
-	struct cx18 *cx = NULL;
-	struct cx18_stream *s = NULL;
-	int minor = video_devdata(filp)->minor;
-
-	/* Find which card this open was on */
-	spin_lock(&cx18_cards_lock);
-	for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
-		/* find out which stream this open was on */
-		for (y = 0; y < CX18_MAX_STREAMS; y++) {
-			if (cx18_cards[x] == NULL)
-				continue;
-			s = &cx18_cards[x]->streams[y];
-			if (s->video_dev && s->video_dev->minor == minor) {
-				cx = cx18_cards[x];
-				break;
-			}
-		}
-	}
-	spin_unlock(&cx18_cards_lock);
-
-	if (cx == NULL) {
-		/* Couldn't find a device registered
-		   on that minor, shouldn't happen! */
-		printk(KERN_WARNING "No cx18 device found on minor %d\n",
-				minor);
-		return -ENXIO;
-	}
+	int res;
+	struct video_device *video_dev = video_devdata(filp);
+	struct cx18_stream *s = video_get_drvdata(video_dev);
+	struct cx18 *cx = s->cx;;
 
 	mutex_lock(&cx->serialize_lock);
 	if (cx18_init_on_first_open(cx)) {
-		CX18_ERR("Failed to initialize on minor %d\n", minor);
+		CX18_ERR("Failed to initialize on minor %d\n",
+			 video_dev->minor);
 		mutex_unlock(&cx->serialize_lock);
 		return -ENXIO;
 	}
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 200d9257a926..db2c3e6997d0 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -358,7 +358,7 @@ int init_cx18_i2c(struct cx18 *cx)
 		cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
 
 		sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
-				" #%d-%d", cx->num, i);
+				" #%d-%d", cx->instance, i);
 		i2c_set_adapdata(&cx->i2c_adap[i], cx);
 
 		memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 5c8e9cb244f9..3277b3d3ceae 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -387,20 +387,17 @@ static int cx18_g_chip_ident(struct file *file, void *fh,
 static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 {
 	struct v4l2_dbg_register *regs = arg;
-	unsigned long flags;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
 		return -EINVAL;
 
-	spin_lock_irqsave(&cx18_cards_lock, flags);
 	regs->size = 4;
 	if (cmd == VIDIOC_DBG_G_REGISTER)
 		regs->val = cx18_read_enc(cx, regs->reg);
 	else
 		cx18_write_enc(cx, regs->val, regs->reg);
-	spin_unlock_irqrestore(&cx18_cards_lock, flags);
 	return 0;
 }
 
@@ -847,7 +844,7 @@ static int cx18_log_status(struct file *file, void *fh)
 	int i;
 
 	CX18_INFO("=================  START STATUS CARD #%d  "
-		  "=================\n", cx->num);
+		  "=================\n", cx->instance);
 	CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
 	if (cx->hw_flags & CX18_HW_TVEEPROM) {
 		struct tveeprom tv;
@@ -865,7 +862,7 @@ static int cx18_log_status(struct file *file, void *fh)
 	mutex_unlock(&cx->gpio_lock);
 	CX18_INFO("Tuner: %s\n",
 		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
-	cx2341x_log_status(&cx->params, cx->name);
+	cx2341x_log_status(&cx->params, cx->v4l2_dev.name);
 	CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
 	for (i = 0; i < CX18_MAX_STREAMS; i++) {
 		struct cx18_stream *s = &cx->streams[i];
@@ -880,7 +877,8 @@ static int cx18_log_status(struct file *file, void *fh)
 	CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
 			(long long)cx->mpg_data_received,
 			(long long)cx->vbi_data_inserted);
-	CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
+	CX18_INFO("==================  END STATUS CARD #%d  "
+		  "==================\n", cx->instance);
 	return 0;
 }
 
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 778aa0c0f9b5..eff4a14d0152 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -130,7 +130,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 	struct cx18_stream *s = &cx->streams[type];
 	u32 cap = cx->v4l2_cap;
 	int num_offset = cx18_stream_info[type].num_offset;
-	int num = cx->num + cx18_first_minor + num_offset;
+	int num = cx->instance + cx18_first_minor + num_offset;
 
 	/* These four fields are always initialized. If video_dev == NULL, then
 	   this stream is not in use. In that case no other fields but these
@@ -170,11 +170,11 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 		return -ENOMEM;
 	}
 
-	snprintf(s->video_dev->name, sizeof(s->video_dev->name), "cx18-%d",
-			cx->num);
+	snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+		 cx->v4l2_dev.name, s->name);
 
 	s->video_dev->num = num;
-	s->video_dev->parent = &cx->pci_dev->dev;
+	s->video_dev->v4l2_dev = &cx->v4l2_dev;
 	s->video_dev->fops = &cx18_v4l2_enc_fops;
 	s->video_dev->release = video_device_release;
 	s->video_dev->tvnorms = V4L2_STD_ALL;
@@ -239,6 +239,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
 			num = s_mpg->video_dev->num
 			    + cx18_stream_info[type].num_offset;
 	}
+	video_set_drvdata(s->video_dev, s);
 
 	/* Register device. First try the desired minor, then any free one. */
 	ret = video_register_device(s->video_dev, vfl_type, num);