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

📄 ali5451.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			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(struct snd_pcm_substream *substream,				      struct snd_pcm_hw_params *hw_params){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = runtime->private_data;	struct snd_ali_voice *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) {			evoice = snd_ali_alloc_voice(codec,						     SNDRV_ALI_VOICE_TYPE_PCM,						     0, -1);			if (!evoice)				return -ENOMEM;			pvoice->extra = evoice;			evoice->substream = substream;		}	} else {		if (evoice) {			snd_ali_free_voice(codec, evoice);			pvoice->extra = evoice = NULL;		}	}	return 0;}static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = runtime->private_data;	struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;	snd_pcm_lib_free_pages(substream);	if (evoice) {		snd_ali_free_voice(codec, evoice);		pvoice->extra = NULL;	}	return 0;}static int snd_ali_hw_params(struct snd_pcm_substream *substream,			     struct snd_pcm_hw_params *hw_params){	return snd_pcm_lib_malloc_pages(substream,					params_buffer_bytes(hw_params));}static int snd_ali_hw_free(struct snd_pcm_substream *substream){	return snd_pcm_lib_free_pages(substream);}static int snd_ali_playback_prepare(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = runtime->private_data;	struct snd_ali_voice *evoice = pvoice->extra;	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_irq(&codec->reg_lock);			/* 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");	snd_ali_printk("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) {		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,					 0x7f,					 0x3ff,					 CTRL,					 EC);	}	spin_unlock_irq(&codec->reg_lock);	return 0;}static int snd_ali_prepare(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = runtime->private_data;	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_irq(&codec->reg_lock);	snd_ali_printk("ali_prepare...\n");	snd_ali_enable_special_channel(codec,pvoice->number);	Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||		 pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 		0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);	/* Prepare capture intr channel */	if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {		unsigned int rate;				spin_unlock_irq(&codec->reg_lock);		if (codec->revision != ALI_5451_V02)			return -1;		rate = snd_ali_get_spdif_in_rate(codec);		if (rate == 0) {			snd_printk(KERN_WARNING "ali_capture_preapre: "				   "spdif rate detect err!\n");			rate = 48000;		}		spin_lock_irq(&codec->reg_lock);		bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));		if (bValue & 0x10) {			outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));			printk(KERN_WARNING "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_irq(&codec->reg_lock);	return 0;}static snd_pcm_uframes_tsnd_ali_playback_pointer(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = 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_pointer(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice = runtime->private_data;	unsigned int cso;	spin_lock(&codec->reg_lock);	if (!pvoice->running) {		spin_unlock_irq(&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);	return cso;}static struct snd_pcm_hardware 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 struct snd_pcm_hardware 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(struct snd_pcm_runtime *runtime){	struct snd_ali_voice *pvoice = runtime->private_data;	struct snd_ali *codec;	if (pvoice) {		codec = pvoice->codec;		snd_ali_free_voice(pvoice->codec, pvoice);	}}static int snd_ali_open(struct snd_pcm_substream *substream, int rec,			int channel, struct snd_pcm_hardware *phw){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_ali_voice *pvoice;	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec,				     channel);	if (!pvoice)		return -EAGAIN;	pvoice->substream = substream;	runtime->private_data = pvoice;	runtime->private_free = snd_ali_pcm_free_substream;	runtime->hw = *phw;	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_open(struct snd_pcm_substream *substream){	return snd_ali_open(substream, 0, -1, &snd_ali_playback);}static int snd_ali_capture_open(struct snd_pcm_substream *substream){	return snd_ali_open(substream, 1, -1, &snd_ali_capture);}static int snd_ali_playback_close(struct snd_pcm_substream *substream){	return 0;}static int snd_ali_close(struct snd_pcm_substream *substream){	struct snd_ali *codec = snd_pcm_substream_chip(substream);	struct snd_ali_voice *pvoice = substream->runtime->private_data;	snd_ali_disable_special_channel(codec,pvoice->number);	return 0;}static struct snd_pcm_ops snd_ali_playback_ops = {	.open =		snd_ali_playback_open,	.close =	snd_ali_playback_close,	.ioctl =	snd_pcm_lib_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 struct snd_pcm_ops snd_ali_capture_ops = {	.open =		snd_ali_capture_open,	.close =	snd_ali_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ali_hw_params,	.hw_free =	snd_ali_hw_free,	.prepare =	snd_ali_prepare,	.trigger =	snd_ali_trigger,	.pointer =	snd_ali_pointer,};/* * Modem PCM */static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,				 struct snd_pcm_hw_params *hw_params){	struct snd_ali *chip = snd_pcm_substream_chip(substream);	unsigned int modem_num = chip->num_of_codecs - 1;	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE,		       params_rate(hw_params));	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);	return snd_ali_hw_params(substream, hw_params);}static struct snd_pcm_hardware snd_ali_modem ={	.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_S16_LE,	.rates =	(SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 |			 SNDRV_PCM_RATE_16000),	.rate_min =		8000,	.rate_max =		16000,	.channels_min =		1,	.channels_max =		1,	.buffer_bytes_max =	(256*1024),	.period_bytes_min =	64,	.period_bytes_max =	(256*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec,			      int channel){	static unsigned int rates[] = {8000, 9600, 12000, 16000};	static struct snd_pcm_hw_constraint_list hw_constraint_rates = {		.count = ARRAY_SIZE(rates),		.list = rates,		.mask = 0,	};	int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);	if (err)		return err;	return snd_pcm_hw_constraint_list(substream->runtime, 0,			SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);}static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream){	return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);}static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream){	return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);}static struct snd_pcm_ops snd_ali_modem_playback_ops = {	.open =		snd_ali_modem_playback_open,	.close =	snd_ali_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ali_modem_hw_params,	.hw_free =	snd_ali_hw_free,	.prepare =	snd_ali_prepare,	.trigger =	snd_ali_trigger,	.pointer =	snd_ali_pointer,};static struct snd_pcm_ops snd_ali_modem_capture_ops = {	.open =		snd_ali_modem_capture_open,	.close =	snd_ali_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ali_modem_hw_params,	.hw_free =	snd_ali_hw_free,	.prepare =	snd_ali_prepare,	.trigger =	snd_ali_trigger,	.pointer =	snd_ali_pointer,};struct ali_pcm_description {	char *name;	unsigned int playback_num;	unsigned int capture_num;	struct snd_pcm_ops *playback_ops;	struct snd_pcm_ops *capture_ops;	unsigned short class;};static void snd_ali_pcm_free(struct snd_pcm *pcm){	struct snd_ali *codec = pcm->private_data;	codec->pcm[pcm->device] = NULL;}static int __devinit snd_ali_pcm(struct snd_ali * codec, int device,				 struct ali_pcm_description *desc){	struct snd_pcm *pcm;	int err;	err = snd_pcm_new(codec->card, desc->name, device,			  desc->playback_num, desc->capture_num, &pcm);	if (err < 0) {		snd_printk(KERN_ERR "snd_ali_pcm: err called snd_pcm_new.\n");		return err;	}	pcm->private_data = codec;	pcm->private_free = snd_ali_pcm_free;	if (desc->playback_ops)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,				desc->playback_ops);	if (desc->capture_ops)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,				desc->capture_ops);	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(codec->pci),					      64*1024, 128*1024);	pcm->info_flags = 0;	pcm->dev_class = desc->class;	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;	strcpy(pcm->name, desc->name);	codec->pcm[0] = pcm;	return 0;}static struct ali_pcm_description ali_pcms[] = {	{ .name = "ALI 5451",	  .playback_num = ALI_CHANNELS,	  .capture_num = 1,	  .playback_ops = &snd_ali_playback_ops,	  .capture_ops = &snd_ali_capture_ops	},	{ .name = "ALI 5451 modem",	  .playback_num = 1,	  .capture_num = 1,	  .playback_ops = &snd_ali_modem_playback_ops,	  .capture_ops = &snd_ali_modem_capture_ops,	  .class = SNDRV_PCM_CLASS_MODEM	}};

⌨️ 快捷键说明

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