All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch] v4l: #7 - saa7134 driver update
@ 2003-05-12 17:26 Gerd Knorr
  0 siblings, 0 replies; only message in thread
From: Gerd Knorr @ 2003-05-12 17:26 UTC (permalink / raw)
  To: Linus Torvalds, Kernel List

  Hi,

Yet another big one (due to not being updated for a long time) --
saa7134 driver update.  Changes:

 * various bugfixes / cleanups.
 * new cards added to the cardlist.
 * started support for saa7133/35 chips.
 * make the driver check pci quirks.

Please apply,

  Gerd

diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-cards.c linux/drivers/media/video/saa7134/saa7134-cards.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-cards.c	2003-05-08 13:31:45.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-cards.c	2003-05-08 13:55:12.000000000 +0200
@@ -29,6 +29,7 @@
 static char name_mute[]    = "mute";
 static char name_radio[]   = "Radio";
 static char name_tv[]      = "Television";
+static char name_tv_mono[] = "TV (mono only)";
 static char name_comp1[]   = "Composite1";
 static char name_comp2[]   = "Composite2";
 static char name_svideo[]  = "S-Video";
@@ -61,6 +62,11 @@
 			.vmux = 1,
 			.amux = TV,
 			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
 		}},
 	},
 	[SAA7134_BOARD_FLYVIDEO3000] = {
@@ -68,27 +74,39 @@
 		.name		= "LifeView FlyVIDEO3000",
 		.audio_clock	= 0x00200000,
 		.tuner_type	= TUNER_PHILIPS_PAL,
+		.gpiomask       = 0xe000,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
 			.amux = TV,
+			.gpio = 0x8000,
+			.tv   = 1,
+                },{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
 			.tv   = 1,
 		},{
 			.name = name_comp1,
 			.vmux = 0,
-			.amux = LINE1,
+			.amux = LINE2,
+			.gpio = 0x4000,
 		},{
 			.name = name_comp2,
 			.vmux = 3,
-			.amux = LINE1,
+			.amux = LINE2,
+			.gpio = 0x4000,
 		},{
 			.name = name_svideo,
 			.vmux = 8,
-			.amux = LINE1,
+			.amux = LINE2,
+			.gpio = 0x4000,
 		}},
 		.radio = {
 			.name = name_radio,
 			.amux = LINE2,
+			.gpio = 0x2000,
 		},
 	},
 	[SAA7134_BOARD_FLYVIDEO2000] = {
@@ -96,7 +114,7 @@
 		.name           = "LifeView FlyVIDEO2000",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-		.gpiomask       = 0x6000,
+		.gpiomask       = 0xe000,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -122,10 +140,12 @@
                 .radio = {
                         .name = name_radio,
                         .amux = LINE2,
+			.gpio = 0x2000,
                 },
 		.mute = {
 			.name = name_mute,
-			.amux = LINE1,
+                        .amux = LINE2,
+			.gpio = 0x8000,
 		},
 	},
 	[SAA7134_BOARD_EMPRESS] = {
@@ -190,7 +210,7 @@
 			.tv   = 1,
 		},{
 			/* workaround for problems with normal TV sound */
-			.name = "TV (mono only)",
+			.name = name_tv_mono,
 			.vmux = 1,
 			.amux = LINE2,
 			.tv   = 1,
@@ -270,6 +290,12 @@
 			.amux = TV,
 			.tv   = 1,
 		},{
+			/* workaround for problems with normal TV sound */
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
 			.name = name_comp1,
 			.vmux = 0,
 			.amux = LINE2,
@@ -302,7 +328,7 @@
                 },{
                         .name = name_tv,
                         .vmux = 1,
-                        .amux = TV,
+                        .amux = LINE2,
                         .tv   = 1,
                 }},
         },
@@ -332,7 +358,6 @@
 			.name = name_radio,
 			.amux = LINE2,
                },
-
         },
 	[SAA7134_BOARD_MD7134] = {
 		.name           = "Medion 7134",
@@ -343,7 +368,7 @@
 			.name   = name_tv,
 			.vmux   = 1,
 			.amux   = LINE2,
-			.tv     =   1,
+			.tv     = 1,
 		},{
 			.name   = name_comp1,
 			.vmux   = 0,
@@ -361,9 +386,67 @@
 			.name   = name_radio,
 			.amux   = LINE2,
 		},
-      },
+	},
+	[SAA7134_BOARD_TYPHOON_90031] = {
+		.name           = "Typhoon TV+Radio 90031",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ELSA] = {
+		.name           = "ELSA EX-VISION 300TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_HITACHI_NTSC,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 4,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+        },
+	[SAA7134_BOARD_ELSA_500TV] = {
+		.name           = "ELSA EX-VISION 500TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_HITACHI_NTSC,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 7,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 8,
+			.amux = TV,
+			.tv   = 1,
+		}},
+        },
+	
 };
-const int saa7134_bcount = (sizeof(saa7134_boards)/sizeof(struct saa7134_board));
+const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
 
 /* ------------------------------------------------------------------ */
 /* PCI ids + subsystem IDs                                            */
@@ -377,6 +460,12 @@
 		.driver_data  = SAA7134_BOARD_PROTEUS_PRO,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2001,
+		.driver_data  = SAA7134_BOARD_PROTEUS_PRO,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = PCI_VENDOR_ID_PHILIPS,
 		.subdevice    = 0x6752,
@@ -407,11 +496,29 @@
 		.driver_data  = SAA7134_BOARD_FLYVIDEO3000,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x16be,
 		.subdevice    = 0x0003,
 		.driver_data  = SAA7134_BOARD_MD7134,
 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1048,
+		.subdevice    = 0x226b,
+		.driver_data  = SAA7134_BOARD_ELSA,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1048,
+		.subdevice    = 0x226b,
+		.driver_data  = SAA7134_BOARD_ELSA_500TV,
+	},{
 		
 		/* --- boards without eeprom + subsystem ID --- */
                 .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -435,10 +542,22 @@
 		.driver_data  = SAA7134_BOARD_UNKNOWN,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+                .subvendor    = PCI_ANY_ID,
+                .subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
                 .subvendor    = PCI_ANY_ID,
                 .subdevice    = PCI_ANY_ID,
 		.driver_data  = SAA7134_BOARD_UNKNOWN,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+                .subvendor    = PCI_ANY_ID,
+                .subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
 	},{
 		/* --- end of list --- */
 	}
@@ -446,6 +565,67 @@
 MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
 
 /* ----------------------------------------------------------- */
+/* flyvideo tweaks                                             */
+
+#if 0
+static struct {
+	char  *model;
+	int   tuner_type;
+} fly_list[0x20] = {
+	/* default catch ... */
+	[ 0 ... 0x1f ] = {
+		.model      = "UNKNOWN",
+		.tuner_type = TUNER_ABSENT,
+	},
+	/* ... the ones known so far */
+	[ 0x05 ] = {
+		.model      = "PAL-BG",
+		.tuner_type = TUNER_LG_PAL_NEW_TAPC,
+	},
+	[ 0x10 ] = {
+		.model      = "PAL-BG / PAL-DK",
+		.tuner_type = TUNER_PHILIPS_PAL,
+	},
+	[ 0x15 ] = {
+		.model      = "NTSC",
+		.tuner_type = TUNER_ABSENT /* FIXME */,
+	},
+};
+#endif
+
+static void board_flyvideo(struct saa7134_dev *dev)
+{
+	u32 value;
+	int index;
+
+	saa_writel(SAA7134_GPIO_GPMODE0 >> 2,   0);
+	value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+#if 0
+	index = (value & 0x1f00) >> 8;
+	printk(KERN_INFO "%s: flyvideo: gpio is 0x%x [model=%s,tuner=%d]\n",
+	       dev->name, value, fly_list[index].model,
+	       fly_list[index].tuner_type);
+	dev->tuner_type = fly_list[index].tuner_type;
+#else
+	printk(KERN_INFO "%s: flyvideo: gpio is 0x%x\n",
+	       dev->name, value);
+#endif
+}
+
+/* ----------------------------------------------------------- */
+
+int saa7134_board_init(struct saa7134_dev *dev)
+{
+	switch (dev->board) {
+	case SAA7134_BOARD_FLYVIDEO2000:
+	case SAA7134_BOARD_FLYVIDEO3000:
+		board_flyvideo(dev);
+		break;
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------- */
 /*
  * Local variables:
  * c-basic-offset: 8
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-core.c linux/drivers/media/video/saa7134/saa7134-core.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-core.c	2003-05-08 13:30:27.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-core.c	2003-05-08 13:55:12.000000000 +0200
@@ -2,7 +2,7 @@
  * device driver for philips saa7134 based TV cards
  * driver core
  *
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
  *  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
@@ -67,6 +67,10 @@
 MODULE_PARM(radio_nr,"i");
 MODULE_PARM_DESC(radio_nr,"radio device number");
 
+static unsigned int oss = 0;
+MODULE_PARM(oss,"i");
+MODULE_PARM_DESC(oss,"register oss devices (default: no)");
+
 static unsigned int dsp_nr = -1;
 MODULE_PARM(dsp_nr,"i");
 MODULE_PARM_DESC(dsp_nr,"oss dsp device number");
@@ -75,20 +79,20 @@
 MODULE_PARM(mixer_nr,"i");
 MODULE_PARM_DESC(mixer_nr,"oss mixer device number");
 
-static int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = -1};
+static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 MODULE_PARM(tuner,"1-" __stringify(SAA7134_MAXBOARDS) "i");
 MODULE_PARM_DESC(tuner,"tuner type");
 
-static int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = -1};
+static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 MODULE_PARM(card,"1-" __stringify(SAA7134_MAXBOARDS) "i");
 MODULE_PARM_DESC(card,"card type");
 
-static int latency = -1;
+static unsigned int latency = UNSET;
 MODULE_PARM(latency,"i");
 MODULE_PARM_DESC(latency,"pci latency timer");
 
 struct list_head  saa7134_devlist;
-int               saa7134_devcount;
+unsigned int      saa7134_devcount;
 
 #define dprintk(fmt, arg...)	if (core_debug) \
 	printk(KERN_DEBUG "%s/core: " fmt, dev->name, ## arg)
@@ -102,7 +106,7 @@
 	"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
 	"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
 	"SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*))
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
 
 static const char *v4l2_ioctls[] = {
 	"QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
@@ -116,7 +120,7 @@
 	"S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
 	"S_MODULATOR"
 };
-#define V4L2_IOCTLS (sizeof(v4l2_ioctls)/sizeof(char*))
+#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
 static const char *osspcm_ioctls[] = {
 	"RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
@@ -125,7 +129,7 @@
 	"GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
 	"SETDUPLEX", "GETODELAY"
 };
-#define OSSPCM_IOCTLS (sizeof(v4l2_ioctls)/sizeof(char*))
+#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
 void saa7134_print_ioctl(char *name, unsigned int cmd)
 {
@@ -236,9 +240,9 @@
 
 /* calc max # of buffers from size (must not exceed the 4MB virtual
  * address space per DMA channel) */
-int saa7134_buffer_count(int size, int count)
+int saa7134_buffer_count(unsigned int size, unsigned int count)
 {
-	int maxcount;
+	unsigned int maxcount;
 	
 	maxcount = 1024 / saa7134_buffer_pages(size);
 	if (count > maxcount)
@@ -277,11 +281,11 @@
 }
 
 int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
-			  struct scatterlist *list, int length,
-			  int startpage)
+			  struct scatterlist *list, unsigned int length,
+			  unsigned int startpage)
 {
-	u32   *ptr;
-	int   i,p;
+	u32           *ptr;
+	unsigned int  i,p;
 
 	BUG_ON(NULL == pt || NULL == pt->cpu);
 
@@ -319,14 +323,25 @@
 			 struct saa7134_dmaqueue *q,
 			 struct saa7134_buf *buf)
 {
+	struct saa7134_buf *next = NULL;
 #if DEBUG_SPINLOCKS
 	BUG_ON(!spin_is_locked(&dev->slock));
 #endif
 	
 	dprintk("buffer_queue %p\n",buf);
 	if (NULL == q->curr) {
-		q->curr = buf;
-		buf->activate(dev,buf,NULL);
+		if (!q->need_two) {
+			q->curr = buf;
+			buf->activate(dev,buf,NULL);
+		} else if (list_empty(&q->queue)) {
+			list_add_tail(&buf->vb.queue,&q->queue);
+			buf->vb.state = STATE_QUEUED;
+		} else {
+			next = list_entry(q->queue.next,struct saa7134_buf,
+					  vb.queue);
+			q->curr = buf;
+			buf->activate(dev,buf,next);
+		}
 	} else {
 		list_add_tail(&buf->vb.queue,&q->queue);
 		buf->vb.state = STATE_QUEUED;
@@ -336,7 +351,7 @@
 
 void saa7134_buffer_finish(struct saa7134_dev *dev,
 			   struct saa7134_dmaqueue *q,
-			   int state)
+			   unsigned int state)
 {
 #if DEBUG_SPINLOCKS
 	BUG_ON(!spin_is_locked(&dev->slock));
@@ -388,6 +403,14 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->slock,flags);
+
+	/* try to reset the hardware (SWRST) */
+	saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+	saa_writeb(SAA7134_REGION_ENABLE, 0x80);
+	saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+
+	/* flag current buffer as failed,
+	   try to start over with the next one. */
 	if (q->curr) {
 		dprintk("timeout on %p\n",q->curr);
 		saa7134_buffer_finish(dev,q,STATE_ERROR);
@@ -400,7 +423,7 @@
 
 int saa7134_set_dmabits(struct saa7134_dev *dev)
 {
-	unsigned long task=0, ctrl=0, irq=0, split = 0;
+	u32 split, task=0, ctrl=0, irq=0;
 	enum v4l2_field cap = V4L2_FIELD_ANY;
 	enum v4l2_field ov  = V4L2_FIELD_ANY;
 
@@ -460,12 +483,12 @@
 	
 	/* set task conditions + field handling */
 	if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
-		/* default config -- use full frames:
-		   odd A, even A, odd B, even B, repeat */
+		/* default config -- use full frames */
 		saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
 		saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
 		saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x02);
 		saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x02);
+		split = 0;
 	} else {
 		/* split fields between tasks */
 		if (V4L2_FIELD_TOP == cap) {
@@ -494,7 +517,7 @@
 		   SAA7134_MAIN_CTRL_TE5 |
 		   SAA7134_MAIN_CTRL_TE6,
 		   ctrl);
-	dprintk("dmabits: task=0x%02lx ctrl=0x%02lx irq=0x%lx split=%s\n",
+	dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
 		task, ctrl, irq, split ? "no" : "yes");
 
 	return 0;
@@ -508,12 +531,12 @@
 	"AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
 	"TRIG_ERR", "CONF_ERR", "LOAD_ERR"
 };
-#define IRQBITS (sizeof(irqbits)/sizeof(char*))
+#define IRQBITS ARRAY_SIZE(irqbits)
 
 static void print_irqstatus(struct saa7134_dev *dev, int loop,
 			    unsigned long report, unsigned long status)
 {
-	int i;
+	unsigned int i;
 	
 	printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
 	       dev->name,loop,jiffies,report,status);
@@ -536,18 +559,19 @@
 {
 	struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
 	unsigned long report,status;
-	int loop;
+	int loop, handled = 0;
 
 	for (loop = 0; loop < 10; loop++) {
 		report = saa_readl(SAA7134_IRQ_REPORT);
 		status = saa_readl(SAA7134_IRQ_STATUS);
-		saa_writel(SAA7134_IRQ_REPORT,report);
 		if (0 == report) {
 			if (irq_debug > 1)
 				printk(KERN_DEBUG "%s/irq: no (more) work\n",
 				       dev->name);
 			goto out;
 		}
+		handled = 1;
+		saa_writel(SAA7134_IRQ_REPORT,report);
 		if (irq_debug)
 			print_irqstatus(dev,loop,report,status);
 
@@ -582,8 +606,9 @@
 		saa_writel(SAA7134_IRQ1,0);
 		saa_writel(SAA7134_IRQ2,0);
 	}
-out:
-	return IRQ_HANDLED;
+
+ out:
+	return IRQ_RETVAL(handled);
 }
 
 /* ------------------------------------------------------------------ */
@@ -599,8 +624,14 @@
 	saa7134_vbi_init(dev);
 	if (card_has_ts(dev))
 		saa7134_ts_init(dev);
-	if (card_has_audio(dev))
+
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
 		saa7134_oss_init(dev);
+		break;
+	}
 	
 	/* RAM FIFO config */
 	saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
@@ -634,12 +665,15 @@
 	/* enable peripheral devices */
 	saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
 
+	/* set vertical line numbering start (vbi needs this) */
+	saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
+	
 	return 0;
 }
 
 static void __devinit must_configure_manually(void)
 {
-	int i,p;
+	unsigned int i,p;
 
 	printk(KERN_WARNING
 	       "saa7134: <rant>\n"
@@ -675,18 +709,39 @@
 		return -ENOMEM;
 	memset(dev,0,sizeof(*dev));
 
-	/* pci stuff */
+	/* pci init */
 	dev->pci = pci_dev;
 	if (pci_enable_device(pci_dev)) {
 		err = -EIO;
 		goto fail1;
 	}
 	sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount);
-	if (-1 != latency) {
+
+	/* pci quirks */
+	if (pci_pci_problems) {
+		if (pci_pci_problems & PCIPCI_TRITON)
+			printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
+		if (pci_pci_problems & PCIPCI_NATOMA)
+			printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
+		if (pci_pci_problems & PCIPCI_VIAETBF)
+			printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
+		if (pci_pci_problems & PCIPCI_VSFX)
+			printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
+#ifdef PCIPCI_ALIMAGIK
+		if (pci_pci_problems & PCIPCI_ALIMAGIK) {
+			printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+			       dev->name);
+			latency = 0x0A;
+		}
+#endif
+	}
+	if (UNSET != latency) {
 		printk(KERN_INFO "%s: setting pci latency timer to %d\n",
 		       dev->name,latency);
 		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
 	}
+
+	/* print pci info */
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
         pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
         printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
@@ -710,7 +765,7 @@
 		dev->board = SAA7134_BOARD_UNKNOWN;
 	}
 	dev->tuner_type = saa7134_boards[dev->board].tuner_type;
-	if (-1 != tuner[saa7134_devcount])
+	if (UNSET != tuner[saa7134_devcount])
 		dev->tuner_type = tuner[saa7134_devcount];
         printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
 	       dev->name,pci_dev->subsystem_vendor,
@@ -730,6 +785,13 @@
 	dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
 	dev->bmmio = (__u8*)dev->lmmio;
 
+	/* register i2c bus */
+	saa7134_i2c_register(dev);
+
+	/* initialize hardware */
+	saa7134_board_init(dev);
+	saa7134_hwinit(dev);
+
 	/* get irq */
 	err = request_irq(pci_dev->irq, saa7134_irq,
 			  SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
@@ -739,12 +801,8 @@
 		goto fail2;
 	}
 
-	/* initialize hardware */
-	saa7134_hwinit(dev);
-
-	/* register i2c bus + load i2c helpers */
-	saa7134_i2c_register(dev);
-	if (TUNER_ABSENT != card(dev).tuner_type)
+	/* load i2c helpers */
+	if (TUNER_ABSENT != dev->tuner_type)
 		request_module("tuner");
 	if (saa7134_boards[dev->board].need_tda9887)
 		request_module("tda9887");
@@ -793,19 +851,27 @@
 	}
 
 	/* register oss devices */
-	if (card_has_audio(dev)) {
-		dev->oss.minor_dsp = register_sound_dsp(&saa7134_dsp_fops,dsp_nr);
-		if (dev->oss.minor_dsp < 0)
-			goto fail7;
-		printk(KERN_INFO "%s: registered device dsp%d\n",
-		       dev->name,dev->oss.minor_dsp >> 4);
-		
-		dev->oss.minor_mixer =
-			register_sound_mixer(&saa7134_mixer_fops,mixer_nr);
-		if (dev->oss.minor_mixer < 0)
-			goto fail8;
-		printk(KERN_INFO "%s: registered device mixer%d\n",
-		       dev->name,dev->oss.minor_mixer >> 4);
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		if (oss) {
+			err = dev->oss.minor_dsp =
+				register_sound_dsp(&saa7134_dsp_fops,dsp_nr);
+			if (err < 0) {
+				goto fail7;
+			}
+			printk(KERN_INFO "%s: registered device dsp%d\n",
+			       dev->name,dev->oss.minor_dsp >> 4);
+			
+			err = dev->oss.minor_mixer =
+				register_sound_mixer(&saa7134_mixer_fops,mixer_nr);
+			if (err < 0)
+				goto fail8;
+			printk(KERN_INFO "%s: registered device mixer%d\n",
+			       dev->name,dev->oss.minor_mixer >> 4);
+		}
+		break;
 	}
 
 	/* everything worked */
@@ -815,8 +881,14 @@
 	return 0;
 
  fail8:
-	if (card_has_audio(dev))
-		unregister_sound_dsp(dev->oss.minor_dsp);
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		if (oss)
+			unregister_sound_dsp(dev->oss.minor_dsp);
+		break;
+	}
  fail7:
 	if (card_has_radio(dev))
 		video_unregister_device(&dev->radio_dev);
@@ -828,16 +900,21 @@
  fail4:
 	video_unregister_device(&dev->video_dev);
  fail3:
-	if (card_has_audio(dev))
+	saa7134_i2c_unregister(dev);
+	free_irq(pci_dev->irq, dev);
+ fail2:
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
 		saa7134_oss_fini(dev);
+		break;
+	}
 	if (card_has_ts(dev))
 		saa7134_ts_fini(dev);
 	saa7134_vbi_fini(dev);
 	saa7134_video_fini(dev);
 	saa7134_tvaudio_fini(dev);
-	saa7134_i2c_unregister(dev);
-	free_irq(pci_dev->irq, dev);
- fail2:
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
  fail1:
@@ -849,6 +926,13 @@
 {
         struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
 
+	/* debugging ... */
+	if (irq_debug) {
+		u32 report = saa_readl(SAA7134_IRQ_REPORT);
+		u32 status = saa_readl(SAA7134_IRQ_STATUS);
+		print_irqstatus(dev,42,report,status);
+	}
+
 	/* disable peripheral devices */
 	saa_writeb(SAA7134_SPECIAL_MODE,0);
 
@@ -858,8 +942,13 @@
 	saa_writel(SAA7134_MAIN_CTRL,0);
 
 	/* shutdown subsystems */
-	if (card_has_audio(dev))
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
 		saa7134_oss_fini(dev);
+		break;
+	}
 	if (card_has_ts(dev))
 		saa7134_ts_fini(dev);
 	saa7134_vbi_fini(dev);
@@ -874,9 +963,15 @@
 
 	/* unregister */
 	saa7134_i2c_unregister(dev);
-	if (card_has_audio(dev)) {
-		unregister_sound_mixer(dev->oss.minor_mixer);
-		unregister_sound_dsp(dev->oss.minor_dsp);
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		if (oss) {
+			unregister_sound_mixer(dev->oss.minor_mixer);
+			unregister_sound_dsp(dev->oss.minor_dsp);
+		}
+		break;
 	}
 	if (card_has_radio(dev))
 		video_unregister_device(&dev->radio_dev);
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c linux/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c	2003-05-08 13:30:00.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-i2c.c	2003-05-08 13:55:12.000000000 +0200
@@ -153,10 +153,7 @@
 		status = i2c_get_status(dev);
 		if (!i2c_is_busy(status))
 			break;
-		if (need_resched())
-                        schedule();
-		else
-			udelay(I2C_WAIT_DELAY);
+		saa_wait(I2C_WAIT_DELAY);
 	}
 	if (I2C_WAIT_RETRY == count)
 		return FALSE;
@@ -318,7 +315,7 @@
 static int attach_inform(struct i2c_client *client)
 {
         struct saa7134_dev *dev = client->adapter->algo_data;
-	int tuner = card(dev).tuner_type;
+	int tuner = dev->tuner_type;
 
 	saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner);
         return 0;
@@ -334,9 +331,9 @@
 
 static struct i2c_adapter saa7134_adap_template = {
 	.owner         = THIS_MODULE,
+	.class         = I2C_ADAP_CLASS_TV_ANALOG,
 	I2C_DEVNAME("saa7134"),
 	.id            = I2C_ALGO_SAA7134,
-	.class         = I2C_ADAP_CLASS_TV_ANALOG,
 	.algo          = &saa7134_algo,
 	.client_register = attach_inform,
 };
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-oss.c linux/drivers/media/video/saa7134/saa7134-oss.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-oss.c	2003-05-08 13:30:55.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-oss.c	2003-05-08 13:55:12.000000000 +0200
@@ -94,8 +94,9 @@
 
 static int dsp_rec_start(struct saa7134_dev *dev)
 {
-	int err, fmt, bswap, wswap;
-	unsigned long control,flags;
+	int err, bswap, sign;
+	u32 fmt, control;
+	unsigned long flags;
 
 	/* prepare buffer */
 	if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
@@ -110,45 +111,60 @@
 
 	/* sample format */
 	switch (dev->oss.afmt) {
-	case AFMT_U8:     fmt = 0x00;         break;
-	case AFMT_S8:     fmt = 0x00 | 0x04;  break;
+	case AFMT_U8:
+	case AFMT_S8:     fmt = 0x00;  break;
 	case AFMT_U16_LE:
-	case AFMT_U16_BE: fmt = 0x01;         break;
+	case AFMT_U16_BE:
 	case AFMT_S16_LE:
-	case AFMT_S16_BE: fmt = 0x01 | 0x04;  break;
-/* 4front API specs mention these ones,
-   the (2.4.15) kernel header hasn't them ... */
-#ifdef AFMT_S32_LE
-	case AFMT_S32_LE:
-	case AFMT_S32_BE: fmt = 0x02 | 0x04;  break;
-#endif
+	case AFMT_S16_BE: fmt = 0x01;  break;
 	default:
 		err = -EINVAL;
 		goto fail2;
 	}
 
 	switch (dev->oss.afmt) {
+	case AFMT_S8:     
+	case AFMT_S16_LE:
+	case AFMT_S16_BE: sign = 1; break;
+	default:          sign = 0; break;
+	}
+
+	switch (dev->oss.afmt) {
 	case AFMT_U16_BE:
-	case AFMT_S16_BE: bswap = 1; wswap = 0; break;
-#ifdef AFMT_S32_LE
-	case AFMT_S32_BE: bswap = 1; wswap = 1; break;
-#endif
-	default:          bswap = 0; wswap = 0; break;
+	case AFMT_S16_BE: bswap = 1; break;
+	default:          bswap = 0; break;
 	}
 
-	if (1 == dev->oss.channels)
-		fmt |= (1 << 3);
-	if (2 == dev->oss.channels)
-		fmt |= (3 << 3);
-	fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
-	
-	saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
-	saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >>  8);
-	saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
-	saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
-	dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c%c\n",
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		if (1 == dev->oss.channels)
+			fmt |= (1 << 3);
+		if (2 == dev->oss.channels)
+			fmt |= (3 << 3);
+		if (sign)
+			fmt |= 0x04;
+		fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
+		
+		saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
+		saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >>  8);
+		saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
+		saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		if (1 == dev->oss.channels)
+			fmt |= (1 << 4);
+		if (2 == dev->oss.channels)
+			fmt |= (2 << 4);
+		if (!sign)
+			fmt |= 0x04;
+		saa_writel(0x588 >> 2, dev->oss.blksize);
+		saa_writel(0x58c >> 2, 0x543210 | (fmt << 24));
+		break;
+	}
+	dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c\n",
 		dev->oss.afmt, dev->oss.channels, fmt,
-		bswap ? 'b' : '-', wswap ? 'w' : '-');
+		bswap ? 'b' : '-');
 
 	/* dma: setup channel 6 (= AUDIO) */
 	control = SAA7134_RS_CONTROL_BURST_16 |
@@ -156,8 +172,6 @@
 		(dev->oss.pt.dma >> 12);
 	if (bswap)
 		control |= SAA7134_RS_CONTROL_BSWAP;
-	if (wswap)
-		control |= SAA7134_RS_CONTROL_WSWAP;
 	saa_writel(SAA7134_RS_BA1(6),0);
 	saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize);
 	saa_writel(SAA7134_RS_PITCH(6),0);
@@ -201,7 +215,7 @@
 
 static int dsp_open(struct inode *inode, struct file *file)
 {
-	unsigned int minor = minor(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct saa7134_dev *h,*dev = NULL;
 	struct list_head *list;
 	int err;
@@ -259,7 +273,8 @@
 {
 	struct saa7134_dev *dev = file->private_data;
 	DECLARE_WAITQUEUE(wait, current);
-	int bytes,err,ret = 0;
+	unsigned int bytes;
+	int err,ret = 0;
 
 	add_wait_queue(&dev->oss.wq, &wait);
 	down(&dev->oss.lock);
@@ -390,10 +405,6 @@
 		case AFMT_U16_BE:
 		case AFMT_S16_LE:
 		case AFMT_S16_BE:
-#ifdef AFMT_S32_LE
-		case AFMT_S32_LE:
-		case AFMT_S32_BE:
-#endif
 			down(&dev->oss.lock);
 			dev->oss.afmt = val;
 			if (dev->oss.recording) {
@@ -416,11 +427,6 @@
 		case AFMT_S16_LE:
 		case AFMT_S16_BE:
 			return put_user(16, (int*)arg);
-#ifdef AFMT_S32_LE
-		case AFMT_S32_LE:
-		case AFMT_S32_BE:
-			return put_user(20, (int*)arg);
-#endif
 		default:
 			return -EINVAL;
 		}
@@ -499,14 +505,10 @@
 /* ------------------------------------------------------------------ */
 
 static int
-mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
+mixer_recsrc_7134(struct saa7134_dev *dev)
 {
-	static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
 	int analog_io,rate;
 	
-	dev->oss.count++;
-	dev->oss.input = src;
-	dprintk("mixer input = %s\n",iname[dev->oss.input]);
 	switch (dev->oss.input) {
 	case TV:
 		saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
@@ -525,27 +527,78 @@
 }
 
 static int
-mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
+mixer_recsrc_7133(struct saa7134_dev *dev)
 {
-	switch (src) {
+	u32 value = 0xbbbbbb;
+	
+	switch (dev->oss.input) {
 	case TV:
-		/* nothing */
+		value = 0xbbbb10;  /* MAIN */
 		break;
 	case LINE1:
-		saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
-			   (100 == level) ? 0x00 : 0x10);
+		value = 0xbbbb32;  /* AUX1 */
 		break;
 	case LINE2:
-		saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
-			   (100 == level) ? 0x00 : 0x20);
+		value = 0xbbbb54;  /* AUX2 */
 		break;
 	}
+	saa_dsp_writel(dev, 0x46c >> 2, value);
 	return 0;
 }
 
+static int
+mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
+{
+	static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
+
+	dev->oss.count++;
+	dev->oss.input = src;
+	dprintk("mixer input = %s\n",iname[dev->oss.input]);
+
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		mixer_recsrc_7134(dev);
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		mixer_recsrc_7133(dev);
+		break;
+	}
+	return 0;
+}
+
+static int
+mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
+{
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		switch (src) {
+		case TV:
+			/* nothing */
+			break;
+		case LINE1:
+			saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
+				   (100 == level) ? 0x00 : 0x10);
+			break;
+		case LINE2:
+			saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
+				   (100 == level) ? 0x00 : 0x20);
+			break;
+		}
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		/* nothing */
+		break;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
 static int mixer_open(struct inode *inode, struct file *file)
 {
-	unsigned int minor = minor(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct saa7134_dev *h,*dev = NULL;
 	struct list_head *list;
 
@@ -681,13 +734,20 @@
 
 int saa7134_oss_init(struct saa7134_dev *dev)
 {
+	/* general */
         init_MUTEX(&dev->oss.lock);
 	init_waitqueue_head(&dev->oss.wq);
-	dev->oss.line1 = 50;
-	dev->oss.line2 = 50;
-	mixer_level(dev,LINE1,dev->oss.line1);
-	mixer_level(dev,LINE2,dev->oss.line2);
-	
+
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		saa_writel(0x588 >> 2, 0x00000fff);
+		saa_writel(0x58c >> 2, 0x00543210);
+		saa_dsp_writel(dev, 0x46c >> 2, 0xbbbbbb);
+		break;
+	}
+
+	/* dsp */
 	dev->oss.rate = 32000;
 	if (oss_rate)
 		dev->oss.rate = oss_rate;
@@ -695,7 +755,13 @@
 		dev->oss.rate = saa7134_boards[dev->board].i2s_rate;
 	dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000;
 
+	/* mixer */
+	dev->oss.line1 = 50;
+	dev->oss.line2 = 50;
+	mixer_level(dev,LINE1,dev->oss.line1);
+	mixer_level(dev,LINE2,dev->oss.line2);
 	mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2);
+	
 	return 0;
 }
 
@@ -710,7 +776,7 @@
 	int next_blk, reg = 0;
 
 	spin_lock(&dev->slock);
-	if (-1 == dev->oss.dma_blk) {
+	if (UNSET == dev->oss.dma_blk) {
 		dprintk("irq: recording stopped%s\n","");
 		goto done;
 	}
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-reg.h linux/drivers/media/video/saa7134/saa7134-reg.h
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-reg.h	2003-05-08 13:31:33.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-reg.h	2003-05-08 13:55:12.000000000 +0200
@@ -9,9 +9,15 @@
 #ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
 # define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
 #endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
+# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
+#endif
 #ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
 # define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
 #endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
+# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
+#endif
 
 /* ------------------------------------------------------------------ */
 /*
@@ -329,6 +335,13 @@
 /* test modes */
 #define SAA7134_SPECIAL_MODE                    0x1d0
 
+/* audio -- saa7133 + saa7135 only */
+#define SAA7135_DSP_RWSTATE                     0x580
+#define SAA7135_DSP_RWSTATE_ERR                 (1 << 3)
+#define SAA7135_DSP_RWSTATE_IDA                 (1 << 2)
+#define SAA7135_DSP_RWSTATE_RDB                 (1 << 1)
+#define SAA7135_DSP_RWSTATE_WRR                 (1 << 0)
+
 /* ------------------------------------------------------------------ */
 /*
  * Local variables:
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-ts.c linux/drivers/media/video/saa7134/saa7134-ts.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-ts.c	2003-05-08 13:29:45.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-ts.c	2003-05-08 13:55:12.000000000 +0200
@@ -52,8 +52,9 @@
 {
 	u32 control;
 	
-	dprintk("buffer_activate [%p]\n",buf);
+	dprintk("buffer_activate [%p]",buf);
 	buf->vb.state = STATE_ACTIVE;
+	buf->top_seen = 0;
 	
         /* dma: setup channel 5 (= TS) */
         control = SAA7134_RS_CONTROL_BURST_16 |
@@ -63,11 +64,11 @@
 	if (NULL == next)
 		next = buf;
 	if (V4L2_FIELD_TOP == buf->vb.field) {
-		dprintk("[top]     buf=%p next=%p",buf,next);
+		dprintk("- [top]     buf=%p next=%p\n",buf,next);
 		saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
 		saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
 	} else {
-		dprintk("[bottom]  buf=%p next=%p",buf,next);
+		dprintk("- [bottom]  buf=%p next=%p\n",buf,next);
 		saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
 		saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
 	}
@@ -86,8 +87,11 @@
 {
 	struct saa7134_dev *dev = file->private_data;
 	struct saa7134_buf *buf = (struct saa7134_buf *)vb;
-	int lines, llength, size, err;
+	unsigned int lines, llength, size;
+	int err;
 	
+	dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
+
 	llength = TS_PACKET_SIZE;
 	lines = TS_NR_PACKETS;
 	
@@ -116,7 +120,6 @@
 			goto oops;
 	}
 	buf->vb.state = STATE_PREPARED;
-	buf->top_seen = 0;
 	buf->activate = buffer_activate;
 	buf->vb.field = field;
 	return 0;
@@ -163,7 +166,7 @@
 
 static int ts_open(struct inode *inode, struct file *file)
 {
-	unsigned int minor = minor(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct saa7134_dev *h,*dev = NULL;
 	struct list_head *list;
 	int err;
@@ -414,6 +417,7 @@
 	dev->ts_q.timeout.function = saa7134_buffer_timeout;
 	dev->ts_q.timeout.data     = (unsigned long)(&dev->ts_q);
 	dev->ts_q.dev              = dev;
+	dev->ts_q.need_two         = 1;
 	videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_ALTERNATE,
@@ -445,7 +449,7 @@
 
 	spin_lock(&dev->slock);
 	if (dev->ts_q.curr) {
-		field = dev->video_q.curr->vb.field;
+		field = dev->ts_q.curr->vb.field;
 		if (field == V4L2_FIELD_TOP) {
 			if ((status & 0x100000) != 0x100000)
 				goto done;
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-tvaudio.c linux/drivers/media/video/saa7134/saa7134-tvaudio.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-tvaudio.c	2003-05-08 13:29:43.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-tvaudio.c	2003-05-08 13:55:12.000000000 +0200
@@ -37,13 +37,23 @@
 MODULE_PARM(audio_debug,"i");
 MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
 
+static unsigned int audio_carrier = 0;
+MODULE_PARM(audio_carrier,"i");
+MODULE_PARM_DESC(audio_carrier,"audio carrier location");
+
 #define dprintk(fmt, arg...)	if (audio_debug) \
 	printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
+#define d2printk(fmt, arg...)	if (audio_debug > 1) \
+	printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
 
 #define print_regb(reg) printk("%s:   reg 0x%03x [%-16s]: 0x%02x\n", \
 		dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
 
+#define SCAN_INITIAL_DELAY  (HZ)
+#define SCAN_SAMPLE_DELAY   (HZ/10)
+
 /* ------------------------------------------------------------------ */
+/* saa7134 code                                                       */
 
 static struct saa7134_tvaudio tvaudio[] = {
 	{
@@ -95,6 +105,12 @@
 		.carr2         = 5850,
 		.mode          = TVAUDIO_NICAM_AM,
 	},{
+		.name          = "SECAM-D/K",
+		.std           = V4L2_STD_SECAM,
+		.carr1         = 6500,
+		.carr2         = -1,
+		.mode          = TVAUDIO_FM_MONO,
+	},{
 		.name          = "NTSC-M",
 		.std           = V4L2_STD_NTSC,
 		.carr1         = 4500,
@@ -122,7 +138,7 @@
 		schedule();
 	else
 		udelay(10);
-		
+
 	saa_writeb(SAA7134_AUDIO_CLOCK0,      clock        & 0xff);
 	saa_writeb(SAA7134_AUDIO_CLOCK1,     (clock >>  8) & 0xff);
 	saa_writeb(SAA7134_AUDIO_CLOCK2,     (clock >> 16) & 0xff);
@@ -134,9 +150,9 @@
 	saa_writeb(SAA7134_FM_DEMATRIX,      0x80);
 }
 
-static __u32 tvaudio_carr2reg(__u32 carrier)
+static u32 tvaudio_carr2reg(u32 carrier)
 {
-	__u64 a = carrier;
+	u64 a = carrier;
 
 	a <<= 24;
 	do_div(a,12288);
@@ -152,17 +168,19 @@
 	saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary));
 }
 
-static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
+static void mute_input_7134(struct saa7134_dev *dev)
 {
-	int mute;
+	unsigned int mute;
 	struct saa7134_input *in;
 	int reg = 0;
 	int mask;
 
 	/* look what is to do ... */
 	in   = dev->input;
-	mute = (dev->ctl_mute || dev->automute);
-	if (!card_has_audio(dev) && card(dev).mute.name) {
+	mute = (dev->ctl_mute ||
+		(dev->automute  &&  (&card(dev).radio) != in));
+	if (PCI_DEVICE_ID_PHILIPS_SAA7130 == dev->pci->device &&
+	    card(dev).mute.name) {
 		/* 7130 - we'll mute using some unconnected audio input */
 		if (mute)
 			in = &card(dev).mute;
@@ -171,14 +189,12 @@
 	    dev->hw_input == in)
 		return;
 
-#if 1
 	dprintk("ctl_mute=%d automute=%d input=%s  =>  mute=%d input=%s\n",
 		dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
-#endif
 	dev->hw_mute  = mute;
 	dev->hw_input = in;
 
-	if (card_has_audio(dev))
+	if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
 		/* 7134 mute */
 		saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb);
 
@@ -199,25 +215,6 @@
 	saa7134_track_gpio(dev,in->name);
 }
 
-void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
-{
-	saa7134_tvaudio_do_mute_input(dev);
-}
-
-void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
-			      struct saa7134_input *in)
-{
-	dev->input = in;
-	saa7134_tvaudio_do_mute_input(dev);
-}
-
-void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
-{
-	saa_writeb(SAA7134_CHANNEL1_LEVEL,     level & 0x1f);
-	saa_writeb(SAA7134_CHANNEL2_LEVEL,     level & 0x1f);
-	saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
-}
-
 static void tvaudio_setmode(struct saa7134_dev *dev,
 			    struct saa7134_tvaudio *audio,
 			    char *note)
@@ -274,8 +271,77 @@
 	saa_writel(0x174 >> 2, 0x0001e000); /* FIXME */
 }
 
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
-			      struct saa7134_tvaudio *audio)
+static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	
+	add_wait_queue(&dev->thread.wq, &wait);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(timeout);
+	remove_wait_queue(&dev->thread.wq, &wait);
+	return dev->thread.scan1 != dev->thread.scan2;
+}
+
+static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
+{
+	__s32 left,right,value;
+
+	if (audio_debug > 1) {
+		int i;
+		dprintk("debug %d:",carrier);
+		for (i = -150; i <= 150; i += 30) {
+			tvaudio_setcarrier(dev,carrier+i,carrier+i);
+			saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+			if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+				return -1;
+			value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+			if (0 == i)
+				printk("  #  %6d  # ",value >> 16);
+			else
+				printk(" %6d",value >> 16);
+		}
+		printk("\n");
+	}
+	
+	tvaudio_setcarrier(dev,carrier-90,carrier-90);
+	saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+	if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+		return -1;
+	left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+	tvaudio_setcarrier(dev,carrier+90,carrier+90);
+	saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+	if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+		return -1;
+	right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+	left >>= 16;
+        right >>= 16;
+	value = left > right ? left - right : right - left;
+	dprintk("scanning %d.%03d MHz =>  dc is %5d [%d/%d]\n",
+		carrier/1000,carrier%1000,value,left,right);
+	return value;
+}
+
+#if 0
+static void sifdebug_dump_regs(struct saa7134_dev *dev)
+{
+	print_regb(AUDIO_STATUS);
+	print_regb(IDENT_SIF);
+	print_regb(LEVEL_READOUT1);
+	print_regb(LEVEL_READOUT2);
+	print_regb(DCXO_IDENT_CTRL);
+	print_regb(DEMODULATOR);
+	print_regb(AGC_GAIN_SELECT);
+	print_regb(MONITOR_SELECT);
+	print_regb(FM_DEEMPHASIS);
+	print_regb(FM_DEMATRIX);
+	print_regb(SIF_SAMPLE_FREQ);
+	print_regb(ANALOG_IO_SELECT);
+}
+#endif
+
+static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio)
 {
 	__u32 idp,nicam;
 	int retval = -1;
@@ -321,62 +387,42 @@
 	return retval;
 }
 
-static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
+static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio,
+			     u32 mode)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	
-	add_wait_queue(&dev->thread.wq, &wait);
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(timeout);
-	remove_wait_queue(&dev->thread.wq, &wait);
-	return dev->thread.scan1 != dev->thread.scan2;
-}
-
-static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
-{
-	__s32 left,right,value;
-	
-	tvaudio_setcarrier(dev,carrier-100,carrier-100);
-	if (tvaudio_sleep(dev,HZ/10))
-		return -1;
-	left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-	if (tvaudio_sleep(dev,HZ/10))
-		return -1;
-	left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-	tvaudio_setcarrier(dev,carrier+100,carrier+100);
-	if (tvaudio_sleep(dev,HZ/10))
-		return -1;
-        right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-	if (tvaudio_sleep(dev,HZ/10))
-		return -1;
-	right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+	static char *name[] = {
+		[ V4L2_TUNER_MODE_MONO   ] = "mono",
+		[ V4L2_TUNER_MODE_STEREO ] = "stereo",
+		[ V4L2_TUNER_MODE_LANG1  ] = "lang1",
+		[ V4L2_TUNER_MODE_LANG2  ] = "lang2",
+	};
+	static u32 fm[] = {
+		[ V4L2_TUNER_MODE_MONO   ] = 0x00,  /* ch1  */
+		[ V4L2_TUNER_MODE_STEREO ] = 0x80,  /* auto */
+		[ V4L2_TUNER_MODE_LANG1  ] = 0x00,  /* ch1  */
+		[ V4L2_TUNER_MODE_LANG2  ] = 0x01,  /* ch2  */
+	};
+	u32 reg;
 
-	left >>= 16;
-        right >>= 16;
-	value = left > right ? left - right : right - left;
-	dprintk("scanning %d.%03d MHz =>  dc is %5d [%d/%d]\n",
-		carrier/1000,carrier%1000,value,left,right);
-	return value;
-}
-
-#if 0
-static void sifdebug_dump_regs(struct saa7134_dev *dev)
-{
-	print_regb(AUDIO_STATUS);
-	print_regb(IDENT_SIF);
-	print_regb(LEVEL_READOUT1);
-	print_regb(LEVEL_READOUT2);
-	print_regb(DCXO_IDENT_CTRL);
-	print_regb(DEMODULATOR);
-	print_regb(AGC_GAIN_SELECT);
-	print_regb(MONITOR_SELECT);
-	print_regb(FM_DEEMPHASIS);
-	print_regb(FM_DEMATRIX);
-	print_regb(SIF_SAMPLE_FREQ);
-	print_regb(ANALOG_IO_SELECT);
+	switch (audio->mode) {
+	case TVAUDIO_FM_MONO:
+		/* nothing to do ... */
+		break;
+	case TVAUDIO_FM_K_STEREO:
+	case TVAUDIO_FM_BG_STEREO:
+		dprintk("setstereo [fm] => %s\n",
+			name[ mode % ARRAY_SIZE(name) ]);
+		reg = fm[ mode % ARRAY_SIZE(fm) ];
+		saa_writeb(SAA7134_FM_DEMATRIX, reg);
+		break;
+	case TVAUDIO_FM_SAT_STEREO:
+	case TVAUDIO_NICAM_AM:
+	case TVAUDIO_NICAM_FM:
+		/* FIXME */
+		break;
+	}
+	return 0;
 }
-#endif
 
 static int tvaudio_thread(void *data)
 {
@@ -388,7 +434,8 @@
 	struct saa7134_dev *dev = data;
 	const int *carr_scan;
 	int carr_vals[4];
-	int i,max,carrier,audio;
+	unsigned int i, audio;
+	int max1,max2,carrier,rx,mode;
 
 	lock_kernel();
 	daemonize("%s", dev->name);
@@ -410,10 +457,10 @@
 		dev->tvaudio  = NULL;
 		tvaudio_init(dev);
 		dev->automute = 1;
-		saa7134_tvaudio_setmute(dev);
+		mute_input_7134(dev);
 
 		/* give the tuner some time */
-		if (tvaudio_sleep(dev,HZ/2))
+		if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
 			goto restart;
 
 		/* find the main carrier */
@@ -433,55 +480,280 @@
 			if (dev->thread.scan1 != dev->thread.scan2)
 				goto restart;
 		}
-		for (carrier = 0, max = 0, i = 0; i < MAX_SCAN; i++) {
+		for (carrier = 0, max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) {
 			if (!carr_scan[i])
 				continue;
-			if (max < carr_vals[i]) {
-				max = carr_vals[i];
+			if (max1 < carr_vals[i]) {
+				max2 = max1;
+				max1 = carr_vals[i];
 				carrier = carr_scan[i];
+			} else if (max2 < carr_vals[i]) {
+				max2 = carr_vals[i];
 			}
 		}
-		if (0 == carrier) {
-			/* Oops: autoscan didn't work for some reason :-/ */
-			printk(KERN_WARNING "%s/audio: oops: audio carrier "
-			       "scan failed\n", dev->name);
+
+		if (0 != carrier && max1 > 2000 && max1 > max2*3) {
+			/* found good carrier */
+			dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
+				dev->tvnorm->name, carrier/1000, carrier%1000,
+				max1, max2);
+			dev->last_carrier = carrier;
+		} else if (0 != audio_carrier) {
+			/* no carrier -- try insmod option as fallback */
+			carrier = audio_carrier;
+			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+			       "using %d.%03d MHz [insmod option]\n",
+			       dev->name, carrier/1000, carrier%1000);
+		} else if (0 != dev->last_carrier) {
+			/* no carrier -- try last detected one as fallback */
+			carrier = dev->last_carrier;
+			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+			       "using %d.%03d MHz [last detected]\n",
+			       dev->name, carrier/1000, carrier%1000);
 		} else {
-			dprintk("found %s main sound carrier @ %d.%03d MHz\n",
-				dev->tvnorm->name,
-				carrier/1000,carrier%1000);
+			/* no carrier + no fallback -- try first in list */
+			carrier = carr_scan[0];
+			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+			       "using %d.%03d MHz [default]\n",
+			       dev->name, carrier/1000, carrier%1000);
 		}
 		tvaudio_setcarrier(dev,carrier,carrier);
 		dev->automute = 0;
+		saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
 		saa7134_tvaudio_setmute(dev);
 
 		/* find the exact tv audio norm */
-		for (audio = -1, i = 0; i < TVAUDIO; i++) {
-			if (dev->tvnorm->id != -1 &&
+		for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
+			if (dev->tvnorm->id != UNSET &&
 			    dev->tvnorm->id != tvaudio[i].std)
 				continue;
 			if (tvaudio[i].carr1 != carrier)
 				continue;
 
-			if (-1 == audio)
+			if (UNSET == audio)
 				audio = i;
 			tvaudio_setmode(dev,&tvaudio[i],"trying");
 			if (tvaudio_sleep(dev,HZ))
 				goto restart;
-			if (-1 != saa7134_tvaudio_getstereo(dev,&tvaudio[i])) {
+			if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
 				audio = i;
 				break;
 			}
 		}
-		if (-1 == audio)
+		saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);
+		if (UNSET == audio)
 			continue;
 		tvaudio_setmode(dev,&tvaudio[audio],"using");
+		tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);
 		dev->tvaudio = &tvaudio[audio];
 
-#if 1
 		if (tvaudio_sleep(dev,3*HZ))
 			goto restart;
-		saa7134_tvaudio_getstereo(dev,&tvaudio[i]);
+		rx = tvaudio_getstereo(dev,&tvaudio[i]);
+		mode = saa7134_tvaudio_rx2mode(rx);
+		tvaudio_setstereo(dev,&tvaudio[audio],mode);
+	}
+
+ done:
+	dev->thread.task = NULL;
+	if(dev->thread.notify != NULL)
+		up(dev->thread.notify);
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* saa7133 / saa7135 code                                             */
+
+static char *stdres[0x20] = {
+	[0x00] = "no standard detected",
+	[0x01] = "B/G (in progress)",
+	[0x02] = "D/K (in progress)",
+	[0x03] = "M (in progress)",
+
+	[0x04] = "B/G A2",
+	[0x05] = "B/G NICAM",
+	[0x06] = "D/K A2 (1)",
+	[0x07] = "D/K A2 (2)",
+	[0x08] = "D/K A2 (3)",
+	[0x09] = "D/K NICAM",
+	[0x0a] = "L NICAM",
+	[0x0b] = "I NICAM",
+	
+	[0x0c] = "M Korea",
+	[0x0d] = "M BTSC ",
+	[0x0e] = "M EIAJ",
+
+	[0x0f] = "FM radio / IF 10.7 / 50 deemp",
+	[0x10] = "FM radio / IF 10.7 / 75 deemp",
+	[0x11] = "FM radio / IF sel / 50 deemp",
+	[0x12] = "FM radio / IF sel / 75 deemp",
+
+	[0x13 ... 0x1e ] = "unknown",
+	[0x1f] = "??? [in progress]",
+};
+
+#define DSP_RETRY 16
+#define DSP_DELAY 16
+
+static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+{
+	int state, count = DSP_RETRY;
+
+	state = saa_readb(SAA7135_DSP_RWSTATE);
+	if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+		printk("%s: dsp access error\n",dev->name);
+		/* FIXME: send ack ... */
+		return -EIO;
+	}
+	while (0 == (state & bit)) {
+		if (unlikely(0 == count)) {
+			printk("%s: dsp access wait timeout [bit=%s]\n",
+			       dev->name,
+			       (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
+			       (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
+			       (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
+			       "???");
+			return -EIO;
+		}
+		saa_wait(DSP_DELAY);
+		state = saa_readb(SAA7135_DSP_RWSTATE);
+		count--;
+	}
+	return 0;
+}
+
+#if 0
+static int saa_dsp_readl(struct saa7134_dev *dev, int reg, u32 *value)
+{
+	int err;
+
+	d2printk("dsp read reg 0x%x\n", reg<<2);
+	saa_readl(reg);
+	err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_RDB);
+	if (err < 0)
+		return err;
+	*value = saa_readl(reg);
+	d2printk("dsp read   => 0x%06x\n", *value & 0xffffff);
+	err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_IDA);
+	if (err < 0)
+		return err;
+	return 0;
+}
 #endif
+
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value)
+{
+	int err;
+
+	d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value);
+	err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+	if (err < 0)
+		return err;
+	saa_writel(reg,value);
+	err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int getstereo_7133(struct saa7134_dev *dev)
+{
+	int retval = V4L2_TUNER_SUB_MONO;
+	u32 value;
+
+	value = saa_readl(0x528 >> 2);
+	if (value & 0x20)
+		retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+	if (value & 0x40)
+		retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	return retval;
+}
+
+static int mute_input_7133(struct saa7134_dev *dev)
+{
+	u32 reg = 0;
+	
+	switch (dev->input->amux) {
+	case TV:    reg = 0x02; break;
+	case LINE1: reg = 0x00; break;
+	case LINE2: reg = 0x01; break;
+	}
+	if (dev->ctl_mute)
+		reg = 0x07;
+	saa_writel(0x594 >> 2, reg);
+	return 0;
+}
+
+static int tvaudio_thread_ddep(void *data)
+{
+	struct saa7134_dev *dev = data;
+	u32 value, norms;
+
+	lock_kernel();
+	daemonize("%s", dev->name);
+	dev->thread.task = current;
+	unlock_kernel();
+	if (dev->thread.notify != NULL)
+		up(dev->thread.notify);
+
+	/* unmute */
+	saa_dsp_writel(dev, 0x474 >> 2, 0x00);
+	saa_dsp_writel(dev, 0x450 >> 2, 0x00);
+
+	for (;;) {
+		if (dev->thread.exit || signal_pending(current))
+			goto done;
+		interruptible_sleep_on(&dev->thread.wq);
+		if (dev->thread.exit || signal_pending(current))
+			goto done;
+
+	restart:
+		dev->thread.scan1 = dev->thread.scan2;
+		dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+
+		norms = 0;
+		if (dev->tvnorm->id & V4L2_STD_PAL)
+			norms |= 0x2c; /* B/G + D/K + I */
+		if (dev->tvnorm->id & V4L2_STD_NTSC)
+			norms |= 0x40; /* M */
+		if (dev->tvnorm->id & V4L2_STD_SECAM)
+			norms |= 0x18; /* L + D/K */
+		if (0 == norms)
+			norms = 0x0000007c;
+
+		/* quick & dirty -- to be fixed up later ... */
+		saa_dsp_writel(dev, 0x454 >> 2, 0);
+		saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80);
+		saa_dsp_writel(dev, 0x464 >> 2, 0x000000);
+		saa_dsp_writel(dev, 0x470 >> 2, 0x101010);
+
+		if (tvaudio_sleep(dev,3*HZ))
+			goto restart;
+		value = saa_readl(0x528 >> 2) & 0xffffff;
+
+		dprintk("tvaudio thread status: 0x%x [%s%s%s]\n",
+			value, stdres[value & 0x1f],
+			(value & 0x000020) ? ",stereo" : "",
+			(value & 0x000040) ? ",dual"   : "");
+		dprintk("detailed status: "
+			"%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+			(value & 0x000080) ? " A2/EIAJ pilot tone "     : "",
+			(value & 0x000100) ? " A2/EIAJ dual "           : "",
+			(value & 0x000200) ? " A2/EIAJ stereo "         : "",
+			(value & 0x000400) ? " A2/EIAJ noise mute "     : "",
+
+			(value & 0x000800) ? " BTSC/FM radio pilot "    : "",
+			(value & 0x001000) ? " SAP carrier "            : "",
+			(value & 0x002000) ? " BTSC stereo noise mute " : "",
+			(value & 0x004000) ? " SAP noise mute "         : "",
+			(value & 0x008000) ? " VDSP "                   : "",
+			
+			(value & 0x010000) ? " NICST "                  : "",
+			(value & 0x020000) ? " NICDU "                  : "",
+			(value & 0x040000) ? " NICAM muted "            : "",
+			(value & 0x080000) ? " NICAM reserve sound "    : "",
+			
+			(value & 0x100000) ? " init done "              : "");
 	}
 
  done:
@@ -492,14 +764,89 @@
 }
 
 /* ------------------------------------------------------------------ */
+/* common stuff + external entry points                               */
+
+int saa7134_tvaudio_rx2mode(u32 rx)
+{
+	u32 mode;
+	
+	mode = V4L2_TUNER_MODE_MONO;
+	if (rx & V4L2_TUNER_SUB_STEREO)
+		mode = V4L2_TUNER_MODE_STEREO;
+	else if (rx & V4L2_TUNER_SUB_LANG1)
+		mode = V4L2_TUNER_MODE_LANG1;
+	else if (rx & V4L2_TUNER_SUB_LANG2)
+		mode = V4L2_TUNER_MODE_LANG2;
+	return mode;
+}
+	
+void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
+{
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7130:
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		mute_input_7134(dev);
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		mute_input_7133(dev);
+		break;
+	}
+}
+
+void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
+			      struct saa7134_input *in)
+{
+	dev->input = in;
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7130:
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		mute_input_7134(dev);
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		mute_input_7133(dev);
+		break;
+	}
+}
+
+void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
+{
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		saa_writeb(SAA7134_CHANNEL1_LEVEL,     level & 0x1f);
+		saa_writeb(SAA7134_CHANNEL2_LEVEL,     level & 0x1f);
+		saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
+		break;
+	}
+}
+
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
+{
+	int retval = V4L2_TUNER_SUB_MONO;
+
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		if (dev->tvaudio)
+			retval = tvaudio_getstereo(dev,dev->tvaudio);
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		retval = getstereo_7133(dev);
+		break;
+	}
+	return retval;
+}
 
 int saa7134_tvaudio_init(struct saa7134_dev *dev)
 {
 	DECLARE_MUTEX_LOCKED(sem);
+	int (*my_thread)(void *data) = NULL;
 
 	/* enable I2S audio output */
 	if (saa7134_boards[dev->board].i2s_rate) {
-		int rate = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x01 : 0x03;
+		int rate = (32000 == saa7134_boards[dev->board].i2s_rate)
+			? 0x01 : 0x03;
 		
 		/* set rate */ 
 		saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
@@ -512,13 +859,24 @@
 		saa_writeb(SAA7134_I2S_AUDIO_OUTPUT,   0x01);
 	}
 
-	/* start tvaudio thread */
-	init_waitqueue_head(&dev->thread.wq);
-	dev->thread.notify = &sem;
-	kernel_thread(tvaudio_thread,dev,0);
-	down(&sem);
-	dev->thread.notify = NULL;
-	wake_up_interruptible(&dev->thread.wq);
+	switch (dev->pci->device) {
+	case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		my_thread = tvaudio_thread;
+		break;
+	case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		my_thread = tvaudio_thread_ddep;
+		break;
+	}
+	if (my_thread) {
+		/* start tvaudio thread */
+		init_waitqueue_head(&dev->thread.wq);
+		dev->thread.notify = &sem;
+		kernel_thread(my_thread,dev,0);
+		down(&sem);
+		dev->thread.notify = NULL;
+		wake_up_interruptible(&dev->thread.wq);
+	}
 
 	return 0;
 }
@@ -541,8 +899,13 @@
 
 int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
 {
-	dev->thread.scan2++;
-	wake_up_interruptible(&dev->thread.wq);
+	if (dev->thread.task) {
+		dev->thread.scan2++;
+		wake_up_interruptible(&dev->thread.wq);
+	} else {
+		dev->automute = 0;
+		saa7134_tvaudio_setmute(dev);
+	}
 	return 0;
 }
 
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-vbi.c linux/drivers/media/video/saa7134/saa7134-vbi.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-vbi.c	2003-05-08 13:32:06.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-vbi.c	2003-05-08 13:55:12.000000000 +0200
@@ -85,6 +85,7 @@
 
 	dprintk("buffer_activate [%p]\n",buf);
 	buf->vb.state = STATE_ACTIVE;
+	buf->top_seen = 0;
 
 	task_init(dev,buf,TASK_A);
 	task_init(dev,buf,TASK_B);
@@ -119,7 +120,8 @@
 	struct saa7134_dev *dev = fh->dev;
 	struct saa7134_buf *buf = (struct saa7134_buf *)vb;
 	struct saa7134_tvnorm *norm = dev->tvnorm;
-	int lines, llength, size, err;
+	unsigned int lines, llength, size;
+	int err;
 
 	lines   = norm->vbi_v_stop - norm->vbi_v_start +1;
 	if (lines > VBI_LINE_COUNT)
@@ -155,7 +157,6 @@
 			goto oops;
 	}
 	buf->vb.state = STATE_PREPARED;
-	buf->top_seen = 0;
 	buf->activate = buffer_activate;
 	buf->vb.field = field;
 	return 0;
@@ -166,7 +167,7 @@
 }
 
 static int
-buffer_setup(struct file *file, int *count, int *size)
+buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
 {
 	struct saa7134_fh *fh   = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
@@ -241,7 +242,7 @@
 	if (dev->vbi_q.curr) {
 		dev->vbi_fieldcount++;
 		/* make sure we have seen both fields */
-		if ((status & 0x10) == 0x10) {
+		if ((status & 0x10) == 0x00) {
 			dev->vbi_q.curr->top_seen = 1;
 			goto done;
 		}
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134-video.c linux/drivers/media/video/saa7134/saa7134-video.c
--- linux-2.5.69/drivers/media/video/saa7134/saa7134-video.c	2003-05-08 13:30:01.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134-video.c	2003-05-08 13:55:12.000000000 +0200
@@ -2,7 +2,7 @@
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
  *
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
  *  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
@@ -127,7 +127,7 @@
 		.vshift   = 1,
 	}
 };
-#define FORMATS (sizeof(formats)/sizeof(struct saa7134_format))
+#define FORMATS ARRAY_SIZE(formats)
 
 static struct saa7134_tvnorm tvnorms[] = {
 	{
@@ -141,13 +141,15 @@
 		.chroma_ctrl1  = 0x81,
 		.chroma_gain   = 0x2a,
 		.chroma_ctrl2  = 0x06,
+		.vgate_misc    = 0x1c,
 
 		.h_start       = 0,
 		.h_stop        = 719,
 		.video_v_start = 24,
 		.video_v_stop  = 311,
-		.vbi_v_start   = 7-3,  /* FIXME */
-		.vbi_v_stop    = 22-3,
+		.vbi_v_start   = 7,
+		.vbi_v_stop    = 22,
+		.src_timing    = 4,
 	},{
 		.name          = "NTSC",
 		.id            = V4L2_STD_NTSC,
@@ -159,6 +161,7 @@
 		.chroma_ctrl1  = 0x89,
 		.chroma_gain   = 0x2a,
 		.chroma_ctrl2  = 0x0e,
+		.vgate_misc    = 0x18,
 
 		.h_start       = 0,
 		.h_stop        = 719,
@@ -166,17 +169,19 @@
 		.video_v_stop  = 22+240,
 		.vbi_v_start   = 10, /* FIXME */
 		.vbi_v_stop    = 21, /* FIXME */
+		.src_timing    = 1,
 	},{
 		.name          = "SECAM",
 		.id            = V4L2_STD_SECAM,
 		.width         = 720,
 		.height        = 576,
 
-		.sync_control  = 0x58,
+		.sync_control  = 0x18, /* old: 0x58, */
 		.luma_control  = 0x1b,
 		.chroma_ctrl1  = 0xd1,
 		.chroma_gain   = 0x80,
 		.chroma_ctrl2  = 0x00,
+		.vgate_misc    = 0x1c,
 
 		.h_start       = 0,
 		.h_stop        = 719,
@@ -184,6 +189,47 @@
 		.video_v_stop  = 311,
 		.vbi_v_start   = 7,
 		.vbi_v_stop    = 22,
+		.src_timing    = 4,
+	},{
+		.name          = "PAL-M",
+		.id            = V4L2_STD_PAL_M,
+		.width         = 720,
+		.height        = 480,
+
+		.sync_control  = 0x59,
+		.luma_control  = 0x40,
+		.chroma_ctrl1  = 0xb9,
+		.chroma_gain   = 0x2a,
+		.chroma_ctrl2  = 0x0e,
+		.vgate_misc    = 0x18,
+
+		.h_start       = 0,
+		.h_stop        = 719,
+		.video_v_start = 22,
+		.video_v_stop  = 22+240,
+		.vbi_v_start   = 10, /* FIXME */
+		.vbi_v_stop    = 21, /* FIXME */
+		.src_timing    = 1,
+	},{
+		.name          = "PAL-Nc",
+		.id            = V4L2_STD_PAL_Nc,
+		.width         = 720,
+		.height        = 576,
+
+		.sync_control  = 0x18,
+		.luma_control  = 0x40,
+		.chroma_ctrl1  = 0xa1,
+		.chroma_gain   = 0x2a,
+		.chroma_ctrl2  = 0x06,
+		.vgate_misc    = 0x1c,
+
+		.h_start       = 0,
+		.h_stop        = 719,
+		.video_v_start = 24,
+		.video_v_stop  = 311,
+		.vbi_v_start   = 7,
+		.vbi_v_stop    = 22,
+		.src_timing    = 4,
 #if 0
 	},{
 		.name          = "AUTO",
@@ -196,6 +242,7 @@
 		.chroma_ctrl1  = 0x8b,
 		.chroma_gain   = 0x00,
 		.chroma_ctrl2  = 0x00,
+		.vgate_misc    = 0x18,
 
 		.h_start       = 0,
 		.h_stop        = 719,
@@ -203,11 +250,11 @@
 		.video_v_stop  = 311,
 		.vbi_v_start   = 7,
 		.vbi_v_stop    = 22,
+		.src_timing    = 4,
 #endif
 	}
 };
-#define TVNORMS (sizeof(tvnorms)/sizeof(struct saa7134_tvnorm))
-
+#define TVNORMS ARRAY_SIZE(tvnorms)
 
 #define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
 #define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
@@ -298,11 +345,11 @@
 		.type          = V4L2_CTRL_TYPE_INTEGER,
 	}
 };
-const int CTRLS = (sizeof(video_ctrls)/sizeof(struct v4l2_queryctrl));
+static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
 
-static const struct v4l2_queryctrl* ctrl_by_id(int id)
+static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
 {
-	int i;
+	unsigned int i;
 	
 	for (i = 0; i < CTRLS; i++)
 		if (video_ctrls[i].id == id)
@@ -310,9 +357,9 @@
 	return NULL;
 }
 
-static struct saa7134_format* format_by_fourcc(int  fourcc)
+static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < FORMATS; i++)
 		if (formats[i].fourcc == fourcc)
@@ -323,7 +370,7 @@
 /* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
-static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, int bit)
+static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit)
 {
 	if (fh->resources & bit)
 		/* have it already allocated */
@@ -345,19 +392,19 @@
 }
 
 static
-int res_check(struct saa7134_fh *fh, int bit)
+int res_check(struct saa7134_fh *fh, unsigned int bit)
 {
 	return (fh->resources & bit);
 }
 
 static
-int res_locked(struct saa7134_dev *dev, int bit)
+int res_locked(struct saa7134_dev *dev, unsigned int bit)
 {
 	return (dev->resources & bit);
 }
 
 static
-void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, int bits)
+void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
 {
 	if ((fh->resources & bits) != bits)
 		BUG();
@@ -393,7 +440,8 @@
 	saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);
 	saa_writeb(SAA7134_HSYNC_START,           0xeb);
 	saa_writeb(SAA7134_HSYNC_STOP,            0xe0);
-
+	saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);
+	
 	saa_writeb(SAA7134_SYNC_CTRL,             norm->sync_control);
 	saa_writeb(SAA7134_LUMA_CTRL,             luma_control);
 	saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);
@@ -410,7 +458,7 @@
 	saa_writeb(SAA7134_ANALOG_ADC,            0x01);
 	saa_writeb(SAA7134_VGATE_START,           0x11);
 	saa_writeb(SAA7134_VGATE_STOP,            0xfe);
-	saa_writeb(SAA7134_MISC_VGATE_MSB,        0x18); /* FIXME */
+	saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);
 	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);
 	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);
 
@@ -454,7 +502,7 @@
 		{    9,  15,    0,    4,   3 },
 		{   10,  16,    1,    5,   3 },
 	};
-	static const int count = sizeof(vals)/sizeof(vals[0]);
+	static const int count = ARRAY_SIZE(vals);
 	int i;
 
 	for (i = 0; i < count; i++)
@@ -532,14 +580,14 @@
 	/* deinterlace y offsets */
 	if (interlace) {
 		y_odd  = dev->ctl_y_odd;
-		y_even = dev->ctl_y_even + yscale / 32;
+		y_even = dev->ctl_y_even;
 		saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
 		saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
 		saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
 		saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);
 	} else {
 		y_odd  = dev->ctl_y_odd;
-		y_even = dev->ctl_y_even + yscale / 64;
+		y_even = dev->ctl_y_even;
 		saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
 		saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
 		saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
@@ -688,7 +736,8 @@
 	err = verify_preview(dev,&fh->win);
 	if (0 != err)
 		return err;
-	
+
+	dev->ovfield = fh->win.field;
 	dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
 		fh->win.w.width,fh->win.w.height,
 		fh->win.w.left,fh->win.w.top,
@@ -752,6 +801,7 @@
 
 	dprintk("buffer_activate buf=%p\n",buf);
 	buf->vb.state = STATE_ACTIVE;
+	buf->top_seen = 0;
 	
 	set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
 		 V4L2_FIELD_HAS_BOTH(buf->vb.field));
@@ -828,7 +878,8 @@
 	struct saa7134_fh *fh = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
 	struct saa7134_buf *buf = (struct saa7134_buf *)vb;
-	int size,err;
+	unsigned int size;
+	int err;
 	
 	/* sanity checks */
 	if (NULL == fh->fmt)
@@ -842,8 +893,8 @@
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
 
-	dprintk("buffer_prepare [size=%dx%d,bytes=%d,fields=%s,%s]\n",
-		fh->width,fh->height,size,v4l2_field_names[field],
+	dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
+		vb->i,fh->width,fh->height,size,v4l2_field_names[field],
 		fh->fmt->name);
 	if (buf->vb.width  != fh->width  ||
 	    buf->vb.height != fh->height ||
@@ -872,7 +923,6 @@
 			goto oops;
 	}
 	buf->vb.state = STATE_PREPARED;
-	buf->top_seen = 0;
 	buf->activate = buffer_activate;
 	return 0;
 
@@ -1081,7 +1131,7 @@
 
 static int video_open(struct inode *inode, struct file *file)
 {
-	unsigned int minor = minor(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct saa7134_dev *h,*dev = NULL;
 	struct saa7134_fh *fh;
 	struct list_head *list;
@@ -1117,8 +1167,8 @@
 	fh->radio    = radio;
 	fh->type     = type;
 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-	fh->width    = 320;
-	fh->height   = 240;
+	fh->width    = 768;
+	fh->height   = 576;
 
 	videobuf_queue_init(&fh->cap, &video_qops,
 			    dev->pci, &dev->slock,
@@ -1138,7 +1188,9 @@
 
 	if (fh->radio) {
 		/* switch to radio mode */
+		u32 v = 400*16;
 		saa7134_tvaudio_setinput(dev,&card(dev).radio);
+		saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&v);
 		saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL);
 	} else {
 		/* switch to video/vbi mode */
@@ -1185,7 +1237,7 @@
 			buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
 	} else {
 		down(&fh->cap.lock);
-		if (-1 == fh->cap.read_off) {
+		if (UNSET == fh->cap.read_off) {
                         /* need to capture a new frame */
 			if (res_locked(fh->dev,RESOURCE_VIDEO)) {
                                 up(&fh->cap.lock);
@@ -1263,6 +1315,29 @@
 
 /* ------------------------------------------------------------------ */
 
+void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
+{
+	struct saa7134_tvnorm *norm = dev->tvnorm;
+
+	f->fmt.vbi.sampling_rate = 6750000 * 4;
+	f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
+	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+	f->fmt.vbi.offset = 64 * 4;
+	f->fmt.vbi.start[0] = norm->vbi_v_start;
+	f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
+	f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1;
+	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+	f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */;
+
+#if 0
+	if (V4L2_STD_PAL == norm->id) {
+		/* FIXME */
+		f->fmt.vbi.start[0] += 3;
+		f->fmt.vbi.start[1] += 3*2;
+	}
+#endif
+}
+
 int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
 		  struct v4l2_format *f)
 {
@@ -1273,27 +1348,17 @@
 		f->fmt.pix.height       = fh->height;
 		f->fmt.pix.field        = fh->cap.field;
 		f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-		f->fmt.pix.sizeimage    =
-			(fh->width*fh->height*fh->fmt->depth)/8;
+		f->fmt.pix.bytesperline =
+			(f->fmt.pix.width * fh->fmt->depth) >> 3;
+		f->fmt.pix.sizeimage =
+			f->fmt.pix.height * f->fmt.pix.bytesperline;
 		return 0;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 		f->fmt.win = fh->win;
 		return 0;
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
-	{
-		struct saa7134_tvnorm *norm = fh->dev->tvnorm;
-			
-		f->fmt.vbi.sampling_rate = 6750000 * 4;
-		f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
-		f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-		f->fmt.vbi.offset = 64 * 4;
-		f->fmt.vbi.start[0] = norm->vbi_v_start;
-		f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
-		f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start + 1;
-		f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
-		f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */;
+		saa7134_vbi_fmt(dev,f);
 		return 0;
-	}
 	default:
 		return -EINVAL;
 	}
@@ -1309,7 +1374,7 @@
 	{
 		struct saa7134_format *fmt;
 		enum v4l2_field field;
-		int maxw, maxh;
+		unsigned int maxw, maxh;
 
 		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 		if (NULL == fmt)
@@ -1336,12 +1401,18 @@
 		}
 
 		f->fmt.pix.field = field;
+		if (f->fmt.pix.width  < 48)
+			f->fmt.pix.width  = 48;
+		if (f->fmt.pix.height < 32)
+			f->fmt.pix.height = 32;
 		if (f->fmt.pix.width > maxw)
 			f->fmt.pix.width = maxw;
 		if (f->fmt.pix.height > maxh)
 			f->fmt.pix.height = maxh;
+		f->fmt.pix.bytesperline =
+			(f->fmt.pix.width * fmt->depth) >> 3;
 		f->fmt.pix.sizeimage =
-			(fh->width * fh->height * fmt->depth)/8;
+			f->fmt.pix.height * f->fmt.pix.bytesperline;
 		
 		return 0;
 	}
@@ -1350,6 +1421,9 @@
 		if (0 != err)
 			return err;
 		return 0;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		saa7134_vbi_fmt(dev,f);
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1397,6 +1471,9 @@
 		up(&dev->lock);
 		return 0;
 		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		saa7134_vbi_fmt(dev,f);
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1442,10 +1519,10 @@
 	case VIDIOC_ENUMSTD:
 	{
 		struct v4l2_standard *e = arg;
-		int i;
+		unsigned int i;
 
 		i = e->index;
-		if (i < 0 || i >= TVNORMS)
+		if (i >= TVNORMS)
 			return -EINVAL;
 		err = v4l2_video_std_construct(e, tvnorms[e->index].id,
 					       tvnorms[e->index].name);
@@ -1464,7 +1541,7 @@
 	case VIDIOC_S_STD:
 	{
 		v4l2_std_id *id = arg;
-		int i;
+		unsigned int i;
 
 		for(i = 0; i < TVNORMS; i++)
 			if (*id & tvnorms[i].id)
@@ -1489,7 +1566,7 @@
 	case VIDIOC_ENUMINPUT:
 	{
 		struct v4l2_input *i = arg;
-		int n;
+		unsigned int n;
 
 		n = i->index;
 		if (n >= SAA7134_INPUT_MAX)
@@ -1557,22 +1634,8 @@
 				V4L2_TUNER_CAP_LANG1 |
 				V4L2_TUNER_CAP_LANG2;
 			t->rangehigh = 0xffffffffUL;
-			t->rxsubchans = -1;
-			if (dev->tvaudio)
-				t->rxsubchans = saa7134_tvaudio_getstereo
-					(dev,dev->tvaudio);
-			if (-1 == t->rxsubchans)
-				t->rxsubchans = V4L2_TUNER_SUB_MONO;
-#if 1
-			/* fill audmode -- FIXME: allow manual switching */
-			t->audmode = V4L2_TUNER_MODE_MONO;
-			if (t->rxsubchans & V4L2_TUNER_SUB_STEREO)
-				t->audmode = V4L2_TUNER_MODE_STEREO;
-			else if (t->rxsubchans & V4L2_TUNER_SUB_LANG1)
-				t->audmode = V4L2_TUNER_MODE_LANG1;
-			else if (t->rxsubchans & V4L2_TUNER_SUB_LANG2)
-				t->audmode = V4L2_TUNER_MODE_LANG2;
-#endif
+			t->rxsubchans = saa7134_tvaudio_getstereo(dev);
+			t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);
 		}
 		if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))
 			t->signal = 0xffff;
@@ -1655,14 +1718,14 @@
 	{
 		struct v4l2_fmtdesc *f = arg;
 		enum v4l2_buf_type type;
-		int index;
+		unsigned int index;
 
 		index = f->index;
 		type  = f->type;
 		switch (type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-			if (index < 0 || index >= FORMATS)
+			if (index >= FORMATS)
 				return -EINVAL;
 			if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY &&
 			    formats[index].planar)
@@ -1760,21 +1823,23 @@
 	{
 		struct video_mbuf *mbuf = arg;
 		struct videobuf_queue *q;
-		int i;
+		struct v4l2_requestbuffers req;
+		unsigned int i;
 
 		q = saa7134_queue(fh);
-		down(&q->lock);
-		err = videobuf_mmap_setup(file,q,gbuffers,gbufsize);
-		if (err < 0) {
-			up(&q->lock);
+		memset(&req,0,sizeof(req));
+		req.type  = q->type;
+		req.count = gbuffers;
+		err = videobuf_reqbufs(file,q,&req);
+		if (err < 0)
 			return err;
-		}
 		memset(mbuf,0,sizeof(*mbuf));
-		mbuf->frames = gbuffers;
-		mbuf->size   = gbuffers * gbufsize;
-		for (i = 0; i < gbuffers; i++)
-			mbuf->offsets[i] = i * gbufsize;
-		up(&q->lock);
+		mbuf->frames = req.count;
+		mbuf->size   = 0;
+		for (i = 0; i < mbuf->frames; i++) {
+			mbuf->offsets[i]  = q->bufs[i]->boff;
+			mbuf->size       += q->bufs[i]->bsize;
+		}
 		return 0;
 	}
 	case VIDIOC_REQBUFS:
@@ -1800,7 +1865,10 @@
 	case VIDIOC_STREAMOFF:
 	{
 		int res = saa7134_resource(fh);
+
 		err = videobuf_streamoff(file,saa7134_queue(fh));
+		if (err < 0)
+			return err;
 		res_free(dev,fh,res);
 		return 0;
 	}
@@ -1879,9 +1947,16 @@
 		strcpy(a->name,"Radio");
 		return 0;
 	}
+	case VIDIOC_G_STD:
+	{
+		v4l2_std_id *id = arg;
+		*id = 0;
+		return 0;
+	}
 	case VIDIOC_S_AUDIO:
 	case VIDIOC_S_TUNER:
 	case VIDIOC_S_INPUT:
+	case VIDIOC_S_STD:
 		return 0;
 
 	case VIDIOC_QUERYCTRL:
@@ -2055,7 +2130,7 @@
 		
 		if (V4L2_FIELD_HAS_BOTH(field)) {
 			/* make sure we have seen both fields */
-			if ((status & 0x10) == 0x10) {
+			if ((status & 0x10) == 0x00) {
 				dev->video_q.curr->top_seen = 1;
 				goto done;
 			}
diff -u linux-2.5.69/drivers/media/video/saa7134/saa7134.h linux/drivers/media/video/saa7134/saa7134.h
--- linux-2.5.69/drivers/media/video/saa7134/saa7134.h	2003-05-08 13:31:35.000000000 +0200
+++ linux/drivers/media/video/saa7134/saa7134.h	2003-05-08 13:55:12.000000000 +0200
@@ -28,7 +28,7 @@
 #include <media/audiochip.h>
 #include <media/id.h>
 
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,2)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,8)
 
 #ifndef TRUE
 # define TRUE (1==1)
@@ -36,6 +36,7 @@
 #ifndef FALSE
 # define FALSE (1==0)
 #endif
+#define UNSET (-1U)
 
 /* 2.4 / 2.5 driver compatibility stuff */
 
@@ -67,50 +68,52 @@
 struct saa7134_tvnorm {
 	char          *name;
 	v4l2_std_id   id;
-	int           width;
-	int           height;
+	unsigned int  width;
+	unsigned int  height;
 
 	/* video decoder */
-	int           sync_control;
-	int           luma_control;
-	int           chroma_ctrl1;
-	int           chroma_gain;
-	int           chroma_ctrl2;
+	unsigned int  sync_control;
+	unsigned int  luma_control;
+	unsigned int  chroma_ctrl1;
+	unsigned int  chroma_gain;
+	unsigned int  chroma_ctrl2;
+	unsigned int  vgate_misc;
 
 	/* video scaler */
-	int           h_start;
-	int           h_stop;
-	int           video_v_start;
-	int           video_v_stop;
-	int           vbi_v_start;
-	int           vbi_v_stop;
+	unsigned int  h_start;
+	unsigned int  h_stop;
+	unsigned int  video_v_start;
+	unsigned int  video_v_stop;
+	unsigned int  vbi_v_start;
+	unsigned int  vbi_v_stop;
+	unsigned int  src_timing;
 };
 
 struct saa7134_tvaudio {
-	char  *name;
-	int   std;
-	enum  saa7134_tvaudio_mode mode;
-	int   carr1;
-	int   carr2;
+	char         *name;
+	v4l2_std_id  std;
+	enum         saa7134_tvaudio_mode mode;
+	int          carr1;
+	int          carr2;
 };
 
 struct saa7134_format {
-	char  *name;
-	int   fourcc;
-	int   depth;
-	int   pm;
-	int   vshift;   /* vertical downsampling (for planar yuv) */
-	int   hshift;   /* horizontal downsampling (for planar yuv) */
-	int   bswap:1;
-	int   wswap:1;
-	int   yuv:1;
-	int   planar:1;
+	char           *name;
+	unsigned int   fourcc;
+	unsigned int   depth;
+	unsigned int   pm;
+	unsigned int   vshift;   /* vertical downsampling (for planar yuv) */
+	unsigned int   hshift;   /* horizontal downsampling (for planar yuv) */
+	unsigned int   bswap:1;
+	unsigned int   wswap:1;
+	unsigned int   yuv:1;
+	unsigned int   planar:1;
 };
 
 /* ----------------------------------------------------------- */
 /* card configuration                                          */
 
-#define SAA7134_BOARD_NOAUTO           -1
+#define SAA7134_BOARD_NOAUTO        UNSET
 #define SAA7134_BOARD_UNKNOWN           0
 #define SAA7134_BOARD_PROTEUS_PRO       1
 #define SAA7134_BOARD_FLYVIDEO3000      2
@@ -124,38 +127,40 @@
 #define SAA7134_BOARD_KWORLD           10
 #define SAA7134_BOARD_CINERGY600       11
 #define SAA7134_BOARD_MD7134           12
+#define SAA7134_BOARD_TYPHOON_90031    13
+#define SAA7134_BOARD_ELSA             14
+#define SAA7134_BOARD_ELSA_500TV       15
 
 #define SAA7134_INPUT_MAX 8
 
 struct saa7134_input {
 	char                    *name;
-	int                     vmux;
+	unsigned int            vmux;
 	enum saa7134_audio_in   amux;
-	int                     gpio;
-	int                     tv:1;
+	unsigned int            gpio;
+	unsigned int            tv:1;
 };
 
 struct saa7134_board {
 	char                    *name;
-	int                     audio_clock;
+	unsigned int            audio_clock;
 
 	/* input switching */
-	int                     gpiomask;
+	unsigned int            gpiomask;
 	struct saa7134_input    inputs[SAA7134_INPUT_MAX];
 	struct saa7134_input    radio;
 	struct saa7134_input    mute;
 	
 	/* peripheral I/O */
-	int                     i2s_rate;
-	int                     has_ts;
+	unsigned int            i2s_rate;
+	unsigned int            has_ts;
 	enum saa7134_video_out  video_out;
 
 	/* i2c chip info */
-	int                     tuner_type;
-	int                     need_tda9887:1;
+	unsigned int            tuner_type;
+	unsigned int            need_tda9887:1;
 };
 
-#define card_has_audio(dev)   (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7134)
 #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
 #define card_has_ts(dev)      (saa7134_boards[dev->board].has_ts)
 #define card(dev)             (saa7134_boards[dev->board])
@@ -189,9 +194,9 @@
 	struct task_struct         *task;
 	wait_queue_head_t          wq;
 	struct semaphore           *notify;
-	int                        exit;
-	int                        scan1;
-	int                        scan2;
+	unsigned int               exit;
+	unsigned int               scan1;
+	unsigned int               scan2;
 };
 
 /* buffer for one video/vbi/ts frame */
@@ -201,7 +206,7 @@
 
 	/* saa7134 specific */
 	struct saa7134_format   *fmt;
-	int                     top_seen;
+	unsigned int            top_seen;
 	int (*activate)(struct saa7134_dev *dev,
 			struct saa7134_buf *buf,
 			struct saa7134_buf *next);
@@ -215,22 +220,23 @@
 	struct saa7134_buf         *curr;
 	struct list_head           queue;
 	struct timer_list          timeout;
+	unsigned int               need_two;
 };
 
 /* video filehandle status */
 struct saa7134_fh {
 	struct saa7134_dev         *dev;
-	int                        radio;
+	unsigned int               radio;
 	enum v4l2_buf_type         type;
 
 	struct v4l2_window         win;
 	struct v4l2_clip           clips[8];
-	int                        nclips;
-	int                        resources;
+	unsigned int               nclips;
+	unsigned int               resources;
 
 	/* video capture */
 	struct saa7134_format      *fmt;
-	int                        width,height;
+	unsigned int               width,height;
 	struct videobuf_queue      cap;
 	struct saa7134_pgtable     pt_cap;
 
@@ -241,7 +247,7 @@
 
 /* TS status */
 struct saa7134_ts {
-	int                        users;
+	unsigned int               users;
 
 	/* TS capture */
 	struct videobuf_queue      ts;
@@ -253,28 +259,28 @@
         struct semaphore           lock;
 	int                        minor_mixer;
 	int                        minor_dsp;
-	int                        users_dsp;
+	unsigned int               users_dsp;
 
 	/* mixer */
 	enum saa7134_audio_in      input;
-	int                        count;
-	int                        line1;
-	int                        line2;
+	unsigned int               count;
+	unsigned int               line1;
+	unsigned int               line2;
 
 	/* dsp */
-	int                        afmt;
-	int                        rate;
-	int                        channels;
-	int                        recording;
-	int                        blocks;
-	int                        blksize;
-	int                        bufsize;
+	unsigned int               afmt;
+	unsigned int               rate;
+	unsigned int               channels;
+	unsigned int               recording;
+	unsigned int               blocks;
+	unsigned int               blksize;
+	unsigned int               bufsize;
 	struct saa7134_pgtable     pt;
 	struct videobuf_dmabuf     dma;
 	wait_queue_head_t          wq;
-	int                        dma_blk;
-	int                        read_offset;
-	int                        read_count;
+	unsigned int               dma_blk;
+	unsigned int               read_offset;
+	unsigned int               read_count;
 };
 
 /* global device status */
@@ -284,7 +290,7 @@
        	spinlock_t                 slock;
 
 	/* various device info */
-	int                        resources;
+	unsigned int               resources;
 	struct video_device        video_dev;
 	struct video_device        ts_dev;
 	struct video_device        radio_dev;
@@ -300,8 +306,8 @@
 	__u8                       *bmmio;
 
 	/* config info */
-	int                        board;
-	int                        tuner_type;
+	unsigned int               board;
+	unsigned int               tuner_type;
 
 	/* i2c i/o */
 	struct i2c_adapter         i2c_adap;
@@ -311,19 +317,19 @@
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
 	struct saa7134_format      *ovfmt;
-	int                        ovenable;
+	unsigned int               ovenable;
 	enum v4l2_field            ovfield;
 
 	/* video+ts+vbi capture */
 	struct saa7134_dmaqueue    video_q;
 	struct saa7134_dmaqueue    ts_q;
 	struct saa7134_dmaqueue    vbi_q;
-	int                        vbi_fieldcount;
+	unsigned int               vbi_fieldcount;
 
 	/* various v4l controls */
 	struct saa7134_tvnorm      *tvnorm;              /* video */
 	struct saa7134_tvaudio     *tvaudio;
-	int                        ctl_input;
+	unsigned int               ctl_input;
 	int                        ctl_bright;
 	int                        ctl_contrast;
 	int                        ctl_hue;
@@ -337,11 +343,12 @@
 	int                        ctl_y_even;
 
 	/* other global state info */
-	int                        automute;
+	unsigned int               automute;
 	struct saa7134_thread      thread;
 	struct saa7134_input       *input;
 	struct saa7134_input       *hw_input;
-	int                        hw_mute;
+	unsigned int               hw_mute;
+	int                        last_carrier;
 };
 
 /* ----------------------------------------------------------- */
@@ -362,12 +369,13 @@
 #define saa_setb(reg,bit)          saa_andorb((reg),(bit),(bit))
 #define saa_clearb(reg,bit)        saa_andorb((reg),(bit),0)
 
+#define saa_wait(d) { if (need_resched()) schedule(); else udelay(d);}
 
 /* ----------------------------------------------------------- */
 /* saa7134-core.c                                              */
 
 extern struct list_head  saa7134_devlist;
-extern int               saa7134_devcount;
+extern unsigned int      saa7134_devcount;
 
 void saa7134_print_ioctl(char *name, unsigned int cmd);
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
@@ -376,18 +384,18 @@
 
 int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
 int  saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
-			   struct scatterlist *list, int length,
-			   int startpage);
+			   struct scatterlist *list, unsigned int length,
+			   unsigned int startpage);
 void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt);
 
-int saa7134_buffer_count(int size, int count);
+int saa7134_buffer_count(unsigned int size, unsigned int count);
 int saa7134_buffer_startpage(struct saa7134_buf *buf);
 unsigned long saa7134_buffer_base(struct saa7134_buf *buf);
 
 int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
 			 struct saa7134_buf *buf);
 void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
-			   int state);
+			   unsigned int state);
 void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
 void saa7134_buffer_timeout(unsigned long data);
 void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf);
@@ -398,9 +406,11 @@
 /* saa7134-cards.c                                             */
 
 extern struct saa7134_board saa7134_boards[];
-extern const int saa7134_bcount;
+extern const unsigned int saa7134_bcount;
 extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
 
+extern int saa7134_board_init(struct saa7134_dev *dev);
+
 
 /* ----------------------------------------------------------- */
 /* saa7134-i2c.c                                               */
@@ -449,17 +459,19 @@
 /* ----------------------------------------------------------- */
 /* saa7134-tvaudio.c                                           */
 
+int saa7134_tvaudio_rx2mode(u32 rx);
+
 void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
 void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
 			      struct saa7134_input *in);
 void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
-			      struct saa7134_tvaudio *audio);
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
 
 int saa7134_tvaudio_init(struct saa7134_dev *dev);
 int saa7134_tvaudio_fini(struct saa7134_dev *dev);
 int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
 
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
 
 /* ----------------------------------------------------------- */
 /* saa7134-oss.c                                               */

-- 
sigfault

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-05-12 17:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-12 17:26 [patch] v4l: #7 - saa7134 driver update Gerd Knorr

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.