⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 saa7134-tvaudio.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 2 页
字号:
		tvaudio_sleep(dev,-1);		if (dev->thread.shutdown || signal_pending(current))			goto done;	restart:		dev->thread.scan1 = dev->thread.scan2;		dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);		dev->tvaudio  = NULL;		tvaudio_init(dev);		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;		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;			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 < 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];				}			}		}		if (0 != carrier && max1 > 2000 && max1 > max2*3) {			/* found good carrier */			dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",				dev->tvnorm->name, carrier/1000, carrier%1000,				max1, max2);			dev->last_carrier = carrier;		} else if (0 != dev->last_carrier) {			/* no carrier -- try last detected one as fallback */			carrier = dev->last_carrier;			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 -- 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);		}		tvaudio_setcarrier(dev,carrier,carrier);		dev->automute = 0;		saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);		saa7134_tvaudio_setmute(dev);		/* find the exact tv audio norm */		for (audio = UNSET, i = 0; i < TVAUDIO; i++) {			if (dev->tvnorm->id != UNSET &&				!(dev->tvnorm->id & tvaudio[i].std))				continue;			if (tvaudio[i].carr1 != carrier)				continue;			if (UNSET == audio)				audio = i;			tvaudio_setmode(dev,&tvaudio[i],"trying");			if (tvaudio_sleep(dev,SCAN_SUBCARRIER_DELAY))				goto restart;			if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {				audio = i;				break;			}		}		saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);		if (UNSET == audio)			continue;		tvaudio_setmode(dev,&tvaudio[audio],"using");		tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);		dev->tvaudio = &tvaudio[audio];		lastmode = 42;		for (;;) {			if (tvaudio_sleep(dev,5000))				goto restart;			if (dev->thread.shutdown || signal_pending(current))				break;			if (UNSET == dev->thread.mode) {				rx = tvaudio_getstereo(dev,&tvaudio[i]);				mode = saa7134_tvaudio_rx2mode(rx);			} else {				mode = dev->thread.mode;			}			if (lastmode != mode) {				tvaudio_setstereo(dev,&tvaudio[audio],mode);				lastmode = mode;			}		}	} done:	complete_and_exit(&dev->thread.exit, 0);	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 32#define DSP_DELAY 16static 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 0static 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;}#endifint 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;	u32 xbarin, xbarout;	int mask;	struct saa7134_input *in;	/* Hac 0506 route OSS sound simultanously  */	xbarin = 0x03;	switch (dev->input->amux) {	case TV:		reg = 0x02;		xbarin = 0;		break;	case LINE1:		reg = 0x00;		break;	case LINE2:	case LINE2_LEFT:		reg = 0x09;		break;	}	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, clock;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)	lock_kernel();	daemonize();	sigfillset(&current->blocked);	sprintf(current->comm, "%s", dev->name);	unlock_kernel();#else	daemonize("%s", dev->name);	allow_signal(SIGTERM);#endif	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);	for (;;) {		tvaudio_sleep(dev,-1);		if (dev->thread.shutdown || signal_pending(current))			goto done;	restart:		dev->thread.scan1 = dev->thread.scan2;		dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);		if (audio_ddep >= 0x04 && audio_ddep <= 0x0e) {			/* insmod option override */			norms = (audio_ddep << 2) | 0x01;			dprintk("ddep override: %s\n",stdres[audio_ddep]);		} 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 (0 == norms)				norms = 0x7c; /* all */			dprintk("scanning:%s%s%s%s%s\n",				(norms & 0x04) ? " B/G"  : "",				(norms & 0x08) ? " D/K"  : "",				(norms & 0x10) ? " L/L'" : "",				(norms & 0x20) ? " I"    : "",				(norms & 0x40) ? " M"    : "");		}		/* 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,3000))			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:	complete_and_exit(&dev->thread.exit, 0);	return 0;}/* ------------------------------------------------------------------ *//* 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;	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;	}	saa7134_enable_i2s(dev);}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_init2(struct saa7134_dev *dev){	DECLARE_MUTEX_LOCKED(sem);	int (*my_thread)(void *data) = NULL;	switch (dev->pci->device) {	case PCI_DEVICE_ID_PHILIPS_SAA7134:		my_thread = tvaudio_thread;		break;	case PCI_DEVICE_ID_PHILIPS_SAA7133:	case PCI_DEVICE_ID_PHILIPS_SAA7135:		my_thread = tvaudio_thread_ddep;		break;	}	dev->thread.pid = -1;	if (my_thread) {		/* start tvaudio thread */		init_waitqueue_head(&dev->thread.wq);		init_completion(&dev->thread.exit);		dev->thread.pid = kernel_thread(my_thread,dev,0);		if (dev->thread.pid < 0)			printk(KERN_WARNING "%s: kernel_thread() failed\n",			       dev->name);		saa7134_tvaudio_do_scan(dev);	}	saa7134_enable_i2s(dev);	return 0;}int saa7134_tvaudio_fini(struct saa7134_dev *dev){	/* shutdown tvaudio thread */	if (dev->thread.pid >= 0) {		dev->thread.shutdown = 1;		wake_up_interruptible(&dev->thread.wq);		wait_for_completion(&dev->thread.exit);	}	saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */	return 0;}int saa7134_tvaudio_do_scan(struct saa7134_dev *dev){	if (dev->thread.pid >= 0) {		dev->thread.mode = UNSET;		dev->thread.scan2++;		wake_up_interruptible(&dev->thread.wq);	} else {		dev->automute = 0;		saa7134_tvaudio_setmute(dev);	}	return 0;}EXPORT_SYMBOL(saa_dsp_writel);/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -