From: Gerd Knorr 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 25-akpm/drivers/media/video/saa7134/saa7134-cards.c | 202 +++++- 25-akpm/drivers/media/video/saa7134/saa7134-core.c | 217 ++++-- 25-akpm/drivers/media/video/saa7134/saa7134-i2c.c | 9 25-akpm/drivers/media/video/saa7134/saa7134-oss.c | 188 +++-- 25-akpm/drivers/media/video/saa7134/saa7134-reg.h | 13 25-akpm/drivers/media/video/saa7134/saa7134-ts.c | 18 25-akpm/drivers/media/video/saa7134/saa7134-tvaudio.c | 591 ++++++++++++++---- 25-akpm/drivers/media/video/saa7134/saa7134-vbi.c | 9 25-akpm/drivers/media/video/saa7134/saa7134-video.c | 237 ++++--- 25-akpm/drivers/media/video/saa7134/saa7134.h | 170 ++--- 10 files changed, 1230 insertions(+), 424 deletions(-) diff -puN drivers/media/video/saa7134/saa7134-cards.c~v4l-7 drivers/media/video/saa7134/saa7134-cards.c --- 25/drivers/media/video/saa7134/saa7134-cards.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-cards.c Mon May 12 15:33:16 2003 @@ -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 @@ struct saa7134_board saa7134_boards[] = .vmux = 1, .amux = TV, .tv = 1, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .tv = 1, }}, }, [SAA7134_BOARD_FLYVIDEO3000] = { @@ -68,27 +74,39 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct saa7134_board saa7134_boards[] = },{ .name = name_tv, .vmux = 1, - .amux = TV, + .amux = LINE2, .tv = 1, }}, }, @@ -332,7 +358,6 @@ struct saa7134_board saa7134_boards[] = .name = name_radio, .amux = LINE2, }, - }, [SAA7134_BOARD_MD7134] = { .name = "Medion 7134", @@ -343,7 +368,7 @@ struct saa7134_board saa7134_boards[] = .name = name_tv, .vmux = 1, .amux = LINE2, - .tv = 1, + .tv = 1, },{ .name = name_comp1, .vmux = 0, @@ -361,9 +386,67 @@ struct saa7134_board saa7134_boards[] = .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 @@ struct pci_device_id __devinitdata saa71 .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 @@ struct pci_device_id __devinitdata saa71 .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 @@ struct pci_device_id __devinitdata saa71 .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 @@ struct pci_device_id __devinitdata saa71 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 -puN drivers/media/video/saa7134/saa7134-core.c~v4l-7 drivers/media/video/saa7134/saa7134-core.c --- 25/drivers/media/video/saa7134/saa7134-core.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-core.c Mon May 12 15:33:16 2003 @@ -2,7 +2,7 @@ * device driver for philips saa7134 based TV cards * driver core * - * (c) 2001,02 Gerd Knorr [SuSE Labs] + * (c) 2001-03 Gerd Knorr [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 @@ static unsigned int radio_nr = -1; 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 @@ static unsigned int mixer_nr = -1; 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 @@ static const char *v4l1_ioctls[] = { "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 @@ static const char *v4l2_ioctls[] = { "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 @@ static const char *osspcm_ioctls[] = { "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 @@ int saa7134_buffer_pages(int size) /* 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_alloc(struct pci_dev } 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 @@ int saa7134_buffer_queue(struct saa7134_ 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 @@ int saa7134_buffer_queue(struct saa7134_ 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 @@ void saa7134_buffer_timeout(unsigned lon 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 @@ void saa7134_buffer_timeout(unsigned lon 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 @@ int saa7134_set_dmabits(struct saa7134_d /* 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 @@ int saa7134_set_dmabits(struct saa7134_d 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 @@ static char *irqbits[] = { "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 @@ static irqreturn_t saa7134_irq(int irq, { 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 @@ static irqreturn_t saa7134_irq(int irq, saa_writel(SAA7134_IRQ1,0); saa_writel(SAA7134_IRQ2,0); } -out: - return IRQ_HANDLED; + + out: + return IRQ_RETVAL(handled); } /* ------------------------------------------------------------------ */ @@ -599,8 +624,14 @@ static int saa7134_hwinit(struct saa7134 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 @@ static int saa7134_hwinit(struct saa7134 /* 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: \n" @@ -675,18 +709,39 @@ static int __devinit saa7134_initdev(str 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 @@ static int __devinit saa7134_initdev(str 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 @@ static int __devinit saa7134_initdev(str 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 @@ static int __devinit saa7134_initdev(str 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 @@ static int __devinit saa7134_initdev(str } /* 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 @@ static int __devinit saa7134_initdev(str 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 @@ static int __devinit saa7134_initdev(str 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 @@ static void __devexit saa7134_finidev(st { 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 @@ static void __devexit saa7134_finidev(st 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 @@ static void __devexit saa7134_finidev(st /* 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 -puN drivers/media/video/saa7134/saa7134.h~v4l-7 drivers/media/video/saa7134/saa7134.h --- 25/drivers/media/video/saa7134/saa7134.h~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134.h Mon May 12 15:33:17 2003 @@ -28,7 +28,7 @@ #include #include -#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 @@ enum saa7134_video_out { 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 @@ struct saa7134_format { #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 saa7134_thread { 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 @@ struct saa7134_buf { /* 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_dmaqueue { 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 @@ struct saa7134_fh { /* TS status */ struct saa7134_ts { - int users; + unsigned int users; /* TS capture */ struct videobuf_queue ts; @@ -253,28 +259,28 @@ struct saa7134_oss { 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 @@ struct saa7134_dev { 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 @@ struct saa7134_dev { __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 @@ struct saa7134_dev { /* 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 @@ struct saa7134_dev { 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 @@ struct saa7134_dev { #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 @@ void saa7134_track_gpio(struct saa7134_d 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 @@ int saa7134_set_dmabits(struct saa7134_d /* 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 @@ void saa7134_irq_vbi_done(struct saa7134 /* ----------------------------------------------------------- */ /* 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 */ diff -puN drivers/media/video/saa7134/saa7134-i2c.c~v4l-7 drivers/media/video/saa7134/saa7134-i2c.c --- 25/drivers/media/video/saa7134/saa7134-i2c.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-i2c.c Mon May 12 15:33:16 2003 @@ -153,10 +153,7 @@ static int i2c_is_busy_wait(struct saa71 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 u32 functionality(struct i2c_adap 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_algorithm saa7134_algo 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 -puN drivers/media/video/saa7134/saa7134-oss.c~v4l-7 drivers/media/video/saa7134/saa7134-oss.c --- 25/drivers/media/video/saa7134/saa7134-oss.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-oss.c Mon May 12 15:33:16 2003 @@ -94,8 +94,9 @@ static int dsp_buffer_free(struct saa713 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 @@ static int dsp_rec_start(struct saa7134_ /* 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 @@ static int dsp_rec_start(struct saa7134_ (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_rec_stop(struct saa7134_d 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 @@ static ssize_t dsp_read(struct file *fil { 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 @@ static int dsp_ioctl(struct inode *inode 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 @@ static int dsp_ioctl(struct inode *inode 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 @@ struct file_operations saa7134_dsp_fops /* ------------------------------------------------------------------ */ 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 @@ mixer_recsrc(struct saa7134_dev *dev, en } 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 @@ struct file_operations saa7134_mixer_fop 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 @@ int saa7134_oss_init(struct saa7134_dev 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 @@ void saa7134_irq_oss_done(struct saa7134 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 -puN drivers/media/video/saa7134/saa7134-reg.h~v4l-7 drivers/media/video/saa7134/saa7134-reg.h --- 25/drivers/media/video/saa7134/saa7134-reg.h~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-reg.h Mon May 12 15:33:16 2003 @@ -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 -puN drivers/media/video/saa7134/saa7134-ts.c~v4l-7 drivers/media/video/saa7134/saa7134-ts.c --- 25/drivers/media/video/saa7134/saa7134-ts.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-ts.c Mon May 12 15:33:16 2003 @@ -52,8 +52,9 @@ static int buffer_activate(struct saa713 { 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 @@ static int buffer_activate(struct saa713 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 @@ static int buffer_prepare(struct file *f { 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 @@ static int buffer_prepare(struct file *f 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 struct videobuf_queue_ops ts_qops 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 @@ int saa7134_ts_init(struct saa7134_dev * 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 @@ void saa7134_irq_ts_done(struct saa7134_ 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 -puN drivers/media/video/saa7134/saa7134-tvaudio.c~v4l-7 drivers/media/video/saa7134/saa7134-tvaudio.c --- 25/drivers/media/video/saa7134/saa7134-tvaudio.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-tvaudio.c Mon May 12 15:33:16 2003 @@ -37,13 +37,23 @@ static unsigned int audio_debug = 0; 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 @@ static struct saa7134_tvaudio tvaudio[] .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 @@ static void tvaudio_init(struct saa7134_ 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 @@ static void tvaudio_init(struct saa7134_ 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 @@ static void tvaudio_setcarrier(struct sa 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 @@ static void saa7134_tvaudio_do_mute_inpu 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 @@ static void saa7134_tvaudio_do_mute_inpu 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 @@ static void tvaudio_setmode(struct saa71 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 @@ int saa7134_tvaudio_getstereo(struct saa 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 @@ static int tvaudio_thread(void *data) 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 @@ static int tvaudio_thread(void *data) 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 @@ static int tvaudio_thread(void *data) 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 @@ static int tvaudio_thread(void *data) } /* ------------------------------------------------------------------ */ +/* 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 @@ int saa7134_tvaudio_init(struct saa7134_ 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_fini(struct saa7134_ 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 -puN drivers/media/video/saa7134/saa7134-vbi.c~v4l-7 drivers/media/video/saa7134/saa7134-vbi.c --- 25/drivers/media/video/saa7134/saa7134-vbi.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-vbi.c Mon May 12 15:33:16 2003 @@ -85,6 +85,7 @@ static int buffer_activate(struct saa713 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 @@ static int buffer_prepare(struct file *f 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 @@ static int buffer_prepare(struct file *f 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_prepare(struct file *f } 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 @@ void saa7134_irq_vbi_done(struct saa7134 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 -puN drivers/media/video/saa7134/saa7134-video.c~v4l-7 drivers/media/video/saa7134/saa7134-video.c --- 25/drivers/media/video/saa7134/saa7134-video.c~v4l-7 Mon May 12 15:33:16 2003 +++ 25-akpm/drivers/media/video/saa7134/saa7134-video.c Mon May 12 15:33:16 2003 @@ -2,7 +2,7 @@ * device driver for philips saa7134 based TV cards * video4linux video interface * - * (c) 2001,02 Gerd Knorr [SuSE Labs] + * (c) 2001-03 Gerd Knorr [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 @@ static struct saa7134_format formats[] = .vshift = 1, } }; -#define FORMATS (sizeof(formats)/sizeof(struct saa7134_format)) +#define FORMATS ARRAY_SIZE(formats) static struct saa7134_tvnorm tvnorms[] = { { @@ -141,13 +141,15 @@ static struct saa7134_tvnorm tvnorms[] = .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 @@ static struct saa7134_tvnorm tvnorms[] = .chroma_ctrl1 = 0x89, .chroma_gain = 0x2a, .chroma_ctrl2 = 0x0e, + .vgate_misc = 0x18, .h_start = 0, .h_stop = 719, @@ -166,17 +169,19 @@ static struct saa7134_tvnorm tvnorms[] = .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 @@ static struct saa7134_tvnorm tvnorms[] = .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 @@ static struct saa7134_tvnorm tvnorms[] = .chroma_ctrl1 = 0x8b, .chroma_gain = 0x00, .chroma_ctrl2 = 0x00, + .vgate_misc = 0x18, .h_start = 0, .h_stop = 719, @@ -203,11 +250,11 @@ static struct saa7134_tvnorm tvnorms[] = .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 @@ static const struct v4l2_queryctrl video .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 @@ static const struct v4l2_queryctrl* ctrl 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 @@ static struct saa7134_format* format_by_ /* ----------------------------------------------------------------------- */ /* 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_get(struct saa7134_dev *d } 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 @@ static void set_tvnorm(struct saa7134_de 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 @@ static void set_tvnorm(struct saa7134_de 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 @@ static void set_h_prescale(struct saa713 { 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 @@ static void set_size(struct saa7134_dev /* 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 @@ static int start_preview(struct saa7134_ 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 @@ static int buffer_activate(struct saa713 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 @@ static int buffer_prepare(struct file *f 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 @@ static int buffer_prepare(struct file *f 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 @@ static int buffer_prepare(struct file *f goto oops; } buf->vb.state = STATE_PREPARED; - buf->top_seen = 0; buf->activate = buffer_activate; return 0; @@ -1081,7 +1131,7 @@ static int saa7134_resource(struct saa71 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 @@ static int video_open(struct inode *inod 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 @@ static int video_open(struct inode *inod 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 @@ video_poll(struct file *file, struct pol 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 @@ video_mmap(struct file *file, struct vm_ /* ------------------------------------------------------------------ */ +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 @@ int saa7134_g_fmt(struct saa7134_dev *de 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 @@ int saa7134_try_fmt(struct saa7134_dev * { 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 @@ int saa7134_try_fmt(struct saa7134_dev * } 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 @@ int saa7134_try_fmt(struct saa7134_dev * 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 @@ int saa7134_s_fmt(struct saa7134_dev *de 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 @@ static int video_do_ioctl(struct inode * 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 @@ static int video_do_ioctl(struct inode * 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 @@ static int video_do_ioctl(struct inode * 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 @@ static int video_do_ioctl(struct inode * 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 @@ static int video_do_ioctl(struct inode * { 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 @@ static int video_do_ioctl(struct inode * { 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 @@ static int video_do_ioctl(struct inode * 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 @@ static int radio_do_ioctl(struct inode * 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 @@ void saa7134_irq_video_done(struct saa71 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; } _