diff options
Diffstat (limited to 'linux/drivers/media/video/saa7134/saa7134-tvaudio.c')
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-tvaudio.c | 147 |
1 files changed, 84 insertions, 63 deletions
diff --git a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c index a300717ea..c5950ba28 100644 --- a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -37,10 +37,6 @@ static unsigned int audio_debug = 0; MODULE_PARM(audio_debug,"i"); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); -static unsigned int audio_carrier = 0; -MODULE_PARM(audio_carrier,"i"); -MODULE_PARM_DESC(audio_carrier,"audio carrier location"); - static unsigned int audio_ddep = 0; MODULE_PARM(audio_ddep,"i"); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); @@ -67,6 +63,30 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with /* ------------------------------------------------------------------ */ /* saa7134 code */ +static struct mainscan { + char *name; + v4l2_std_id std; + int carr; +} mainscan[] = { + { + .name = "M", + .std = V4L2_STD_NTSC | V4L2_STD_PAL_M, + .carr = 4500, + },{ + .name = "BG", + .std = V4L2_STD_PAL_BG, + .carr = 5500, + },{ + .name = "I", + .std = V4L2_STD_PAL_I, + .carr = 6000, + },{ + .name = "DKL", + .std = V4L2_STD_PAL_DK | V4L2_STD_SECAM, + .carr = 6500, + } +}; + static struct saa7134_tvaudio tvaudio[] = { { .name = "PAL-B/G FM-stereo", @@ -314,15 +334,15 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) return dev->thread.scan1 != dev->thread.scan2; } -static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier) +static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) { __s32 left,right,value; if (audio_debug > 1) { int i; - dprintk("debug %d:",carrier); + dprintk("debug %d:",scan->carr); for (i = -150; i <= 150; i += 30) { - tvaudio_setcarrier(dev,carrier+i,carrier+i); + tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i); saa_readl(SAA7134_LEVEL_READOUT1 >> 2); if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) return -1; @@ -334,24 +354,31 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier) } 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); + + if (dev->tvnorm->id & scan->std) { + tvaudio_setcarrier(dev,scan->carr-90,scan->carr-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,scan->carr+90,scan->carr+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 [%4s] => dc is %5d [%d/%d]\n", + scan->carr / 1000, scan->carr % 1000, + scan->name, value, left, right); + } else { + value = 0; + dprintk("skipping %d.%03d MHz [%4s]\n", + scan->carr / 1000, scan->carr % 1000, scan->name); + } return value; } @@ -460,16 +487,10 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au static int tvaudio_thread(void *data) { -#define MAX_SCAN 4 - static const int carr_pal[MAX_SCAN] = { 5500, 6000, 6500 }; - static const int carr_ntsc[MAX_SCAN] = { 4500 }; - static const int carr_secam[MAX_SCAN] = { 6500 }; - static const int carr_default[MAX_SCAN] = { 4500, 5500, 6000, 6500 }; struct saa7134_dev *dev = data; - const int *carr_scan; - int carr_vals[4]; - unsigned int i, audio, retries; - int max1,max2,carrier,rx,mode,lastmode; + int carr_vals[ARRAY_SIZE(mainscan)]; + unsigned int i, audio, nscan; + int max1,max2,carrier,rx,mode,lastmode,default_carrier; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61) lock_kernel(); @@ -498,33 +519,37 @@ static int tvaudio_thread(void *data) if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY)) goto restart; - /* find the main carrier */ - carr_scan = carr_default; - if (dev->tvnorm->id & V4L2_STD_PAL) - carr_scan = carr_pal; - if (dev->tvnorm->id & V4L2_STD_NTSC) - carr_scan = carr_ntsc; - if (dev->tvnorm->id & V4L2_STD_SECAM) - carr_scan = carr_secam; - saa_writeb(SAA7134_MONITOR_SELECT,0x00); - tvaudio_setmode(dev,&tvaudio[0],NULL); - + max1 = 0; + max2 = 0; + nscan = 0; carrier = 0; - for (retries = 3; retries > 0 && 0 == carrier; retries--) { - for (i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) - continue; - carr_vals[i] = tvaudio_checkcarrier(dev,carr_scan[i]); + default_carrier = 0; + for (i = 0; i < ARRAY_SIZE(mainscan); i++) { + if (!(dev->tvnorm->id & mainscan[i].std)) + continue; + if (!default_carrier) + default_carrier = mainscan[i].carr; + nscan++; + } + + if (1 == nscan) { + /* only one candidate -- skip scan ;) */ + max1 = 12345; + carrier = default_carrier; + } else { + /* scan for the main carrier */ + saa_writeb(SAA7134_MONITOR_SELECT,0x00); + tvaudio_setmode(dev,&tvaudio[0],NULL); + for (i = 0; i < ARRAY_SIZE(mainscan); i++) { + carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i); if (dev->thread.scan1 != dev->thread.scan2) goto restart; } - for (max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) - continue; + for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) { if (max1 < carr_vals[i]) { max2 = max1; max1 = carr_vals[i]; - carrier = carr_scan[i]; + carrier = mainscan[i].carr; } else if (max2 < carr_vals[i]) { max2 = carr_vals[i]; } @@ -537,21 +562,17 @@ static int tvaudio_thread(void *data) 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 { - /* no carrier + no fallback -- try first in list */ - carrier = carr_scan[0]; + /* no carrier + no fallback -- use default */ + carrier = default_carrier; printk(KERN_WARNING "%s/audio: audio carrier scan failed, " "using %d.%03d MHz [default]\n", dev->name, carrier/1000, carrier%1000); @@ -564,7 +585,7 @@ static int tvaudio_thread(void *data) /* find the exact tv audio norm */ for (audio = UNSET, i = 0; i < TVAUDIO; i++) { if (dev->tvnorm->id != UNSET && - dev->tvnorm->id != tvaudio[i].std) + !(dev->tvnorm->id & tvaudio[i].std)) continue; if (tvaudio[i].carr1 != carrier) continue; |