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

📄 ali5451.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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);	snd_pcm_substream_t *s;	unsigned int what, whati, capture_flag;	snd_ali_voice_t *pvoice = NULL, *evoice = NULL;	unsigned int val;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_STOP:	{		what = whati = capture_flag = 0;		s = substream;		do {			if ((ali_t *) _snd_pcm_chip(s->pcm) == 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 (cmd == SNDRV_PCM_TRIGGER_START) {					pvoice->running = 1;					if (evoice != NULL)						evoice->running = 1;				}				snd_pcm_trigger_done(s, substream);				if (pvoice->mode)					capture_flag = 1;			}			s = s->link_next;		} while (s != substream);		spin_lock(&codec->reg_lock);		if (cmd == SNDRV_PCM_TRIGGER_STOP) {			outl(what, ALI_REG(codec, ALI_STOP));			pvoice->running = 0;			if (evoice != NULL)				evoice->running = 0;		}		val = inl(ALI_REG(codec, ALI_AINTEN));		if (cmd == SNDRV_PCM_TRIGGER_START) {			val |= whati;		} else {			val &= ~whati;		}		outl(val, ALI_REG(codec, ALI_AINTEN));		if (cmd == SNDRV_PCM_TRIGGER_START) {			outl(what, ALI_REG(codec, ALI_START));		}		snd_ali_printk("trigger: what=%xh whati=%xh\n",what,whati);		spin_unlock(&codec->reg_lock);		break;	}	default:		return -EINVAL;	}	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 ((inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & (1<<15)) 		&& (pvoice->number == ALI_SPDIF_OUT_CHANNEL)) {		if (codec->revision == ALI_5451_V02) {			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)			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;	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);	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_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_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 = snd_magic_cast(ali_t, pcm->private_data, return);	codec->pcm = NULL;}static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm) *rpcm = NULL;	err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm);	if (err < 0) {		snd_printk("snd_ali_pcm: err called snd_pcm_new.\n");		return err;	}	pcm->private_data = codec;	pcm->private_free = snd_ali_pcm_free;	pcm->info_flags = 0;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops);	snd_pcm_lib_preallocate_pci_pages_for_all(codec->pci, pcm, 64*1024, 128*1024);	pcm->info_flags = 0;	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;	strcpy(pcm->name, "ALI 5451");	codec->pcm = pcm;	if (rpcm) *rpcm = pcm;	return 0;

⌨️ 快捷键说明

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