<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">diff -urN linux-2.6.14-rc2.orig/drivers/media/video/Makefile linux-2.6.14-rc2/drivers/media/video/Makefile
--- linux-2.6.14-rc2.orig/drivers/media/video/Makefile	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/Makefile	2005-10-11 23:31:01.000000000 -0700
@@ -15,7 +15,7 @@
 	tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o
 obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
-obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
+obj-$(CONFIG_VIDEO_ZR36120) += saa7110.o saa7111.o zoran.o
 obj-$(CONFIG_VIDEO_SAA6588) += rds.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
 obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
diff -urN linux-2.6.14-rc2.orig/drivers/media/video/zr36120.c linux-2.6.14-rc2/drivers/media/video/zr36120.c
--- linux-2.6.14-rc2.orig/drivers/media/video/zr36120.c	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/zr36120.c	2005-10-11 23:26:01.000000000 -0700
@@ -2,6 +2,9 @@
     zr36120.c - Zoran 36120/36125 based framegrabbers
 
     Copyright (C) 1998-1999 Pauline Middelink &lt;middelin@polyware.nl&gt;
+    Partial port to Linux 2.6 by ???
+    Full port to Linux 2.6, and other cleanup by Joachim Feise (Oct. 2005)
+    Copyright (C) 2005 Joachim Feise &lt;jfeise@feise.com&gt;
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -29,6 +32,7 @@
 #include &lt;linux/vmalloc.h&gt;
 #include &lt;linux/mm.h&gt;
 #include &lt;linux/pci.h&gt;
+#include &lt;linux/interrupt.h&gt;
 #include &lt;linux/signal.h&gt;
 #include &lt;linux/wait.h&gt;
 #include &lt;asm/io.h&gt;
@@ -39,8 +43,8 @@
 
 #include &lt;asm/uaccess.h&gt;
 
-#include "tuner.h"
 #include "zr36120.h"
+#include &lt;media/tuner.h&gt;
 #include "zr36120_mem.h"
 
 /* mark an required function argument unused - lintism */
@@ -54,10 +58,11 @@
 /* Anybody who uses more than four? */
 #define ZORAN_MAX 4
 
-static unsigned int triton1=0;			/* triton1 chipset? */
-static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };
-static int video_nr = -1;
-static int vbi_nr = -1;
+static int triton1=0;			/* triton1 chipset? */
+/*static int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };*/
+static int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };
+static int debug = 0;
+static int mode = VIDEO_MODE_NTSC;
 
 static struct pci_device_id zr36120_pci_tbl[] = {
 	{ PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120,
@@ -67,13 +72,22 @@
 MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl);
 
 MODULE_AUTHOR("Pauline Middelink &lt;middelin@polyware.nl&gt;");
+MODULE_AUTHOR("Joachim Feise &lt;jfeise@feise.com&gt;");
 MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(triton1,"i");
-MODULE_PARM(cardtype,"1-" __MODULE_STRING(ZORAN_MAX) "i");
-MODULE_PARM(video_nr,"i");
-MODULE_PARM(vbi_nr,"i");
+module_param(triton1, bool, 0);
+MODULE_PARM_DESC(triton1, "Running on Triton1 chipset");
+
+module_param_array(cardtype, int, NULL, 0);
+MODULE_PARM_DESC(cardtype, "The ZR36120-based card type (see sources)");
+
+module_param(mode, int, VIDEO_MODE_NTSC);
+MODULE_PARM_DESC(mode, "The video mode [0:PAL, 1:NTSC (default), 2:SECAM]");
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level [0-2:increasing verbosity, 9:debug intr]");
+
 
 static int zoran_cards;
 static struct zoran zorans[ZORAN_MAX];
@@ -91,22 +105,34 @@
 static struct tvcard tvcards[] = {
 	/* reported working by &lt;middelin@polyware.nl&gt; */
 /*0*/	{ "Trust Victor II",
-	  2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
+	  2, 0, T, T, T, T, T, F, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
 	/* reported working by &lt;Michael.Paxton@aihw.gov.au&gt;  */
 /*1*/   { "Aitech WaveWatcher TV-PCI",
-	  3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } },
+	  3, 0, T, F, T, T, T, F, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } },
 	/* reported working by ? */
 /*2*/	{ "Genius Video Wonder PCI Video Capture Card",
-	  2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
+	  2, 0, T, T, T, T, T, F, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
 	/* reported working by &lt;Pascal.Gabriel@wanadoo.fr&gt; */
 /*3*/	{ "Guillemot Maxi-TV PCI",
-	  2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
+	  2, 0, T, T, T, T, T, F, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
 	/* reported working by "Craig Whitmore &lt;lennon@igrin.co.nz&gt; */
 /*4*/	{ "Quadrant Buster",
-	  3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } },
+	  3, 3, T, F, T, T, T, F, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } },
+        /* reported by &lt;Peter.Schlaf@org.chemie.uni-giessen.de&gt; */
+/*5*/   { "MediaFocus Satellite TV Card",
+          3, 0, T, F, T, F, T, F, 0xE0, 0x11, { 0, TUNER(2), SVHS(4) }, { 0 } },
+        /* reported working by &lt;rfassano@teletel.com.ar&gt; */
+/*6*/   { "Genius TV Wonder Pro",
+          3, 1, F, T, T, T, T, F, 0x7F, 0x80, { 1, TUNER(2), SVHS(3) }, { 0 } },
+        /* reported working by Joel Fuster &lt;j@fuster.org&gt; */
+/*7*/   { "Boca BVPSZ1",
+          1, 0, F, T, T, F, T, F, 0xFD, 0x00, { 1 }, { 0 } },
+        /* reported working by Joe Feise &lt;jfeise@feise.com&gt; */
+/*8*/   { "Focus Enhancements InVideo/PCI",
+          2, 0, F, F, T, T, T, F, 0x7F, 0x80, { 1, 2 }, { 0 } },
 	/* a debug entry which has all inputs mapped */
-/*5*/	{ "ZR36120 based framegrabber (all inputs enabled)",
-	  6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } }
+/*9*/	{ "ZR36120 based framegrabber (all inputs enabled)",
+	  6, 0, T, T, T, T, T, F, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } }
 };
 #undef T
 #undef F
@@ -114,29 +140,47 @@
 
 #ifdef __sparc__
 #define	ENDIANESS	0
+#define	ENDIANESS2	ZORAN_VFEC_LE
 #else
 #define	ENDIANESS	ZORAN_VFEC_LE
+#define	ENDIANESS2	0
 #endif
 
 static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = {
-/* n/a     */	{ "n/a",     0, 0 },
-/* GREY    */	{ "GRAY",    0, 0 },
-/* HI240   */	{ "HI240",   0, 0 },
-/* RGB565  */	{ "RGB565",  ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 },
-/* RGB24   */	{ "RGB24",   ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 },
-/* RGB32   */	{ "RGB32",   ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 },
-/* RGB555  */	{ "RGB555",  ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 },
-/* YUV422  */	{ "YUV422",  ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 },
-/* YUYV    */	{ "YUYV",    0, 0 },
-/* UYVY    */	{ "UYVY",    0, 0 },
-/* YUV420  */	{ "YUV420",  0, 0 },
-/* YUV411  */	{ "YUV411",  0, 0 },
-/* RAW     */	{ "RAW",     0, 0 },
-/* YUV422P */	{ "YUV422P", 0, 0 },
-/* YUV411P */	{ "YUV411P", 0, 0 }};
+/* n/a     : 0  */ { "n/a",     0, 0 },
+/* GREY    : 1  */ { "GRAY",    0, 0 },
+/* HI240   : 2  */ { "HI240",   0, 0 },
+/* RGB565  : 3  */ { "RGB565",  ZORAN_VFEC_RGB_RGB565|ENDIANESS,  2 },
+/* RGB24   : 4  */ { "RGB24",   ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 },
+/* RGB32   : 5  */ { "RGB32",   ZORAN_VFEC_RGB_RGB888|ENDIANESS,  4 },
+/* RGB555  : 6  */ { "RGB555",  ZORAN_VFEC_RGB_RGB555|ENDIANESS,  2 },
+/* YUV422  : 7  */ { "YUV422",  ZORAN_VFEC_RGB_YUV422|ENDIANESS,  2 },
+/* YUYV    : 8  */ { "YUYV",    ZORAN_VFEC_RGB_YUV422|ENDIANESS2, 2 },
+/* UYVY    : 9  */ { "UYVY",    ZORAN_VFEC_RGB_YUV422|ENDIANESS,  2 },
+/* YUV420  : 10 */ { "YUV420",  0, 0 },
+/* YUV411  : 11 */ { "YUV411",  0, 0 },
+/* RAW     : 12 */ { "RAW",     0, 0 },
+/* YUV422P : 13 */ { "YUV422P", 0, 0 },
+/* YUV411P : 14 */ { "YUV411P", 0, 0 }};
 #define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0]))
 #undef ENDIANESS
 
+struct tvmode
+{
+	u16 Wt, Wa, Ht, Ha, HStart, VStart;
+};
+
+static struct tvmode tvmodes[] = {
+        /* PAL-BDGHI */
+/*00*/  { 864, 768, 625, 576, 85, 17 },
+        /* NTSC */
+/*01*/  { 858, 720, 525, 480, 121, 10 },
+        /* SECAM */
+/*02*/  { 864, 720, 625, 576, 131, 21 },
+};
+#define TVNORMS (sizeof(tvmodes)/sizeof(tvmodes[0]))
+
+
 /* ----------------------------------------------------------------------- */
 /* ZORAN chipset detector                                                 */
 /* shamelessly stolen from bttv.c                                         */
@@ -151,7 +195,7 @@
 		triton1 = ZORAN_VDC_TRICOM;
 
 	if (pci_pci_problems &amp; PCIPCI_TRITON) {
-		printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n");
+		dprintk(0, KERN_INFO "zr36120: Host bridge 82437FX Triton PIIX\n");
 		triton1 = ZORAN_VDC_TRICOM;
 	}
 }
@@ -172,7 +216,7 @@
 
 	for (i=0; i&lt;0x60; i+=4) {
 		if ((i % 16) == 0) {
-			if (i) printk("%s\n",str);
+			if (i) dprintk(0, "%s\n", str);
 			p = str;
 			p+= sprintf(str, KERN_DEBUG "       %04x: ",i);
 		}
@@ -200,7 +244,9 @@
 		if (zrread(ZORAN_VSTR) &amp; ZORAN_VSTR_GRAB)
 			return;
 
-DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv-&gt;workqueue-&gt;kindof==FBUFFER_GRAB?"grab":"read",ztv-&gt;workqueue));
+		dprintk(2, CARD_DEBUG "completed %s at %p\n",
+			CARD, ztv-&gt;workqueue-&gt;kindof==FBUFFER_GRAB?"grab":"read",
+			ztv-&gt;workqueue);
 
 		/* we are done with this buffer, tell everyone */
 		ztv-&gt;workqueue-&gt;status = FBUFFER_DONE;
@@ -212,11 +258,15 @@
 		 case FBUFFER_GRAB:
 			wake_up_interruptible(&amp;ztv-&gt;grabq);
 			break;
+
 		 case FBUFFER_VBI:
 			wake_up_interruptible(&amp;ztv-&gt;vbiq);
 			break;
+
 		 default:
-			printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv-&gt;workqueue-&gt;kindof);
+			dprintk(0,
+				CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",
+				CARD, ztv-&gt;workqueue-&gt;kindof);
 		}
 
 		/* item completed, skip to next item in queue */
@@ -236,7 +286,9 @@
 		struct vidinfo* newitem;
 again:
 
-DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv-&gt;workqueue-&gt;kindof==FBUFFER_GRAB?"grab":"read",ztv-&gt;workqueue));
+		dprintk(2, CARD_DEBUG "starting %s at %p\n",
+			CARD, ztv-&gt;workqueue-&gt;kindof==FBUFFER_GRAB?"grab":"read",
+			ztv-&gt;workqueue);
 
 		/* loadup the frame settings */
 		read_lock(&amp;ztv-&gt;lock);
@@ -253,8 +305,11 @@
 			/* start single-shot grab */
 			zror(ZORAN_VSTR_GRAB, ZORAN_VSTR);
 			break;
+
 		 default:
-			printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv-&gt;workqueue-&gt;kindof);
+			dprintk(0,
+				CARD_INFO "what is this doing on the queue? (kindof=%d)\n",
+				CARD, ztv-&gt;workqueue-&gt;kindof);
 			write_lock(&amp;ztv-&gt;lock);
 			newitem = ztv-&gt;workqueue-&gt;next;
 			ztv-&gt;workqueue-&gt;next = 0;
@@ -266,7 +321,7 @@
 		/* bye for now */
 		return;
 	}
-DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD));
+	dprintk(2, CARD_DEBUG "nothing in queue\n", CARD);
 
 	/*
 	 * What? Even the workqueue is empty? Am i really here
@@ -280,7 +335,7 @@
 		if (!(zrread(ZORAN_OCR) &amp; ZORAN_OCR_OVLEN) ||
 		    !(zrread(ZORAN_VDC) &amp; ZORAN_VDC_VIDEN))
 		{
-DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD));
+			dprintk(2, CARD_DEBUG "starting overlay\n", CARD);
 
 			read_lock(&amp;ztv-&gt;lock);
 			zoran_set_geo(ztv,&amp;ztv-&gt;overinfo);
@@ -312,7 +367,7 @@
 		for (item=ztv-&gt;readinfo; item!=ztv-&gt;readinfo+ZORAN_VBI_BUFFERS; item++)
 			if (item-&gt;next == 0 &amp;&amp; item-&gt;status == FBUFFER_FREE)
 			{
-DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item));
+				dprintk(2, CARD_DEBUG "%p added to queue\n",CARD, item);
 				item-&gt;status = FBUFFER_BUSY;
 				if (!lastitem)
 					ztv-&gt;workqueue = item;
@@ -328,14 +383,14 @@
 	/*
 	 * Then we must be realy IDLE
 	 */
-DEBUG(printk(CARD_DEBUG "turning off\n",CARD));
+	dprintk(2, CARD_DEBUG "turning off\n", CARD);
 	/* nothing further to do, disable DMA and further IRQs */
 	zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
 	zrand(~ZORAN_ICR_EN,ZORAN_ICR);
 }
 
 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;
@@ -347,55 +402,69 @@
 		stat=zrread(ZORAN_ISR);
 		estat=stat &amp; 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));
+		dprintk(9, CARD_DEBUG "estat %08x\n", CARD, estat);
+		dprintk(9, CARD_DEBUG " stat %08x\n", CARD, stat);
 
 		if (estat &amp; ZORAN_ISR_CODE)
 		{
-			IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD));
+			dprintk(9, CARD_DEBUG "CodReplIRQ\n", CARD);
 		}
 		if (estat &amp; ZORAN_ISR_GIRQ0)
 		{
-			IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD));
+			dprintk(9, CARD_DEBUG "GIRQ0\n", CARD);
 			if (!ztv-&gt;card-&gt;usegirq1)
 				reap_states(ztv);
 		}
 		if (estat &amp; ZORAN_ISR_GIRQ1)
 		{
-			IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD));
+			dprintk(9, CARD_DEBUG "GIRQ1\n", CARD);
 			if (ztv-&gt;card-&gt;usegirq1)
 				reap_states(ztv);
 		}
 
 		count++;
 		if (count &gt; 10)
-			printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat);
+			dprintk(0, CARD_ERR "irq loop %d (%x)\n", CARD, count, estat);
 		if (count &gt; 20)
 		{
 			zrwrite(0, ZORAN_ICR);
-			printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD);
+			dprintk(0, CARD_ERR "IRQ lockup, cleared int mask\n", CARD);
 		}
 	}
+
+	return IRQ_HANDLED;
 }
 
 static
-int zoran_muxsel(struct zoran* ztv, int channel, int norm)
+int zoran_muxsel(struct zoran* ztv, int channel, int mode)
 {
-	int	rv;
-
-	/* set the new video norm */
-	rv = i2c_control_device(&amp;(ztv-&gt;i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &amp;norm);
-	if (rv)
-		return rv;
-	ztv-&gt;norm = norm;
+	int	rv = 0;
+	int     changed = 0;
 
 	/* map the given channel to the cards decoder's channel */
 	channel = ztv-&gt;card-&gt;video_mux[channel] &amp; CHANNEL_MASK;
 
-	/* set the new channel */
-	rv = i2c_control_device(&amp;(ztv-&gt;i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &amp;channel);
+	/*
+	 * First set the new channel, for AUTO we need the mode of
+	 * the new channel, not the old!
+	 */
+	if (ztv-&gt;channel != channel) {
+		/* set the new channel */
+		rv = zoran_i2c_command(ztv, DECODER_SET_INPUT, &amp;channel);
+		ztv-&gt;channel = channel;
+		changed = 1;
+	}
+
+	/* set the new video mode */
+	if (changed || ztv-&gt;mode == VIDEO_MODE_AUTO || ztv-&gt;mode != mode) {
+		rv = zoran_i2c_command(ztv, DECODER_SET_NORM, &amp;mode);
+		if (rv)
+			return rv;
+		ztv-&gt;mode = mode;
+	}
+
 	return rv;
 }
 
@@ -403,7 +472,7 @@
 static
 void zoran_cap(struct zoran* ztv, int on)
 {
-DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv-&gt;state));
+	dprintk(2, CARD_DEBUG "zoran_cap(%d) state=%lx\n", CARD, on, ztv-&gt;state);
 
 	if (on) {
 		ztv-&gt;running = 1;
@@ -443,12 +512,14 @@
 	int	ystep = (ztv-&gt;vidXshift + ztv-&gt;vidWidth+31)/32;	/* next DWORD */
 	int	i;
 
-DEBUG(printk(KERN_DEBUG "       overlay at %p, ystep=%d, clips=%d\n",ztv-&gt;overinfo.overlay,ystep,count));
+	dprintk(2, KERN_DEBUG "       overlay at %p, ystep=%d, clips=%d\n",
+		ztv-&gt;overinfo.overlay, ystep, count);
 
 	for (i=0; i&lt;count; i++) {
 		struct video_clip *vp = vcp+i;
 		UNUSED(vp);
-DEBUG(printk(KERN_DEBUG "       %d: clip(%d,%d,%d,%d)\n", i,vp-&gt;x,vp-&gt;y,vp-&gt;width,vp-&gt;height));
+	dprintk(2, KERN_DEBUG "       %d: clip(%d,%d,%d,%d)\n",
+		i, vp-&gt;x, vp-&gt;y, vp-&gt;width, vp-&gt;height);
 	}
 
 	/*
@@ -485,7 +556,10 @@
 		    vcp-&gt;width &lt; 0 || (uint)(vcp-&gt;x+vcp-&gt;width) &gt; ztv-&gt;overinfo.w ||
 		    vcp-&gt;height &lt; 0 || (vcp-&gt;y+vcp-&gt;height) &gt; ztv-&gt;overinfo.h)
 		{
-			DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp-&gt;x,vcp-&gt;y,vcp-&gt;width,vcp-&gt;height,ztv-&gt;overinfo.w,ztv-&gt;overinfo.h));
+			dprintk(2,
+				CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",
+				CARD, vcp-&gt;x, vcp-&gt;y, vcp-&gt;width, vcp-&gt;height,
+				ztv-&gt;overinfo.w, ztv-&gt;overinfo.h);
 			if (vcp-&gt;x &lt; 0) vcp-&gt;x = 0;
 			if ((uint)vcp-&gt;x &gt; ztv-&gt;overinfo.w) vcp-&gt;x = ztv-&gt;overinfo.w;
 			if (vcp-&gt;y &lt; 0) vcp-&gt;y = 0;
@@ -516,26 +590,6 @@
 	zraor((ztv-&gt;vidInterlace*ystep)&lt;&lt;0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR);
 }
 
-struct tvnorm 
-{
-	u16 Wt, Wa, Ht, Ha, HStart, VStart;
-};
-
-static struct tvnorm tvnorms[] = {
-	/* PAL-BDGHI */
-/*	{ 864, 720, 625, 576, 131, 21 },*/
-/*00*/	{ 864, 768, 625, 576, 81, 17 },
-	/* NTSC */
-/*01*/	{ 858, 720, 525, 480, 121, 10 },
-	/* SECAM */
-/*02*/	{ 864, 720, 625, 576, 131, 21 },
-	/* BW50 */
-/*03*/	{ 864, 720, 625, 576, 131, 21 },
-	/* BW60 */
-/*04*/	{ 858, 720, 525, 480, 121, 10 }
-};
-#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
-
 /*
  * Program the chip for a setup as described in the vidinfo struct.
  *
@@ -556,7 +610,10 @@
 	int	maxWidth, maxHeight, maxXOffset, maxYOffset;
 	long	vfec;
 
-DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i-&gt;x,i-&gt;y,i-&gt;w,i-&gt;h,ztv-&gt;norm,i-&gt;format,i-&gt;bpp,i-&gt;bpl,i-&gt;busadr,i-&gt;overlay));
+	dprintk(2,
+		CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), mode=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",
+		CARD, i-&gt;x, i-&gt;y, i-&gt;w, i-&gt;h, ztv-&gt;mode, i-&gt;format, i-&gt;bpp,
+		i-&gt;bpl, i-&gt;busadr, i-&gt;overlay);
 
 	/*
 	 * make sure the DMA transfers are inhibited during our
@@ -564,10 +621,10 @@
 	 */
 	zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
 
-	maxWidth = tvnorms[ztv-&gt;norm].Wa;
-	maxHeight = tvnorms[ztv-&gt;norm].Ha/2;
-	maxXOffset = tvnorms[ztv-&gt;norm].HStart;
-	maxYOffset = tvnorms[ztv-&gt;norm].VStart;
+	maxWidth = tvmodes[ztv-&gt;mode].Wa;
+	maxHeight = tvmodes[ztv-&gt;mode].Ha/2;
+	maxXOffset = tvmodes[ztv-&gt;mode].HStart;
+	maxYOffset = tvmodes[ztv-&gt;mode].VStart;
 
 	/* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */
 	vfec = (zrread(ZORAN_VFEC) &amp; (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) |
@@ -587,7 +644,8 @@
 	if (top &amp; 3) {
 		ztv-&gt;vidXshift = (top &amp; 3) / i-&gt;bpp;
 		winWidth += ztv-&gt;vidXshift;
-		DEBUG(printk(KERN_DEBUG "       window-x shifted %d pixels left\n",ztv-&gt;vidXshift));
+		dprintk(2, KERN_DEBUG "       window-x shifted %d pixels left\n",
+			ztv-&gt;vidXshift);
 		top &amp;= ~3;
 	}
 
@@ -606,7 +664,8 @@
 	 * next line is DWORD aligned too (as required by spec).
 	 */
 	if ((winWidth*i-&gt;bpp) &amp; 3) {
-DEBUG(printk(KERN_DEBUG "       window-width enlarged by %d pixels\n",(winWidth*i-&gt;bpp) &amp; 3));
+		dprintk(2, KERN_DEBUG "       window-width enlarged by %d pixels\n",
+			(winWidth*i-&gt;bpp) &amp; 3);
 		winWidth += (winWidth*i-&gt;bpp) &amp; 3;
 	}
 
@@ -629,7 +688,7 @@
 
 	/* safety net, sometimes bpl is too short??? */
 	if (stride&lt;0) {
-DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride));
+		dprintk(2, CARD_DEBUG "WARNING stride = %d\n", CARD, stride);
 		stride = 0;
 	}
 
@@ -639,10 +698,10 @@
 	/* remember vidWidth, vidHeight for overlay calculations */
 	ztv-&gt;vidWidth = winWidth;
 	ztv-&gt;vidHeight = winHeight;
-DEBUG(printk(KERN_DEBUG "       top=%08lx, bottom=%08lx\n",top,bot));
-DEBUG(printk(KERN_DEBUG "       winWidth=%d, winHeight=%d\n",winWidth,winHeight));
-DEBUG(printk(KERN_DEBUG "       maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight));
-DEBUG(printk(KERN_DEBUG "       stride=%d\n",stride));
+	dprintk(2, KERN_DEBUG "       top=%08lx, bottom=%08lx\n", top, bot);
+	dprintk(2, KERN_DEBUG "       winWidth=%d, winHeight=%d\n", winWidth, winHeight);
+	dprintk(2, KERN_DEBUG "       maxWidth=%d, maxHeight=%d\n", maxWidth, maxHeight);
+	dprintk(2, KERN_DEBUG "       stride=%d\n", stride);
 
 	/*
 	 * determine horizontal scales and crops
@@ -650,7 +709,8 @@
 	if (i-&gt;w &lt; 0) {
 		int Hstart = 1;
 		int Hend = Hstart + winWidth;
-DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Hstart, Hend));
+		dprintk(2, KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n",
+			Hstart, Hend);
 		zraor((Hstart&lt;&lt;10)|(Hend&lt;&lt;0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
 	}
 	else {
@@ -667,7 +727,8 @@
 		int Hstart = (maxXOffset + hcrop1) | 1;
 		int Hend = Hstart + We - 1;
 
-DEBUG(printk(KERN_DEBUG "       X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend));
+		dprintk(2, KERN_DEBUG "       X: scale=%d, start=%d, end=%d\n",
+			HorDcm, Hstart, Hend);
 
 		zraor((Hstart&lt;&lt;10)|(Hend&lt;&lt;0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
 		vfec |= HorDcm&lt;&lt;14;
@@ -690,7 +751,8 @@
 	if (i-&gt;h &lt; 0) {
 		int Vstart = 0;
 		int Vend = Vstart + winHeight;
-DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Vstart, Vend));
+		dprintk(2, KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n",
+			Vstart, Vend);
 		zraor((Vstart&lt;&lt;10)|(Vend&lt;&lt;0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
 	}
 	else {
@@ -702,12 +764,14 @@
 		int Vstart = maxYOffset + vcrop1;
 		int Vend = Vstart + He - 1;
 
-DEBUG(printk(KERN_DEBUG "       Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend));
+		dprintk(2, KERN_DEBUG "       Y: scale=%d, start=%d, end=%d\n",
+			VerDcm, Vstart, Vend);
 		zraor((Vstart&lt;&lt;10)|(Vend&lt;&lt;0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
 		vfec |= VerDcm&lt;&lt;8;
 	}
 
-DEBUG(printk(KERN_DEBUG "       F: format=%d(=%s)\n",i-&gt;format,palette2fmt[i-&gt;format].name));
+	dprintk(2, KERN_DEBUG "       F: format=%d(=%s)\n",
+		i-&gt;format, palette2fmt[i-&gt;format].name);
 
 	/* setup the requested format */
 	zrwrite(vfec, ZORAN_VFEC);
@@ -732,10 +796,10 @@
 	ztv-&gt;picture.brightness=128&lt;&lt;8;
 	ztv-&gt;picture.hue=128&lt;&lt;8;
 	ztv-&gt;picture.contrast=216&lt;&lt;7;
-	i2c_control_device(&amp;ztv-&gt;i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &amp;ztv-&gt;picture);
+	zoran_i2c_command(ztv, DECODER_SET_PICTURE, &amp;ztv-&gt;picture);
 
 	/* default to the composite input since my camera is there */
-	zoran_muxsel(ztv, 0, VIDEO_MODE_PAL);
+	zoran_muxsel(ztv, 0, mode);
 }
 
 static
@@ -754,13 +818,46 @@
 /*
  * 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-&gt;i_rdev);
+	struct zoran *ztv = NULL;
 	struct vidinfo* item;
 	char* pos;
+	int i;
+
+	if (!try_module_get(THIS_MODULE)) {
+		dprintk(0, KERN_ERR "failed to acquire lock on myself\n");
+		return -EIO;
+	}
+
+	/* find the device */
+	for (i = 0; i &lt; zoran_cards; i++) {
+		if (zorans[i].video_dev-&gt;minor == minor) {
+			ztv = &amp;zorans[i];
+			break;
+		}
+	}
+	if (!ztv)
+		return -ENODEV;
+
+	if (ztv-&gt;have_decoder &amp;&amp;
+	    !try_module_get(ztv-&gt;decoder-&gt;driver-&gt;owner)) {
+		dprintk(0, KERN_ERR "Failed to acquire lock on TV decoder\n");
+		module_put(THIS_MODULE);
+		return -EIO;
+	} 
+	if (ztv-&gt;have_tuner &amp;&amp;
+	    !try_module_get(ztv-&gt;tuner-&gt;driver-&gt;owner)) {
+		dprintk(0, KERN_ERR "Failed to acquire lock on TV tuner\n");
+		if (ztv-&gt;have_decoder)
+			module_put(ztv-&gt;decoder-&gt;driver-&gt;owner);
+		module_put(THIS_MODULE);
+		return -EIO;
+	}
 
-	DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags));
+	dprintk(2, CARD_DEBUG "open(dev,%d)\n", CARD, file-&gt;f_flags);
 
 	/*********************************************
 	 * We really should be doing lazy allocing...
@@ -769,7 +866,13 @@
 	if (!ztv-&gt;fbuffer)
 		ztv-&gt;fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE);
 	if (!ztv-&gt;fbuffer) {
+		dprintk(0, KERN_INFO "Memory allocation failed\n");
 		/* could not get a buffer, bail out */
+		module_put(THIS_MODULE);
+		if (ztv-&gt;have_decoder)
+			module_put(ztv-&gt;decoder-&gt;driver-&gt;owner);
+		if (ztv-&gt;have_tuner)
+			module_put(ztv-&gt;tuner-&gt;driver-&gt;owner);
 		return -ENOBUFS;
 	}
 	/* at this time we _always_ have a framebuffer */
@@ -778,8 +881,14 @@
 	if (!ztv-&gt;overinfo.overlay)
 		ztv-&gt;overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL);
 	if (!ztv-&gt;overinfo.overlay) {
+		dprintk(0, KERN_INFO "zr32120: Overlay memory allocation failed\n");
 		/* could not get an overlay buffer, bail out */
 		bfree(ztv-&gt;fbuffer, ZORAN_MAX_FBUFSIZE);
+		module_put(THIS_MODULE);
+		if (ztv-&gt;have_decoder)
+			module_put(ztv-&gt;decoder-&gt;driver-&gt;owner);
+		if (ztv-&gt;have_tuner)
+			module_put(ztv-&gt;tuner-&gt;driver-&gt;owner);
 		return -ENOBUFS;
 	}
 	/* at this time we _always_ have a overlay */
@@ -795,22 +904,26 @@
 	}
 
 	/* do the common part of all open's */
-	zoran_common_open(ztv, flags);
+	zoran_common_open(ztv, file-&gt;f_flags);
+
+	file-&gt;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-&gt;private_data;
 
-	DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD));
+	UNUSED(inode);
+	dprintk(2, CARD_DEBUG "close(dev)\n", CARD);
 
 	/* driver specific closure */
 	clear_bit(STATE_OVERLAY, &amp;ztv-&gt;state);
 
 	zoran_common_close(ztv);
+	file-&gt;private_data = NULL;
 
         /*
          *      This is sucky but right now I can't find a good way to
@@ -825,6 +938,13 @@
 	kfree(ztv-&gt;overinfo.overlay);
 	ztv-&gt;overinfo.overlay = 0;
 
+	module_put(THIS_MODULE);
+	if (ztv-&gt;have_decoder)
+		module_put(ztv-&gt;decoder-&gt;driver-&gt;owner);
+	if (ztv-&gt;have_tuner)
+		module_put(ztv-&gt;tuner-&gt;driver-&gt;owner);
+
+	return 0;
 }
 
 /*
@@ -835,14 +955,17 @@
  * 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-&gt;private_data;
 	unsigned long max;
 	struct vidinfo* unused = 0;
 	struct vidinfo* done = 0;
+	int nonblock = file-&gt;f_flags &amp; O_NONBLOCK;
 
-	DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock));
+	UNUSED(ppos);
+	dprintk(2, CARD_DEBUG "zoran_read(%p,%ld,%d)\n",
+		CARD, buf, (long)count, nonblock);
 
 	/* find ourself a free or completed buffer */
 	for (;;) {
@@ -923,23 +1046,23 @@
 	wake_up_interruptible(&amp;ztv-&gt;grabq);
 
 	/* goodbye */
-	DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count));
+	dprintk(2, CARD_DEBUG "zoran_read() returns %lu\n", CARD, (long)count);
 	return count;
 }
 
 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);
-	DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD));
+	struct zoran *ztv = file-&gt;private_data;
+	UNUSED(ztv); UNUSED(data); UNUSED(count); UNUSED(ppos);
+	dprintk(2, 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-&gt;private_data;
 	struct vidinfo* item;
 	unsigned int mask = 0;
 
@@ -952,7 +1075,7 @@
 			break;
 		}
 
-	DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask));
+	dprintk(2, CARD_DEBUG "zoran_poll()=%x\n", CARD, mask);
 
 	return mask;
 }
@@ -969,237 +1092,235 @@
 }
 
 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-&gt;private_data;
+
+	UNUSED(inode);
 
 	switch (cmd) {
 	 case VIDIOCGCAP:
 	 {
-		struct video_capability c;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD));
+		struct video_capability* c = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGCAP\n", CARD);
 
-		strcpy(c.name,ztv-&gt;video_dev.name);
-		c.type = VID_TYPE_CAPTURE|
+                memset(c, 0, sizeof(struct video_capability));
+		strcpy(c-&gt;name,ztv-&gt;video_dev-&gt;name);
+		c-&gt;type = VID_TYPE_CAPTURE|
 			 VID_TYPE_OVERLAY|
 			 VID_TYPE_CLIPPING|
 			 VID_TYPE_FRAMERAM|
 			 VID_TYPE_SCALES;
 		if (ztv-&gt;have_tuner)
-			c.type |= VID_TYPE_TUNER;
+			c-&gt;type |= VID_TYPE_TUNER;
 		if (ztv-&gt;have_decoder) {
-			c.channels = ztv-&gt;card-&gt;video_inputs;
-			c.audios = ztv-&gt;card-&gt;audio_inputs;
+			c-&gt;channels = ztv-&gt;card-&gt;video_inputs;
+			c-&gt;audios = ztv-&gt;card-&gt;audio_inputs;
 		} else
 			/* no decoder -&gt; no channels */
-			c.channels = c.audios = 0;
-		c.maxwidth = 768;
-		c.maxheight = 576;
-		c.minwidth = 32;
-		c.minheight = 32;
-		if (copy_to_user(arg,&amp;c,sizeof(c)))
-			return -EFAULT;
+			c-&gt;channels = c-&gt;audios = 0;
+		c-&gt;maxwidth = tvmodes[ztv-&gt;mode].Wa;	/*768*/
+		c-&gt;maxheight = tvmodes[ztv-&gt;mode].Ha;	/*576*/
+		c-&gt;minwidth = 32;
+		c-&gt;minheight = 32;
 		break;
 	 }
 
 	 case VIDIOCGCHAN:
 	 {
-		struct video_channel v;
+		struct video_channel* v = arg;
 		int mux;
-		if (copy_from_user(&amp;v, arg,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel));
-		v.flags=VIDEO_VC_AUDIO
-#ifdef VIDEO_VC_NORM
-			|VIDEO_VC_NORM
-#endif
-			;
-		v.tuners=0;
-		v.type=VIDEO_TYPE_CAMERA;
-#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API
-		v.norm=VIDEO_MODE_PAL|
-		       VIDEO_MODE_NTSC|
-		       VIDEO_MODE_SECAM;
-#else
-		v.norm=VIDEO_MODE_PAL;
-#endif
+                int channel = v-&gt;channel;
+
+		dprintk(1, CARD_DEBUG "VIDIOCGCHAN(%d)\n", CARD, v-&gt;channel);
+                memset(v, 0, sizeof(struct video_channel));
+		v-&gt;flags = VIDEO_VC_AUDIO;
+		v-&gt;tuners = 0;
+		v-&gt;type = VIDEO_TYPE_CAMERA;
+		v-&gt;norm = ztv-&gt;mode;
 		/* too many inputs? no decoder -&gt; no channels */
-		if (!ztv-&gt;have_decoder || v.channel &lt; 0 ||  v.channel &gt;= ztv-&gt;card-&gt;video_inputs)
+		if (!ztv-&gt;have_decoder || channel &lt; 0 || channel &gt;= ztv-&gt;card-&gt;video_inputs)
+		{
+			dprintk(1, CARD_DEBUG "VIDIOCGCHAN invalid\n", CARD);
 			return -EINVAL;
+		}
 
 		/* now determine the name of the channel */
-		mux = ztv-&gt;card-&gt;video_mux[v.channel];
+		mux = ztv-&gt;card-&gt;video_mux[channel];
 		if (mux &amp; IS_TUNER) {
 			/* lets assume only one tuner, yes? */
-			strcpy(v.name,"Television");
-			v.type = VIDEO_TYPE_TV;
+			strcpy(v-&gt;name,"Television");
+			v-&gt;type = VIDEO_TYPE_TV;
 			if (ztv-&gt;have_tuner) {
-				v.flags |= VIDEO_VC_TUNER;
-				v.tuners = 1;
+				v-&gt;flags |= VIDEO_VC_TUNER;
+				v-&gt;tuners = 1;
 			}
 		}
 		else if (mux &amp; IS_SVHS)
-			sprintf(v.name,"S-Video-%d",v.channel);
+			sprintf(v-&gt;name, "S-Video-%d", channel);
 		else
-			sprintf(v.name,"CVBS-%d",v.channel);
+			sprintf(v-&gt;name, "CVBS-%d", channel);
 
-		if (copy_to_user(arg,&amp;v,sizeof(v)))
-			return -EFAULT;
 		break;
 	 }
+
 	 case VIDIOCSCHAN:
 	 {	/* set video channel */
-		struct video_channel v;
-		if (copy_from_user(&amp;v, arg,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm));
+		struct video_channel* v=arg;
+		dprintk(1, CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n", CARD, v-&gt;channel, v-&gt;norm);
 
 		/* too many inputs? no decoder -&gt; no channels */
-		if (!ztv-&gt;have_decoder || v.channel &gt;= ztv-&gt;card-&gt;video_inputs || v.channel &lt; 0)
+		if (!ztv-&gt;have_decoder || v-&gt;channel &gt;= ztv-&gt;card-&gt;video_inputs || v-&gt;channel &lt; 0)
+		{
+			dprintk(1, CARD_DEBUG" VIDIOSCHAN invalid\n", CARD);
 			return -EINVAL;
+		}
 
-		if (v.norm != VIDEO_MODE_PAL &amp;&amp;
-		    v.norm != VIDEO_MODE_NTSC &amp;&amp;
-		    v.norm != VIDEO_MODE_SECAM &amp;&amp;
-		    v.norm != VIDEO_MODE_AUTO)
+		if (v-&gt;norm != VIDEO_MODE_PAL &amp;&amp;
+		    v-&gt;norm != VIDEO_MODE_NTSC &amp;&amp;
+		    v-&gt;norm != VIDEO_MODE_SECAM &amp;&amp;
+		    v-&gt;norm != VIDEO_MODE_AUTO)
 			return -EOPNOTSUPP;
 
 		/* make it happen, nr1! */
-		return zoran_muxsel(ztv,v.channel,v.norm);
+		return zoran_muxsel(ztv, v-&gt;channel, v-&gt;norm);
 	 }
 
 	 case VIDIOCGTUNER:
 	 {
-		struct video_tuner v;
-		if (copy_from_user(&amp;v, arg,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner));
+		struct video_tuner* v=arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGTUNER(%d)\n", CARD, v-&gt;tuner);
 
 		/* Only no or one tuner for now */
-		if (!ztv-&gt;have_tuner || v.tuner)
+		if (!ztv-&gt;have_tuner || v-&gt;tuner)
 			return -EINVAL;
 
-		strcpy(v.name,"Television");
-		v.rangelow  = 0;
-		v.rangehigh = ~0;
-		v.flags     = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
-		v.mode      = ztv-&gt;norm;
-		v.signal    = 0xFFFF; /* unknown */
+		/*memset(v, 0, sizeof(struct video_tuner));*/
+		strcpy(v-&gt;name,"Television");
+		v-&gt;rangelow  = 0;
+		v-&gt;rangehigh = ~0;
+		v-&gt;flags     = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+		v-&gt;mode      = ztv-&gt;mode;
+		v-&gt;signal    = 0xFFFF; /* unknown */
 
-		if (copy_to_user(arg,&amp;v,sizeof(v)))
-			return -EFAULT;
 		break;
 	 }
+
 	 case VIDIOCSTUNER:
 	 {
-		struct video_tuner v;
-		if (copy_from_user(&amp;v, arg, sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode));
+		struct video_tuner* v=arg;
+		dprintk(1, CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n", CARD, v-&gt;tuner, v-&gt;mode);
 
 		/* Only no or one tuner for now */
-		if (!ztv-&gt;have_tuner || v.tuner)
+		if (!ztv-&gt;have_tuner || v-&gt;tuner)
 			return -EINVAL;
 
 		/* and it only has certain valid modes */
-		if( v.mode != VIDEO_MODE_PAL &amp;&amp;
-		    v.mode != VIDEO_MODE_NTSC &amp;&amp;
-		    v.mode != VIDEO_MODE_SECAM)
+		if( v-&gt;mode != VIDEO_MODE_PAL &amp;&amp;
+		    v-&gt;mode != VIDEO_MODE_NTSC &amp;&amp;
+		    v-&gt;mode != VIDEO_MODE_SECAM)
 			return -EOPNOTSUPP;
 
 		/* engage! */
-		return zoran_muxsel(ztv,v.tuner,v.mode);
+		return zoran_muxsel(ztv, v-&gt;tuner, v-&gt;mode);
 	 }
 
 	 case VIDIOCGPICT:
 	 {
-		struct video_picture p = ztv-&gt;picture;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD));
-		p.depth = ztv-&gt;depth;
-		switch (p.depth) {
-		 case  8: p.palette=VIDEO_PALETTE_YUV422;
-			  break;
-		 case 15: p.palette=VIDEO_PALETTE_RGB555;
-			  break;
-		 case 16: p.palette=VIDEO_PALETTE_RGB565;
-			  break;
-		 case 24: p.palette=VIDEO_PALETTE_RGB24;
-			  break;
-		 case 32: p.palette=VIDEO_PALETTE_RGB32;
-			  break;
-		}
-		if (copy_to_user(arg, &amp;p, sizeof(p)))
-			return -EFAULT;
+		struct video_picture* p = &amp;(ztv-&gt;picture);
+		struct video_picture* parg = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGPICT\n", CARD);
+		p-&gt;depth = ztv-&gt;depth;
+                p-&gt;palette = ztv-&gt;overinfo.format;
+		memcpy(parg, p, sizeof(struct video_picture));
 		break;
 	 }
+
 	 case VIDIOCSPICT:
 	 {
-		struct video_picture p;
-		if (copy_from_user(&amp;p, arg,sizeof(p)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette));
+		struct video_picture* p = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n", CARD,
+			p-&gt;brightness, p-&gt;hue, p-&gt;colour, p-&gt;contrast, p-&gt;whiteness,
+			p-&gt;depth, p-&gt;palette);
 
 		/* depth must match with framebuffer */
-		if (p.depth != ztv-&gt;depth)
+		if (p-&gt;depth != ztv-&gt;depth)
 			return -EINVAL;
 
 		/* check if palette matches this bpp */
-		if (p.palette&gt;NRPALETTES ||
-		    palette2fmt[p.palette].bpp != ztv-&gt;overinfo.bpp)
+		if (p-&gt;palette&gt;NRPALETTES ||
+		    palette2fmt[p-&gt;palette].bpp != ztv-&gt;overinfo.bpp)
 			return -EINVAL;
 
 		write_lock_irq(&amp;ztv-&gt;lock);
-		ztv-&gt;overinfo.format = p.palette;
-		ztv-&gt;picture = p;
+		ztv-&gt;overinfo.format = p-&gt;palette;
+		ztv-&gt;picture = *p;
 		write_unlock_irq(&amp;ztv-&gt;lock);
 
 		/* tell the decoder */
-		i2c_control_device(&amp;ztv-&gt;i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &amp;p);
+		zoran_i2c_command(ztv, DECODER_SET_PICTURE, &amp;p);
 		break;
 	 }
 
 	 case VIDIOCGWIN:
 	 {
-		struct video_window vw;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD));
+		struct video_window* vw = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGWIN\n", CARD);
+		memset(vw, 0, sizeof(struct video_window));
 		read_lock(&amp;ztv-&gt;lock);
-		vw.x      = ztv-&gt;overinfo.x;
-		vw.y      = ztv-&gt;overinfo.y;
-		vw.width  = ztv-&gt;overinfo.w;
-		vw.height = ztv-&gt;overinfo.h;
-		vw.chromakey= 0;
-		vw.flags  = 0;
+		vw-&gt;x      = ztv-&gt;overinfo.x;
+		vw-&gt;y      = ztv-&gt;overinfo.y;
+		vw-&gt;width  = ztv-&gt;overinfo.w;
+		vw-&gt;height = ztv-&gt;overinfo.h;
+		vw-&gt;chromakey= 0;
+		vw-&gt;flags  = 0;
 		if (ztv-&gt;vidInterlace)
-			vw.flags|=VIDEO_WINDOW_INTERLACE;
+			vw-&gt;flags|=VIDEO_WINDOW_INTERLACE;
 		read_unlock(&amp;ztv-&gt;lock);
-		if (copy_to_user(arg,&amp;vw,sizeof(vw)))
-			return -EFAULT;
 		break;
 	 }
+
 	 case VIDIOCSWIN:
 	 {
-		struct video_window vw;
-		struct video_clip *vcp;
+		struct video_window* vw = arg;
+		struct video_clip *vcp = NULL;
 		int on;
-		if (copy_from_user(&amp;vw,arg,sizeof(vw)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount));
+		dprintk(1, CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n", CARD,
+			vw-&gt;x, vw-&gt;y, vw-&gt;width, vw-&gt;height, vw-&gt;flags, vw-&gt;clipcount);
 
-		if (vw.flags)
+		if (vw-&gt;flags ||
+			vw-&gt;width&lt;32 || vw-&gt;width&gt;tvmodes[ztv-&gt;mode].Wa ||
+			vw-&gt;height&lt;32 || vw-&gt;height&gt;tvmodes[ztv-&gt;mode].Ha)
 			return -EINVAL;
 
-		if (vw.clipcount &lt;0 || vw.clipcount&gt;256)
+		if (vw-&gt;clipcount != VIDEO_CLIP_BITMAP &amp;&amp;
+			(vw-&gt;clipcount &lt;0 || vw-&gt;clipcount&gt;256))
 			return -EDOM;   /* Too many! */
 
 		/*
-		 *      Do any clips.
-		 */
-		vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
-		if (vcp==NULL)
-			return -ENOMEM;
-		if (vw.clipcount &amp;&amp; copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {
-			vfree(vcp);
-			return -EFAULT;
+		*      Do any clips. Note that it now possble
+		*      to get a clipmap when clipcount has a
+		*      'magic' value. In a clipmap, '1' denotes
+		*      a clipped pixel, not a visible pixel!
+		*/
+		if (vw-&gt;clipcount == VIDEO_CLIP_BITMAP) {
+			vcp = vmalloc(VIDEO_CLIPMAP_SIZE);
+			if (vcp == NULL)
+				return -ENOMEM;
+			if (copy_from_user(vcp, vw-&gt;clips, VIDEO_CLIPMAP_SIZE)) {
+				dprintk(1, CARD_DEBUG "VIDIOCSWIN copy error[1]\n", CARD);
+				vfree(vcp);
+				return -EFAULT;
+			}
+		} else if (vw-&gt;clipcount) {
+			vcp = vmalloc(sizeof(struct video_clip)*(vw-&gt;clipcount+4));
+			if (vcp==NULL)
+				return -ENOMEM;
+			if (vw-&gt;clipcount &amp;&amp; copy_from_user(vcp, vw-&gt;clips, sizeof(struct video_clip)*vw-&gt;clipcount)) {
+				dprintk(1, CARD_DEBUG "VIDIOCSWIN copy error[2]\n", CARD);
+				vfree(vcp);
+				return -EFAULT;
+			}
 		}
 
 		on = ztv-&gt;running;
@@ -1208,32 +1329,32 @@
 
 		/*
 		 * strange, it seems xawtv sometimes calls us with 0
-		 * width and/or height. Ignore these values
+		 * x and/or y position. Ignore these values
 		 */
-		if (vw.x == 0)
-			vw.x = ztv-&gt;overinfo.x;
-		if (vw.y == 0)
-			vw.y = ztv-&gt;overinfo.y;
+		if (vw-&gt;x == 0)
+			vw-&gt;x = ztv-&gt;overinfo.x;
+		if (vw-&gt;y == 0)
+			vw-&gt;y = ztv-&gt;overinfo.y;
 
 		/* by now we are committed to the new data... */
 		write_lock_irq(&amp;ztv-&gt;lock);
-		ztv-&gt;overinfo.x = vw.x;
-		ztv-&gt;overinfo.y = vw.y;
-		ztv-&gt;overinfo.w = vw.width;
-		ztv-&gt;overinfo.h = vw.height;
+		ztv-&gt;overinfo.x = vw-&gt;x;
+		ztv-&gt;overinfo.y = vw-&gt;y;
+		ztv-&gt;overinfo.w = vw-&gt;width;
+		ztv-&gt;overinfo.h = vw-&gt;height;
 		write_unlock_irq(&amp;ztv-&gt;lock);
 
 		/*
 		 *      Impose display clips
 		 */
-		if (vw.x+vw.width &gt; ztv-&gt;swidth)
-			new_clip(&amp;vw, vcp, ztv-&gt;swidth-vw.x, 0, vw.width-1, vw.height-1);
-		if (vw.y+vw.height &gt; ztv-&gt;sheight)
-			new_clip(&amp;vw, vcp, 0, ztv-&gt;sheight-vw.y, vw.width-1, vw.height-1);
+		if (vw-&gt;x+vw-&gt;width &gt; ztv-&gt;swidth)
+			new_clip(vw, vcp, ztv-&gt;swidth-vw-&gt;x, 0, vw-&gt;width-1, vw-&gt;height-1);
+		if (vw-&gt;y+vw-&gt;height &gt; ztv-&gt;sheight)
+			new_clip(vw, vcp, 0, ztv-&gt;sheight-vw-&gt;y, vw-&gt;width-1, vw-&gt;height-1);
 
 		/* built the requested clipping zones */
 		zoran_set_geo(ztv, &amp;ztv-&gt;overinfo);
-		zoran_built_overlay(ztv, vw.clipcount, vcp);
+		zoran_built_overlay(ztv, vw-&gt;clipcount, vcp);
 		vfree(vcp);
 
 		/* if we were on, restart the video engine */
@@ -1244,19 +1365,20 @@
 
 	 case VIDIOCCAPTURE:
 	 {
-		int v;
-		if (get_user(v, (int *)arg))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v));
+		int* v = (int*)arg;
+		dprintk(1, CARD_DEBUG "VIDIOCCAPTURE(%d)\n", CARD, *v);
 
-		if (v==0) {
+		if (*v == 0) {
 			clear_bit(STATE_OVERLAY, &amp;ztv-&gt;state);
 			zoran_cap(ztv, 1);
 		}
 		else {
 			/* is VIDIOCSFBUF, VIDIOCSWIN done? */
-			if (ztv-&gt;overinfo.busadr==0 || ztv-&gt;overinfo.w==0 || ztv-&gt;overinfo.h==0)
+			if (ztv-&gt;overinfo.busadr==0 || ztv-&gt;overinfo.w&lt;32 || ztv-&gt;overinfo.h&lt;32)
+			{
+				dprintk(1, CARD_DEBUG "VIDIOCAPTURE not done\n", CARD);
 				return -EINVAL;
+			}
 
 			set_bit(STATE_OVERLAY, &amp;ztv-&gt;state);
 			zoran_cap(ztv, 1);
@@ -1266,41 +1388,39 @@
 
 	 case VIDIOCGFBUF:
 	 {
-		struct video_buffer v;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD));
+		struct video_buffer* v=arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGFBUF\n",CARD);
 		read_lock(&amp;ztv-&gt;lock);
-		v.base   = (void *)ztv-&gt;overinfo.busadr;
-		v.height = ztv-&gt;sheight;
-		v.width  = ztv-&gt;swidth;
-		v.depth  = ztv-&gt;depth;
-		v.bytesperline = ztv-&gt;overinfo.bpl;
+		v-&gt;base   = (void *)ztv-&gt;overinfo.busadr;
+		v-&gt;height = ztv-&gt;sheight;
+		v-&gt;width  = ztv-&gt;swidth;
+		v-&gt;depth  = ztv-&gt;depth;
+		v-&gt;bytesperline = ztv-&gt;overinfo.bpl;
 		read_unlock(&amp;ztv-&gt;lock);
-		if(copy_to_user(arg, &amp;v,sizeof(v)))
-			return -EFAULT;
 		break;
 	 }
+
 	 case VIDIOCSFBUF:
 	 {
-		struct video_buffer v;
+		struct video_buffer* v=arg;
 		if(!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&amp;v, arg,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline));
+		dprintk(1, CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n", CARD,
+			v-&gt;base, v-&gt;width, v-&gt;height, v-&gt;depth, v-&gt;bytesperline);
 
-		if (v.depth!=15 &amp;&amp; v.depth!=16 &amp;&amp; v.depth!=24 &amp;&amp; v.depth!=32)
+		if (v-&gt;depth!=15 &amp;&amp; v-&gt;depth!=16 &amp;&amp; v-&gt;depth!=24 &amp;&amp; v-&gt;depth!=32)
 			return -EINVAL;
-		if (v.bytesperline&lt;1)
+		if (v-&gt;bytesperline&lt;1)
 			return -EINVAL;
 		if (ztv-&gt;running)
 			return -EBUSY;
 		write_lock_irq(&amp;ztv-&gt;lock);
-		ztv-&gt;overinfo.busadr  = (ulong)v.base;
-		ztv-&gt;sheight      = v.height;
-		ztv-&gt;swidth       = v.width;
-		ztv-&gt;depth        = v.depth;		/* bits per pixel */
-		ztv-&gt;overinfo.bpp = ((v.depth+1)&amp;0x38)/8;/* bytes per pixel */
-		ztv-&gt;overinfo.bpl = v.bytesperline;	/* bytes per line */
+		ztv-&gt;overinfo.busadr  = (ulong)v-&gt;base;
+		ztv-&gt;sheight      = v-&gt;height;
+		ztv-&gt;swidth       = v-&gt;width;
+		ztv-&gt;depth        = v-&gt;depth;		/* bits per pixel */
+		ztv-&gt;overinfo.bpp = ((v-&gt;depth+1)&amp;0x38)/8;/* bytes per pixel */
+		ztv-&gt;overinfo.bpl = v-&gt;bytesperline;	/* bytes per line */
 		write_unlock_irq(&amp;ztv-&gt;lock);
 		break;
 	 }
@@ -1313,58 +1433,64 @@
 
 	 case VIDIOCSYNC:
 	 {
-		int i;
-		if (get_user(i, (int *) arg))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i));
-		if (i&lt;0 || i&gt;ZORAN_MAX_FBUFFERS)
-			return -EINVAL;
-		switch (ztv-&gt;grabinfo[i].status) {
-		 case FBUFFER_FREE:
+		int* i = arg;
+		dprintk(1, CARD_DEBUG "VIDEOCSYNC(%d)\n", CARD, *i);
+		if (*i&lt;0 || *i&gt;ZORAN_MAX_FBUFFERS)
+		{
+			dprintk(1, CARD_DEBUG "VIDEOCSYNC invalid buffer\n", CARD);
 			return -EINVAL;
-		 case FBUFFER_BUSY:
-			/* wait till this buffer gets grabbed */
-			wait_event_interruptible(ztv-&gt;grabq,
-					(ztv-&gt;grabinfo[i].status != FBUFFER_BUSY));
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -EINTR;
-			/* don't fall through; a DONE buffer is not UNUSED */
-			break;
-		 case FBUFFER_DONE:
-			ztv-&gt;grabinfo[i].status = FBUFFER_FREE;
-			/* tell ppl we have a spare buffer */
-			wake_up_interruptible(&amp;ztv-&gt;grabq);
-			break;
 		}
-		DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i));
+		switch (ztv-&gt;grabinfo[*i].status) {
+			case FBUFFER_FREE:
+				return -EINVAL;
+			case FBUFFER_BUSY:
+				/* wait till this buffer gets grabbed */
+				wait_event_interruptible(ztv-&gt;grabq,
+					(ztv-&gt;grabinfo[*i].status != FBUFFER_BUSY));
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -EINTR;
+				/* don't fall through; a DONE buffer is not UNUSED */
+				break;
+			case FBUFFER_DONE:
+				ztv-&gt;grabinfo[*i].status = FBUFFER_FREE;
+				/* tell ppl we have a spare buffer */
+				wake_up_interruptible(&amp;ztv-&gt;grabq);
+				break;
+		}
+		dprintk(1, CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD, *i);
 		break;
 	 }
 
 	 case VIDIOCMCAPTURE:
 	 {
-		struct video_mmap vm;
+		struct video_mmap* vm = arg;
 		struct vidinfo* frame;
-		if (copy_from_user(&amp;vm,arg,sizeof(vm)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format));
-		if (vm.frame&lt;0 || vm.frame&gt;ZORAN_MAX_FBUFFERS ||
-		    vm.width&lt;32 || vm.width&gt;768 ||
-		    vm.height&lt;32 || vm.height&gt;576 ||
-		    vm.format&gt;NRPALETTES ||
-		    palette2fmt[vm.format].mode == 0)
+		dprintk(1, CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",
+			CARD, vm-&gt;frame, vm-&gt;width, vm-&gt;height, vm-&gt;format);
+
+		/* sanity checks */
+		if (vm-&gt;frame&lt;0 || vm-&gt;frame&gt;ZORAN_MAX_FBUFFERS ||
+		    vm-&gt;width&lt;32 || vm-&gt;width&gt;tvmodes[ztv-&gt;mode].Wa ||
+		    vm-&gt;height&lt;32 || vm-&gt;height&gt;tvmodes[ztv-&gt;mode].Ha ||
+		    vm-&gt;format&gt;NRPALETTES ||
+		    palette2fmt[vm-&gt;format].bpp == 0)
+		{
+			dprintk(1, CARD_DEBUG "VIDIOMCAPTURE sanity check failed.\n",
+				CARD);
 			return -EINVAL;
+		}
 
 		/* we are allowed to take over UNUSED and DONE buffers */
-		frame = &amp;ztv-&gt;grabinfo[vm.frame];
+		frame = &amp;ztv-&gt;grabinfo[vm-&gt;frame];
 		if (frame-&gt;status == FBUFFER_BUSY)
 			return -EBUSY;
 
 		/* setup the other parameters if they are given */
 		write_lock_irq(&amp;ztv-&gt;lock);
-		frame-&gt;w = vm.width;
-		frame-&gt;h = vm.height;
-		frame-&gt;format = vm.format;
+		frame-&gt;w = vm-&gt;width;
+		frame-&gt;h = vm-&gt;height;
+		frame-&gt;format = vm-&gt;format;
 		frame-&gt;bpp = palette2fmt[frame-&gt;format].bpp;
 		frame-&gt;bpl = frame-&gt;w*frame-&gt;bpp;
 		frame-&gt;status = FBUFFER_BUSY;
@@ -1384,68 +1510,50 @@
 
 	 case VIDIOCGMBUF:
 	 {
-		struct video_mbuf mb;
+		struct video_mbuf* mb = arg;
 		int i;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD));
-		mb.size = ZORAN_MAX_FBUFSIZE;
-		mb.frames = ZORAN_MAX_FBUFFERS;
+		dprintk(1, CARD_DEBUG "VIDIOCGMBUF\n", CARD);
+		mb-&gt;size = ZORAN_MAX_FBUFSIZE;
+		mb-&gt;frames = ZORAN_MAX_FBUFFERS;
 		for (i=0; i&lt;ZORAN_MAX_FBUFFERS; i++)
-			mb.offsets[i] = i*ZORAN_MAX_FBUFFER;
-		if(copy_to_user(arg, &amp;mb,sizeof(mb)))
-			return -EFAULT;
+			mb-&gt;offsets[i] = i*ZORAN_MAX_FBUFFER;
 		break;
 	 }
 
 	 case VIDIOCGUNIT:
 	 {
-		struct video_unit vu;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD));
-		vu.video = ztv-&gt;video_dev.minor;
-		vu.vbi = ztv-&gt;vbi_dev.minor;
-		vu.radio = VIDEO_NO_UNIT;
-		vu.audio = VIDEO_NO_UNIT;
-		vu.teletext = VIDEO_NO_UNIT;
-		if(copy_to_user(arg, &amp;vu,sizeof(vu)))
-			return -EFAULT;
+		struct video_unit* vu = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGUNIT\n", CARD);
+		vu-&gt;video = ztv-&gt;video_dev-&gt;minor;
+		vu-&gt;vbi = ztv-&gt;vbi_dev-&gt;minor;
+		vu-&gt;radio = VIDEO_NO_UNIT;
+		vu-&gt;audio = VIDEO_NO_UNIT;
+		vu-&gt;teletext = VIDEO_NO_UNIT;
 		break;
 	 }
 
 	 case VIDIOCGFREQ:
 	 {
-		unsigned long v = ztv-&gt;tuner_freq;
-		if (copy_to_user(arg,&amp;v,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD));
+		unsigned long* v = arg;
+		dprintk(1, CARD_DEBUG "VIDIOCGFREQ\n", CARD);
+		*v = ztv-&gt;tuner_freq;
 		break;
 	 }
+
 	 case VIDIOCSFREQ:
 	 {
-		unsigned long v;
-		if (copy_from_user(&amp;v, arg, sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD));
+		unsigned long* v = (unsigned long*)arg;
+		dprintk(1, CARD_DEBUG "VIDIOCSFREQ\n", CARD);
 
 		if (ztv-&gt;have_tuner) {
-			int fixme = v;
-			if (i2c_control_device(&amp;(ztv-&gt;i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &amp;fixme) &lt; 0)
+			int fixme = (int)*v;
+			if (zoran_i2c_tuner_command(ztv, TUNER_SET_TVFREQ, &amp;fixme) &lt; 0)
 				return -EAGAIN;
 		}
-		ztv-&gt;tuner_freq = v;
+		ztv-&gt;tuner_freq = *v;
 		break;
 	 }
 
-	 /* Why isn't this in the API?
-	  * And why doesn't it take a buffer number?
-	 case BTTV_FIELDNR: 
-	 {
-		unsigned long v = ztv-&gt;lastfieldnr;
-		if (copy_to_user(arg,&amp;v,sizeof(v)))
-			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD));
-		break;
-	 }
-	 */
-
 	 default:
 		return -ENOIOCTLCMD;
 	}
@@ -1453,13 +1561,21 @@
 }
 
 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)
 {
-	struct zoran* ztv = (struct zoran*)dev;
-	unsigned long start = (unsigned long)adr;
+	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 = file-&gt;private_data;
+	unsigned long size = (vma-&gt;vm_end - vma-&gt;vm_start);
+	unsigned long start = vma-&gt;vm_start;
 	unsigned long pos;
 
-	DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size));
+	//dprintk(2, CARD_DEBUG "zoran_mmap(0x%p,%ld)\n", CARD, adr, size);
 
 	/* sanity checks */
 	if (size &gt; ZORAN_MAX_FBUFSIZE || !ztv-&gt;fbuffer)
@@ -1478,29 +1594,57 @@
 	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		= "zr36120",
+	.type		= VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
+	.hardware	= VID_HARDWARE_ZR36120,
+	.fops		= &amp;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 = dev-&gt;priv;
+	unsigned int minor = MINOR(inode-&gt;i_rdev);
+	struct zoran *ztv = NULL;
 	struct vidinfo* item;
+	int i;
 
-	DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags));
+	if (!try_module_get(THIS_MODULE)) {
+		dprintk(0, KERN_ERR "failed to acquire lock on myself\n");
+		return -EIO;
+	}
+
+	/* find the device */
+	for (i = 0; i &lt; zoran_cards; i++) {
+		if (zorans[i].video_dev-&gt;minor == minor) {
+			ztv = &amp;zorans[i];
+			break;
+		}
+	}
+
+	dprintk(2, CARD_DEBUG "vbi_open(dev,%d)\n", CARD, file-&gt;f_flags);
 
 	/*
 	 * During VBI device open, we continiously grab VBI-like
@@ -1525,6 +1669,7 @@
 					item-&gt;memadr = 0;
 					item-&gt;busadr = 0;
 				}
+				module_put(THIS_MODULE);
 				return -ENOBUFS;
 			}
 		}
@@ -1534,7 +1679,7 @@
 	}
 
 	/* do the common part of all open's */
-	zoran_common_open(ztv, flags);
+	zoran_common_open(ztv, file-&gt;f_flags);
 
 	set_bit(STATE_VBI, &amp;ztv-&gt;state);
 	/* start read-ahead */
@@ -1544,12 +1689,13 @@
 }
 
 static
-void vbi_close(struct video_device *dev)
+int vbi_close(struct inode* inode, struct file* file)
 {
-	struct zoran *ztv = dev-&gt;priv;
+	struct zoran *ztv = file-&gt;private_data;
 	struct vidinfo* item;
 
-	DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD));
+	UNUSED(inode);
+	dprintk(2, CARD_DEBUG "vbi_close(dev)\n", CARD);
 
 	/* driver specific closure */
 	clear_bit(STATE_VBI, &amp;ztv-&gt;state);
@@ -1570,6 +1716,9 @@
 		item-&gt;memadr = 0;
 	}
 
+	module_put(THIS_MODULE);
+
+	return 0;
 }
 
 /*
@@ -1580,14 +1729,17 @@
  * 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 = dev-&gt;priv;
+	struct zoran *ztv = file-&gt;private_data;
 	unsigned long max;
 	struct vidinfo* unused = 0;
 	struct vidinfo* done = 0;
+	int nonblock = file-&gt;f_flags &amp; O_NONBLOCK;
 
-	DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock));
+	UNUSED(ppos);
+	dprintk(2, CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",
+		CARD, buf, (long)count, nonblock);
 
 	/* find ourself a free or completed buffer */
 	for (;;) {
@@ -1665,6 +1817,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) {
@@ -1717,7 +1870,7 @@
 	/* API compliance:
 	 * place the framenumber (half fieldnr) in the last long
 	 */
-	__put_user(done-&gt;fieldnr/2, ((ulong*)eptr)[-1]);
+	__put_user(done-&gt;fieldnr/2, lptr);
 	}
 
 	/* keep the engine running */
@@ -1729,14 +1882,15 @@
 
 	/* goodbye */
 out:
-	DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count));
+	dprintk(2, CARD_DEBUG "vbi_read() returns %lu\n",
+		CARD, (unsigned long)count);
 	return count;
 }
 
 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 = dev-&gt;priv;
+	struct zoran *ztv = file-&gt;private_data;
 	struct vidinfo* item;
 	unsigned int mask = 0;
 
@@ -1749,21 +1903,23 @@
 			break;
 		}
 
-	DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask));
+	dprintk(2, CARD_DEBUG "vbi_poll()=%x\n", CARD, mask);
 
 	return mask;
 }
 
 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 = dev-&gt;priv;
+	struct zoran *ztv = file-&gt;private_data;
+
+	UNUSED(inode);
 
 	switch (cmd) {
 	 case VIDIOCGVBIFMT:
 	 {
 		struct vbi_format f;
-		DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD));
+		dprintk(1, CARD_DEBUG "VIDIOCGVBIINFO\n", CARD);
 		f.sampling_rate = 14750000UL;
 		f.samples_per_line = -ztv-&gt;readinfo[0].w;
 		f.sample_format = VIDEO_PALETTE_RAW;
@@ -1781,7 +1937,9 @@
 		int i;
 		if (copy_from_user(&amp;f, arg,sizeof(f)))
 			return -EFAULT;
-		DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags));
+		dprintk(1, CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",
+			CARD, f.sampling_rate, f.samples_per_line, f.sample_format,
+			f.start[0], f.start[1], f.count[0], f.count[1], f.flags);
 
 		/* lots of parameters are fixed... (PAL) */
 		if (f.sampling_rate != 14750000UL ||
@@ -1810,18 +1968,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		= "zr36120",
+	.type		= VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
+	.hardware	= VID_HARDWARE_ZR36120,
+	.fops		= &amp;vbi_fops,
+	.release	= zoran_vdev_release,
 	.minor		= -1,
 };
 
@@ -1837,46 +2010,65 @@
 	unsigned char revision;
 	int zoran_num=0;
 
-	while ((dev = pci_find_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev)))
+	while ((dev = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev)))
 	{
 		/* Ok, a ZR36120/ZR36125 found! */
 		ztv = &amp;zorans[zoran_num];
 		ztv-&gt;dev = dev;
 
-		if (pci_enable_device(dev))
+		if (pci_enable_device(dev)) {
+			dprintk(0, KERN_WARNING "zr36120-%d: Can't enable device\n",
+				zoran_num);
 			return -EIO;
+		}
+
+                if (!request_mem_region(pci_resource_start(dev, 0),
+                        pci_resource_len(dev, 0),
+                        "zr36120")) {
+			dprintk(0, KERN_WARNING "zr36120-%d: Can't request io memory (0x%lx\n",
+				zoran_num, pci_resource_start(dev, 0));
+                        return -EBUSY;
+		}
+
+                ztv-&gt;zoran_adr = pci_resource_start(dev, 0);
 
 		pci_read_config_byte(dev, PCI_CLASS_REVISION, &amp;revision);
-		printk(KERN_INFO "zoran: Zoran %x (rev %d) ",
-			dev-&gt;device, revision);
-		printk("bus: %d, devfn: %d, irq: %d, ",
+		dprintk(0, KERN_INFO "zr36120-%d: Zoran %x (rev %d) ",
+			zoran_num, dev-&gt;device, revision);
+		dprintk(0, "bus: %d, devfn: %d, irq: %d, ",
 			dev-&gt;bus-&gt;number, dev-&gt;devfn, dev-&gt;irq);
-		printk("memory: 0x%08lx.\n", ztv-&gt;zoran_adr);
+		dprintk(0, "memory: 0x%08lx.\n", ztv-&gt;zoran_adr);
 
-		ztv-&gt;zoran_mem = ioremap(ztv-&gt;zoran_adr, 0x1000);
-		DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv-&gt;zoran_mem));
+		/*ztv-&gt;zoran_mem = ioremap(ztv-&gt;zoran_adr, 0x1000);*/
+		ztv-&gt;zoran_mem = ioremap(ztv-&gt;zoran_adr, pci_resource_len(dev, 0));
+		dprintk(2, KERN_DEBUG "zr36120-%d: mapped-memory at 0x%p\n",
+			zoran_num, ztv-&gt;zoran_mem);
 
 		result = request_irq(dev-&gt;irq, zoran_irq,
-			SA_SHIRQ|SA_INTERRUPT,"zoran", ztv);
+			SA_SHIRQ|SA_INTERRUPT, "zr36120", ztv);
 		if (result==-EINVAL)
 		{
 			iounmap(ztv-&gt;zoran_mem);
-			printk(KERN_ERR "zoran: Bad irq number or handler\n");
+			dprintk(0, KERN_ERR "zr36120-%d: Bad irq number or handler\n",
+				zoran_num);
 			return -EINVAL;
 		}
 		if (result==-EBUSY)
-			printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev-&gt;irq);
+			dprintk(0, KERN_ERR
+				"zr36120-%d: IRQ %d busy, change your PnP config in BIOS\n",
+				zoran_num, dev-&gt;irq);
 		if (result &lt; 0) {
 			iounmap(ztv-&gt;zoran_mem);
 			return result;
 		}
 		/* Enable bus-mastering */
 		pci_set_master(dev);
+		pci_set_drvdata(dev, ztv);
 
 		zoran_num++;
 	}
 	if(zoran_num)
-		printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num);
+		dprintk(0, KERN_INFO "zr36120: %d Zoran card(s) found.\n",zoran_num);
 	return zoran_num;
 }
 
@@ -1885,10 +2077,21 @@
 {
 	struct zoran *ztv = &amp;zorans[card];
 	int	i;
+	void* alloc_mem1, * alloc_mem2;
 
 	/* if the given cardtype valid? */
 	if (cardtype[card]&gt;=NRTVCARDS) {
-		printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]);
+		dprintk(0, KERN_INFO "zr36120: Invalid cardtype(%d) detected\n",
+			cardtype[card]);
+		return -1;
+	}
+
+	if (!(alloc_mem1 = kmalloc(sizeof(struct video_device), GFP_KERNEL)) ||
+	    !(alloc_mem2 = kmalloc(sizeof(struct video_device), GFP_KERNEL))) {
+		dprintk(0, KERN_ERR
+			"zr36120: failed to kmalloc data for video_device entries\n");
+		if (alloc_mem1)
+			kfree(alloc_mem1);
 		return -1;
 	}
 
@@ -1900,7 +2103,7 @@
 
 	/* zoran chip specific details */
 	ztv-&gt;card = tvcards+cardtype[card];	/* point to the selected card */
-	ztv-&gt;norm = 0;				/* PAL */
+	ztv-&gt;mode = 0;				/* PAL */
 	ztv-&gt;tuner_freq = 0;
 
 	/* videocard details */
@@ -1950,12 +2153,20 @@
 	ztv-&gt;workqueue = 0;
 	ztv-&gt;fieldnr = 0;
 	ztv-&gt;lastfieldnr = 0;
+	ztv-&gt;mode = mode;
+	ztv-&gt;channel = 0;
 
 	if (triton1)
 		zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC);
 
 	/* external FL determines TOP frame */
-	zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); 
+	if (ztv-&gt;card-&gt;ext_fl) {
+		/* positive signal =&gt; topfield? */
+		if (ztv-&gt;card-&gt;fld_pos)
+			zror(ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD, ZORAN_VFEC);
+		else
+			zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC);
+	}
 
 	/* set HSpol */
 	if (ztv-&gt;card-&gt;hsync_pos)
@@ -1964,44 +2175,47 @@
 	if (ztv-&gt;card-&gt;vsync_pos)
 		zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV);
 
-	/* Set the proper General Purpuse register bits */
+	/* Set the proper General Purpose register bits */
 	/* implicit: no softreset, 0 waitstates */
-	zrwrite(ZORAN_PCI_SOFTRESET|(ztv-&gt;card-&gt;gpdir&lt;&lt;0),ZORAN_PCI);
+	zrwrite(ZORAN_PCI_SOFTRESET|(ztv-&gt;card-&gt;gpdir&lt;&lt;0), ZORAN_PCI);
 	/* implicit: 3 duration and recovery PCI clocks on guest 0-3 */
-	zrwrite(ztv-&gt;card-&gt;gpval&lt;&lt;24,ZORAN_GUEST);
+	zrwrite(ztv-&gt;card-&gt;gpval&lt;&lt;24, ZORAN_GUEST);
 
 	/* clear interrupt status */
 	zrwrite(~0, ZORAN_ISR);
 
 	/*
-	 * i2c template
-	 */
-	ztv-&gt;i2c = zoran_i2c_bus_template;
-	sprintf(ztv-&gt;i2c.name,"zoran-%d",card);
-	ztv-&gt;i2c.data = ztv;
-
-	/*
 	 * Now add the template and register the device unit
 	 */
-	ztv-&gt;video_dev = zr36120_template;
-	strcpy(ztv-&gt;video_dev.name, ztv-&gt;i2c.name);
-	ztv-&gt;video_dev.priv = ztv;
-	if (video_register_device(&amp;ztv-&gt;video_dev, VFL_TYPE_GRABBER, video_nr) &lt; 0)
+	ztv-&gt;video_dev = alloc_mem1;
+	memcpy(ztv-&gt;video_dev, &amp;zr36120_template, sizeof(struct video_device));
+	ztv-&gt;video_dev-&gt;priv = ztv;
+	if (video_register_device(ztv-&gt;video_dev, VFL_TYPE_GRABBER, video_nr) &lt; 0) {
+		kfree(alloc_mem1);
+		kfree(alloc_mem2);
 		return -1;
+	}
 
-	ztv-&gt;vbi_dev = vbi_template;
-	strcpy(ztv-&gt;vbi_dev.name, ztv-&gt;i2c.name);
-	ztv-&gt;vbi_dev.priv = ztv;
-	if (video_register_device(&amp;ztv-&gt;vbi_dev, VFL_TYPE_VBI, vbi_nr) &lt; 0) {
-		video_unregister_device(&amp;ztv-&gt;video_dev);
+	ztv-&gt;vbi_dev = alloc_mem2;
+	memcpy(ztv-&gt;vbi_dev, &amp;vbi_template, sizeof(struct video_device));
+	ztv-&gt;vbi_dev-&gt;priv = ztv;
+	if (video_register_device(ztv-&gt;vbi_dev, VFL_TYPE_VBI, vbi_nr) &lt; 0) {
+		video_unregister_device(ztv-&gt;video_dev);
+		kfree(alloc_mem1);
+		kfree(alloc_mem2);
 		return -1;
 	}
-	i2c_register_bus(&amp;ztv-&gt;i2c);
+	ztv-&gt;i2cbr = 0;
+	if (zoran_i2c_load(ztv, debug) &lt; 0) {
+		dprintk(0, KERN_ERR "%s: can't initialize i2c bus\n",
+			ztv-&gt;i2c_adapter.name);
+	}
 
 	/* 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-&gt;i2c.name,ztv-&gt;card-&gt;name);
+	dprintk(0, KERN_INFO "%s: installed %s\n",
+		ztv-&gt;i2c_adapter.name, ztv-&gt;card-&gt;name);
 	return 0;
 }
 
@@ -2030,14 +2244,18 @@
 		free_irq(ztv-&gt;dev-&gt;irq,ztv);
  
     		/* unregister i2c_bus */
-		i2c_unregister_bus((&amp;ztv-&gt;i2c));
+		zoran_i2c_unload(ztv);
 
 		/* unmap and free memory */
 		if (ztv-&gt;zoran_mem)
 			iounmap(ztv-&gt;zoran_mem);
 
-		video_unregister_device(&amp;ztv-&gt;video_dev);
-		video_unregister_device(&amp;ztv-&gt;vbi_dev);
+		release_mem_region(pci_resource_start(ztv-&gt;dev, 0),
+			pci_resource_len(ztv-&gt;dev, 0));
+		pci_set_drvdata(ztv-&gt;dev, NULL);
+
+		video_unregister_device(ztv-&gt;video_dev);
+		video_unregister_device(ztv-&gt;vbi_dev);
 	}
 }
 
@@ -2053,8 +2271,11 @@
 	handle_chipset();
 	zoran_cards = find_zoran();
 	if (zoran_cards&lt;0)
+	{
 		/* no cards found, no need for a driver */
+		dprintk(0, KERN_WARNING "zr36120: no cards found\n");
 		return -EIO;
+	}
 
 	/* initialize Zorans */
 	for (card=0; card&lt;zoran_cards; card++) {
diff -urN linux-2.6.14-rc2.orig/drivers/media/video/zr36120.h linux-2.6.14-rc2/drivers/media/video/zr36120.h
--- linux-2.6.14-rc2.orig/drivers/media/video/zr36120.h	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/zr36120.h	2005-10-11 23:26:01.000000000 -0700
@@ -2,6 +2,9 @@
     zr36120.h - Zoran 36120/36125 based framegrabbers
 
     Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl)
+    Partial port to Linux 2.6 by ???
+    Full port to Linux 2.6, and other cleanup by Joachim Feise (Oct. 2005)
+    Copyright (C) 2005 Joachim Feise &lt;jfeise@feise.com&gt;
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -26,28 +29,34 @@
 #include &lt;linux/types.h&gt;
 #include &lt;linux/wait.h&gt;
 
-#include &lt;linux/i2c-old.h&gt;
+#include &lt;linux/i2c.h&gt;
+#include &lt;linux/i2c-algo-bit.h&gt;
 #include &lt;linux/videodev.h&gt;
 
 #include &lt;asm/io.h&gt;
 
 /*
- * Debug macro's, place an x behind the ) for actual debug-compilation
- * E.g. #define DEBUG(x...)	x
+ * Debug print macro, allows debugging by module parameter
+ * 0 - minimal info
+ * 1 - ioctl debugging
+ * 2 - general debugging
+ * 9 - intr debugging
  */
-#define DEBUG(x...)			/* Debug driver */
-#define IDEBUG(x...)			/* Debug interrupt handler */
+#define dprintk(num, format, args...) \
+	do { \
+		if (debug &gt;= num) \
+			printk(format, ##args); \
+	} while (0)
+
 #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_FBUFFER	(768*576*3)
 #define	ZORAN_MAX_FBUFSIZE	(ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER)
 
-#define	ZORAN_VBI_BUFFERS	2
-#define	ZORAN_VBI_BUFSIZE	(22*1024*2)
+#define	ZORAN_VBI_BUFFERS	8
+#define	ZORAN_VBI_BUFSIZE	(44*1024*2)
 
 struct tvcard {
 	char*	name;		/* name of the cardtype */
@@ -57,6 +66,8 @@
 		usegirq1:1,	/* VSYNC at GIRQ1 instead of GIRQ0? */
 		vsync_pos:1,	/* positive VSYNC signal? */
 		hsync_pos:1,	/* positive HSYNC signal? */
+		ext_fl:1,	/* external field detection? */
+		fld_pos:1,	/* positive field signal = top? */
 		gpdir:8,	/* General Purpose Direction register */
 		gpval:8;	/* General Purpose Value register */
 	int	video_mux[6];	/* mapping channel number to physical input */
@@ -65,6 +76,7 @@
 #define		CHANNEL_MASK	0x3F
 	int	audio_mux[6];	/* mapping channel number to physical input */
 };
+
 #define	TUNER(x)	((x)|IS_TUNER)
 #define	SVHS(x)		((x)|IS_SVHS)
 
@@ -91,19 +103,25 @@
 
 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-&gt;video_dev.name,ztv-&gt;fieldnr
+#define CARD		ztv-&gt;video_dev-&gt;name,ztv-&gt;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	*/
 	struct tvcard*	card;		/* the cardtype			*/
-	uint		norm;		/* 0=PAL, 1=NTSC, 2=SECAM	*/
+	uint		mode;		/* 0=PAL, 1=NTSC, 2=SECAM	*/
+	uint		channel;	/* input channel		*/
 	uint		tuner_freq;	/* Current freq in kHz		*/
 	struct video_picture picture;	/* Current picture params	*/
   
@@ -119,7 +137,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 +161,12 @@
 	uint		vidHeight;	/* calculated */
 };
 
+/* defined in zr36120_i2c */
+extern int	zoran_i2c_load		(struct zoran *ztv, int debugflag);
+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-&gt;zoran_mem+(adr)))
 #define zrread(adr)         readl(ztv-&gt;zoran_mem+(adr))
 
@@ -265,10 +289,10 @@
 #define	ZORAN_ICR_GIRQ1		(1&lt;&lt;30)
 
 #define	ZORAN_I2C		0x044	/* I2C-Bus */
-#define ZORAN_I2C_SCL		(1&lt;&lt;1)
-#define ZORAN_I2C_SDA		(1&lt;&lt;0)
+#define ZORAN_I2C_SCL		(1&lt;&lt;0)
+#define ZORAN_I2C_SDA		(1&lt;&lt;1)
 
-#define	ZORAN_POST		0x48	/* PostOffice */
+#define	ZORAN_POST		0x200	/* PostOffice */
 #define	ZORAN_POST_PEN		(1&lt;&lt;25)
 #define	ZORAN_POST_TIME		(1&lt;&lt;24)
 #define	ZORAN_POST_DIR		(1&lt;&lt;23)
diff -urN linux-2.6.14-rc2.orig/drivers/media/video/zr36120_i2c.c linux-2.6.14-rc2/drivers/media/video/zr36120_i2c.c
--- linux-2.6.14-rc2.orig/drivers/media/video/zr36120_i2c.c	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/zr36120_i2c.c	2005-10-11 23:26:01.000000000 -0700
@@ -2,6 +2,9 @@
     zr36120_i2c.c - Zoran 36120/36125 based framegrabbers
 
     Copyright (C) 1998-1999 Pauline Middelink &lt;middelin@polyware.nl&gt;
+    Partial port to Linux 2.6 by ???
+    Full port to Linux 2.6, and other cleanup by Joachim Feise (Oct. 2005)
+    Copyright (C) 2005 Joachim Feise &lt;jfeise@feise.com&gt;
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -25,8 +28,10 @@
 #include &lt;linux/video_decoder.h&gt;
 #include &lt;asm/uaccess.h&gt;
 
-#include "tuner.h"
 #include "zr36120.h"
+#include &lt;media/tuner.h&gt;
+
+static int debug = 0;
 
 /* ----------------------------------------------------------------------- */
 /* I2C functions							   */
@@ -34,99 +39,189 @@
 
 /* software I2C functions */
 
-#define I2C_DELAY   10
+#define I2C_DELAY   20
+
+/* software I2C functions */
+static int zoran_i2c_getsda (void* data)
+{
+	struct zoran* ztv = (struct zoran*)data;
+	return zrread(ZORAN_I2C) &amp; (ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+}
 
-static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
+static
+int zoran_i2c_getscl (void* data)
 {
-	struct zoran *ztv = (struct zoran*)bus-&gt;data;
-	unsigned int b = 0;
-	if (data) b |= ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA;
-	if (ctrl) b |= ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL;
-	zrwrite(b, ZORAN_I2C);
-	udelay(I2C_DELAY);
+	struct zoran* ztv = (struct zoran*)data;
+	return zrread(ZORAN_I2C) &amp; (ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
 }
 
-static int i2c_getdataline(struct i2c_bus *bus)
+static
+void zoran_i2c_setsda (void* data, int state)
+{
+	struct zoran* ztv = (struct zoran*)data;
+	if (state)
+		ztv-&gt;i2cbr |= (ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+	else
+		ztv-&gt;i2cbr &amp;= ~(ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA);
+	zrwrite(ztv-&gt;i2cbr, ZORAN_I2C);
+}
+
+static
+void zoran_i2c_setscl (void* data, int state)
 {
-	struct zoran *ztv = (struct zoran*)bus-&gt;data;
-	if (ztv-&gt;card-&gt;swapi2c)
-		return zrread(ZORAN_I2C) &amp; ZORAN_I2C_SCL;
-	return zrread(ZORAN_I2C) &amp; ZORAN_I2C_SDA;
+	struct zoran* ztv = (struct zoran*)data;
+	if (state)
+		ztv-&gt;i2cbr |= (ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
+	else
+		ztv-&gt;i2cbr &amp;= ~(ztv-&gt;card-&gt;swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL);
+	zrwrite(ztv-&gt;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-&gt;data;
+	struct zoran* ztv = (struct zoran*)i2c_get_adapdata(client-&gt;adapter);
 	struct video_decoder_capability dc;
 	int rv;
 
-	switch (id) {
-	 case I2C_DRIVERID_VIDEODECODER:
-		DEBUG(printk(CARD_INFO "decoder attached\n",CARD));
-
-		/* fetch the capabilites of the decoder */
-		rv = i2c_control_device(&amp;ztv-&gt;i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &amp;dc);
-		if (rv) {
-			DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD));
+	dprintk(2, CARD_DEBUG "attach_inform, id: %d\n", CARD, client-&gt;driver-&gt;id);
+
+	if (ztv-&gt;users &gt; 0) {
+		dprintk(0, KERN_ERR "cannot connect i2c devices while running\n");
+		return -EBUSY;
+	}
+
+	switch (client-&gt;driver-&gt;id) {
+		case I2C_DRIVERID_SAA7110:
+		case I2C_DRIVERID_SAA7111A:
+			dprintk(2, CARD_INFO "decoder attached\n", CARD);
+
+			ztv-&gt;decoder = client;
+			/* fetch the capabilites of the decoder */
+			rv = zoran_i2c_command(ztv, DECODER_GET_CAPABILITIES, &amp;dc);
+			if (rv) {
+				dprintk(2, CARD_DEBUG "decoder is not V4L aware!\n",
+					CARD);
+				break;
+			}
+			dprintk(2, CARD_DEBUG "capabilities %d %d %d\n",
+				CARD, dc.flags, dc.inputs, dc.outputs);
+
+			/* Test if the decoder can de VBI transfers */
+			if (dc.flags &amp; 16 /*VIDEO_DECODER_VBI*/)
+				ztv-&gt;have_decoder = 2;
+			else
+				ztv-&gt;have_decoder = 1;
 			break;
-		}
-		DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs));
 
-		/* Test if the decoder can de VBI transfers */
-		if (dc.flags &amp; 16 /*VIDEO_DECODER_VBI*/)
-			ztv-&gt;have_decoder = 2;
-		else
-			ztv-&gt;have_decoder = 1;
-		break;
-	 case I2C_DRIVERID_TUNER:
-		ztv-&gt;have_tuner = 1;
-		DEBUG(printk(CARD_INFO "tuner attached\n",CARD));
-		if (ztv-&gt;tuner_type &gt;= 0)
-		{
-			if (i2c_control_device(&amp;ztv-&gt;i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&amp;ztv-&gt;tuner_type)&lt;0)
-			DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv-&gt;tuner_type));
-		}
-		break;
-	 default:
-		DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id));
-		break;
+		case I2C_DRIVERID_TUNER:
+			ztv-&gt;have_tuner = 1;
+			ztv-&gt;tuner = client;
+			dprintk(2, CARD_INFO "tuner attached\n", CARD);
+			if (ztv-&gt;tuner_type &gt;= 0)
+			{
+				if (zoran_i2c_tuner_command(ztv ,TUNER_SET_TYPE,
+					&amp;ztv-&gt;tuner_type)&lt;0)
+				dprintk(2, CARD_INFO
+					"attach_inform; tuner won't be set to type %d\n",
+					CARD, ztv-&gt;tuner_type);
+			}
+			break;
+
+		default:
+			dprintk(2, CARD_INFO "attach_inform; unknown device id=%d\n",
+				CARD, client-&gt;driver-&gt;id);
+			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-&gt;data;
+	struct zoran *ztv = (struct zoran*)i2c_get_adapdata(client-&gt;adapter);
 
-	switch (id) {
-	 case I2C_DRIVERID_VIDEODECODER:
-		ztv-&gt;have_decoder = 0;
-		DEBUG(printk(CARD_INFO "decoder detached\n",CARD));
-		break;
-	 case I2C_DRIVERID_TUNER:
-		ztv-&gt;have_tuner = 0;
-		DEBUG(printk(CARD_INFO "tuner detached\n",CARD));
+	dprintk(2, CARD_DEBUG "detach_inform, id: %d\n", CARD, client-&gt;driver-&gt;id);
+
+	switch (client-&gt;driver-&gt;id) {
+		case I2C_DRIVERID_SAA7110:
+		case I2C_DRIVERID_SAA7111A:
+			ztv-&gt;have_decoder = 0;
+			ztv-&gt;decoder = NULL;
+			dprintk(2, CARD_INFO "decoder detached\n", CARD);
+			break;
+
+		case I2C_DRIVERID_TUNER:
+			ztv-&gt;have_tuner = 0;
+			ztv-&gt;tuner = NULL;
+			dprintk(2, CARD_INFO "tuner detached\n", CARD);
 		break;
-	 default:
-		DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id));
+
+		default:
+			dprintk(2, CARD_INFO "detach_inform; unknown device id=%d\n",
+				CARD, client-&gt;driver-&gt;id);
 		break;
 	}
+
+	return 0;
 }
 
-struct i2c_bus zoran_i2c_bus_template =
+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 = 10,
+	.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, int debugflag)
 {
-	"ZR36120",
-	I2C_BUSID_ZORAN,
-	NULL,
+	debug = debugflag;
 
-	SPIN_LOCK_UNLOCKED,
+	memcpy(&amp;ztv-&gt;i2c_algo, &amp;zoran_i2c_bit_data_template,
+	       sizeof(struct i2c_algo_bit_data));
+	ztv-&gt;i2c_algo.data = ztv;
+	memcpy(&amp;ztv-&gt;i2c_adapter, &amp;zoran_i2c_adapter_template,
+	       sizeof(struct i2c_adapter));
+	i2c_set_adapdata(&amp;ztv-&gt;i2c_adapter, ztv);
+	ztv-&gt;i2c_adapter.algo_data = &amp;ztv-&gt;i2c_algo;
+
+	/* give the output a defined value */
+	zoran_i2c_setscl(ztv, 1);
+	zoran_i2c_setsda(ztv, 1);
 
-	attach_inform,
-	detach_inform,
+	return i2c_bit_add_bus(&amp;ztv-&gt;i2c_adapter);
+}
 
-	i2c_setlines,
-	i2c_getdataline,
-	NULL,
-	NULL
-};
+void zoran_i2c_unload (struct zoran *ztv)
+{
+	i2c_bit_del_bus(&amp;ztv-&gt;i2c_adapter);
+	debug = 0;
+}
+
+int zoran_i2c_command (struct zoran *ztv, int cmd, void *data)
+{
+	if (!ztv-&gt;decoder)
+		return -EIO;
+
+	return ztv-&gt;decoder-&gt;driver-&gt;command(ztv-&gt;decoder, cmd, data);
+}
+
+int zoran_i2c_tuner_command (struct zoran *ztv, int cmd, void *data)
+{
+	if (!ztv-&gt;tuner)
+		return -EIO;
+
+	return ztv-&gt;tuner-&gt;driver-&gt;command(ztv-&gt;tuner, cmd, data);
+}
diff -urN linux-2.6.14-rc2.orig/drivers/media/video/zr36120_mem.c linux-2.6.14-rc2/drivers/media/video/zr36120_mem.c
--- linux-2.6.14-rc2.orig/drivers/media/video/zr36120_mem.c	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/zr36120_mem.c	2005-10-11 23:26:01.000000000 -0700
@@ -2,6 +2,9 @@
     zr36120_mem.c - Zoran 36120/36125 based framegrabbers
 
     Copyright (C) 1998-1999 Pauline Middelink &lt;middelin@polyware.nl&gt;
+    Partial port to Linux 2.6 by ???
+    Full port to Linux 2.6, and other cleanup by Joachim Feise (Oct. 2005)
+    Copyright (C) 2005 Joachim Feise &lt;jfeise@feise.com&gt;
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -45,12 +48,12 @@
 	 * The following function got a lot of memory at boottime,
 	 * so we know its always there...
 	 */
-	mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size));
+	mem = (void*)__get_free_pages(GFP_USER|GFP_DMA, get_order(size));
 #endif
 	if (mem) {
 		unsigned long adr = (unsigned long)mem;
 		while (size &gt; 0) {
-			SetPageReserved(virt_to_page(phys_to_virt(adr)));
+			SetPageReserved(virt_to_page(adr));
 			adr += PAGE_SIZE;
 			size -= PAGE_SIZE;
 		}
@@ -64,7 +67,7 @@
 		unsigned long adr = (unsigned long)mem;
 		unsigned long siz = size;
 		while (siz &gt; 0) {
-			ClearPageReserved(virt_to_page(phys_to_virt(adr)));
+			ClearPageReserved(virt_to_page(adr));
 			adr += PAGE_SIZE;
 			siz -= PAGE_SIZE;
 		}
diff -urN linux-2.6.14-rc2.orig/drivers/media/video/zr36120_mem.h linux-2.6.14-rc2/drivers/media/video/zr36120_mem.h
--- linux-2.6.14-rc2.orig/drivers/media/video/zr36120_mem.h	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/drivers/media/video/zr36120_mem.h	2005-10-11 23:26:01.000000000 -0700
@@ -1,3 +1,26 @@
+/*
+    zr36120_mem.h - Zoran 36120/36125 based framegrabbers
+
+    Copyright (C) 1998-1999 Pauline Middelink &lt;middelin@polyware.nl&gt;
+    Partial port to Linux 2.6 by ???
+    Full port to Linux 2.6, and other cleanup by Joachim Feise (Oct. 2005)
+    Copyright (C) 2005 Joachim Feise &lt;jfeise@feise.com&gt;
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
 /* either kmalloc() or bigphysarea() alloced memory - continuous */
 void*	bmalloc(unsigned long size);
 void	bfree(void* mem, unsigned long size);
diff -urN linux-2.6.14-rc2.orig/include/media/tuner.h linux-2.6.14-rc2/include/media/tuner.h
--- linux-2.6.14-rc2.orig/include/media/tuner.h	2005-09-19 20:00:41.000000000 -0700
+++ linux-2.6.14-rc2/include/media/tuner.h	2005-10-11 23:26:01.000000000 -0700
@@ -133,6 +133,8 @@
 #define TCL     11
 #define THOMSON 12
 
+#define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
+#define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
 #define TUNER_SET_TYPE_ADDR          _IOW('T',3,int)
 #define TUNER_SET_STANDBY            _IOW('T',4,int)
 #define TDA9887_SET_CONFIG           _IOW('t',5,int)
</pre></body></html>