linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168)
       [not found]       ` <20030925102635.GA25634@polyware.nl>
@ 2003-09-25 15:59         ` Ronald Bultje
  2003-09-25 16:10           ` Christoph Hellwig
  2003-09-25 16:43           ` Gerd Knorr
  0 siblings, 2 replies; 4+ messages in thread
From: Ronald Bultje @ 2003-09-25 15:59 UTC (permalink / raw)
  To: Pauline Middelink; +Cc: linux-kernel, kraxel

[-- Attachment #1: Type: text/plain, Size: 1709 bytes --]

Hi Pauline,

[CC: to kernel, since it matters a bit there...]

On Thu, 2003-09-25 at 12:26, Pauline Middelink wrote:
> Regarding the patch: would be nice.

It was easier than I thought (all code is in zr36120.c, the i2c
(zr36120_i2c.c) was a piece of cake and zr36120_mem.c is untouched). See
attachment. I have no clue whether it works, but this is how my driver
does it.

Changes:
* move to new i2c
* move to new videodev
* implement a zoran_vdev_release() function to free memory after it's no
longer in use (this is a hack imo, but it's the suggested way of doing
it... There was an article somewhere about it and it's also been
discussed on the v4l mailinglist... Can't find a link, though)
* proper module use-counting
* changed a __put_user() call somewhere because it failed to compile
here - not sure whether this is a real issue or just a local error
(RH90)... Probably some macro change in 2.6.x. It still does the same
thing, but in a different way.
* add zr36120 i2c HW id
* it compiles in my local 2.6.x tree

It accepts I2C_DRIVERID_TUNER as tuner (tuner.ko) and
I2C_DRIVERID_SAA7110 as decoder (saa7110.ko). If there's any others that
need adding, simply add them to the case: list.

Things left to do (for you ;) ): v4l2 (sounds like a good thing, though
it'll take some time), multiple opens (if you want), and (IIRC, Gerd?)
videodev + vbidev fops should be the same. This wasn't the case in
2.4.x, but it's the case in 2.6.x, I think. I'm actually not totally
sure, I think Gerd knows more about this, and can give you some pointers
to how others have done this.

Please let me know the results. :).

Ronald

-- 
Ronald Bultje <rbultje@ronald.bitfreak.net>
Linux Video/Multimedia developer

[-- Attachment #2: zr36120.diff --]
[-- Type: text/plain, Size: 25034 bytes --]

--- linux-2.6.0-test4/drivers/media/video/zr36120-old/i2c-id.h	2003-09-25 16:52:52.000000000 +0200
+++ linux-2.6.0-test4/include/linux/i2c-id.h	2003-09-25 16:53:50.000000000 +0200
@@ -95,7 +95,6 @@
 #define I2C_DRIVERID_DS1307	47     /* DS1307 real time clock	*/
 #define I2C_DRIVERID_ADV7175	48     /* ADV 7175/7176 video encoder	*/
 #define I2C_DRIVERID_SAA7114	49	/* video decoder		*/
-#define I2C_DRIVERID_ZR36120	50     /* Zoran 36120 video encoder	*/
 #define I2C_DRIVERID_24LC32A	51	/* Microchip 24LC32A 32k EEPROM	*/
 #define I2C_DRIVERID_STM41T00	52	/* real time clock		*/
 #define I2C_DRIVERID_UDA1342	53	/* UDA1342 audio codec		*/
@@ -220,6 +219,7 @@
 #define I2C_HW_B_IXP425 0x17	/* GPIO on IXP425 systems		*/
 #define I2C_HW_B_S3VIA	0x18	/* S3Via ProSavage adapter		*/
 #define I2C_HW_B_ZR36067 0x19	/* Zoran-36057/36067 based boards	*/
+#define I2C_HW_B_ZR36120 0x20	/* Zoran 36120/36125 based boards	*/
 
 /* --- PCF 8584 based algorithms					*/
 #define I2C_HW_P_LP	0x00	/* Parallel port interface		*/
--- linux-2.6.0-test4/drivers/media/video/zr36120-old/zr36120.c	2003-09-25 12:21:18.000000000 +0200
+++ linux-2.6.0-test4/drivers/media/video/zr36120.c	2003-09-25 17:43:38.000000000 +0200
@@ -29,6 +29,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -39,8 +40,8 @@
 #include <linux/version.h>
 #include <asm/uaccess.h>
 
-#include "tuner.h"
 #include "zr36120.h"
+#include <media/tuner.h>
 #include "zr36120_mem.h"
 
 /* mark an required function argument unused - lintism */
@@ -338,7 +339,7 @@
 }
 
 static
-void zoran_irq(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t zoran_irq(int irq, void *dev_id, struct pt_regs * regs)
 {
 	u32 stat,estat;
 	int count = 0;
@@ -350,7 +351,7 @@
 		stat=zrread(ZORAN_ISR);
 		estat=stat & zrread(ZORAN_ICR);
 		if (!estat)
-			return;
+			break;
 		zrwrite(estat,ZORAN_ISR);
 		IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat));
 		IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat));
@@ -381,6 +382,8 @@
 			printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD);
 		}
 	}
+
+	return IRQ_HANDLED;
 }
 
 static
@@ -389,7 +392,7 @@
 	int	rv;
 
 	/* set the new video norm */
-	rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm);
+	rv = zoran_i2c_command(ztv, DECODER_SET_NORM, &norm);
 	if (rv)
 		return rv;
 	ztv->norm = norm;
@@ -398,7 +401,7 @@
 	channel = ztv->card->video_mux[channel] & CHANNEL_MASK;
 
 	/* set the new channel */
-	rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel);
+	rv = zoran_i2c_command(ztv, DECODER_SET_INPUT, &channel);
 	return rv;
 }
 
@@ -735,7 +738,7 @@
 	ztv->picture.brightness=128<<8;
 	ztv->picture.hue=128<<8;
 	ztv->picture.contrast=216<<7;
-	i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture);
+	zoran_i2c_command(ztv, DECODER_SET_PICTURE, &ztv->picture);
 
 	/* default to the composite input since my camera is there */
 	zoran_muxsel(ztv, 0, VIDEO_MODE_PAL);
@@ -757,11 +760,44 @@
 /*
  * Open a zoran card. Right now the flags are just a hack
  */
-static int zoran_open(struct video_device *dev, int flags)
+static
+int zoran_open(struct inode* inode, struct file* file)
 {
-	struct zoran *ztv = (struct zoran*)dev;
+	unsigned int minor = minor(inode->i_rdev);
+	struct zoran *ztv = NULL;
 	struct vidinfo* item;
 	char* pos;
+	int i;
+
+	if (!try_module_get(THIS_MODULE)) {
+		printk(KERN_ERR "failed to acquire lock on myself\n");
+		return -EIO;
+	}
+
+	/* find the device */
+	for (i = 0; i < zoran_cards; i++) {
+		if (zorans[i].video_dev->minor == minor) {
+			ztv = &zorans[i];
+			break;
+		}
+	}
+	if (!ztv)
+		return -ENODEV;
+
+	if (ztv->have_decoder &&
+	    !try_module_get(ztv->decoder->driver->owner)) {
+		printk(KERN_ERR "Failed to acquire lock on TV decoder\n");
+		module_put(THIS_MODULE);
+		return -EIO;
+	} 
+	if (ztv->have_tuner &&
+	    !try_module_get(ztv->tuner->driver->owner)) {
+		printk(KERN_ERR "Failed to acquire lock on TV tuner\n");
+		if (ztv->have_decoder)
+			module_put(ztv->decoder->driver->owner);
+		module_put(THIS_MODULE);
+		return -EIO;
+	}
 
 	DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags));
 
@@ -773,6 +809,11 @@
 		ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE);
 	if (!ztv->fbuffer) {
 		/* could not get a buffer, bail out */
+		module_put(THIS_MODULE);
+		if (ztv->have_decoder)
+			module_put(ztv->decoder->driver->owner);
+		if (ztv->have_tuner)
+			module_put(ztv->tuner->driver->owner);
 		return -ENOBUFS;
 	}
 	/* at this time we _always_ have a framebuffer */
@@ -783,6 +824,11 @@
 	if (!ztv->overinfo.overlay) {
 		/* could not get an overlay buffer, bail out */
 		bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
+		module_put(THIS_MODULE);
+		if (ztv->have_decoder)
+			module_put(ztv->decoder->driver->owner);
+		if (ztv->have_tuner)
+			module_put(ztv->tuner->driver->owner);
 		return -ENOBUFS;
 	}
 	/* at this time we _always_ have a overlay */
@@ -798,22 +844,26 @@
 	}
 
 	/* do the common part of all open's */
-	zoran_common_open(ztv, flags);
+	zoran_common_open(ztv, file->f_flags);
+
+	file->private_data = ztv;
 
 	return 0;
 }
 
 static
-void zoran_close(struct video_device* dev)
+int zoran_close(struct inode* inode, struct file* file)
 {
-	struct zoran *ztv = (struct zoran*)dev;
+	struct zoran *ztv = file->private_data;
 
+	UNUSED(inode);
 	DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD));
 
 	/* driver specific closure */
 	clear_bit(STATE_OVERLAY, &ztv->state);
 
 	zoran_common_close(ztv);
+	file->private_data = NULL;
 
         /*
          *      This is sucky but right now I can't find a good way to
@@ -831,6 +881,13 @@
 		kfree( ztv->overinfo.overlay );
 	ztv->overinfo.overlay = 0;
 
+	module_put(THIS_MODULE);
+	if (ztv->have_decoder)
+		module_put(ztv->decoder->driver->owner);
+	if (ztv->have_tuner)
+		module_put(ztv->tuner->driver->owner);
+
+	return 0;
 }
 
 /*
@@ -841,13 +898,15 @@
  * be released as soon as possible to prevent lock contention.
  */
 static
-long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
+ssize_t zoran_read(struct file* file, char* buf, size_t count, loff_t* ppos)
 {
-	struct zoran *ztv = (struct zoran*)dev;
+	struct zoran *ztv = file->private_data;
 	unsigned long max;
 	struct vidinfo* unused = 0;
 	struct vidinfo* done = 0;
+	int nonblock = file->f_flags & O_NONBLOCK;
 
+	UNUSED(ppos);
 	DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock));
 
 	/* find ourself a free or completed buffer */
@@ -935,18 +994,18 @@
 }
 
 static
-long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock)
+ssize_t zoran_write(struct file* file, const char* data, size_t count, loff_t* ppos)
 {
-	struct zoran *ztv = (struct zoran *)dev;
-	UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock);
+	struct zoran *ztv = file->private_data;
+	UNUSED(ztv); UNUSED(data); UNUSED(count); UNUSED(ppos);
 	DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD));
 	return -EINVAL;
 }
 
 static
-unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait)
+unsigned int zoran_poll(struct file* file, poll_table* wait)
 {
-	struct zoran *ztv = (struct zoran *)dev;
+	struct zoran *ztv = file->private_data;
 	struct vidinfo* item;
 	unsigned int mask = 0;
 
@@ -976,9 +1035,11 @@
 }
 
 static
-int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
+int zoran_do_ioctl(struct inode* inode, struct file* file, unsigned int cmd, void* arg)
 {
-	struct zoran* ztv = (struct zoran*)dev;
+	struct zoran *ztv = file->private_data;
+
+	UNUSED(inode);
 
 	switch (cmd) {
 	 case VIDIOCGCAP:
@@ -986,7 +1047,7 @@
 		struct video_capability c;
 		DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD));
 
-		strcpy(c.name,ztv->video_dev.name);
+		strcpy(c.name,ztv->video_dev->name);
 		c.type = VID_TYPE_CAPTURE|
 			 VID_TYPE_OVERLAY|
 			 VID_TYPE_CLIPPING|
@@ -1161,7 +1222,7 @@
 		write_unlock_irq(&ztv->lock);
 
 		/* tell the decoder */
-		i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p);
+		zoran_i2c_command(ztv, DECODER_SET_PICTURE, &p);
 		break;
 	 }
 
@@ -1408,8 +1469,8 @@
 	 {
 		struct video_unit vu;
 		DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD));
-		vu.video = ztv->video_dev.minor;
-		vu.vbi = ztv->vbi_dev.minor;
+		vu.video = ztv->video_dev->minor;
+		vu.vbi = ztv->vbi_dev->minor;
 		vu.radio = VIDEO_NO_UNIT;
 		vu.audio = VIDEO_NO_UNIT;
 		vu.teletext = VIDEO_NO_UNIT;
@@ -1435,7 +1496,7 @@
 
 		if (ztv->have_tuner) {
 			int fixme = v;
-			if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0)
+			if (zoran_i2c_tuner_command(ztv, TUNER_SET_TVFREQ, &fixme) < 0)
 				return -EAGAIN;
 		}
 		ztv->tuner_freq = v;
@@ -1461,10 +1522,18 @@
 }
 
 static
-int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size)
+int zoran_ioctl (struct inode* inode, struct file* file, unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, zoran_do_ioctl);
+}
+
+
+static
+int zoran_mmap (struct file* file, struct vm_area_struct* vma)
 {
-	struct zoran* ztv = (struct zoran*)dev;
-	unsigned long start = (unsigned long)adr;
+	struct zoran *ztv = file->private_data;
+	unsigned long size = (vma->vm_end - vma->vm_start);
+	unsigned long start = vma->vm_start;
 	unsigned long pos;
 
 	DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size));
@@ -1486,27 +1555,55 @@
 	return 0;
 }
 
-static struct video_device zr36120_template=
+static
+void zoran_vdev_release(struct video_device* vdev)
 {
+        kfree(vdev);
+}
+
+static struct file_operations zoran_fops = {
 	.owner		= THIS_MODULE,
-	.name		= "UNSET",
-	.type		= VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
-	.hardware	= VID_HARDWARE_ZR36120,
 	.open		= zoran_open,
-	.close		= zoran_close,
+	.release	= zoran_close,
+	.ioctl		= zoran_ioctl,
+	.llseek		= no_llseek,
 	.read		= zoran_read,
 	.write		= zoran_write,
-	.poll		= zoran_poll,
-	.ioctl		= zoran_ioctl,
 	.mmap		= zoran_mmap,
+	.poll		= zoran_poll,
+};
+
+static struct video_device zr36120_template=
+{
+	.owner		= THIS_MODULE,
+	.name		= "UNSET",
+	.type		= VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
+	.hardware	= VID_HARDWARE_ZR36120,
+	.fops		= &zoran_fops,
+	.release	= zoran_vdev_release,
 	.minor		= -1,
 };
 
 static
-int vbi_open(struct video_device *dev, int flags)
+int vbi_open(struct inode* inode, struct file* file)
 {
-	struct zoran *ztv = (struct zoran*)dev->priv;
+	unsigned int minor = minor(inode->i_rdev);
+	struct zoran *ztv = NULL;
 	struct vidinfo* item;
+	int i;
+
+	if (!try_module_get(THIS_MODULE)) {
+		printk(KERN_ERR "failed to acquire lock on myself\n");
+		return -EIO;
+	}
+
+	/* find the device */
+	for (i = 0; i < zoran_cards; i++) {
+		if (zorans[i].video_dev->minor == minor) {
+			ztv = &zorans[i];
+			break;
+		}
+	}
 
 	DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags));
 
@@ -1533,6 +1630,7 @@
 					item->memadr = 0;
 					item->busadr = 0;
 				}
+				module_put(THIS_MODULE);
 				return -ENOBUFS;
 			}
 		}
@@ -1542,7 +1640,7 @@
 	}
 
 	/* do the common part of all open's */
-	zoran_common_open(ztv, flags);
+	zoran_common_open(ztv, file->f_flags);
 
 	set_bit(STATE_VBI, &ztv->state);
 	/* start read-ahead */
@@ -1552,11 +1650,12 @@
 }
 
 static
-void vbi_close(struct video_device *dev)
+int vbi_close(struct inode* inode, struct file* file)
 {
-	struct zoran *ztv = (struct zoran*)dev->priv;
+	struct zoran *ztv = file->private_data;
 	struct vidinfo* item;
 
+	UNUSED(inode);
 	DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD));
 
 	/* driver specific closure */
@@ -1579,6 +1678,9 @@
 		item->memadr = 0;
 	}
 
+	module_put(THIS_MODULE);
+
+	return 0;
 }
 
 /*
@@ -1589,13 +1691,15 @@
  * be released as soon as possible to prevent lock contention.
  */
 static
-long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
+ssize_t vbi_read(struct file* file, char* buf, size_t count, loff_t* ppos)
 {
-	struct zoran *ztv = (struct zoran*)dev->priv;
+	struct zoran *ztv = file->private_data;
 	unsigned long max;
 	struct vidinfo* unused = 0;
 	struct vidinfo* done = 0;
+	int nonblock = file->f_flags & O_NONBLOCK;
 
+	UNUSED(ppos);
 	DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock));
 
 	/* find ourself a free or completed buffer */
@@ -1675,6 +1779,7 @@
 	{
 	unsigned char* optr = buf;
 	unsigned char* eptr = buf+count;
+	unsigned long* lptr = --((unsigned long*)eptr);
 
 	/* are we beeing accessed from an old driver? */
 	if (count == 2*19*2048) {
@@ -1727,7 +1832,7 @@
 	/* API compliance:
 	 * place the framenumber (half fieldnr) in the last long
 	 */
-	__put_user(done->fieldnr/2, ((ulong*)eptr)[-1]);
+	__put_user(done->fieldnr/2, lptr);
 	}
 
 	/* keep the engine running */
@@ -1744,9 +1849,9 @@
 }
 
 static
-unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait)
+unsigned int vbi_poll(struct file* file, poll_table* wait)
 {
-	struct zoran *ztv = (struct zoran*)dev->priv;
+	struct zoran *ztv = file->private_data;
 	struct vidinfo* item;
 	unsigned int mask = 0;
 
@@ -1765,9 +1870,11 @@
 }
 
 static
-int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+int vbi_do_ioctl(struct inode* inode, struct file* file, unsigned int cmd, void* arg)
 {
-	struct zoran* ztv = (struct zoran*)dev->priv;
+	struct zoran *ztv = file->private_data;
+
+	UNUSED(inode);
 
 	switch (cmd) {
 	 case VIDIOCGVBIFMT:
@@ -1820,18 +1927,33 @@
 	return 0;
 }
 
-static struct video_device vbi_template=
+static
+int vbi_ioctl(struct inode* inode, struct file* file, unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, vbi_do_ioctl);
+}
+
+
+static struct file_operations vbi_fops =
 {
 	.owner		= THIS_MODULE,
-	.name		= "UNSET",
-	.type		= VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
-	.hardware	= VID_HARDWARE_ZR36120,
 	.open		= vbi_open,
-	.close		= vbi_close,
+	.release	= vbi_close,
 	.read		= vbi_read,
 	.write		= zoran_write,
+	.llseek		= no_llseek,
 	.poll		= vbi_poll,
 	.ioctl		= vbi_ioctl,
+};
+
+static struct video_device vbi_template=
+{
+	.owner		= THIS_MODULE,
+	.name		= "UNSET",
+	.type		= VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
+	.hardware	= VID_HARDWARE_ZR36120,
+	.fops		= &vbi_fops,
+	.release	= zoran_vdev_release,
 	.minor		= -1,
 };
 
@@ -1895,6 +2017,7 @@
 {
 	struct zoran *ztv = &zorans[card];
 	int	i;
+	void* alloc_mem1, * alloc_mem2;
 
 	/* if the given cardtype valid? */
 	if (cardtype[card]>=NRTVCARDS) {
@@ -1902,6 +2025,14 @@
 		return -1;
 	}
 
+	if (!(alloc_mem1 = kmalloc(sizeof(struct video_device), GFP_KERNEL)) ||
+	    !(alloc_mem2 = kmalloc(sizeof(struct video_device), GFP_KERNEL))) {
+		printk(KERN_ERR "failed to kmalloc data for video_device entries\n");
+		if (alloc_mem1)
+			kfree(alloc_mem1);
+		return -1;
+	}
+
 	/* reset the zoran */
 	zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);
 	udelay(10);
@@ -1984,34 +2115,35 @@
 	zrwrite(~0, ZORAN_ISR);
 
 	/*
-	 * i2c template
-	 */
-	ztv->i2c = zoran_i2c_bus_template;
-	sprintf(ztv->i2c.name,"zoran-%d",card);
-	ztv->i2c.data = ztv;
-
-	/*
 	 * Now add the template and register the device unit
 	 */
-	ztv->video_dev = zr36120_template;
-	strcpy(ztv->video_dev.name, ztv->i2c.name);
-	ztv->video_dev.priv = ztv;
-	if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0)
+	ztv->video_dev = alloc_mem1;
+	memcpy(ztv->video_dev, &zr36120_template, sizeof(struct video_device));
+	strcpy(ztv->video_dev->name, ztv->i2c_adapter.name);
+	ztv->video_dev->priv = ztv;
+	if (video_register_device(ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		kfree(alloc_mem1);
+		kfree(alloc_mem2);
 		return -1;
+	}
 
-	ztv->vbi_dev = vbi_template;
-	strcpy(ztv->vbi_dev.name, ztv->i2c.name);
-	ztv->vbi_dev.priv = ztv;
-	if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {
-		video_unregister_device(&ztv->video_dev);
+	ztv->vbi_dev = alloc_mem2;
+	memcpy(ztv->vbi_dev, &vbi_template, sizeof(struct video_device));
+	strcpy(ztv->vbi_dev->name, ztv->i2c_adapter.name);
+	ztv->vbi_dev->priv = ztv;
+	if (video_register_device(ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {
+		video_unregister_device(ztv->video_dev);
+		kfree(alloc_mem1);
+		kfree(alloc_mem2);
 		return -1;
 	}
-	i2c_register_bus(&ztv->i2c);
+	ztv->i2cbr = 0;
+	zoran_i2c_load(ztv);
 
 	/* set interrupt mask - the PIN enable will be set later */
 	zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR);
 
-	printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name);
+	printk(KERN_INFO "%s: installed %s\n",ztv->i2c_adapter.name,ztv->card->name);
 	return 0;
 }
 
@@ -2040,14 +2172,14 @@
 		free_irq(ztv->dev->irq,ztv);
  
     		/* unregister i2c_bus */
-		i2c_unregister_bus((&ztv->i2c));
+		zoran_i2c_unload(ztv);
 
 		/* unmap and free memory */
 		if (ztv->zoran_mem)
 			iounmap(ztv->zoran_mem);
 
-		video_unregister_device(&ztv->video_dev);
-		video_unregister_device(&ztv->vbi_dev);
+		video_unregister_device(ztv->video_dev);
+		video_unregister_device(ztv->vbi_dev);
 	}
 }
 
--- linux-2.6.0-test4/drivers/media/video/zr36120-old/zr36120.h	2003-09-25 12:21:18.000000000 +0200
+++ linux-2.6.0-test4/drivers/media/video/zr36120.h	2003-09-25 16:43:44.000000000 +0200
@@ -26,7 +26,8 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-#include <linux/i2c-old.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
 #include <linux/videodev.h>
 
 #include <asm/io.h>
@@ -39,9 +40,6 @@
 #define IDEBUG(x...)			/* Debug interrupt handler */
 #define PDEBUG		0		/* Debug PCI writes */
 
-/* defined in zr36120_i2c */
-extern struct i2c_bus zoran_i2c_bus_template;
-
 #define	ZORAN_MAX_FBUFFERS	2
 #define	ZORAN_MAX_FBUFFER	(768*576*2)
 #define	ZORAN_MAX_FBUFSIZE	(ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER)
@@ -91,14 +89,19 @@
 
 struct zoran 
 {
-	struct video_device video_dev;
+	struct video_device* video_dev;
 #define CARD_DEBUG	KERN_DEBUG "%s(%lu): "
 #define CARD_INFO	KERN_INFO "%s(%lu): "
 #define CARD_ERR	KERN_ERR "%s(%lu): "
-#define CARD		ztv->video_dev.name,ztv->fieldnr
+#define CARD		ztv->video_dev->name,ztv->fieldnr
 
 	/* zoran chip specific details */
-	struct i2c_bus	i2c;		/* i2c registration data	*/
+	struct i2c_adapter i2c_adapter;	/* i2c registration data	*/
+	struct i2c_algo_bit_data
+			i2c_algo; 	/* i2c bit-banging algorithm	*/
+	unsigned int	i2cbr;		/* i2c state cache		*/
+	struct i2c_client* decoder,
+			 * tuner;	/* pointer to the decoder+tuner	*/
 	struct pci_dev*	dev;		/* ptr to PCI device		*/
 	ulong		zoran_adr;	/* bus address of IO memory	*/
 	char*		zoran_mem;	/* kernel address of IO memory	*/
@@ -119,7 +122,7 @@
 	wait_queue_head_t grabq;	/* grabbers queue		*/
 
 	/* VBI details */
-	struct video_device vbi_dev;
+	struct video_device *vbi_dev;
 	struct vidinfo	readinfo[2];	/* VBI data - flip buffers	*/
 	wait_queue_head_t vbiq;		/* vbi queue			*/
 
@@ -143,6 +146,12 @@
 	uint		vidHeight;	/* calculated */
 };
 
+/* defined in zr36120_i2c */
+extern int	zoran_i2c_load		(struct zoran *ztv);
+extern void	zoran_i2c_unload	(struct zoran *ztv);
+extern int	zoran_i2c_command	(struct zoran *ztv, int cmd, void *data);
+extern int	zoran_i2c_tuner_command	(struct zoran *ztv, int cmd, void *data);
+
 #define zrwrite(dat,adr)    writel((dat),(char *) (ztv->zoran_mem+(adr)))
 #define zrread(adr)         readl(ztv->zoran_mem+(adr))
 
--- linux-2.6.0-test4/drivers/media/video/zr36120-old/zr36120_i2c.c	2003-09-25 12:21:18.000000000 +0200
+++ linux-2.6.0-test4/drivers/media/video/zr36120_i2c.c	2003-09-25 17:30:03.000000000 +0200
@@ -26,8 +26,8 @@
 #include <linux/video_decoder.h>
 #include <asm/uaccess.h>
 
-#include "tuner.h"
 #include "zr36120.h"
+#include <media/tuner.h>
 
 /* ----------------------------------------------------------------------- */
 /* I2C functions							   */
@@ -37,37 +37,60 @@
 
 #define I2C_DELAY   10
 
-static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
+/* software I2C functions */
+static int zoran_i2c_getsda (void* data)
+{
+	struct zoran* ztv = (struct zoran*)data;
+	return zrread(ZORAN_I2C) & (ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+}
+
+static
+int zoran_i2c_getscl (void* data)
+{
+	struct zoran* ztv = (struct zoran*)data;
+	return zrread(ZORAN_I2C) & (ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
+}
+
+static
+void zoran_i2c_setsda (void* data, int state)
+{
+	struct zoran* ztv = (struct zoran*)data;
+	if (state)
+		ztv->i2cbr |= (ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+	else
+		ztv->i2cbr &= ~(ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+	zrwrite(ztv->i2cbr, ZORAN_I2C);
+}
+
+static
+void zoran_i2c_setscl (void* data, int state)
 {
-	struct zoran *ztv = (struct zoran*)bus->data;
-	unsigned int b = 0;
-	if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA;
-	if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL;
-	zrwrite(b, ZORAN_I2C);
-	udelay(I2C_DELAY);
-}
-
-static int i2c_getdataline(struct i2c_bus *bus)
-{
-	struct zoran *ztv = (struct zoran*)bus->data;
-	if (ztv->card->swapi2c)
-		return zrread(ZORAN_I2C) & ZORAN_I2C_SCL;
-	return zrread(ZORAN_I2C) & ZORAN_I2C_SDA;
+	struct zoran* ztv = (struct zoran*)data;
+	if (state)
+		ztv->i2cbr |= (ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
+	else
+		ztv->i2cbr &= ~(ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
+	zrwrite(ztv->i2cbr, ZORAN_I2C);
 }
 
 static
-void attach_inform(struct i2c_bus *bus, int id)
+int attach_inform(struct i2c_client* client)
 {
-	struct zoran *ztv = (struct zoran*)bus->data;
+	struct zoran* ztv = (struct zoran*)i2c_get_adapdata(client->adapter);
 	struct video_decoder_capability dc;
 	int rv;
 
-	switch (id) {
-	 case I2C_DRIVERID_VIDEODECODER:
+	if (ztv->users > 0) {
+		printk(KERN_ERR "cannot connect i2c devices while running\n");
+		return -EBUSY;
+	}
+
+	switch (client->driver->id) {
+	 case I2C_DRIVERID_SAA7110:
 		DEBUG(printk(CARD_INFO "decoder attached\n",CARD));
 
 		/* fetch the capabilites of the decoder */
-		rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc);
+		rv = zoran_i2c_command(ztv, DECODER_GET_CAPABILITIES, &dc);
 		if (rv) {
 			DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD));
 			break;
@@ -85,23 +108,25 @@
 		DEBUG(printk(CARD_INFO "tuner attached\n",CARD));
 		if (ztv->tuner_type >= 0)
 		{
-			if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0)
+			if (zoran_i2c_tuner_command(ztv ,TUNER_SET_TYPE,&ztv->tuner_type)<0)
 			DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type));
 		}
 		break;
 	 default:
 		DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id));
-		break;
+		return -1;
 	}
+
+	return 0;
 }
 
 static
-void detach_inform(struct i2c_bus *bus, int id)
+int detach_inform(struct i2c_client* client)
 {
-	struct zoran *ztv = (struct zoran*)bus->data;
+	struct zoran *ztv = (struct zoran*)i2c_get_adapdata(client->adapter);
 
-	switch (id) {
-	 case I2C_DRIVERID_VIDEODECODER:
+	switch (client->driver->id) {
+	 case I2C_DRIVERID_SAA7110:
 		ztv->have_decoder = 0;
 		DEBUG(printk(CARD_INFO "decoder detached\n",CARD));
 		break;
@@ -113,21 +138,57 @@
 		DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id));
 		break;
 	}
+
+	return 0;
+}
+
+static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
+	.setsda = zoran_i2c_setsda,
+	.setscl = zoran_i2c_setscl,
+	.getsda = zoran_i2c_getsda,
+	.getscl = zoran_i2c_getscl,
+	.udelay = I2C_DELAY,
+	.mdelay = 0,
+	.timeout = 100,
+};
+
+static struct i2c_adapter zoran_i2c_adapter_template = {
+	.name = "ZR36120",
+	.id = I2C_HW_B_ZR36120,
+	.algo = NULL,
+	.client_register = attach_inform,
+	.client_unregister = detach_inform,
+};
+
+int zoran_i2c_load (struct zoran *ztv)
+{
+	memcpy(&ztv->i2c_algo, &zoran_i2c_bit_data_template,
+	       sizeof(struct i2c_algo_bit_data));
+	ztv->i2c_algo.data = ztv;
+	memcpy(&ztv->i2c_adapter, &zoran_i2c_adapter_template,
+	       sizeof(struct i2c_adapter));
+	i2c_set_adapdata(&ztv->i2c_adapter, ztv);
+	ztv->i2c_adapter.algo_data = &ztv->i2c_algo;
+	return i2c_bit_add_bus(&ztv->i2c_adapter);
+}
+
+void zoran_i2c_unload (struct zoran *ztv)
+{
+	i2c_bit_del_bus(&ztv->i2c_adapter);
 }
 
-struct i2c_bus zoran_i2c_bus_template =
+int zoran_i2c_command (struct zoran *ztv, int cmd, void *data)
 {
-	"ZR36120",
-	I2C_BUSID_ZORAN,
-	NULL,
+	if (!ztv->decoder)
+		return -EIO;
 
-	SPIN_LOCK_UNLOCKED,
+	return ztv->decoder->driver->command(ztv->decoder, cmd, data);
+}
 
-	attach_inform,
-	detach_inform,
+int zoran_i2c_tuner_command (struct zoran *ztv, int cmd, void *data)
+{
+	if (!ztv->tuner)
+		return -EIO;
 
-	i2c_setlines,
-	i2c_getdataline,
-	NULL,
-	NULL
-};
+	return ztv->tuner->driver->command(ztv->tuner, cmd, data);
+}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168)
  2003-09-25 15:59         ` zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168) Ronald Bultje
@ 2003-09-25 16:10           ` Christoph Hellwig
  2003-09-25 19:21             ` Ronald Bultje
  2003-09-25 16:43           ` Gerd Knorr
  1 sibling, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2003-09-25 16:10 UTC (permalink / raw)
  To: Ronald Bultje; +Cc: Pauline Middelink, linux-kernel, kraxel

On Thu, Sep 25, 2003 at 05:59:44PM +0200, Ronald Bultje wrote:
> +	if (!try_module_get(THIS_MODULE)) {
> +		printk(KERN_ERR "failed to acquire lock on myself\n");
> +		return -EIO;
> +	}

This is broken, you need an owner outside the open routine.

> +
> +	/* find the device */
> +	for (i = 0; i < zoran_cards; i++) {
> +		if (zorans[i].video_dev->minor == minor) {
> +			ztv = &zorans[i];
> +			break;
> +		}
> +	}

What serializes this?

> +	if (ztv->have_decoder &&
> +	    !try_module_get(ztv->decoder->driver->owner)) {
> +		printk(KERN_ERR "Failed to acquire lock on TV decoder\n");
> +		module_put(THIS_MODULE);
> +		return -EIO;
> +	} 
> +	if (ztv->have_tuner &&
> +	    !try_module_get(ztv->tuner->driver->owner)) {
> +		printk(KERN_ERR "Failed to acquire lock on TV tuner\n");
> +		if (ztv->have_decoder)
> +			module_put(ztv->decoder->driver->owner);
> +		module_put(THIS_MODULE);
> +		return -EIO;
> +	}

You probably want to add a few gotos to unwind at the end of the
function with less code deuplication..


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168)
  2003-09-25 15:59         ` zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168) Ronald Bultje
  2003-09-25 16:10           ` Christoph Hellwig
@ 2003-09-25 16:43           ` Gerd Knorr
  1 sibling, 0 replies; 4+ messages in thread
From: Gerd Knorr @ 2003-09-25 16:43 UTC (permalink / raw)
  To: Ronald Bultje; +Cc: Pauline Middelink, linux-kernel

> * implement a zoran_vdev_release() function to free memory after it's no
> longer in use (this is a hack imo, but it's the suggested way of doing
> it... There was an article somewhere about it and it's also been
> discussed on the v4l mailinglist... Can't find a link, though)

If you just kfree() there you don't need your own bur can simply use
video_device_release() ...

> Things left to do (for you ;) ): v4l2 (sounds like a good thing, though
> it'll take some time), multiple opens (if you want), and (IIRC, Gerd?)
> videodev + vbidev fops should be the same. This wasn't the case in
> 2.4.x, but it's the case in 2.6.x, I think.

That's a v4l vs. v4l2 API thing.  The v4l2 API allows applications to
switch a device handle into vbi mode via S_FMT, thus you don't need
separate devices any more.  For v4l1 backward comparibility this is
still needed through.  For v4l2 drivers /dev/video and /dev/vbi almost
the same, /dev/vbi has just some other default settings after opening
the device.

  Gerd


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168)
  2003-09-25 16:10           ` Christoph Hellwig
@ 2003-09-25 19:21             ` Ronald Bultje
  0 siblings, 0 replies; 4+ messages in thread
From: Ronald Bultje @ 2003-09-25 19:21 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Pauline Middelink, linux-kernel, kraxel

Hi,

On Thu, 2003-09-25 at 18:10, Christoph Hellwig wrote:
> On Thu, Sep 25, 2003 at 05:59:44PM +0200, Ronald Bultje wrote:
> > +	if (!try_module_get(THIS_MODULE)) {
> > +		printk(KERN_ERR "failed to acquire lock on myself\n");
> > +		return -EIO;
> > +	}
> 
> This is broken, you need an owner outside the open routine.

Eh? could you explain, please?

> > +
> > +	/* find the device */
> > +	for (i = 0; i < zoran_cards; i++) {
> > +		if (zorans[i].video_dev->minor == minor) {
> > +			ztv = &zorans[i];
> > +			break;
> > +		}
> > +	}
> 
> What serializes this?

We have an array of devices, and in order to find the right one, we go
through the array until the inode belonging to the device that's being
opened matches the one in the video device that we reigstered during
module loading. I don't know of a way to get that information in any
direct (non-loop) way, but that might be because I never cared to. I
admit it's ugly, but it's correct and used in other drivers, too.

Ronald

-- 
Ronald Bultje <rbultje@ronald.bitfreak.net>
Linux Video/Multimedia developer


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2003-09-25 19:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <BAY7-F62oStVwgTlLlJ0001924a@hotmail.com>
     [not found] ` <1064478814.2220.326.camel@shrek.bitfreak.net>
     [not found]   ` <20030925084932.GA22441@polyware.nl>
     [not found]     ` <1064484678.2227.465.camel@shrek.bitfreak.net>
     [not found]       ` <20030925102635.GA25634@polyware.nl>
2003-09-25 15:59         ` zr36120 2.6.x port (was: Re: [Mjpeg-users] DC30+ can't capture size greater than 224x168) Ronald Bultje
2003-09-25 16:10           ` Christoph Hellwig
2003-09-25 19:21             ` Ronald Bultje
2003-09-25 16:43           ` Gerd Knorr

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).