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

📄 waveartist.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	waveartist_cmd2(devc, WACMD_INPUTSIZE, count);	devc->xfer_count = count;	devc->audio_mode |= PCM_ENABLE_INPUT;	spin_unlock_irqrestore(&waveartist_lock, flags);}static intwaveartist_ioctl(int dev, unsigned int cmd, caddr_t arg){	return -EINVAL;}static unsigned intwaveartist_get_speed(wavnc_port_info *portc){	unsigned int speed;	/*	 * program the speed, channels, bits	 */	if (portc->speed == 8000)		speed = 0x2E71;	else if (portc->speed == 11025)		speed = 0x4000;	else if (portc->speed == 22050)		speed = 0x8000;	else if (portc->speed == 44100)		speed = 0x0;	else {		/*		 * non-standard - just calculate		 */		speed = portc->speed << 16;		speed = (speed / 44100) & 65535;	}	return speed;}static unsigned intwaveartist_get_bits(wavnc_port_info *portc){	unsigned int bits;	if (portc->audio_format == AFMT_S16_LE)		bits = 1;	else if (portc->audio_format == AFMT_S8)		bits = 0;	else		bits = 2;	//default AFMT_U8	return bits;}static intwaveartist_prepare_for_input(int dev, int bsize, int bcount){	unsigned long	flags;	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;	unsigned int	speed, bits;	speed = waveartist_get_speed(portc);	bits  = waveartist_get_bits(portc);	spin_lock_irqsave(&waveartist_lock, flags);	if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))		printk(KERN_WARNING "waveartist: error setting the "		       "record format to %d\n", portc->audio_format);	if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels))		printk(KERN_WARNING "waveartist: error setting record "		       "to %d channels\n", portc->channels);	/*	 * write cmd SetSampleSpeedTimeConstant	 */	if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed))		printk(KERN_WARNING "waveartist: error setting the record "		       "speed to %dHz.\n", portc->speed);	if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1))		printk(KERN_WARNING "waveartist: error setting the record "		       "data path to 0x%X\n", 1);	if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))		printk(KERN_WARNING "waveartist: error setting the record "		       "format to %d\n", portc->audio_format);	devc->xfer_count = 0;	spin_unlock_irqrestore(&waveartist_lock, flags);	waveartist_halt_input(dev);	if (debug_flg & DEBUG_INTR) {		printk("WA CTLR reg: 0x%02X.\n",		       inb(devc->hw.io_base + CTLR));		printk("WA STAT reg: 0x%02X.\n",		       inb(devc->hw.io_base + STATR));		printk("WA IRQS reg: 0x%02X.\n",		       inb(devc->hw.io_base + IRQSTAT));	}	return 0;}static intwaveartist_prepare_for_output(int dev, int bsize, int bcount){	unsigned long	flags;	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;	unsigned int	speed, bits;	/*	 * program the speed, channels, bits	 */	speed = waveartist_get_speed(portc);	bits  = waveartist_get_bits(portc);	spin_lock_irqsave(&waveartist_lock, flags);	if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) &&	    waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed))		printk(KERN_WARNING "waveartist: error setting the playback "		       "speed to %dHz.\n", portc->speed);	if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels))		printk(KERN_WARNING "waveartist: error setting the playback "		       "to %d channels\n", portc->channels);	if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0))		printk(KERN_WARNING "waveartist: error setting the playback "		       "data path to 0x%X\n", 0);	if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits))		printk(KERN_WARNING "waveartist: error setting the playback "		       "format to %d\n", portc->audio_format);	devc->xfer_count = 0;	spin_unlock_irqrestore(&waveartist_lock, flags);	waveartist_halt_output(dev);	if (debug_flg & DEBUG_INTR) {		printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));		printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));		printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));	}	return 0;}static voidwaveartist_halt(int dev){	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;	wavnc_info	*devc;	if (portc->open_mode & OPEN_WRITE)		waveartist_halt_output(dev);	if (portc->open_mode & OPEN_READ)		waveartist_halt_input(dev);	devc = (wavnc_info *) audio_devs[dev]->devc;	devc->audio_mode = 0;}static voidwaveartist_halt_input(int dev){	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;	unsigned long	flags;	spin_lock_irqsave(&waveartist_lock, flags);	/*	 * Stop capture	 */	waveartist_cmd1(devc, WACMD_INPUTSTOP);	devc->audio_mode &= ~PCM_ENABLE_INPUT;	/*	 * Clear interrupt by toggling	 * the IRQ_ACK bit in CTRL	 */	if (inb(devc->hw.io_base + STATR) & IRQ_REQ)		waveartist_iack(devc);//	devc->audio_mode &= ~PCM_ENABLE_INPUT;	spin_unlock_irqrestore(&waveartist_lock, flags);}static voidwaveartist_halt_output(int dev){	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;	unsigned long	flags;	spin_lock_irqsave(&waveartist_lock, flags);	waveartist_cmd1(devc, WACMD_OUTPUTSTOP);	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;	/*	 * Clear interrupt by toggling	 * the IRQ_ACK bit in CTRL	 */	if (inb(devc->hw.io_base + STATR) & IRQ_REQ)		waveartist_iack(devc);//	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;	spin_unlock_irqrestore(&waveartist_lock, flags);}static voidwaveartist_trigger(int dev, int state){	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;	unsigned long	flags;	if (debug_flg & DEBUG_TRIGGER) {		printk("wavnc: audio trigger ");		if (state & PCM_ENABLE_INPUT)			printk("in ");		if (state & PCM_ENABLE_OUTPUT)			printk("out");		printk("\n");	}	spin_lock_irqsave(&waveartist_lock, flags);	state &= devc->audio_mode;	if (portc->open_mode & OPEN_READ &&	    state & PCM_ENABLE_INPUT)		/*		 * enable ADC Data Transfer to PC		 */		waveartist_cmd1(devc, WACMD_INPUTSTART);	if (portc->open_mode & OPEN_WRITE &&	    state & PCM_ENABLE_OUTPUT)		/*		 * enable DAC data transfer from PC		 */		waveartist_cmd1(devc, WACMD_OUTPUTSTART);	spin_unlock_irqrestore(&waveartist_lock, flags);}static intwaveartist_set_speed(int dev, int arg){	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;	if (arg <= 0)		return portc->speed;	if (arg < 5000)		arg = 5000;	if (arg > 44100)		arg = 44100;	portc->speed = arg;	return portc->speed;}static shortwaveartist_set_channels(int dev, short arg){	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;	if (arg != 1 && arg != 2)		return portc->channels;	portc->channels = arg;	return arg;}static unsigned intwaveartist_set_bits(int dev, unsigned int arg){	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;	if (arg == 0)		return portc->audio_format;	if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8))		arg = AFMT_U8;	portc->audio_format = arg;	return arg;}static struct audio_driver waveartist_audio_driver = {	owner:			THIS_MODULE,	open:			waveartist_open,	close:			waveartist_close,	output_block:		waveartist_output_block,	start_input:		waveartist_start_input,	ioctl:			waveartist_ioctl,	prepare_for_input:	waveartist_prepare_for_input,	prepare_for_output:	waveartist_prepare_for_output,	halt_io:		waveartist_halt,	halt_input:		waveartist_halt_input,	halt_output:		waveartist_halt_output,	trigger:		waveartist_trigger,	set_speed:		waveartist_set_speed,	set_bits:		waveartist_set_bits,	set_channels:		waveartist_set_channels};static voidwaveartist_intr(int irq, void *dev_id, struct pt_regs *regs){	wavnc_info *devc = (wavnc_info *)dev_id;	int	   irqstatus, status;	irqstatus = inb(devc->hw.io_base + IRQSTAT);	status    = inb(devc->hw.io_base + STATR);	if (debug_flg & DEBUG_INTR)		printk("waveartist_intr: stat=%02x, irqstat=%02x\n",		       status, irqstatus);	if (status & IRQ_REQ)	/* Clear interrupt */		waveartist_iack(devc);	else		printk(KERN_WARNING "waveartist: unexpected interrupt\n");	if (irqstatus & 0x01) {		int temp = 1;		/* PCM buffer done		 */		if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) {			DMAbuf_outputintr(devc->playback_dev, 1);			temp = 0;		}		if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) {			DMAbuf_inputintr(devc->record_dev);			temp = 0;		}		if (temp)	//default:			printk(KERN_WARNING "waveartist: Unknown interrupt\n");	}	if (irqstatus & 0x2)		// We do not use SB mode natively...		printk(KERN_WARNING "waveartist: Unexpected SB interrupt...\n");}/* ------------------------------------------------------------------------- * Mixer stuff */struct mix_ent {	unsigned char	reg_l;	unsigned char	reg_r;	unsigned char	shift;	unsigned char	max;};static const struct mix_ent mix_devs[SOUND_MIXER_NRDEVICES] = {	{ 2, 6, 1,  7 }, /* SOUND_MIXER_VOLUME   */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_BASS     */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_TREBLE   */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_SYNTH    */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_PCM      */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_SPEAKER  */	{ 0, 4, 6, 31 }, /* SOUND_MIXER_LINE     */	{ 2, 6, 4,  3 }, /* SOUND_MIXER_MIC      */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_CD       */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_IMIX     */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_ALTPCM   */#if 0	{ 3, 7, 0, 10 }, /* SOUND_MIXER_RECLEV   */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_IGAIN    */#else	{ 0, 0, 0,  0 }, /* SOUND_MIXER_RECLEV   */	{ 3, 7, 0,  7 }, /* SOUND_MIXER_IGAIN    */#endif	{ 0, 0, 0,  0 }, /* SOUND_MIXER_OGAIN    */	{ 0, 4, 1, 31 }, /* SOUND_MIXER_LINE1    */	{ 1, 5, 6, 31 }, /* SOUND_MIXER_LINE2    */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_LINE3    */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL1 */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL2 */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL3 */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_PHONEIN  */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_PHONEOUT */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_VIDEO    */	{ 0, 0, 0,  0 }, /* SOUND_MIXER_RADIO    */	{ 0, 0, 0,  0 }  /* SOUND_MIXER_MONITOR  */};static voidwaveartist_mixer_update(wavnc_info *devc, int whichDev){	unsigned int lev_left, lev_right;	lev_left  = devc->levels[whichDev] & 0xff;	lev_right = devc->levels[whichDev] >> 8;	if (lev_left > 100)		lev_left = 100;	if (lev_right > 100)		lev_right = 100;#define SCALE(lev,max)	((lev) * (max) / 100)	if (machine_is_netwinder() && whichDev == SOUND_MIXER_PHONEOUT)		whichDev = SOUND_MIXER_VOLUME;	if (mix_devs[whichDev].reg_l || mix_devs[whichDev].reg_r) {		const struct mix_ent *mix = mix_devs + whichDev;		unsigned int mask, left, right;		mask = mix->max << mix->shift;		lev_left  = SCALE(lev_left,  mix->max) << mix->shift;		lev_right = SCALE(lev_right, mix->max) << mix->shift;		/* read left setting */		left  = waveartist_cmd1_r(devc, WACMD_GET_LEVEL |					       mix->reg_l << 8);		/* read right setting */		right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL |						mix->reg_r << 8);		left  = (left  & ~mask) | (lev_left  & mask);		right = (right & ~mask) | (lev_right & mask);		/* write left,right back */		waveartist_cmd3(devc, WACMD_SET_MIXER, left, right);	} else {		switch(whichDev) {		case SOUND_MIXER_PCM:			waveartist_cmd3(devc, WACMD_SET_LEVEL,					SCALE(lev_left,  32767),					SCALE(lev_right, 32767));			break;		case SOUND_MIXER_SYNTH:			waveartist_cmd3(devc, 0x0100 | WACMD_SET_LEVEL,					SCALE(lev_left,  32767),					SCALE(lev_right, 32767));			break;		}	}}/* * Set the ADC MUX to the specified values.  We do NOT do any * checking of the values passed, since we assume that the * relevant *_select_input function has done that for us. */static voidwaveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev){	unsigned int reg_08, reg_09;	reg_08 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0800);	reg_09 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0900);	reg_08 = (reg_08 & ~0x3f) | right_dev << 3 | left_dev;	waveartist_cmd3(devc, WACMD_SET_MIXER, reg_08, reg_09);}/* * Decode a recording mask into a mixer selection as follows: * *     OSS Source	WA Source	Actual source *  SOUND_MASK_IMIX	Mixer		Mixer output (same as AD1848) *  SOUND_MASK_LINE	Line		Line in *  SOUND_MASK_LINE1	Aux 1		Aux 1 in *  SOUND_MASK_LINE2	Aux 2		Aux 2 in *  SOUND_MASK_MIC	Mic		Microphone */static unsigned intwaveartist_select_input(wavnc_info *devc, unsigned int recmask,			unsigned char *dev_l, unsigned char *dev_r){	unsigned int recdev = ADC_MUX_NONE;	if (recmask & SOUND_MASK_IMIX) {		recmask = SOUND_MASK_IMIX;		recdev = ADC_MUX_MIXER;	} else if (recmask & SOUND_MASK_LINE2) {		recmask = SOUND_MASK_LINE2;		recdev = ADC_MUX_AUX2;	} else if (recmask & SOUND_MASK_LINE1) {		recmask = SOUND_MASK_LINE1;		recdev = ADC_MUX_AUX1;	} else if (recmask & SOUND_MASK_LINE) {		recmask = SOUND_MASK_LINE;		recdev = ADC_MUX_LINE;

⌨️ 快捷键说明

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