X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fsaa7134%2Fsaa7134-tvaudio.c;h=dd759d6d8d25c88a831f4b0a9689d714222717fe;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=a896cd83dea50ad372189027693940d1e64f2919;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index a896cd83d..dd759d6d8 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -1,4 +1,5 @@ /* + * * device driver for philips saa7134 based TV cards * tv audio decoder (fm stereo, nicam, ...) * @@ -22,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -34,22 +36,18 @@ /* ------------------------------------------------------------------ */ static unsigned int audio_debug = 0; -MODULE_PARM(audio_debug,"i"); +module_param(audio_debug, int, 0644); 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_param(audio_ddep, int, 0644); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); static int audio_clock_override = UNSET; -MODULE_PARM(audio_clock_override, "i"); +module_param(audio_clock_override, int, 0644); static int audio_clock_tweak = 0; -MODULE_PARM(audio_clock_tweak, "i"); +module_param(audio_clock_tweak, int, 0644); MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); #define dprintk(fmt, arg...) if (audio_debug) \ @@ -60,80 +58,105 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with #define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \ dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg))) -#define SCAN_INITIAL_DELAY (HZ) -#define SCAN_SAMPLE_DELAY (HZ/5) -#define SCAN_SUBCARRIER_DELAY (HZ*2) +/* msecs */ +#define SCAN_INITIAL_DELAY 1000 +#define SCAN_SAMPLE_DELAY 200 +#define SCAN_SUBCARRIER_DELAY 2000 /* ------------------------------------------------------------------ */ /* saa7134 code */ +static struct mainscan { + char *name; + v4l2_std_id std; + int carr; +} mainscan[] = { + { + .name = "MN", + .std = V4L2_STD_MN, + .carr = 4500, + },{ + .name = "BGH", + .std = V4L2_STD_B | V4L2_STD_GH, + .carr = 5500, + },{ + .name = "I", + .std = V4L2_STD_PAL_I, + .carr = 6000, + },{ + .name = "DKL", + .std = V4L2_STD_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC, + .carr = 6500, + } +}; + static struct saa7134_tvaudio tvaudio[] = { { .name = "PAL-B/G FM-stereo", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_BG, .mode = TVAUDIO_FM_BG_STEREO, .carr1 = 5500, .carr2 = 5742, },{ .name = "PAL-D/K1 FM-stereo", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_DK, .carr1 = 6500, .carr2 = 6258, .mode = TVAUDIO_FM_BG_STEREO, },{ .name = "PAL-D/K2 FM-stereo", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_DK, .carr1 = 6500, .carr2 = 6742, .mode = TVAUDIO_FM_BG_STEREO, },{ .name = "PAL-D/K3 FM-stereo", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_DK, .carr1 = 6500, .carr2 = 5742, .mode = TVAUDIO_FM_BG_STEREO, },{ .name = "PAL-B/G NICAM", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_BG, .carr1 = 5500, .carr2 = 5850, .mode = TVAUDIO_NICAM_FM, },{ .name = "PAL-I NICAM", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_I, .carr1 = 6000, .carr2 = 6552, .mode = TVAUDIO_NICAM_FM, },{ .name = "PAL-D/K NICAM", - .std = V4L2_STD_PAL, + .std = V4L2_STD_PAL_DK, .carr1 = 6500, .carr2 = 5850, .mode = TVAUDIO_NICAM_FM, },{ .name = "SECAM-L NICAM", - .std = V4L2_STD_SECAM, + .std = V4L2_STD_SECAM_L, .carr1 = 6500, .carr2 = 5850, .mode = TVAUDIO_NICAM_AM, },{ - .name = "SECAM-D/K", - .std = V4L2_STD_SECAM, + .name = "SECAM-D/K NICAM", + .std = V4L2_STD_SECAM_DK, .carr1 = 6500, - .carr2 = -1, - .mode = TVAUDIO_FM_MONO, - },{ - .name = "NTSC-M", - .std = V4L2_STD_NTSC, - .carr1 = 4500, - .carr2 = -1, - .mode = TVAUDIO_FM_MONO, + .carr2 = 5850, + .mode = TVAUDIO_NICAM_FM, },{ .name = "NTSC-A2 FM-stereo", .std = V4L2_STD_NTSC, .carr1 = 4500, .carr2 = 4724, .mode = TVAUDIO_FM_K_STEREO, + },{ + .name = "NTSC-M", + .std = V4L2_STD_NTSC, + .carr1 = 4500, + .carr2 = -1, + .mode = TVAUDIO_FM_MONO, } }; #define TVAUDIO (sizeof(tvaudio)/sizeof(struct saa7134_tvaudio)) @@ -145,7 +168,7 @@ static void tvaudio_init(struct saa7134_dev *dev) int clock = saa7134_boards[dev->board].audio_clock; if (UNSET != audio_clock_override) - clock = audio_clock_override; + clock = audio_clock_override; /* init all audio registers */ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x00); @@ -157,6 +180,7 @@ static void tvaudio_init(struct saa7134_dev *dev) saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); + /* frame locked audio is mandatory for NICAM */ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01); saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); @@ -183,6 +207,10 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev, saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary)); } +#define SAA7134_MUTE_MASK 0xbb +#define SAA7134_MUTE_ANALOG 0x04 +#define SAA7134_MUTE_I2S 0x40 + static void mute_input_7134(struct saa7134_dev *dev) { unsigned int mute; @@ -194,14 +222,17 @@ static void mute_input_7134(struct saa7134_dev *dev) in = dev->input; mute = (dev->ctl_mute || (dev->automute && (&card(dev).radio) != in)); - if (PCI_DEVICE_ID_PHILIPS_SAA7130 == dev->pci->device && - card(dev).mute.name) { - /* 7130 - we'll mute using some unconnected audio input */ + if (card(dev).mute.name) { + /* + * 7130 - we'll mute using some unconnected audio input + * 7134 - we'll probably should switch external mux with gpio + */ if (mute) in = &card(dev).mute; } + if (dev->hw_mute == mute && - dev->hw_input == in) { + dev->hw_input == in) { dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", mute,in->name); return; @@ -214,21 +245,32 @@ static void mute_input_7134(struct saa7134_dev *dev) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) /* 7134 mute */ - saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb); + saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? + SAA7134_MUTE_MASK | + SAA7134_MUTE_ANALOG | + SAA7134_MUTE_I2S : + SAA7134_MUTE_MASK); /* switch internal audio mux */ switch (in->amux) { - case TV: ausel=0xc0; ics=0x00; ocs=0x02; break; - case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break; - case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break; + case TV: ausel=0xc0; ics=0x00; ocs=0x02; break; + case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break; + case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break; + case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break; } saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs); + // for oss, we need to change the clock configuration + if (in->amux == TV) + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); + else + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x01); /* switch gpio-connected external audio mux */ if (0 == card(dev).gpiomask) return; + mask = card(dev).gpiomask; saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); @@ -261,7 +303,7 @@ static void tvaudio_setmode(struct saa7134_dev *dev, saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD1, (acpf & 0x00ff00) >> 8); saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD2, (acpf & 0x030000) >> 16); tvaudio_setcarrier(dev,audio->carr1,audio->carr2); - + switch (audio->mode) { case TVAUDIO_FM_MONO: case TVAUDIO_FM_BG_STEREO: @@ -301,28 +343,30 @@ static void tvaudio_setmode(struct saa7134_dev *dev, static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) { DECLARE_WAITQUEUE(wait, current); - + add_wait_queue(&dev->thread.wq, &wait); if (dev->thread.scan1 == dev->thread.scan2 && !dev->thread.shutdown) { - set_current_state(TASK_INTERRUPTIBLE); - if (timeout < 0) + if (timeout < 0) { + set_current_state(TASK_INTERRUPTIBLE); schedule(); - else - schedule_timeout(timeout); + } else { + schedule_timeout_interruptible + (msecs_to_jiffies(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) +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,56 +378,46 @@ 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; } -#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, nicam_status; int retval = -1; - + switch (audio->mode) { case TVAUDIO_FM_MONO: return V4L2_TUNER_SUB_MONO; case TVAUDIO_FM_K_STEREO: case TVAUDIO_FM_BG_STEREO: idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5; + dprintk("getstereo: fm/stereo: idp=0x%x\n",idp); if (0x03 == (idp & 0x03)) retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; else if (0x05 == (idp & 0x05)) @@ -396,17 +430,24 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au break; case TVAUDIO_NICAM_FM: case TVAUDIO_NICAM_AM: - nicam = saa_readb(SAA7134_NICAM_STATUS); - switch (nicam & 0x0b) { - case 0x08: - retval = V4L2_TUNER_SUB_MONO; - break; - case 0x09: - retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - break; - case 0x0a: - retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - break; + nicam = saa_readb(SAA7134_AUDIO_STATUS); + dprintk("getstereo: nicam=0x%x\n",nicam); + if (nicam & 0x1) { + nicam_status = saa_readb(SAA7134_NICAM_STATUS); + dprintk("getstereo: nicam_status=0x%x\n", nicam_status); + + switch (nicam_status & 0x03) { + case 0x01: + retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + break; + case 0x02: + retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + break; + default: + retval = V4L2_TUNER_SUB_MONO; + } + } else { + /* No nicam detected */ } break; } @@ -427,12 +468,14 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au [ V4L2_TUNER_MODE_STEREO ] = "stereo", [ V4L2_TUNER_MODE_LANG1 ] = "lang1", [ V4L2_TUNER_MODE_LANG2 ] = "lang2", + [ V4L2_TUNER_MODE_LANG1_LANG2 ] = "lang1+lang2", }; static u32 fm[] = { [ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */ [ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */ [ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */ [ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */ + [ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80, /* auto */ }; u32 reg; @@ -442,15 +485,15 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au break; case TVAUDIO_FM_K_STEREO: case TVAUDIO_FM_BG_STEREO: + case TVAUDIO_NICAM_AM: + case TVAUDIO_NICAM_FM: dprintk("setstereo [fm] => %s\n", name[ mode % ARRAY_SIZE(name) ]); reg = fm[ mode % ARRAY_SIZE(fm) ]; saa_writeb(SAA7134_FM_DEMATRIX, reg); break; case TVAUDIO_FM_SAT_STEREO: - case TVAUDIO_NICAM_AM: - case TVAUDIO_NICAM_FM: - /* FIXME */ + /* Not implemented */ break; } return 0; @@ -458,16 +501,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; - 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; daemonize("%s", dev->name); allow_signal(SIGTERM); @@ -481,39 +518,49 @@ static int tvaudio_thread(void *data) dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1); dev->tvaudio = NULL; tvaudio_init(dev); - dev->automute = 1; + if (dev->ctl_automute) + dev->automute = 1; mute_input_7134(dev); /* give the tuner some time */ 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); - for (i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) + max1 = 0; + max2 = 0; + nscan = 0; + carrier = 0; + default_carrier = 0; + for (i = 0; i < ARRAY_SIZE(mainscan); i++) { + if (!(dev->tvnorm->id & mainscan[i].std)) continue; - carr_vals[i] = tvaudio_checkcarrier(dev,carr_scan[i]); - if (dev->thread.scan1 != dev->thread.scan2) - goto restart; + if (!default_carrier) + default_carrier = mainscan[i].carr; + nscan++; } - for (carrier = 0, max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) - continue; - if (max1 < carr_vals[i]) { - max2 = max1; - max1 = carr_vals[i]; - carrier = carr_scan[i]; - } else if (max2 < carr_vals[i]) { - max2 = carr_vals[i]; + + if (1 == nscan) { + /* only one candidate -- skip scan ;) */ + dprintk("only one main carrier candidate - skipping scan\n"); + 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 < ARRAY_SIZE(mainscan); i++) { + if (max1 < carr_vals[i]) { + max2 = max1; + max1 = carr_vals[i]; + carrier = mainscan[i].carr; + } else if (max2 < carr_vals[i]) { + max2 = carr_vals[i]; + } } } @@ -523,22 +570,18 @@ 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, " + dprintk(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]; - printk(KERN_WARNING "%s/audio: audio carrier scan failed, " + /* no carrier + no fallback -- use default */ + carrier = default_carrier; + dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " "using %d.%03d MHz [default]\n", dev->name, carrier/1000, carrier%1000); } @@ -546,15 +589,14 @@ static int tvaudio_thread(void *data) dev->automute = 0; saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00); saa7134_tvaudio_setmute(dev); - /* 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; - + /* Note: at least the primary carrier is right here */ if (UNSET == audio) audio = i; tvaudio_setmode(dev,&tvaudio[i],"trying"); @@ -569,12 +611,13 @@ static int tvaudio_thread(void *data) if (UNSET == audio) continue; tvaudio_setmode(dev,&tvaudio[audio],"using"); + tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO); dev->tvaudio = &tvaudio[audio]; lastmode = 42; for (;;) { - if (tvaudio_sleep(dev,5*HZ)) + if (tvaudio_sleep(dev,5000)) goto restart; if (dev->thread.shutdown || signal_pending(current)) break; @@ -613,7 +656,7 @@ static char *stdres[0x20] = { [0x09] = "D/K NICAM", [0x0a] = "L NICAM", [0x0b] = "I NICAM", - + [0x0c] = "M Korea", [0x0d] = "M BTSC ", [0x0e] = "M EIAJ", @@ -657,24 +700,6 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit) return 0; } -#if 0 -static int saa_dsp_readl(struct saa7134_dev *dev, int reg, u32 *value) -{ - int err; - - d2printk("dsp read reg 0x%x\n", reg<<2); - saa_readl(reg); - err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_RDB); - if (err < 0) - return err; - *value = saa_readl(reg); - d2printk("dsp read => 0x%06x\n", *value & 0xffffff); - err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_IDA); - if (err < 0) - return err; - return 0; -} -#endif int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value) { @@ -707,26 +732,65 @@ static int getstereo_7133(struct saa7134_dev *dev) static int mute_input_7133(struct saa7134_dev *dev) { u32 reg = 0; - + u32 xbarin, xbarout; + int mask; + struct saa7134_input *in; + + xbarin = 0x03; switch (dev->input->amux) { - case TV: reg = 0x02; break; - case LINE1: reg = 0x00; break; - case LINE2: reg = 0x01; break; + case TV: + reg = 0x02; + xbarin = 0; + break; + case LINE1: + reg = 0x00; + break; + case LINE2: + case LINE2_LEFT: + reg = 0x09; + break; } - if (dev->ctl_mute) + saa_dsp_writel(dev, 0x464 >> 2, xbarin); + if (dev->ctl_mute) { reg = 0x07; + xbarout = 0xbbbbbb; + } else + xbarout = 0xbbbb10; + saa_dsp_writel(dev, 0x46c >> 2, xbarout); + saa_writel(0x594 >> 2, reg); + + + /* switch gpio-connected external audio mux */ + if (0 != card(dev).gpiomask) { + mask = card(dev).gpiomask; + + if (card(dev).mute.name && dev->ctl_mute) + in = &card(dev).mute; + else + in = dev->input; + + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); + saa7134_track_gpio(dev,in->name); + } + return 0; } static int tvaudio_thread_ddep(void *data) { struct saa7134_dev *dev = data; - u32 value, norms; + u32 value, norms, clock; daemonize("%s", dev->name); allow_signal(SIGTERM); + clock = saa7134_boards[dev->board].audio_clock; + if (UNSET != audio_clock_override) + clock = audio_clock_override; + saa_writel(0x598 >> 2, clock); + /* unmute */ saa_dsp_writel(dev, 0x474 >> 2, 0x00); saa_dsp_writel(dev, 0x450 >> 2, 0x00); @@ -744,21 +808,27 @@ static int tvaudio_thread_ddep(void *data) /* insmod option override */ norms = (audio_ddep << 2) | 0x01; dprintk("ddep override: %s\n",stdres[audio_ddep]); - } else{ + } else if (&card(dev).radio == dev->input) { + dprintk("FM Radio\n"); + if (dev->tuner_type == TUNER_PHILIPS_TDA8290) { + norms = (0x11 << 2) | 0x01; + saa_dsp_writel(dev, 0x42c >> 2, 0x729555); + } else { + norms = (0x0f << 2) | 0x01; + } + } else { /* (let chip) scan for sound carrier */ norms = 0; - if (dev->tvnorm->id & V4L2_STD_PAL) { - dprintk("PAL scan\n"); - norms |= 0x2c; /* B/G + D/K + I */ - } - if (dev->tvnorm->id & V4L2_STD_NTSC) { - dprintk("NTSC scan\n"); - norms |= 0x40; /* M */ - } - if (dev->tvnorm->id & V4L2_STD_SECAM) { - dprintk("SECAM scan\n"); - norms |= 0x18; /* L + D/K */ - } + if (dev->tvnorm->id & (V4L2_STD_B | V4L2_STD_GH)) + norms |= 0x04; + if (dev->tvnorm->id & V4L2_STD_PAL_I) + norms |= 0x20; + if (dev->tvnorm->id & V4L2_STD_DK) + norms |= 0x08; + if (dev->tvnorm->id & V4L2_STD_MN) + norms |= 0x40; + if (dev->tvnorm->id & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) + norms |= 0x10; if (0 == norms) norms = 0x7c; /* all */ dprintk("scanning:%s%s%s%s%s\n", @@ -769,13 +839,15 @@ static int tvaudio_thread_ddep(void *data) (norms & 0x40) ? " M" : ""); } - /* quick & dirty -- to be fixed up later ... */ + /* kick automatic standard detection */ saa_dsp_writel(dev, 0x454 >> 2, 0); saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80); + + /* setup crossbars */ saa_dsp_writel(dev, 0x464 >> 2, 0x000000); saa_dsp_writel(dev, 0x470 >> 2, 0x101010); - if (tvaudio_sleep(dev,3*HZ)) + if (tvaudio_sleep(dev,3000)) goto restart; value = saa_readl(0x528 >> 2) & 0xffffff; @@ -795,12 +867,12 @@ static int tvaudio_thread_ddep(void *data) (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 " : ""); } @@ -812,10 +884,25 @@ static int tvaudio_thread_ddep(void *data) /* ------------------------------------------------------------------ */ /* common stuff + external entry points */ +static void saa7134_enable_i2s(struct saa7134_dev *dev) +{ + int i2s_format; + + if (!card_is_empress(dev)) + return; + i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01; + + /* enable I2S audio output for the mpeg encoder */ + saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); + saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format); + saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); + saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); +} + int saa7134_tvaudio_rx2mode(u32 rx) { u32 mode; - + mode = V4L2_TUNER_MODE_MONO; if (rx & V4L2_TUNER_SUB_STEREO) mode = V4L2_TUNER_MODE_STEREO; @@ -825,7 +912,7 @@ int saa7134_tvaudio_rx2mode(u32 rx) mode = V4L2_TUNER_MODE_LANG2; return mode; } - + void saa7134_tvaudio_setmute(struct saa7134_dev *dev) { switch (dev->pci->device) { @@ -854,6 +941,7 @@ void saa7134_tvaudio_setinput(struct saa7134_dev *dev, mute_input_7133(dev); break; } + saa7134_enable_i2s(dev); } void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level) @@ -889,17 +977,6 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) DECLARE_MUTEX_LOCKED(sem); int (*my_thread)(void *data) = NULL; - /* enable I2S audio output */ - if (saa7134_boards[dev->board].i2s_rate) { - int i2sform = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x00 : 0x01; - - /* enable I2S output */ - saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); - saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2sform); - saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); - saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); - } - switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: my_thread = tvaudio_thread; @@ -919,9 +996,10 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) if (dev->thread.pid < 0) printk(KERN_WARNING "%s: kernel_thread() failed\n", dev->name); - wake_up_interruptible(&dev->thread.wq); + saa7134_tvaudio_do_scan(dev); } + saa7134_enable_i2s(dev); return 0; } @@ -939,7 +1017,11 @@ int saa7134_tvaudio_fini(struct saa7134_dev *dev) int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) { - if (dev->thread.pid >= 0) { + if (dev->input->amux != TV) { + dprintk("sound IF not in use, skipping scan\n"); + dev->automute = 0; + saa7134_tvaudio_setmute(dev); + } else if (dev->thread.pid >= 0) { dev->thread.mode = UNSET; dev->thread.scan2++; wake_up_interruptible(&dev->thread.wq); @@ -950,9 +1032,13 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) return 0; } +EXPORT_SYMBOL(saa_dsp_writel); +EXPORT_SYMBOL(saa7134_tvaudio_setmute); + /* ----------------------------------------------------------- */ /* * Local variables: * c-basic-offset: 8 * End: */ +