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

📄 ali5451.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		      ((CTRL & 0x0000000f) << 12) |		      (EC & 0x00000fff);	outb(Channel, ALI_REG(codec, ALI_GC_CIR));	outl(ctlcmds[0], ALI_REG(codec,ALI_CSO_ALPHA_FMS));	outl(ctlcmds[1], ALI_REG(codec,ALI_LBA));	outl(ctlcmds[2], ALI_REG(codec,ALI_ESO_DELTA));	outl(ctlcmds[3], ALI_REG(codec,ALI_GVSEL_PAN_VOC_CTRL_EC));	outl(0x30000000, ALI_REG(codec, ALI_EBUF1));	/* Still Mode */	outl(0x30000000, ALI_REG(codec, ALI_EBUF2));	/* Still Mode */}static unsigned int snd_ali_convert_rate(unsigned int rate, int rec){	unsigned int delta;	if (rate < 4000)  rate = 4000;	if (rate > 48000) rate = 48000;	if (rec) {		if (rate == 44100)			delta = 0x116a;		else if (rate == 8000)			delta = 0x6000;		else if (rate == 48000)			delta = 0x1000;		else			delta = ((48000 << 12) / rate) & 0x0000ffff;	} else {		if (rate == 44100)			delta = 0xeb3;		else if (rate == 8000)			delta = 0x2ab;		else if (rate == 48000)			delta = 0x1000;		else 			delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;	}	return delta;}static unsigned int snd_ali_control_mode(snd_pcm_substream_t *substream){	unsigned int CTRL;	snd_pcm_runtime_t *runtime = substream->runtime;	/* set ctrl mode	   CTRL default: 8-bit (unsigned) mono, loop mode enabled	 */	CTRL = 0x00000001;	if (snd_pcm_format_width(runtime->format) == 16)		CTRL |= 0x00000008;	// 16-bit data	if (!snd_pcm_format_unsigned(runtime->format))		CTRL |= 0x00000002;	// signed data	if (runtime->channels > 1)		CTRL |= 0x00000004;	// stereo data	return CTRL;}/* *  PCM part */static int snd_ali_ioctl(snd_pcm_substream_t * substream,				  unsigned int cmd, void *arg){	return snd_pcm_lib_ioctl(substream, cmd, arg);}static int snd_ali_trigger(snd_pcm_substream_t *substream,			       int cmd)				    {	ali_t *codec = snd_pcm_substream_chip(substream);	struct list_head *pos;	snd_pcm_substream_t *s;	unsigned int what, whati, capture_flag;	snd_ali_voice_t *pvoice = NULL, *evoice = NULL;	unsigned int val;	int do_start;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		do_start = 1; break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		do_start = 0; break;	default:		return -EINVAL;	}	what = whati = capture_flag = 0;	snd_pcm_group_for_each(pos, substream) {		s = snd_pcm_group_substream_entry(pos);		if ((ali_t *) snd_pcm_substream_chip(s) == codec) {			pvoice = (snd_ali_voice_t *) s->runtime->private_data;			evoice = pvoice->extra;			what |= 1 << (pvoice->number & 0x1f);			if (evoice == NULL) {				whati |= 1 << (pvoice->number & 0x1f);			} else {				whati |= 1 << (evoice->number & 0x1f);				what |= 1 << (evoice->number & 0x1f);			}			if (do_start) {				pvoice->running = 1;				if (evoice != NULL)					evoice->running = 1;			} else {				pvoice->running = 0;				if (evoice != NULL)					evoice->running = 0;			}			snd_pcm_trigger_done(s, substream);			if (pvoice->mode)				capture_flag = 1;		}	}	spin_lock(&codec->reg_lock);	if (! do_start) {		outl(what, ALI_REG(codec, ALI_STOP));	}	val = inl(ALI_REG(codec, ALI_AINTEN));	if (do_start) {		val |= whati;	} else {		val &= ~whati;	}	outl(val, ALI_REG(codec, ALI_AINTEN));	if (do_start) {		outl(what, ALI_REG(codec, ALI_START));	}	snd_ali_printk("trigger: what=%xh whati=%xh\n",what,whati);	spin_unlock(&codec->reg_lock);	return 0;}static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,				 snd_pcm_hw_params_t * hw_params){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	snd_ali_voice_t *evoice = pvoice->extra;	int err;	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));	if (err < 0) return err;		/* voice management */	if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {		if (evoice == NULL) {			evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);			if (evoice == NULL)				return -ENOMEM;			pvoice->extra = evoice;			evoice->substream = substream;		}	} else {		if (evoice != NULL) {			snd_ali_free_voice(codec, evoice);			pvoice->extra = evoice = NULL;		}	}	return 0;}static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	snd_ali_voice_t *evoice = pvoice ? pvoice->extra : NULL;	snd_pcm_lib_free_pages(substream);	if (evoice != NULL) {		snd_ali_free_voice(codec, evoice);		pvoice->extra = NULL;	}	return 0;}static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream,				 snd_pcm_hw_params_t * hw_params){	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream){	return snd_pcm_lib_free_pages(substream);}static int snd_ali_playback_prepare(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	snd_ali_voice_t *evoice = pvoice->extra;	unsigned long flags;	unsigned int LBA;	unsigned int Delta;	unsigned int ESO;	unsigned int CTRL;	unsigned int GVSEL;	unsigned int PAN;	unsigned int VOL;	unsigned int EC;		snd_ali_printk("playback_prepare ...\n");	spin_lock_irqsave(&codec->reg_lock, flags);			/* set Delta (rate) value */	Delta = snd_ali_convert_rate(runtime->rate, 0);	if ((pvoice->number == ALI_SPDIF_IN_CHANNEL) || 	    (pvoice->number == ALI_PCM_IN_CHANNEL))		snd_ali_disable_special_channel(codec, pvoice->number);	else if (codec->spdif_support &&		 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_OUT_CH_ENABLE)		 && (pvoice->number == ALI_SPDIF_OUT_CHANNEL)) {		snd_ali_set_spdif_out_rate(codec, runtime->rate);		Delta = 0x1000;	}		/* set Loop Back Address */	LBA = runtime->dma_addr;	/* set interrupt count size */	pvoice->count = runtime->period_size;	/* set target ESO for channel */	pvoice->eso = runtime->buffer_size; 	snd_ali_printk("playback_prepare: eso=%xh count=%xh\n",pvoice->eso,pvoice->count);	/* set ESO to capture first MIDLP interrupt */	ESO = pvoice->eso -1;	/* set ctrl mode */	CTRL = snd_ali_control_mode(substream);	GVSEL = 1;	PAN = 0;	VOL = 0;	EC = 0;	snd_ali_printk("playback_prepare:\n    ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL);	snd_ali_write_voice_regs(    codec,				     pvoice->number,				     LBA,				     0,	/* cso */				     ESO,				     Delta,				     0,	/* alpha */				     GVSEL,				     PAN,				     VOL,				     CTRL,				     EC);	if (evoice != NULL) {		evoice->count = pvoice->count;		evoice->eso = pvoice->count << 1;		ESO = evoice->eso - 1;		snd_ali_write_voice_regs(codec,				     evoice->number,				     LBA,				     0,	/* cso */				     ESO,				     Delta,				     0,	/* alpha */				     GVSEL,				     (unsigned int)0x7f,				     (unsigned int)0x3ff,				     CTRL,				     EC);	}	spin_unlock_irqrestore(&codec->reg_lock, flags);	return 0;}static int snd_ali_capture_prepare(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	unsigned long flags;	unsigned int LBA;	unsigned int Delta;	unsigned int ESO;	unsigned int CTRL;	unsigned int GVSEL;	unsigned int PAN;	unsigned int VOL;	unsigned int EC;	u8	 bValue;	spin_lock_irqsave(&codec->reg_lock, flags);	snd_ali_printk("capture_prepare...\n");	snd_ali_enable_special_channel(codec,pvoice->number);	Delta = snd_ali_convert_rate(runtime->rate, 1);	// Prepare capture intr channel	if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {		unsigned int rate;				if (codec->revision != ALI_5451_V02) {			spin_unlock_irqrestore(&codec->reg_lock, flags);						return -1;		}		rate = snd_ali_get_spdif_in_rate(codec);		if (rate == 0) {			snd_printk("ali_capture_preapre: spdif rate detect err!\n");			rate = 48000;		}		bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));		if (bValue & 0x10) {			outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));			printk("clear SPDIF parity error flag.\n");		}		if (rate != 48000)			Delta = ((rate << 12)/runtime->rate)&0x00ffff;	}	// set target ESO for channel 	pvoice->eso = runtime->buffer_size; 	// set interrupt count size 	pvoice->count = runtime->period_size;	// set Loop Back Address 	LBA = runtime->dma_addr;	// set ESO to capture first MIDLP interrupt 	ESO = pvoice->eso - 1;	CTRL = snd_ali_control_mode(substream);	GVSEL = 0;	PAN = 0x00;	VOL = 0x00;	EC = 0;	snd_ali_write_voice_regs(    codec,				     pvoice->number,				     LBA,				     0,	/* cso */				     ESO,				     Delta,				     0,	/* alpha */				     GVSEL,				     PAN,				     VOL,				     CTRL,				     EC);	spin_unlock_irqrestore(&codec->reg_lock, flags);	return 0;}static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	unsigned int cso;	spin_lock(&codec->reg_lock);	if (!pvoice->running) {		spin_unlock(&codec->reg_lock);		return 0;	}	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));	spin_unlock(&codec->reg_lock);	snd_ali_printk("playback pointer returned cso=%xh.\n", cso);	return cso;}static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	unsigned int cso;	unsigned long flags;	spin_lock_irqsave(&codec->reg_lock, flags);	if (!pvoice->running) {		spin_unlock_irqrestore(&codec->reg_lock, flags);		return 0;	}	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));	spin_unlock_irqrestore(&codec->reg_lock, flags);	return cso;}static snd_pcm_hardware_t snd_ali_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_RESUME |				 SNDRV_PCM_INFO_SYNC_START),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(256*1024),	.period_bytes_min =	64,	.period_bytes_max =	(256*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};/* *  Capture support device description */static snd_pcm_hardware_t snd_ali_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_RESUME |				 SNDRV_PCM_INFO_SYNC_START),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(128*1024),	.period_bytes_min =	64,	.period_bytes_max =	(128*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime){	unsigned long flags;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	ali_t *codec;	if (pvoice) {		codec = pvoice->codec;		spin_lock_irqsave(&codec->reg_lock, flags);		snd_ali_free_voice(pvoice->codec, pvoice);		spin_unlock_irqrestore(&codec->reg_lock, flags);	}}static int snd_ali_playback_open(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice;	unsigned long flags = 0;	spin_lock_irqsave(&codec->reg_lock, flags);	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);	if (pvoice == NULL) {		spin_unlock_irqrestore(&codec->reg_lock, flags);		return -EAGAIN;	}	pvoice->codec = codec;	spin_unlock_irqrestore(&codec->reg_lock, flags);	pvoice->substream = substream;	runtime->private_data = pvoice;	runtime->private_free = snd_ali_pcm_free_substream;	runtime->hw = snd_ali_playback;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);	return 0;}static int snd_ali_capture_open(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice;	unsigned long flags;	spin_lock_irqsave(&codec->reg_lock, flags);	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1);	if (pvoice == NULL) {		spin_unlock_irqrestore(&codec->reg_lock, flags);		return -EAGAIN;	}	pvoice->codec = codec;	spin_unlock_irqrestore(&codec->reg_lock, flags);	pvoice->substream = substream;	runtime->private_data = pvoice;	runtime->private_free = snd_ali_pcm_free_substream;	runtime->hw = snd_ali_capture;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);	return 0;}static int snd_ali_playback_close(snd_pcm_substream_t * substream){	return 0;}static int snd_ali_capture_close(snd_pcm_substream_t * substream){	ali_t *codec = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;	snd_ali_disable_special_channel(codec,pvoice->number);	return 0;}static snd_pcm_ops_t snd_ali_playback_ops = {	.open =		snd_ali_playback_open,	.close =	snd_ali_playback_close,	.ioctl =	snd_ali_ioctl,	.hw_params =	snd_ali_playback_hw_params,	.hw_free =	snd_ali_playback_hw_free,	.prepare =	snd_ali_playback_prepare,	.trigger =	snd_ali_trigger,	.pointer =	snd_ali_playback_pointer,};static snd_pcm_ops_t snd_ali_capture_ops = {	.open =		snd_ali_capture_open,	.close =	snd_ali_capture_close,	.ioctl =	snd_ali_ioctl,	.hw_params =	snd_ali_capture_hw_params,	.hw_free =	snd_ali_capture_hw_free,	.prepare =	snd_ali_capture_prepare,	.trigger =	snd_ali_trigger,	.pointer =	snd_ali_capture_pointer,};static void snd_ali_pcm_free(snd_pcm_t *pcm){	ali_t *codec = pcm->private_data;

⌨️ 快捷键说明

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