Commit d5b973d7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] v4l: #7 - saa7134 driver update

From: Gerd Knorr <kraxel@bytesex.org>

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.
parent 2b270c40
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
static char name_mute[] = "mute"; static char name_mute[] = "mute";
static char name_radio[] = "Radio"; static char name_radio[] = "Radio";
static char name_tv[] = "Television"; static char name_tv[] = "Television";
static char name_tv_mono[] = "TV (mono only)";
static char name_comp1[] = "Composite1"; static char name_comp1[] = "Composite1";
static char name_comp2[] = "Composite2"; static char name_comp2[] = "Composite2";
static char name_svideo[] = "S-Video"; static char name_svideo[] = "S-Video";
...@@ -61,6 +62,11 @@ struct saa7134_board saa7134_boards[] = { ...@@ -61,6 +62,11 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 1, .vmux = 1,
.amux = TV, .amux = TV,
.tv = 1, .tv = 1,
},{
.name = name_tv_mono,
.vmux = 1,
.amux = LINE2,
.tv = 1,
}}, }},
}, },
[SAA7134_BOARD_FLYVIDEO3000] = { [SAA7134_BOARD_FLYVIDEO3000] = {
...@@ -68,27 +74,39 @@ struct saa7134_board saa7134_boards[] = { ...@@ -68,27 +74,39 @@ struct saa7134_board saa7134_boards[] = {
.name = "LifeView FlyVIDEO3000", .name = "LifeView FlyVIDEO3000",
.audio_clock = 0x00200000, .audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL, .tuner_type = TUNER_PHILIPS_PAL,
.gpiomask = 0xe000,
.inputs = {{ .inputs = {{
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
.amux = TV, .amux = TV,
.gpio = 0x8000,
.tv = 1,
},{
.name = name_tv_mono,
.vmux = 1,
.amux = LINE2,
.gpio = 0x0000,
.tv = 1, .tv = 1,
},{ },{
.name = name_comp1, .name = name_comp1,
.vmux = 0, .vmux = 0,
.amux = LINE1, .amux = LINE2,
.gpio = 0x4000,
},{ },{
.name = name_comp2, .name = name_comp2,
.vmux = 3, .vmux = 3,
.amux = LINE1, .amux = LINE2,
.gpio = 0x4000,
},{ },{
.name = name_svideo, .name = name_svideo,
.vmux = 8, .vmux = 8,
.amux = LINE1, .amux = LINE2,
.gpio = 0x4000,
}}, }},
.radio = { .radio = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .amux = LINE2,
.gpio = 0x2000,
}, },
}, },
[SAA7134_BOARD_FLYVIDEO2000] = { [SAA7134_BOARD_FLYVIDEO2000] = {
...@@ -96,7 +114,7 @@ struct saa7134_board saa7134_boards[] = { ...@@ -96,7 +114,7 @@ struct saa7134_board saa7134_boards[] = {
.name = "LifeView FlyVIDEO2000", .name = "LifeView FlyVIDEO2000",
.audio_clock = 0x00200000, .audio_clock = 0x00200000,
.tuner_type = TUNER_LG_PAL_NEW_TAPC, .tuner_type = TUNER_LG_PAL_NEW_TAPC,
.gpiomask = 0x6000, .gpiomask = 0xe000,
.inputs = {{ .inputs = {{
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
...@@ -122,10 +140,12 @@ struct saa7134_board saa7134_boards[] = { ...@@ -122,10 +140,12 @@ struct saa7134_board saa7134_boards[] = {
.radio = { .radio = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .amux = LINE2,
.gpio = 0x2000,
}, },
.mute = { .mute = {
.name = name_mute, .name = name_mute,
.amux = LINE1, .amux = LINE2,
.gpio = 0x8000,
}, },
}, },
[SAA7134_BOARD_EMPRESS] = { [SAA7134_BOARD_EMPRESS] = {
...@@ -190,7 +210,7 @@ struct saa7134_board saa7134_boards[] = { ...@@ -190,7 +210,7 @@ struct saa7134_board saa7134_boards[] = {
.tv = 1, .tv = 1,
},{ },{
/* workaround for problems with normal TV sound */ /* workaround for problems with normal TV sound */
.name = "TV (mono only)", .name = name_tv_mono,
.vmux = 1, .vmux = 1,
.amux = LINE2, .amux = LINE2,
.tv = 1, .tv = 1,
...@@ -269,6 +289,12 @@ struct saa7134_board saa7134_boards[] = { ...@@ -269,6 +289,12 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 1, .vmux = 1,
.amux = TV, .amux = TV,
.tv = 1, .tv = 1,
},{
/* workaround for problems with normal TV sound */
.name = name_tv_mono,
.vmux = 1,
.amux = LINE2,
.tv = 1,
},{ },{
.name = name_comp1, .name = name_comp1,
.vmux = 0, .vmux = 0,
...@@ -302,7 +328,7 @@ struct saa7134_board saa7134_boards[] = { ...@@ -302,7 +328,7 @@ struct saa7134_board saa7134_boards[] = {
},{ },{
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
.amux = TV, .amux = LINE2,
.tv = 1, .tv = 1,
}}, }},
}, },
...@@ -332,7 +358,6 @@ struct saa7134_board saa7134_boards[] = { ...@@ -332,7 +358,6 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .amux = LINE2,
}, },
}, },
[SAA7134_BOARD_MD7134] = { [SAA7134_BOARD_MD7134] = {
.name = "Medion 7134", .name = "Medion 7134",
...@@ -343,7 +368,7 @@ struct saa7134_board saa7134_boards[] = { ...@@ -343,7 +368,7 @@ struct saa7134_board saa7134_boards[] = {
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
.amux = LINE2, .amux = LINE2,
.tv = 1, .tv = 1,
},{ },{
.name = name_comp1, .name = name_comp1,
.vmux = 0, .vmux = 0,
...@@ -361,9 +386,67 @@ struct saa7134_board saa7134_boards[] = { ...@@ -361,9 +386,67 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .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 */ /* PCI ids + subsystem IDs */
...@@ -375,6 +458,12 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = { ...@@ -375,6 +458,12 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.subvendor = PCI_VENDOR_ID_PHILIPS, .subvendor = PCI_VENDOR_ID_PHILIPS,
.subdevice = 0x2001, .subdevice = 0x2001,
.driver_data = SAA7134_BOARD_PROTEUS_PRO, .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, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134, .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
...@@ -405,6 +494,12 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = { ...@@ -405,6 +494,12 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.subvendor = 0x5168, .subvendor = 0x5168,
.subdevice = 0x0138, .subdevice = 0x0138,
.driver_data = SAA7134_BOARD_FLYVIDEO3000, .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, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134, .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
...@@ -412,6 +507,18 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = { ...@@ -412,6 +507,18 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.subdevice = 0x0003, .subdevice = 0x0003,
.driver_data = SAA7134_BOARD_MD7134, .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 --- */ /* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
...@@ -433,18 +540,91 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = { ...@@ -433,18 +540,91 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = SAA7134_BOARD_UNKNOWN, .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, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134, .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = SAA7134_BOARD_UNKNOWN, .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 --- */ /* --- end of list --- */
} }
}; };
MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl); 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: * Local variables:
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* device driver for philips saa7134 based TV cards * device driver for philips saa7134 based TV cards
* driver core * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -67,6 +67,10 @@ static unsigned int radio_nr = -1; ...@@ -67,6 +67,10 @@ static unsigned int radio_nr = -1;
MODULE_PARM(radio_nr,"i"); MODULE_PARM(radio_nr,"i");
MODULE_PARM_DESC(radio_nr,"radio device number"); 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; static unsigned int dsp_nr = -1;
MODULE_PARM(dsp_nr,"i"); MODULE_PARM(dsp_nr,"i");
MODULE_PARM_DESC(dsp_nr,"oss dsp device number"); MODULE_PARM_DESC(dsp_nr,"oss dsp device number");
...@@ -75,20 +79,20 @@ static unsigned int mixer_nr = -1; ...@@ -75,20 +79,20 @@ static unsigned int mixer_nr = -1;
MODULE_PARM(mixer_nr,"i"); MODULE_PARM(mixer_nr,"i");
MODULE_PARM_DESC(mixer_nr,"oss mixer device number"); 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(tuner,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(tuner,"tuner type"); 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(card,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(card,"card type"); MODULE_PARM_DESC(card,"card type");
static int latency = -1; static unsigned int latency = UNSET;
MODULE_PARM(latency,"i"); MODULE_PARM(latency,"i");
MODULE_PARM_DESC(latency,"pci latency timer"); MODULE_PARM_DESC(latency,"pci latency timer");
struct list_head saa7134_devlist; struct list_head saa7134_devlist;
int saa7134_devcount; unsigned int saa7134_devcount;
#define dprintk(fmt, arg...) if (core_debug) \ #define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name, ## arg) printk(KERN_DEBUG "%s/core: " fmt, dev->name, ## arg)
...@@ -102,7 +106,7 @@ static const char *v4l1_ioctls[] = { ...@@ -102,7 +106,7 @@ static const char *v4l1_ioctls[] = {
"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
"SMICROCODE", "GVBIFMT", "SVBIFMT" }; "SMICROCODE", "GVBIFMT", "SVBIFMT" };
#define V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*)) #define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
static const char *v4l2_ioctls[] = { static const char *v4l2_ioctls[] = {
"QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
...@@ -116,7 +120,7 @@ static const char *v4l2_ioctls[] = { ...@@ -116,7 +120,7 @@ static const char *v4l2_ioctls[] = {
"S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
"S_MODULATOR" "S_MODULATOR"
}; };
#define V4L2_IOCTLS (sizeof(v4l2_ioctls)/sizeof(char*)) #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *osspcm_ioctls[] = { static const char *osspcm_ioctls[] = {
"RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT", "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
...@@ -125,7 +129,7 @@ static const char *osspcm_ioctls[] = { ...@@ -125,7 +129,7 @@ static const char *osspcm_ioctls[] = {
"GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO", "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
"SETDUPLEX", "GETODELAY" "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) void saa7134_print_ioctl(char *name, unsigned int cmd)
{ {
...@@ -236,9 +240,9 @@ int saa7134_buffer_pages(int size) ...@@ -236,9 +240,9 @@ int saa7134_buffer_pages(int size)
/* calc max # of buffers from size (must not exceed the 4MB virtual /* calc max # of buffers from size (must not exceed the 4MB virtual
* address space per DMA channel) */ * 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); maxcount = 1024 / saa7134_buffer_pages(size);
if (count > maxcount) if (count > maxcount)
...@@ -277,11 +281,11 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) ...@@ -277,11 +281,11 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
} }
int saa7134_pgtable_build(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, struct scatterlist *list, unsigned int length,
int startpage) unsigned int startpage)
{ {
u32 *ptr; u32 *ptr;
int i,p; unsigned int i,p;
BUG_ON(NULL == pt || NULL == pt->cpu); BUG_ON(NULL == pt || NULL == pt->cpu);
...@@ -319,14 +323,25 @@ int saa7134_buffer_queue(struct saa7134_dev *dev, ...@@ -319,14 +323,25 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q, struct saa7134_dmaqueue *q,
struct saa7134_buf *buf) struct saa7134_buf *buf)
{ {
struct saa7134_buf *next = NULL;
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock)); BUG_ON(!spin_is_locked(&dev->slock));
#endif #endif
dprintk("buffer_queue %p\n",buf); dprintk("buffer_queue %p\n",buf);
if (NULL == q->curr) { if (NULL == q->curr) {
q->curr = buf; if (!q->need_two) {
buf->activate(dev,buf,NULL); 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 { } else {
list_add_tail(&buf->vb.queue,&q->queue); list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = STATE_QUEUED; buf->vb.state = STATE_QUEUED;
...@@ -336,7 +351,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev, ...@@ -336,7 +351,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
void saa7134_buffer_finish(struct saa7134_dev *dev, void saa7134_buffer_finish(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q, struct saa7134_dmaqueue *q,
int state) unsigned int state)
{ {
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock)); BUG_ON(!spin_is_locked(&dev->slock));
...@@ -388,6 +403,14 @@ void saa7134_buffer_timeout(unsigned long data) ...@@ -388,6 +403,14 @@ void saa7134_buffer_timeout(unsigned long data)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev->slock,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) { if (q->curr) {
dprintk("timeout on %p\n",q->curr); dprintk("timeout on %p\n",q->curr);
saa7134_buffer_finish(dev,q,STATE_ERROR); saa7134_buffer_finish(dev,q,STATE_ERROR);
...@@ -400,7 +423,7 @@ void saa7134_buffer_timeout(unsigned long data) ...@@ -400,7 +423,7 @@ void saa7134_buffer_timeout(unsigned long data)
int saa7134_set_dmabits(struct saa7134_dev *dev) 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 cap = V4L2_FIELD_ANY;
enum v4l2_field ov = V4L2_FIELD_ANY; enum v4l2_field ov = V4L2_FIELD_ANY;
...@@ -460,12 +483,12 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ...@@ -460,12 +483,12 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
/* set task conditions + field handling */ /* set task conditions + field handling */
if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) { if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
/* default config -- use full frames: /* default config -- use full frames */
odd A, even A, odd B, even B, repeat */
saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d); saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d); saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x02); saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x02);
saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x02); saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x02);
split = 0;
} else { } else {
/* split fields between tasks */ /* split fields between tasks */
if (V4L2_FIELD_TOP == cap) { if (V4L2_FIELD_TOP == cap) {
...@@ -494,7 +517,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ...@@ -494,7 +517,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
SAA7134_MAIN_CTRL_TE5 | SAA7134_MAIN_CTRL_TE5 |
SAA7134_MAIN_CTRL_TE6, SAA7134_MAIN_CTRL_TE6,
ctrl); 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"); task, ctrl, irq, split ? "no" : "yes");
return 0; return 0;
...@@ -508,12 +531,12 @@ static char *irqbits[] = { ...@@ -508,12 +531,12 @@ static char *irqbits[] = {
"AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC", "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
"TRIG_ERR", "CONF_ERR", "LOAD_ERR" "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, static void print_irqstatus(struct saa7134_dev *dev, int loop,
unsigned long report, unsigned long status) unsigned long report, unsigned long status)
{ {
int i; unsigned int i;
printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx", printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
dev->name,loop,jiffies,report,status); dev->name,loop,jiffies,report,status);
...@@ -536,18 +559,19 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -536,18 +559,19 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
unsigned long report,status; unsigned long report,status;
int loop; int loop, handled = 0;
for (loop = 0; loop < 10; loop++) { for (loop = 0; loop < 10; loop++) {
report = saa_readl(SAA7134_IRQ_REPORT); report = saa_readl(SAA7134_IRQ_REPORT);
status = saa_readl(SAA7134_IRQ_STATUS); status = saa_readl(SAA7134_IRQ_STATUS);
saa_writel(SAA7134_IRQ_REPORT,report);
if (0 == report) { if (0 == report) {
if (irq_debug > 1) if (irq_debug > 1)
printk(KERN_DEBUG "%s/irq: no (more) work\n", printk(KERN_DEBUG "%s/irq: no (more) work\n",
dev->name); dev->name);
goto out; goto out;
} }
handled = 1;
saa_writel(SAA7134_IRQ_REPORT,report);
if (irq_debug) if (irq_debug)
print_irqstatus(dev,loop,report,status); print_irqstatus(dev,loop,report,status);
...@@ -582,8 +606,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -582,8 +606,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
saa_writel(SAA7134_IRQ1,0); saa_writel(SAA7134_IRQ1,0);
saa_writel(SAA7134_IRQ2,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_dev *dev) ...@@ -599,8 +624,14 @@ static int saa7134_hwinit(struct saa7134_dev *dev)
saa7134_vbi_init(dev); saa7134_vbi_init(dev);
if (card_has_ts(dev)) if (card_has_ts(dev))
saa7134_ts_init(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); saa7134_oss_init(dev);
break;
}
/* RAM FIFO config */ /* RAM FIFO config */
saa_writel(SAA7134_FIFO_SIZE, 0x08070503); saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
...@@ -634,12 +665,15 @@ static int saa7134_hwinit(struct saa7134_dev *dev) ...@@ -634,12 +665,15 @@ static int saa7134_hwinit(struct saa7134_dev *dev)
/* enable peripheral devices */ /* enable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE, 0x01); saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
/* set vertical line numbering start (vbi needs this) */
saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
return 0; return 0;
} }
static void __devinit must_configure_manually(void) static void __devinit must_configure_manually(void)
{ {
int i,p; unsigned int i,p;
printk(KERN_WARNING printk(KERN_WARNING
"saa7134: <rant>\n" "saa7134: <rant>\n"
...@@ -675,18 +709,39 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -675,18 +709,39 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
return -ENOMEM; return -ENOMEM;
memset(dev,0,sizeof(*dev)); memset(dev,0,sizeof(*dev));
/* pci stuff */ /* pci init */
dev->pci = pci_dev; dev->pci = pci_dev;
if (pci_enable_device(pci_dev)) { if (pci_enable_device(pci_dev)) {
err = -EIO; err = -EIO;
goto fail1; goto fail1;
} }
sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount); 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", printk(KERN_INFO "%s: setting pci latency timer to %d\n",
dev->name,latency); dev->name,latency);
pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 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_CLASS_REVISION, &dev->pci_rev);
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
...@@ -710,7 +765,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -710,7 +765,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->board = SAA7134_BOARD_UNKNOWN; dev->board = SAA7134_BOARD_UNKNOWN;
} }
dev->tuner_type = saa7134_boards[dev->board].tuner_type; 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]; dev->tuner_type = tuner[saa7134_devcount];
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor, dev->name,pci_dev->subsystem_vendor,
...@@ -730,6 +785,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -730,6 +785,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000); dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
dev->bmmio = (__u8*)dev->lmmio; dev->bmmio = (__u8*)dev->lmmio;
/* register i2c bus */
saa7134_i2c_register(dev);
/* initialize hardware */
saa7134_board_init(dev);
saa7134_hwinit(dev);
/* get irq */ /* get irq */
err = request_irq(pci_dev->irq, saa7134_irq, err = request_irq(pci_dev->irq, saa7134_irq,
SA_SHIRQ | SA_INTERRUPT, dev->name, dev); SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
...@@ -739,12 +801,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -739,12 +801,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
goto fail2; goto fail2;
} }
/* initialize hardware */ /* load i2c helpers */
saa7134_hwinit(dev); if (TUNER_ABSENT != dev->tuner_type)
/* register i2c bus + load i2c helpers */
saa7134_i2c_register(dev);
if (TUNER_ABSENT != card(dev).tuner_type)
request_module("tuner"); request_module("tuner");
if (saa7134_boards[dev->board].need_tda9887) if (saa7134_boards[dev->board].need_tda9887)
request_module("tda9887"); request_module("tda9887");
...@@ -793,19 +851,27 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -793,19 +851,27 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
} }
/* register oss devices */ /* register oss devices */
if (card_has_audio(dev)) { switch (dev->pci->device) {
dev->oss.minor_dsp = register_sound_dsp(&saa7134_dsp_fops,dsp_nr); case PCI_DEVICE_ID_PHILIPS_SAA7134:
if (dev->oss.minor_dsp < 0) case PCI_DEVICE_ID_PHILIPS_SAA7133:
goto fail7; case PCI_DEVICE_ID_PHILIPS_SAA7135:
printk(KERN_INFO "%s: registered device dsp%d\n", if (oss) {
dev->name,dev->oss.minor_dsp >> 4); err = dev->oss.minor_dsp =
register_sound_dsp(&saa7134_dsp_fops,dsp_nr);
dev->oss.minor_mixer = if (err < 0) {
register_sound_mixer(&saa7134_mixer_fops,mixer_nr); goto fail7;
if (dev->oss.minor_mixer < 0) }
goto fail8; printk(KERN_INFO "%s: registered device dsp%d\n",
printk(KERN_INFO "%s: registered device mixer%d\n", dev->name,dev->oss.minor_dsp >> 4);
dev->name,dev->oss.minor_mixer >> 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 */ /* everything worked */
...@@ -815,8 +881,14 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -815,8 +881,14 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
return 0; return 0;
fail8: fail8:
if (card_has_audio(dev)) switch (dev->pci->device) {
unregister_sound_dsp(dev->oss.minor_dsp); 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: fail7:
if (card_has_radio(dev)) if (card_has_radio(dev))
video_unregister_device(&dev->radio_dev); video_unregister_device(&dev->radio_dev);
...@@ -828,16 +900,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, ...@@ -828,16 +900,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
fail4: fail4:
video_unregister_device(&dev->video_dev); video_unregister_device(&dev->video_dev);
fail3: 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); saa7134_oss_fini(dev);
break;
}
if (card_has_ts(dev)) if (card_has_ts(dev))
saa7134_ts_fini(dev); saa7134_ts_fini(dev);
saa7134_vbi_fini(dev); saa7134_vbi_fini(dev);
saa7134_video_fini(dev); saa7134_video_fini(dev);
saa7134_tvaudio_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), release_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0)); pci_resource_len(pci_dev,0));
fail1: fail1:
...@@ -849,6 +926,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) ...@@ -849,6 +926,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
{ {
struct saa7134_dev *dev = pci_get_drvdata(pci_dev); 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 */ /* disable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE,0); saa_writeb(SAA7134_SPECIAL_MODE,0);
...@@ -858,8 +942,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) ...@@ -858,8 +942,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa_writel(SAA7134_MAIN_CTRL,0); saa_writel(SAA7134_MAIN_CTRL,0);
/* shutdown subsystems */ /* 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); saa7134_oss_fini(dev);
break;
}
if (card_has_ts(dev)) if (card_has_ts(dev))
saa7134_ts_fini(dev); saa7134_ts_fini(dev);
saa7134_vbi_fini(dev); saa7134_vbi_fini(dev);
...@@ -874,9 +963,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) ...@@ -874,9 +963,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
/* unregister */ /* unregister */
saa7134_i2c_unregister(dev); saa7134_i2c_unregister(dev);
if (card_has_audio(dev)) { switch (dev->pci->device) {
unregister_sound_mixer(dev->oss.minor_mixer); case PCI_DEVICE_ID_PHILIPS_SAA7134:
unregister_sound_dsp(dev->oss.minor_dsp); 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)) if (card_has_radio(dev))
video_unregister_device(&dev->radio_dev); video_unregister_device(&dev->radio_dev);
......
...@@ -153,10 +153,7 @@ static int i2c_is_busy_wait(struct saa7134_dev *dev) ...@@ -153,10 +153,7 @@ static int i2c_is_busy_wait(struct saa7134_dev *dev)
status = i2c_get_status(dev); status = i2c_get_status(dev);
if (!i2c_is_busy(status)) if (!i2c_is_busy(status))
break; break;
if (need_resched()) saa_wait(I2C_WAIT_DELAY);
schedule();
else
udelay(I2C_WAIT_DELAY);
} }
if (I2C_WAIT_RETRY == count) if (I2C_WAIT_RETRY == count)
return FALSE; return FALSE;
...@@ -318,7 +315,7 @@ static u32 functionality(struct i2c_adapter *adap) ...@@ -318,7 +315,7 @@ static u32 functionality(struct i2c_adapter *adap)
static int attach_inform(struct i2c_client *client) static int attach_inform(struct i2c_client *client)
{ {
struct saa7134_dev *dev = client->adapter->algo_data; 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); saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner);
return 0; return 0;
...@@ -334,9 +331,9 @@ static struct i2c_algorithm saa7134_algo = { ...@@ -334,9 +331,9 @@ static struct i2c_algorithm saa7134_algo = {
static struct i2c_adapter saa7134_adap_template = { static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_TV_ANALOG,
I2C_DEVNAME("saa7134"), I2C_DEVNAME("saa7134"),
.id = I2C_ALGO_SAA7134, .id = I2C_ALGO_SAA7134,
.class = I2C_ADAP_CLASS_TV_ANALOG,
.algo = &saa7134_algo, .algo = &saa7134_algo,
.client_register = attach_inform, .client_register = attach_inform,
}; };
......
...@@ -94,8 +94,9 @@ static int dsp_buffer_free(struct saa7134_dev *dev) ...@@ -94,8 +94,9 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
static int dsp_rec_start(struct saa7134_dev *dev) static int dsp_rec_start(struct saa7134_dev *dev)
{ {
int err, fmt, bswap, wswap; int err, bswap, sign;
unsigned long control,flags; u32 fmt, control;
unsigned long flags;
/* prepare buffer */ /* prepare buffer */
if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
...@@ -110,45 +111,60 @@ static int dsp_rec_start(struct saa7134_dev *dev) ...@@ -110,45 +111,60 @@ static int dsp_rec_start(struct saa7134_dev *dev)
/* sample format */ /* sample format */
switch (dev->oss.afmt) { switch (dev->oss.afmt) {
case AFMT_U8: fmt = 0x00; break; case AFMT_U8:
case AFMT_S8: fmt = 0x00 | 0x04; break; case AFMT_S8: fmt = 0x00; break;
case AFMT_U16_LE: case AFMT_U16_LE:
case AFMT_U16_BE: fmt = 0x01; break; case AFMT_U16_BE:
case AFMT_S16_LE: case AFMT_S16_LE:
case AFMT_S16_BE: fmt = 0x01 | 0x04; break; case AFMT_S16_BE: fmt = 0x01; 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
default: default:
err = -EINVAL; err = -EINVAL;
goto fail2; 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) { switch (dev->oss.afmt) {
case AFMT_U16_BE: case AFMT_U16_BE:
case AFMT_S16_BE: bswap = 1; wswap = 0; break; case AFMT_S16_BE: bswap = 1; break;
#ifdef AFMT_S32_LE default: bswap = 0; break;
case AFMT_S32_BE: bswap = 1; wswap = 1; break;
#endif
default: bswap = 0; wswap = 0; break;
} }
if (1 == dev->oss.channels) switch (dev->pci->device) {
fmt |= (1 << 3); case PCI_DEVICE_ID_PHILIPS_SAA7134:
if (2 == dev->oss.channels) if (1 == dev->oss.channels)
fmt |= (3 << 3); fmt |= (1 << 3);
fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; if (2 == dev->oss.channels)
fmt |= (3 << 3);
saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff)); if (sign)
saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8); fmt |= 0x04;
saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16); fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c%c\n", 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, dev->oss.afmt, dev->oss.channels, fmt,
bswap ? 'b' : '-', wswap ? 'w' : '-'); bswap ? 'b' : '-');
/* dma: setup channel 6 (= AUDIO) */ /* dma: setup channel 6 (= AUDIO) */
control = SAA7134_RS_CONTROL_BURST_16 | control = SAA7134_RS_CONTROL_BURST_16 |
...@@ -156,8 +172,6 @@ static int dsp_rec_start(struct saa7134_dev *dev) ...@@ -156,8 +172,6 @@ static int dsp_rec_start(struct saa7134_dev *dev)
(dev->oss.pt.dma >> 12); (dev->oss.pt.dma >> 12);
if (bswap) if (bswap)
control |= SAA7134_RS_CONTROL_BSWAP; control |= SAA7134_RS_CONTROL_BSWAP;
if (wswap)
control |= SAA7134_RS_CONTROL_WSWAP;
saa_writel(SAA7134_RS_BA1(6),0); saa_writel(SAA7134_RS_BA1(6),0);
saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize);
saa_writel(SAA7134_RS_PITCH(6),0); saa_writel(SAA7134_RS_PITCH(6),0);
...@@ -201,7 +215,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev) ...@@ -201,7 +215,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
static int dsp_open(struct inode *inode, struct file *file) 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 saa7134_dev *h,*dev = NULL;
struct list_head *list; struct list_head *list;
int err; int err;
...@@ -259,7 +273,8 @@ static ssize_t dsp_read(struct file *file, char *buffer, ...@@ -259,7 +273,8 @@ static ssize_t dsp_read(struct file *file, char *buffer,
{ {
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int bytes,err,ret = 0; unsigned int bytes;
int err,ret = 0;
add_wait_queue(&dev->oss.wq, &wait); add_wait_queue(&dev->oss.wq, &wait);
down(&dev->oss.lock); down(&dev->oss.lock);
...@@ -390,10 +405,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -390,10 +405,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_U16_BE: case AFMT_U16_BE:
case AFMT_S16_LE: case AFMT_S16_LE:
case AFMT_S16_BE: case AFMT_S16_BE:
#ifdef AFMT_S32_LE
case AFMT_S32_LE:
case AFMT_S32_BE:
#endif
down(&dev->oss.lock); down(&dev->oss.lock);
dev->oss.afmt = val; dev->oss.afmt = val;
if (dev->oss.recording) { if (dev->oss.recording) {
...@@ -416,11 +427,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -416,11 +427,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_S16_LE: case AFMT_S16_LE:
case AFMT_S16_BE: case AFMT_S16_BE:
return put_user(16, (int*)arg); 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: default:
return -EINVAL; return -EINVAL;
} }
...@@ -499,14 +505,10 @@ struct file_operations saa7134_dsp_fops = { ...@@ -499,14 +505,10 @@ struct file_operations saa7134_dsp_fops = {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static int 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; int analog_io,rate;
dev->oss.count++;
dev->oss.input = src;
dprintk("mixer input = %s\n",iname[dev->oss.input]);
switch (dev->oss.input) { switch (dev->oss.input) {
case TV: case TV:
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
...@@ -525,27 +527,78 @@ mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src) ...@@ -525,27 +527,78 @@ mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
} }
static int 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: case TV:
/* nothing */ value = 0xbbbb10; /* MAIN */
break; break;
case LINE1: case LINE1:
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10, value = 0xbbbb32; /* AUX1 */
(100 == level) ? 0x00 : 0x10);
break; break;
case LINE2: case LINE2:
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, value = 0xbbbb54; /* AUX2 */
(100 == level) ? 0x00 : 0x20);
break; break;
} }
saa_dsp_writel(dev, 0x46c >> 2, value);
return 0; 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) 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 saa7134_dev *h,*dev = NULL;
struct list_head *list; struct list_head *list;
...@@ -681,13 +734,20 @@ struct file_operations saa7134_mixer_fops = { ...@@ -681,13 +734,20 @@ struct file_operations saa7134_mixer_fops = {
int saa7134_oss_init(struct saa7134_dev *dev) int saa7134_oss_init(struct saa7134_dev *dev)
{ {
/* general */
init_MUTEX(&dev->oss.lock); init_MUTEX(&dev->oss.lock);
init_waitqueue_head(&dev->oss.wq); init_waitqueue_head(&dev->oss.wq);
dev->oss.line1 = 50;
dev->oss.line2 = 50; switch (dev->pci->device) {
mixer_level(dev,LINE1,dev->oss.line1); case PCI_DEVICE_ID_PHILIPS_SAA7133:
mixer_level(dev,LINE2,dev->oss.line2); 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; dev->oss.rate = 32000;
if (oss_rate) if (oss_rate)
dev->oss.rate = oss_rate; dev->oss.rate = oss_rate;
...@@ -695,7 +755,13 @@ int saa7134_oss_init(struct saa7134_dev *dev) ...@@ -695,7 +755,13 @@ int saa7134_oss_init(struct saa7134_dev *dev)
dev->oss.rate = saa7134_boards[dev->board].i2s_rate; dev->oss.rate = saa7134_boards[dev->board].i2s_rate;
dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000; 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); mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2);
return 0; return 0;
} }
...@@ -710,7 +776,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) ...@@ -710,7 +776,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
int next_blk, reg = 0; int next_blk, reg = 0;
spin_lock(&dev->slock); spin_lock(&dev->slock);
if (-1 == dev->oss.dma_blk) { if (UNSET == dev->oss.dma_blk) {
dprintk("irq: recording stopped%s\n",""); dprintk("irq: recording stopped%s\n","");
goto done; goto done;
} }
......
...@@ -9,9 +9,15 @@ ...@@ -9,9 +9,15 @@
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7130 #ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
# define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130 # define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
#endif #endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
#endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7134 #ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
# define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134 # define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
#endif #endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
#endif
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* /*
...@@ -329,6 +335,13 @@ ...@@ -329,6 +335,13 @@
/* test modes */ /* test modes */
#define SAA7134_SPECIAL_MODE 0x1d0 #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: * Local variables:
......
...@@ -52,8 +52,9 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -52,8 +52,9 @@ static int buffer_activate(struct saa7134_dev *dev,
{ {
u32 control; u32 control;
dprintk("buffer_activate [%p]\n",buf); dprintk("buffer_activate [%p]",buf);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
buf->top_seen = 0;
/* dma: setup channel 5 (= TS) */ /* dma: setup channel 5 (= TS) */
control = SAA7134_RS_CONTROL_BURST_16 | control = SAA7134_RS_CONTROL_BURST_16 |
...@@ -63,11 +64,11 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -63,11 +64,11 @@ static int buffer_activate(struct saa7134_dev *dev,
if (NULL == next) if (NULL == next)
next = buf; next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) { 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_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next)); saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
} else { } 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_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf)); saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
} }
...@@ -86,8 +87,11 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -86,8 +87,11 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
{ {
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
struct saa7134_buf *buf = (struct saa7134_buf *)vb; 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; llength = TS_PACKET_SIZE;
lines = TS_NR_PACKETS; lines = TS_NR_PACKETS;
...@@ -116,7 +120,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -116,7 +120,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops; goto oops;
} }
buf->vb.state = STATE_PREPARED; buf->vb.state = STATE_PREPARED;
buf->top_seen = 0;
buf->activate = buffer_activate; buf->activate = buffer_activate;
buf->vb.field = field; buf->vb.field = field;
return 0; return 0;
...@@ -163,7 +166,7 @@ static struct videobuf_queue_ops ts_qops = { ...@@ -163,7 +166,7 @@ static struct videobuf_queue_ops ts_qops = {
static int ts_open(struct inode *inode, struct file *file) 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 saa7134_dev *h,*dev = NULL;
struct list_head *list; struct list_head *list;
int err; int err;
...@@ -414,6 +417,7 @@ int saa7134_ts_init(struct saa7134_dev *dev) ...@@ -414,6 +417,7 @@ int saa7134_ts_init(struct saa7134_dev *dev)
dev->ts_q.timeout.function = saa7134_buffer_timeout; dev->ts_q.timeout.function = saa7134_buffer_timeout;
dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q);
dev->ts_q.dev = dev; dev->ts_q.dev = dev;
dev->ts_q.need_two = 1;
videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock, videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE, V4L2_FIELD_ALTERNATE,
...@@ -445,7 +449,7 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) ...@@ -445,7 +449,7 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
spin_lock(&dev->slock); spin_lock(&dev->slock);
if (dev->ts_q.curr) { 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 (field == V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x100000) if ((status & 0x100000) != 0x100000)
goto done; goto done;
......
...@@ -37,13 +37,23 @@ static unsigned int audio_debug = 0; ...@@ -37,13 +37,23 @@ static unsigned int audio_debug = 0;
MODULE_PARM(audio_debug,"i"); MODULE_PARM(audio_debug,"i");
MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); 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) \ #define dprintk(fmt, arg...) if (audio_debug) \
printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg) 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", \ #define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \
dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg))) 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[] = { static struct saa7134_tvaudio tvaudio[] = {
{ {
...@@ -94,6 +104,12 @@ static struct saa7134_tvaudio tvaudio[] = { ...@@ -94,6 +104,12 @@ static struct saa7134_tvaudio tvaudio[] = {
.carr1 = 6500, .carr1 = 6500,
.carr2 = 5850, .carr2 = 5850,
.mode = TVAUDIO_NICAM_AM, .mode = TVAUDIO_NICAM_AM,
},{
.name = "SECAM-D/K",
.std = V4L2_STD_SECAM,
.carr1 = 6500,
.carr2 = -1,
.mode = TVAUDIO_FM_MONO,
},{ },{
.name = "NTSC-M", .name = "NTSC-M",
.std = V4L2_STD_NTSC, .std = V4L2_STD_NTSC,
...@@ -122,7 +138,7 @@ static void tvaudio_init(struct saa7134_dev *dev) ...@@ -122,7 +138,7 @@ static void tvaudio_init(struct saa7134_dev *dev)
schedule(); schedule();
else else
udelay(10); udelay(10);
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
...@@ -134,9 +150,9 @@ static void tvaudio_init(struct saa7134_dev *dev) ...@@ -134,9 +150,9 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_FM_DEMATRIX, 0x80); 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; a <<= 24;
do_div(a,12288); do_div(a,12288);
...@@ -152,17 +168,19 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev, ...@@ -152,17 +168,19 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev,
saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary)); 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; struct saa7134_input *in;
int reg = 0; int reg = 0;
int mask; int mask;
/* look what is to do ... */ /* look what is to do ... */
in = dev->input; in = dev->input;
mute = (dev->ctl_mute || dev->automute); mute = (dev->ctl_mute ||
if (!card_has_audio(dev) && card(dev).mute.name) { (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 */ /* 7130 - we'll mute using some unconnected audio input */
if (mute) if (mute)
in = &card(dev).mute; in = &card(dev).mute;
...@@ -171,14 +189,12 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev) ...@@ -171,14 +189,12 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
dev->hw_input == in) dev->hw_input == in)
return; return;
#if 1
dprintk("ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n", dprintk("ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n",
dev->ctl_mute,dev->automute,dev->input->name,mute,in->name); dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
#endif
dev->hw_mute = mute; dev->hw_mute = mute;
dev->hw_input = in; dev->hw_input = in;
if (card_has_audio(dev)) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
/* 7134 mute */ /* 7134 mute */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb); saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb);
...@@ -199,25 +215,6 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev) ...@@ -199,25 +215,6 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
saa7134_track_gpio(dev,in->name); 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, static void tvaudio_setmode(struct saa7134_dev *dev,
struct saa7134_tvaudio *audio, struct saa7134_tvaudio *audio,
char *note) char *note)
...@@ -274,8 +271,77 @@ static void tvaudio_setmode(struct saa7134_dev *dev, ...@@ -274,8 +271,77 @@ static void tvaudio_setmode(struct saa7134_dev *dev,
saa_writel(0x174 >> 2, 0x0001e000); /* FIXME */ saa_writel(0x174 >> 2, 0x0001e000); /* FIXME */
} }
int saa7134_tvaudio_getstereo(struct saa7134_dev *dev, static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
struct saa7134_tvaudio *audio) {
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; __u32 idp,nicam;
int retval = -1; int retval = -1;
...@@ -321,62 +387,42 @@ int saa7134_tvaudio_getstereo(struct saa7134_dev *dev, ...@@ -321,62 +387,42 @@ int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
return retval; 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; static char *name[] = {
[ V4L2_TUNER_MODE_MONO ] = "mono",
tvaudio_setcarrier(dev,carrier-100,carrier-100); [ V4L2_TUNER_MODE_STEREO ] = "stereo",
if (tvaudio_sleep(dev,HZ/10)) [ V4L2_TUNER_MODE_LANG1 ] = "lang1",
return -1; [ V4L2_TUNER_MODE_LANG2 ] = "lang2",
left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); };
if (tvaudio_sleep(dev,HZ/10)) static u32 fm[] = {
return -1; [ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */
left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); [ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */
[ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */
tvaudio_setcarrier(dev,carrier+100,carrier+100); [ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */
if (tvaudio_sleep(dev,HZ/10)) };
return -1; u32 reg;
right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
if (tvaudio_sleep(dev,HZ/10))
return -1;
right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
left >>= 16; switch (audio->mode) {
right >>= 16; case TVAUDIO_FM_MONO:
value = left > right ? left - right : right - left; /* nothing to do ... */
dprintk("scanning %d.%03d MHz => dc is %5d [%d/%d]\n", break;
carrier/1000,carrier%1000,value,left,right); case TVAUDIO_FM_K_STEREO:
return value; case TVAUDIO_FM_BG_STEREO:
} dprintk("setstereo [fm] => %s\n",
name[ mode % ARRAY_SIZE(name) ]);
#if 0 reg = fm[ mode % ARRAY_SIZE(fm) ];
static void sifdebug_dump_regs(struct saa7134_dev *dev) saa_writeb(SAA7134_FM_DEMATRIX, reg);
{ break;
print_regb(AUDIO_STATUS); case TVAUDIO_FM_SAT_STEREO:
print_regb(IDENT_SIF); case TVAUDIO_NICAM_AM:
print_regb(LEVEL_READOUT1); case TVAUDIO_NICAM_FM:
print_regb(LEVEL_READOUT2); /* FIXME */
print_regb(DCXO_IDENT_CTRL); break;
print_regb(DEMODULATOR); }
print_regb(AGC_GAIN_SELECT); return 0;
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_thread(void *data) static int tvaudio_thread(void *data)
{ {
...@@ -388,7 +434,8 @@ static int tvaudio_thread(void *data) ...@@ -388,7 +434,8 @@ static int tvaudio_thread(void *data)
struct saa7134_dev *dev = data; struct saa7134_dev *dev = data;
const int *carr_scan; const int *carr_scan;
int carr_vals[4]; int carr_vals[4];
int i,max,carrier,audio; unsigned int i, audio;
int max1,max2,carrier,rx,mode;
lock_kernel(); lock_kernel();
daemonize("%s", dev->name); daemonize("%s", dev->name);
...@@ -410,10 +457,10 @@ static int tvaudio_thread(void *data) ...@@ -410,10 +457,10 @@ static int tvaudio_thread(void *data)
dev->tvaudio = NULL; dev->tvaudio = NULL;
tvaudio_init(dev); tvaudio_init(dev);
dev->automute = 1; dev->automute = 1;
saa7134_tvaudio_setmute(dev); mute_input_7134(dev);
/* give the tuner some time */ /* give the tuner some time */
if (tvaudio_sleep(dev,HZ/2)) if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
goto restart; goto restart;
/* find the main carrier */ /* find the main carrier */
...@@ -433,55 +480,280 @@ static int tvaudio_thread(void *data) ...@@ -433,55 +480,280 @@ static int tvaudio_thread(void *data)
if (dev->thread.scan1 != dev->thread.scan2) if (dev->thread.scan1 != dev->thread.scan2)
goto restart; 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]) if (!carr_scan[i])
continue; continue;
if (max < carr_vals[i]) { if (max1 < carr_vals[i]) {
max = carr_vals[i]; max2 = max1;
max1 = carr_vals[i];
carrier = carr_scan[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 :-/ */ if (0 != carrier && max1 > 2000 && max1 > max2*3) {
printk(KERN_WARNING "%s/audio: oops: audio carrier " /* found good carrier */
"scan failed\n", dev->name); 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 { } else {
dprintk("found %s main sound carrier @ %d.%03d MHz\n", /* no carrier + no fallback -- try first in list */
dev->tvnorm->name, carrier = carr_scan[0];
carrier/1000,carrier%1000); 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); tvaudio_setcarrier(dev,carrier,carrier);
dev->automute = 0; dev->automute = 0;
saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
saa7134_tvaudio_setmute(dev); saa7134_tvaudio_setmute(dev);
/* find the exact tv audio norm */ /* find the exact tv audio norm */
for (audio = -1, i = 0; i < TVAUDIO; i++) { for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
if (dev->tvnorm->id != -1 && if (dev->tvnorm->id != UNSET &&
dev->tvnorm->id != tvaudio[i].std) dev->tvnorm->id != tvaudio[i].std)
continue; continue;
if (tvaudio[i].carr1 != carrier) if (tvaudio[i].carr1 != carrier)
continue; continue;
if (-1 == audio) if (UNSET == audio)
audio = i; audio = i;
tvaudio_setmode(dev,&tvaudio[i],"trying"); tvaudio_setmode(dev,&tvaudio[i],"trying");
if (tvaudio_sleep(dev,HZ)) if (tvaudio_sleep(dev,HZ))
goto restart; goto restart;
if (-1 != saa7134_tvaudio_getstereo(dev,&tvaudio[i])) { if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
audio = i; audio = i;
break; break;
} }
} }
if (-1 == audio) saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);
if (UNSET == audio)
continue; continue;
tvaudio_setmode(dev,&tvaudio[audio],"using"); tvaudio_setmode(dev,&tvaudio[audio],"using");
tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);
dev->tvaudio = &tvaudio[audio]; dev->tvaudio = &tvaudio[audio];
#if 1
if (tvaudio_sleep(dev,3*HZ)) if (tvaudio_sleep(dev,3*HZ))
goto restart; 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 #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: done:
...@@ -492,14 +764,89 @@ static int tvaudio_thread(void *data) ...@@ -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) int saa7134_tvaudio_init(struct saa7134_dev *dev)
{ {
DECLARE_MUTEX_LOCKED(sem); DECLARE_MUTEX_LOCKED(sem);
int (*my_thread)(void *data) = NULL;
/* enable I2S audio output */ /* enable I2S audio output */
if (saa7134_boards[dev->board].i2s_rate) { 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 */ /* set rate */
saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
...@@ -512,13 +859,24 @@ int saa7134_tvaudio_init(struct saa7134_dev *dev) ...@@ -512,13 +859,24 @@ int saa7134_tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
} }
/* start tvaudio thread */ switch (dev->pci->device) {
init_waitqueue_head(&dev->thread.wq); case PCI_DEVICE_ID_PHILIPS_SAA7134:
dev->thread.notify = &sem; my_thread = tvaudio_thread;
kernel_thread(tvaudio_thread,dev,0); break;
down(&sem); case PCI_DEVICE_ID_PHILIPS_SAA7133:
dev->thread.notify = NULL; case PCI_DEVICE_ID_PHILIPS_SAA7135:
wake_up_interruptible(&dev->thread.wq); 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; return 0;
} }
...@@ -541,8 +899,13 @@ int saa7134_tvaudio_fini(struct saa7134_dev *dev) ...@@ -541,8 +899,13 @@ int saa7134_tvaudio_fini(struct saa7134_dev *dev)
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
{ {
dev->thread.scan2++; if (dev->thread.task) {
wake_up_interruptible(&dev->thread.wq); dev->thread.scan2++;
wake_up_interruptible(&dev->thread.wq);
} else {
dev->automute = 0;
saa7134_tvaudio_setmute(dev);
}
return 0; return 0;
} }
......
...@@ -85,6 +85,7 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -85,6 +85,7 @@ static int buffer_activate(struct saa7134_dev *dev,
dprintk("buffer_activate [%p]\n",buf); dprintk("buffer_activate [%p]\n",buf);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
buf->top_seen = 0;
task_init(dev,buf,TASK_A); task_init(dev,buf,TASK_A);
task_init(dev,buf,TASK_B); task_init(dev,buf,TASK_B);
...@@ -119,7 +120,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -119,7 +120,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = (struct saa7134_buf *)vb; struct saa7134_buf *buf = (struct saa7134_buf *)vb;
struct saa7134_tvnorm *norm = dev->tvnorm; 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; lines = norm->vbi_v_stop - norm->vbi_v_start +1;
if (lines > VBI_LINE_COUNT) if (lines > VBI_LINE_COUNT)
...@@ -155,7 +157,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -155,7 +157,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops; goto oops;
} }
buf->vb.state = STATE_PREPARED; buf->vb.state = STATE_PREPARED;
buf->top_seen = 0;
buf->activate = buffer_activate; buf->activate = buffer_activate;
buf->vb.field = field; buf->vb.field = field;
return 0; return 0;
...@@ -166,7 +167,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -166,7 +167,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
} }
static int 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_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
...@@ -241,7 +242,7 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status) ...@@ -241,7 +242,7 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
if (dev->vbi_q.curr) { if (dev->vbi_q.curr) {
dev->vbi_fieldcount++; dev->vbi_fieldcount++;
/* make sure we have seen both fields */ /* make sure we have seen both fields */
if ((status & 0x10) == 0x10) { if ((status & 0x10) == 0x00) {
dev->vbi_q.curr->top_seen = 1; dev->vbi_q.curr->top_seen = 1;
goto done; goto done;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* device driver for philips saa7134 based TV cards * device driver for philips saa7134 based TV cards
* video4linux video interface * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -127,7 +127,7 @@ static struct saa7134_format formats[] = { ...@@ -127,7 +127,7 @@ static struct saa7134_format formats[] = {
.vshift = 1, .vshift = 1,
} }
}; };
#define FORMATS (sizeof(formats)/sizeof(struct saa7134_format)) #define FORMATS ARRAY_SIZE(formats)
static struct saa7134_tvnorm tvnorms[] = { static struct saa7134_tvnorm tvnorms[] = {
{ {
...@@ -141,13 +141,15 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -141,13 +141,15 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x81, .chroma_ctrl1 = 0x81,
.chroma_gain = 0x2a, .chroma_gain = 0x2a,
.chroma_ctrl2 = 0x06, .chroma_ctrl2 = 0x06,
.vgate_misc = 0x1c,
.h_start = 0, .h_start = 0,
.h_stop = 719, .h_stop = 719,
.video_v_start = 24, .video_v_start = 24,
.video_v_stop = 311, .video_v_stop = 311,
.vbi_v_start = 7-3, /* FIXME */ .vbi_v_start = 7,
.vbi_v_stop = 22-3, .vbi_v_stop = 22,
.src_timing = 4,
},{ },{
.name = "NTSC", .name = "NTSC",
.id = V4L2_STD_NTSC, .id = V4L2_STD_NTSC,
...@@ -159,6 +161,7 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -159,6 +161,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x89, .chroma_ctrl1 = 0x89,
.chroma_gain = 0x2a, .chroma_gain = 0x2a,
.chroma_ctrl2 = 0x0e, .chroma_ctrl2 = 0x0e,
.vgate_misc = 0x18,
.h_start = 0, .h_start = 0,
.h_stop = 719, .h_stop = 719,
...@@ -166,17 +169,19 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -166,17 +169,19 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 22+240, .video_v_stop = 22+240,
.vbi_v_start = 10, /* FIXME */ .vbi_v_start = 10, /* FIXME */
.vbi_v_stop = 21, /* FIXME */ .vbi_v_stop = 21, /* FIXME */
.src_timing = 1,
},{ },{
.name = "SECAM", .name = "SECAM",
.id = V4L2_STD_SECAM, .id = V4L2_STD_SECAM,
.width = 720, .width = 720,
.height = 576, .height = 576,
.sync_control = 0x58, .sync_control = 0x18, /* old: 0x58, */
.luma_control = 0x1b, .luma_control = 0x1b,
.chroma_ctrl1 = 0xd1, .chroma_ctrl1 = 0xd1,
.chroma_gain = 0x80, .chroma_gain = 0x80,
.chroma_ctrl2 = 0x00, .chroma_ctrl2 = 0x00,
.vgate_misc = 0x1c,
.h_start = 0, .h_start = 0,
.h_stop = 719, .h_stop = 719,
...@@ -184,6 +189,47 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -184,6 +189,47 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311, .video_v_stop = 311,
.vbi_v_start = 7, .vbi_v_start = 7,
.vbi_v_stop = 22, .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 #if 0
},{ },{
.name = "AUTO", .name = "AUTO",
...@@ -196,6 +242,7 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -196,6 +242,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x8b, .chroma_ctrl1 = 0x8b,
.chroma_gain = 0x00, .chroma_gain = 0x00,
.chroma_ctrl2 = 0x00, .chroma_ctrl2 = 0x00,
.vgate_misc = 0x18,
.h_start = 0, .h_start = 0,
.h_stop = 719, .h_stop = 719,
...@@ -203,11 +250,11 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -203,11 +250,11 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311, .video_v_stop = 311,
.vbi_v_start = 7, .vbi_v_start = 7,
.vbi_v_stop = 22, .vbi_v_stop = 22,
.src_timing = 4,
#endif #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_INVERT (V4L2_CID_PRIVATE_BASE + 0)
#define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1)
...@@ -298,11 +345,11 @@ static const struct v4l2_queryctrl video_ctrls[] = { ...@@ -298,11 +345,11 @@ static const struct v4l2_queryctrl video_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER, .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++) for (i = 0; i < CTRLS; i++)
if (video_ctrls[i].id == id) if (video_ctrls[i].id == id)
...@@ -310,9 +357,9 @@ static const struct v4l2_queryctrl* ctrl_by_id(int id) ...@@ -310,9 +357,9 @@ static const struct v4l2_queryctrl* ctrl_by_id(int id)
return NULL; 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++) for (i = 0; i < FORMATS; i++)
if (formats[i].fourcc == fourcc) if (formats[i].fourcc == fourcc)
...@@ -323,7 +370,7 @@ static struct saa7134_format* format_by_fourcc(int fourcc) ...@@ -323,7 +370,7 @@ static struct saa7134_format* format_by_fourcc(int fourcc)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* resource management */ /* 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) if (fh->resources & bit)
/* have it already allocated */ /* have it already allocated */
...@@ -345,19 +392,19 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, int bit) ...@@ -345,19 +392,19 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, int bit)
} }
static static
int res_check(struct saa7134_fh *fh, int bit) int res_check(struct saa7134_fh *fh, unsigned int bit)
{ {
return (fh->resources & bit); return (fh->resources & bit);
} }
static static
int res_locked(struct saa7134_dev *dev, int bit) int res_locked(struct saa7134_dev *dev, unsigned int bit)
{ {
return (dev->resources & bit); return (dev->resources & bit);
} }
static 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) if ((fh->resources & bits) != bits)
BUG(); BUG();
...@@ -393,7 +440,8 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) ...@@ -393,7 +440,8 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_ANALOG_IN_CTRL4, 0x90); saa_writeb(SAA7134_ANALOG_IN_CTRL4, 0x90);
saa_writeb(SAA7134_HSYNC_START, 0xeb); saa_writeb(SAA7134_HSYNC_START, 0xeb);
saa_writeb(SAA7134_HSYNC_STOP, 0xe0); 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_SYNC_CTRL, norm->sync_control);
saa_writeb(SAA7134_LUMA_CTRL, luma_control); saa_writeb(SAA7134_LUMA_CTRL, luma_control);
saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright); saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
...@@ -410,7 +458,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) ...@@ -410,7 +458,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_ANALOG_ADC, 0x01); saa_writeb(SAA7134_ANALOG_ADC, 0x01);
saa_writeb(SAA7134_VGATE_START, 0x11); saa_writeb(SAA7134_VGATE_START, 0x11);
saa_writeb(SAA7134_VGATE_STOP, 0xfe); 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_GAIN, 0x40);
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
...@@ -454,7 +502,7 @@ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) ...@@ -454,7 +502,7 @@ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
{ 9, 15, 0, 4, 3 }, { 9, 15, 0, 4, 3 },
{ 10, 16, 1, 5, 3 }, { 10, 16, 1, 5, 3 },
}; };
static const int count = sizeof(vals)/sizeof(vals[0]); static const int count = ARRAY_SIZE(vals);
int i; int i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
...@@ -532,14 +580,14 @@ static void set_size(struct saa7134_dev *dev, int task, ...@@ -532,14 +580,14 @@ static void set_size(struct saa7134_dev *dev, int task,
/* deinterlace y offsets */ /* deinterlace y offsets */
if (interlace) { if (interlace) {
y_odd = dev->ctl_y_odd; 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_OFFSET0(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even); saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd); saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even); saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);
} else { } else {
y_odd = dev->ctl_y_odd; 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_OFFSET0(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even); saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd); saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
...@@ -688,7 +736,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) ...@@ -688,7 +736,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
err = verify_preview(dev,&fh->win); err = verify_preview(dev,&fh->win);
if (0 != err) if (0 != err)
return err; return err;
dev->ovfield = fh->win.field;
dprintk("start_preview %dx%d+%d+%d %s field=%s\n", dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
fh->win.w.width,fh->win.w.height, fh->win.w.width,fh->win.w.height,
fh->win.w.left,fh->win.w.top, fh->win.w.left,fh->win.w.top,
...@@ -752,6 +801,7 @@ static int buffer_activate(struct saa7134_dev *dev, ...@@ -752,6 +801,7 @@ static int buffer_activate(struct saa7134_dev *dev,
dprintk("buffer_activate buf=%p\n",buf); dprintk("buffer_activate buf=%p\n",buf);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
buf->top_seen = 0;
set_size(dev,TASK_A,buf->vb.width,buf->vb.height, set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
V4L2_FIELD_HAS_BOTH(buf->vb.field)); V4L2_FIELD_HAS_BOTH(buf->vb.field));
...@@ -828,7 +878,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -828,7 +878,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
struct saa7134_fh *fh = file->private_data; struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev; struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = (struct saa7134_buf *)vb; struct saa7134_buf *buf = (struct saa7134_buf *)vb;
int size,err; unsigned int size;
int err;
/* sanity checks */ /* sanity checks */
if (NULL == fh->fmt) if (NULL == fh->fmt)
...@@ -842,8 +893,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -842,8 +893,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
if (0 != buf->vb.baddr && buf->vb.bsize < size) if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL; return -EINVAL;
dprintk("buffer_prepare [size=%dx%d,bytes=%d,fields=%s,%s]\n", dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
fh->width,fh->height,size,v4l2_field_names[field], vb->i,fh->width,fh->height,size,v4l2_field_names[field],
fh->fmt->name); fh->fmt->name);
if (buf->vb.width != fh->width || if (buf->vb.width != fh->width ||
buf->vb.height != fh->height || buf->vb.height != fh->height ||
...@@ -872,7 +923,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -872,7 +923,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops; goto oops;
} }
buf->vb.state = STATE_PREPARED; buf->vb.state = STATE_PREPARED;
buf->top_seen = 0;
buf->activate = buffer_activate; buf->activate = buffer_activate;
return 0; return 0;
...@@ -1081,7 +1131,7 @@ static int saa7134_resource(struct saa7134_fh *fh) ...@@ -1081,7 +1131,7 @@ static int saa7134_resource(struct saa7134_fh *fh)
static int video_open(struct inode *inode, struct file *file) 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_dev *h,*dev = NULL;
struct saa7134_fh *fh; struct saa7134_fh *fh;
struct list_head *list; struct list_head *list;
...@@ -1117,8 +1167,8 @@ static int video_open(struct inode *inode, struct file *file) ...@@ -1117,8 +1167,8 @@ static int video_open(struct inode *inode, struct file *file)
fh->radio = radio; fh->radio = radio;
fh->type = type; fh->type = type;
fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
fh->width = 320; fh->width = 768;
fh->height = 240; fh->height = 576;
videobuf_queue_init(&fh->cap, &video_qops, videobuf_queue_init(&fh->cap, &video_qops,
dev->pci, &dev->slock, dev->pci, &dev->slock,
...@@ -1138,7 +1188,9 @@ static int video_open(struct inode *inode, struct file *file) ...@@ -1138,7 +1188,9 @@ static int video_open(struct inode *inode, struct file *file)
if (fh->radio) { if (fh->radio) {
/* switch to radio mode */ /* switch to radio mode */
u32 v = 400*16;
saa7134_tvaudio_setinput(dev,&card(dev).radio); saa7134_tvaudio_setinput(dev,&card(dev).radio);
saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&v);
saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL); saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL);
} else { } else {
/* switch to video/vbi mode */ /* switch to video/vbi mode */
...@@ -1185,7 +1237,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) ...@@ -1185,7 +1237,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
} else { } else {
down(&fh->cap.lock); down(&fh->cap.lock);
if (-1 == fh->cap.read_off) { if (UNSET == fh->cap.read_off) {
/* need to capture a new frame */ /* need to capture a new frame */
if (res_locked(fh->dev,RESOURCE_VIDEO)) { if (res_locked(fh->dev,RESOURCE_VIDEO)) {
up(&fh->cap.lock); up(&fh->cap.lock);
...@@ -1263,6 +1315,29 @@ video_mmap(struct file *file, struct vm_area_struct * vma) ...@@ -1263,6 +1315,29 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
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, int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
struct v4l2_format *f) struct v4l2_format *f)
{ {
...@@ -1273,27 +1348,17 @@ int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1273,27 +1348,17 @@ int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
f->fmt.pix.height = fh->height; f->fmt.pix.height = fh->height;
f->fmt.pix.field = fh->cap.field; f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc; f->fmt.pix.pixelformat = fh->fmt->fourcc;
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline =
(fh->width*fh->height*fh->fmt->depth)/8; (f->fmt.pix.width * fh->fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0; return 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OVERLAY:
f->fmt.win = fh->win; f->fmt.win = fh->win;
return 0; return 0;
case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_CAPTURE:
{ saa7134_vbi_fmt(dev,f);
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 */;
return 0; return 0;
}
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1309,7 +1374,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1309,7 +1374,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
{ {
struct saa7134_format *fmt; struct saa7134_format *fmt;
enum v4l2_field field; enum v4l2_field field;
int maxw, maxh; unsigned int maxw, maxh;
fmt = format_by_fourcc(f->fmt.pix.pixelformat); fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (NULL == fmt) if (NULL == fmt)
...@@ -1336,12 +1401,18 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1336,12 +1401,18 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
} }
f->fmt.pix.field = field; 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) if (f->fmt.pix.width > maxw)
f->fmt.pix.width = maxw; f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh) if (f->fmt.pix.height > maxh)
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 = f->fmt.pix.sizeimage =
(fh->width * fh->height * fmt->depth)/8; f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0; return 0;
} }
...@@ -1350,6 +1421,9 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1350,6 +1421,9 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
if (0 != err) if (0 != err)
return err; return err;
return 0; return 0;
case V4L2_BUF_TYPE_VBI_CAPTURE:
saa7134_vbi_fmt(dev,f);
return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1397,6 +1471,9 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1397,6 +1471,9 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
up(&dev->lock); up(&dev->lock);
return 0; return 0;
break; break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
saa7134_vbi_fmt(dev,f);
return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1442,10 +1519,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1442,10 +1519,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD: case VIDIOC_ENUMSTD:
{ {
struct v4l2_standard *e = arg; struct v4l2_standard *e = arg;
int i; unsigned int i;
i = e->index; i = e->index;
if (i < 0 || i >= TVNORMS) if (i >= TVNORMS)
return -EINVAL; return -EINVAL;
err = v4l2_video_std_construct(e, tvnorms[e->index].id, err = v4l2_video_std_construct(e, tvnorms[e->index].id,
tvnorms[e->index].name); tvnorms[e->index].name);
...@@ -1464,7 +1541,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1464,7 +1541,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_STD: case VIDIOC_S_STD:
{ {
v4l2_std_id *id = arg; v4l2_std_id *id = arg;
int i; unsigned int i;
for(i = 0; i < TVNORMS; i++) for(i = 0; i < TVNORMS; i++)
if (*id & tvnorms[i].id) if (*id & tvnorms[i].id)
...@@ -1489,7 +1566,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1489,7 +1566,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMINPUT: case VIDIOC_ENUMINPUT:
{ {
struct v4l2_input *i = arg; struct v4l2_input *i = arg;
int n; unsigned int n;
n = i->index; n = i->index;
if (n >= SAA7134_INPUT_MAX) if (n >= SAA7134_INPUT_MAX)
...@@ -1557,22 +1634,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1557,22 +1634,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2; V4L2_TUNER_CAP_LANG2;
t->rangehigh = 0xffffffffUL; t->rangehigh = 0xffffffffUL;
t->rxsubchans = -1; t->rxsubchans = saa7134_tvaudio_getstereo(dev);
if (dev->tvaudio) t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);
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
} }
if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03)) if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))
t->signal = 0xffff; t->signal = 0xffff;
...@@ -1655,14 +1718,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1655,14 +1718,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{ {
struct v4l2_fmtdesc *f = arg; struct v4l2_fmtdesc *f = arg;
enum v4l2_buf_type type; enum v4l2_buf_type type;
int index; unsigned int index;
index = f->index; index = f->index;
type = f->type; type = f->type;
switch (type) { switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (index < 0 || index >= FORMATS) if (index >= FORMATS)
return -EINVAL; return -EINVAL;
if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY && if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY &&
formats[index].planar) formats[index].planar)
...@@ -1760,21 +1823,23 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1760,21 +1823,23 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{ {
struct video_mbuf *mbuf = arg; struct video_mbuf *mbuf = arg;
struct videobuf_queue *q; struct videobuf_queue *q;
int i; struct v4l2_requestbuffers req;
unsigned int i;
q = saa7134_queue(fh); q = saa7134_queue(fh);
down(&q->lock); memset(&req,0,sizeof(req));
err = videobuf_mmap_setup(file,q,gbuffers,gbufsize); req.type = q->type;
if (err < 0) { req.count = gbuffers;
up(&q->lock); err = videobuf_reqbufs(file,q,&req);
if (err < 0)
return err; return err;
}
memset(mbuf,0,sizeof(*mbuf)); memset(mbuf,0,sizeof(*mbuf));
mbuf->frames = gbuffers; mbuf->frames = req.count;
mbuf->size = gbuffers * gbufsize; mbuf->size = 0;
for (i = 0; i < gbuffers; i++) for (i = 0; i < mbuf->frames; i++) {
mbuf->offsets[i] = i * gbufsize; mbuf->offsets[i] = q->bufs[i]->boff;
up(&q->lock); mbuf->size += q->bufs[i]->bsize;
}
return 0; return 0;
} }
case VIDIOC_REQBUFS: case VIDIOC_REQBUFS:
...@@ -1800,7 +1865,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1800,7 +1865,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_STREAMOFF: case VIDIOC_STREAMOFF:
{ {
int res = saa7134_resource(fh); int res = saa7134_resource(fh);
err = videobuf_streamoff(file,saa7134_queue(fh)); err = videobuf_streamoff(file,saa7134_queue(fh));
if (err < 0)
return err;
res_free(dev,fh,res); res_free(dev,fh,res);
return 0; return 0;
} }
...@@ -1879,9 +1947,16 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, ...@@ -1879,9 +1947,16 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
strcpy(a->name,"Radio"); strcpy(a->name,"Radio");
return 0; return 0;
} }
case VIDIOC_G_STD:
{
v4l2_std_id *id = arg;
*id = 0;
return 0;
}
case VIDIOC_S_AUDIO: case VIDIOC_S_AUDIO:
case VIDIOC_S_TUNER: case VIDIOC_S_TUNER:
case VIDIOC_S_INPUT: case VIDIOC_S_INPUT:
case VIDIOC_S_STD:
return 0; return 0;
case VIDIOC_QUERYCTRL: case VIDIOC_QUERYCTRL:
...@@ -2055,7 +2130,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) ...@@ -2055,7 +2130,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
if (V4L2_FIELD_HAS_BOTH(field)) { if (V4L2_FIELD_HAS_BOTH(field)) {
/* make sure we have seen both fields */ /* make sure we have seen both fields */
if ((status & 0x10) == 0x10) { if ((status & 0x10) == 0x00) {
dev->video_q.curr->top_seen = 1; dev->video_q.curr->top_seen = 1;
goto done; goto done;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <media/audiochip.h> #include <media/audiochip.h>
#include <media/id.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 #ifndef TRUE
# define TRUE (1==1) # define TRUE (1==1)
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#ifndef FALSE #ifndef FALSE
# define FALSE (1==0) # define FALSE (1==0)
#endif #endif
#define UNSET (-1U)
/* 2.4 / 2.5 driver compatibility stuff */ /* 2.4 / 2.5 driver compatibility stuff */
...@@ -67,50 +68,52 @@ enum saa7134_video_out { ...@@ -67,50 +68,52 @@ enum saa7134_video_out {
struct saa7134_tvnorm { struct saa7134_tvnorm {
char *name; char *name;
v4l2_std_id id; v4l2_std_id id;
int width; unsigned int width;
int height; unsigned int height;
/* video decoder */ /* video decoder */
int sync_control; unsigned int sync_control;
int luma_control; unsigned int luma_control;
int chroma_ctrl1; unsigned int chroma_ctrl1;
int chroma_gain; unsigned int chroma_gain;
int chroma_ctrl2; unsigned int chroma_ctrl2;
unsigned int vgate_misc;
/* video scaler */ /* video scaler */
int h_start; unsigned int h_start;
int h_stop; unsigned int h_stop;
int video_v_start; unsigned int video_v_start;
int video_v_stop; unsigned int video_v_stop;
int vbi_v_start; unsigned int vbi_v_start;
int vbi_v_stop; unsigned int vbi_v_stop;
unsigned int src_timing;
}; };
struct saa7134_tvaudio { struct saa7134_tvaudio {
char *name; char *name;
int std; v4l2_std_id std;
enum saa7134_tvaudio_mode mode; enum saa7134_tvaudio_mode mode;
int carr1; int carr1;
int carr2; int carr2;
}; };
struct saa7134_format { struct saa7134_format {
char *name; char *name;
int fourcc; unsigned int fourcc;
int depth; unsigned int depth;
int pm; unsigned int pm;
int vshift; /* vertical downsampling (for planar yuv) */ unsigned int vshift; /* vertical downsampling (for planar yuv) */
int hshift; /* horizontal downsampling (for planar yuv) */ unsigned int hshift; /* horizontal downsampling (for planar yuv) */
int bswap:1; unsigned int bswap:1;
int wswap:1; unsigned int wswap:1;
int yuv:1; unsigned int yuv:1;
int planar:1; unsigned int planar:1;
}; };
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* card configuration */ /* card configuration */
#define SAA7134_BOARD_NOAUTO -1 #define SAA7134_BOARD_NOAUTO UNSET
#define SAA7134_BOARD_UNKNOWN 0 #define SAA7134_BOARD_UNKNOWN 0
#define SAA7134_BOARD_PROTEUS_PRO 1 #define SAA7134_BOARD_PROTEUS_PRO 1
#define SAA7134_BOARD_FLYVIDEO3000 2 #define SAA7134_BOARD_FLYVIDEO3000 2
...@@ -124,38 +127,40 @@ struct saa7134_format { ...@@ -124,38 +127,40 @@ struct saa7134_format {
#define SAA7134_BOARD_KWORLD 10 #define SAA7134_BOARD_KWORLD 10
#define SAA7134_BOARD_CINERGY600 11 #define SAA7134_BOARD_CINERGY600 11
#define SAA7134_BOARD_MD7134 12 #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 #define SAA7134_INPUT_MAX 8
struct saa7134_input { struct saa7134_input {
char *name; char *name;
int vmux; unsigned int vmux;
enum saa7134_audio_in amux; enum saa7134_audio_in amux;
int gpio; unsigned int gpio;
int tv:1; unsigned int tv:1;
}; };
struct saa7134_board { struct saa7134_board {
char *name; char *name;
int audio_clock; unsigned int audio_clock;
/* input switching */ /* input switching */
int gpiomask; unsigned int gpiomask;
struct saa7134_input inputs[SAA7134_INPUT_MAX]; struct saa7134_input inputs[SAA7134_INPUT_MAX];
struct saa7134_input radio; struct saa7134_input radio;
struct saa7134_input mute; struct saa7134_input mute;
/* peripheral I/O */ /* peripheral I/O */
int i2s_rate; unsigned int i2s_rate;
int has_ts; unsigned int has_ts;
enum saa7134_video_out video_out; enum saa7134_video_out video_out;
/* i2c chip info */ /* i2c chip info */
int tuner_type; unsigned int tuner_type;
int need_tda9887:1; 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_radio(dev) (NULL != saa7134_boards[dev->board].radio.name)
#define card_has_ts(dev) (saa7134_boards[dev->board].has_ts) #define card_has_ts(dev) (saa7134_boards[dev->board].has_ts)
#define card(dev) (saa7134_boards[dev->board]) #define card(dev) (saa7134_boards[dev->board])
...@@ -189,9 +194,9 @@ struct saa7134_thread { ...@@ -189,9 +194,9 @@ struct saa7134_thread {
struct task_struct *task; struct task_struct *task;
wait_queue_head_t wq; wait_queue_head_t wq;
struct semaphore *notify; struct semaphore *notify;
int exit; unsigned int exit;
int scan1; unsigned int scan1;
int scan2; unsigned int scan2;
}; };
/* buffer for one video/vbi/ts frame */ /* buffer for one video/vbi/ts frame */
...@@ -201,7 +206,7 @@ struct saa7134_buf { ...@@ -201,7 +206,7 @@ struct saa7134_buf {
/* saa7134 specific */ /* saa7134 specific */
struct saa7134_format *fmt; struct saa7134_format *fmt;
int top_seen; unsigned int top_seen;
int (*activate)(struct saa7134_dev *dev, int (*activate)(struct saa7134_dev *dev,
struct saa7134_buf *buf, struct saa7134_buf *buf,
struct saa7134_buf *next); struct saa7134_buf *next);
...@@ -215,22 +220,23 @@ struct saa7134_dmaqueue { ...@@ -215,22 +220,23 @@ struct saa7134_dmaqueue {
struct saa7134_buf *curr; struct saa7134_buf *curr;
struct list_head queue; struct list_head queue;
struct timer_list timeout; struct timer_list timeout;
unsigned int need_two;
}; };
/* video filehandle status */ /* video filehandle status */
struct saa7134_fh { struct saa7134_fh {
struct saa7134_dev *dev; struct saa7134_dev *dev;
int radio; unsigned int radio;
enum v4l2_buf_type type; enum v4l2_buf_type type;
struct v4l2_window win; struct v4l2_window win;
struct v4l2_clip clips[8]; struct v4l2_clip clips[8];
int nclips; unsigned int nclips;
int resources; unsigned int resources;
/* video capture */ /* video capture */
struct saa7134_format *fmt; struct saa7134_format *fmt;
int width,height; unsigned int width,height;
struct videobuf_queue cap; struct videobuf_queue cap;
struct saa7134_pgtable pt_cap; struct saa7134_pgtable pt_cap;
...@@ -241,7 +247,7 @@ struct saa7134_fh { ...@@ -241,7 +247,7 @@ struct saa7134_fh {
/* TS status */ /* TS status */
struct saa7134_ts { struct saa7134_ts {
int users; unsigned int users;
/* TS capture */ /* TS capture */
struct videobuf_queue ts; struct videobuf_queue ts;
...@@ -253,28 +259,28 @@ struct saa7134_oss { ...@@ -253,28 +259,28 @@ struct saa7134_oss {
struct semaphore lock; struct semaphore lock;
int minor_mixer; int minor_mixer;
int minor_dsp; int minor_dsp;
int users_dsp; unsigned int users_dsp;
/* mixer */ /* mixer */
enum saa7134_audio_in input; enum saa7134_audio_in input;
int count; unsigned int count;
int line1; unsigned int line1;
int line2; unsigned int line2;
/* dsp */ /* dsp */
int afmt; unsigned int afmt;
int rate; unsigned int rate;
int channels; unsigned int channels;
int recording; unsigned int recording;
int blocks; unsigned int blocks;
int blksize; unsigned int blksize;
int bufsize; unsigned int bufsize;
struct saa7134_pgtable pt; struct saa7134_pgtable pt;
struct videobuf_dmabuf dma; struct videobuf_dmabuf dma;
wait_queue_head_t wq; wait_queue_head_t wq;
int dma_blk; unsigned int dma_blk;
int read_offset; unsigned int read_offset;
int read_count; unsigned int read_count;
}; };
/* global device status */ /* global device status */
...@@ -284,7 +290,7 @@ struct saa7134_dev { ...@@ -284,7 +290,7 @@ struct saa7134_dev {
spinlock_t slock; spinlock_t slock;
/* various device info */ /* various device info */
int resources; unsigned int resources;
struct video_device video_dev; struct video_device video_dev;
struct video_device ts_dev; struct video_device ts_dev;
struct video_device radio_dev; struct video_device radio_dev;
...@@ -300,8 +306,8 @@ struct saa7134_dev { ...@@ -300,8 +306,8 @@ struct saa7134_dev {
__u8 *bmmio; __u8 *bmmio;
/* config info */ /* config info */
int board; unsigned int board;
int tuner_type; unsigned int tuner_type;
/* i2c i/o */ /* i2c i/o */
struct i2c_adapter i2c_adap; struct i2c_adapter i2c_adap;
...@@ -311,19 +317,19 @@ struct saa7134_dev { ...@@ -311,19 +317,19 @@ struct saa7134_dev {
/* video overlay */ /* video overlay */
struct v4l2_framebuffer ovbuf; struct v4l2_framebuffer ovbuf;
struct saa7134_format *ovfmt; struct saa7134_format *ovfmt;
int ovenable; unsigned int ovenable;
enum v4l2_field ovfield; enum v4l2_field ovfield;
/* video+ts+vbi capture */ /* video+ts+vbi capture */
struct saa7134_dmaqueue video_q; struct saa7134_dmaqueue video_q;
struct saa7134_dmaqueue ts_q; struct saa7134_dmaqueue ts_q;
struct saa7134_dmaqueue vbi_q; struct saa7134_dmaqueue vbi_q;
int vbi_fieldcount; unsigned int vbi_fieldcount;
/* various v4l controls */ /* various v4l controls */
struct saa7134_tvnorm *tvnorm; /* video */ struct saa7134_tvnorm *tvnorm; /* video */
struct saa7134_tvaudio *tvaudio; struct saa7134_tvaudio *tvaudio;
int ctl_input; unsigned int ctl_input;
int ctl_bright; int ctl_bright;
int ctl_contrast; int ctl_contrast;
int ctl_hue; int ctl_hue;
...@@ -337,11 +343,12 @@ struct saa7134_dev { ...@@ -337,11 +343,12 @@ struct saa7134_dev {
int ctl_y_even; int ctl_y_even;
/* other global state info */ /* other global state info */
int automute; unsigned int automute;
struct saa7134_thread thread; struct saa7134_thread thread;
struct saa7134_input *input; struct saa7134_input *input;
struct saa7134_input *hw_input; struct saa7134_input *hw_input;
int hw_mute; unsigned int hw_mute;
int last_carrier;
}; };
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
...@@ -362,12 +369,13 @@ struct saa7134_dev { ...@@ -362,12 +369,13 @@ struct saa7134_dev {
#define saa_setb(reg,bit) saa_andorb((reg),(bit),(bit)) #define saa_setb(reg,bit) saa_andorb((reg),(bit),(bit))
#define saa_clearb(reg,bit) saa_andorb((reg),(bit),0) #define saa_clearb(reg,bit) saa_andorb((reg),(bit),0)
#define saa_wait(d) { if (need_resched()) schedule(); else udelay(d);}
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* saa7134-core.c */ /* saa7134-core.c */
extern struct list_head saa7134_devlist; 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_print_ioctl(char *name, unsigned int cmd);
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
...@@ -376,18 +384,18 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); ...@@ -376,18 +384,18 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt); int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
int saa7134_pgtable_build(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, struct scatterlist *list, unsigned int length,
int startpage); unsigned int startpage);
void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt); 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); int saa7134_buffer_startpage(struct saa7134_buf *buf);
unsigned long saa7134_buffer_base(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, int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
struct saa7134_buf *buf); struct saa7134_buf *buf);
void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, 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_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data); void saa7134_buffer_timeout(unsigned long data);
void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf); void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf);
...@@ -398,9 +406,11 @@ int saa7134_set_dmabits(struct saa7134_dev *dev); ...@@ -398,9 +406,11 @@ int saa7134_set_dmabits(struct saa7134_dev *dev);
/* saa7134-cards.c */ /* saa7134-cards.c */
extern struct saa7134_board saa7134_boards[]; 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 struct pci_device_id __devinitdata saa7134_pci_tbl[];
extern int saa7134_board_init(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* saa7134-i2c.c */ /* saa7134-i2c.c */
...@@ -449,17 +459,19 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status); ...@@ -449,17 +459,19 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status);
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* saa7134-tvaudio.c */ /* saa7134-tvaudio.c */
int saa7134_tvaudio_rx2mode(u32 rx);
void saa7134_tvaudio_setmute(struct saa7134_dev *dev); void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
void saa7134_tvaudio_setinput(struct saa7134_dev *dev, void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
struct saa7134_input *in); struct saa7134_input *in);
void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level); void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
int saa7134_tvaudio_getstereo(struct saa7134_dev *dev, int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
struct saa7134_tvaudio *audio);
int saa7134_tvaudio_init(struct saa7134_dev *dev); int saa7134_tvaudio_init(struct saa7134_dev *dev);
int saa7134_tvaudio_fini(struct saa7134_dev *dev); int saa7134_tvaudio_fini(struct saa7134_dev *dev);
int saa7134_tvaudio_do_scan(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 */ /* saa7134-oss.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment