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

📄 ice1724.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));				spin_unlock_irqrestore(&ice->reg_lock, flags);				mdelay(5);				spin_lock_irqsave(&ice->reg_lock, flags);				/* deassert PRST# */				outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));			}		}	}	spin_unlock_irqrestore(&ice->reg_lock, flags);	/* set up codecs */	for (i = 0; i < ice->akm_codecs; i++) {		if (ice->akm[i].ops.set_rate_val)			ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);	}}static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,				    snd_pcm_hw_params_t * hw_params){	ice1712_t *ice = snd_pcm_substream_chip(substream);	int i, chs;	chs = params_channels(hw_params);	down(&ice->open_mutex);	/* mark surround channels */	if (substream == ice->playback_pro_substream) {		/* PDMA0 can be multi-channel up to 8 */		chs = chs / 2 - 1;		for (i = 0; i < chs; i++) {			if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {				up(&ice->open_mutex);				return -EBUSY;			}			ice->pcm_reserved[i] = substream;		}		for (; i < 3; i++) {			if (ice->pcm_reserved[i] == substream)				ice->pcm_reserved[i] = NULL;		}	} else {		for (i = 0; i < 3; i++) {			/* check individual playback stream */			if (ice->playback_con_substream_ds[i] == substream) {				if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {					up(&ice->open_mutex);					return -EBUSY;				}				ice->pcm_reserved[i] = substream;				break;			}		}	}	up(&ice->open_mutex);	snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0);	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_vt1724_pcm_hw_free(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	int i;	down(&ice->open_mutex);	/* unmark surround channels */	for (i = 0; i < 3; i++)		if (ice->pcm_reserved[i] == substream)			ice->pcm_reserved[i] = NULL;	up(&ice->open_mutex);	return snd_pcm_lib_free_pages(substream);}static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	unsigned char val;	unsigned int size;	spin_lock_irq(&ice->reg_lock);	val = (8 - substream->runtime->channels) >> 1;	outb(val, ICEMT1724(ice, BURST));	outl(substream->runtime->dma_addr, ICEMT1724(ice, PLAYBACK_ADDR));	size = (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1;	// outl(size, ICEMT1724(ice, PLAYBACK_SIZE));	outw(size, ICEMT1724(ice, PLAYBACK_SIZE));	outb(size >> 16, ICEMT1724(ice, PLAYBACK_SIZE) + 2);	size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1;	// outl(size, ICEMT1724(ice, PLAYBACK_COUNT));	outw(size, ICEMT1724(ice, PLAYBACK_COUNT));	outb(size >> 16, ICEMT1724(ice, PLAYBACK_COUNT) + 2);	spin_unlock_irq(&ice->reg_lock);	// printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream));	return 0;}static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & VT1724_PDMA0_START))		return 0;#if 0 /* read PLAYBACK_ADDR */	ptr = inl(ICEMT1724(ice, PLAYBACK_ADDR));	if (ptr < substream->runtime->dma_addr) {		snd_printd("ice1724: invalid negative ptr\n");		return 0;	}	ptr -= substream->runtime->dma_addr;	ptr = bytes_to_frames(substream->runtime, ptr);	if (ptr >= substream->runtime->buffer_size) {		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->period_size);		return 0;	}#else /* read PLAYBACK_SIZE */	ptr = inl(ICEMT1724(ice, PLAYBACK_SIZE)) & 0xffffff;	ptr = (ptr + 1) << 2;	ptr = bytes_to_frames(substream->runtime, ptr);	if (! ptr)		;	else if (ptr <= substream->runtime->buffer_size)		ptr = substream->runtime->buffer_size - ptr;	else {		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);		ptr = 0;	}#endif	return ptr;}static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	struct vt1724_pcm_reg *reg = substream->runtime->private_data;	spin_lock_irq(&ice->reg_lock);	outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);	outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, ice->profi_port + reg->size);	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ice->profi_port + reg->count);	spin_unlock_irq(&ice->reg_lock);	return 0;}static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	struct vt1724_pcm_reg *reg = substream->runtime->private_data;	size_t ptr;	if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))		return 0;#if 0 /* use ADDR register */	ptr = inl(ice->profi_port + reg->addr);	ptr -= substream->runtime->dma_addr;	return bytes_to_frames(substream->runtime, ptr);#else /* use SIZE register */	ptr = inw(ice->profi_port + reg->size);	ptr = (ptr + 1) << 2;	ptr = bytes_to_frames(substream->runtime, ptr);	if (! ptr)		;	else if (ptr <= substream->runtime->buffer_size)		ptr = substream->runtime->buffer_size - ptr;	else {		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);		ptr = 0;	}	return ptr;#endif}static struct vt1724_pcm_reg vt1724_playback_pro_reg = {	.addr = VT1724_MT_PLAYBACK_ADDR,	.size = VT1724_MT_PLAYBACK_SIZE,	.count = VT1724_MT_PLAYBACK_COUNT,	.start = VT1724_PDMA0_START,};static struct vt1724_pcm_reg vt1724_capture_pro_reg = {	.addr = VT1724_MT_CAPTURE_ADDR,	.size = VT1724_MT_CAPTURE_SIZE,	.count = VT1724_MT_CAPTURE_COUNT,	.start = VT1724_RDMA0_START,};static snd_pcm_hardware_t snd_vt1724_playback_pro ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),	.formats =		SNDRV_PCM_FMTBIT_S32_LE,	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_192000,	.rate_min =		8000,	.rate_max =		192000,	.channels_min =		2,	.channels_max =		8,	.buffer_bytes_max =	(1UL << 21),	/* 19bits dword */	.period_bytes_min =	8 * 4 * 2,	/* FIXME: constraints needed */	.period_bytes_max =	(1UL << 21),	.periods_min =		2,	.periods_max =		1024,};static snd_pcm_hardware_t snd_vt1724_spdif ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),	.formats =		SNDRV_PCM_FMTBIT_S32_LE,	.rates =	        SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,	.rate_min =		32000,	.rate_max =		48000,	.channels_min =		2,	.channels_max =		2,	.buffer_bytes_max =	(1UL << 18),	/* 16bits dword */	.period_bytes_min =	2 * 4 * 2,	.period_bytes_max =	(1UL << 18),	.periods_min =		2,	.periods_max =		1024,};static snd_pcm_hardware_t snd_vt1724_2ch_stereo ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),	.formats =		SNDRV_PCM_FMTBIT_S32_LE,	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_192000,	.rate_min =		8000,	.rate_max =		192000,	.channels_min =		2,	.channels_max =		2,	.buffer_bytes_max =	(1UL << 18),	/* 16bits dword */	.period_bytes_min =	2 * 4 * 2,	.period_bytes_max =	(1UL << 18),	.periods_min =		2,	.periods_max =		1024,};/* * set rate constraints */static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {		/* I2S */		/* VT1720 doesn't support more than 96kHz */		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);		else {			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000;			runtime->hw.rate_max = 96000;			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_96);		}	} else if (ice->ac97) {		/* ACLINK */		runtime->hw.rate_max = 48000;		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;		return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);	}	return 0;}/* multi-channel playback needs alignment 8x32bit regardless of the channels * actually used */#define VT1724_BUFFER_ALIGN	0x20static int snd_vt1724_playback_pro_open(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	ice1712_t *ice = snd_pcm_substream_chip(substream);	int chs;	runtime->private_data = &vt1724_playback_pro_reg;	ice->playback_pro_substream = substream;	runtime->hw = snd_vt1724_playback_pro;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);	set_rate_constraints(ice, substream);	down(&ice->open_mutex);	/* calculate the currently available channels */	for (chs = 0; chs < 3; chs++) {		if (ice->pcm_reserved[chs])			break;	}	chs = (chs + 1) * 2;	runtime->hw.channels_max = chs;	if (chs > 2) /* channels must be even */		snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2);	up(&ice->open_mutex);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,				   VT1724_BUFFER_ALIGN);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,				   VT1724_BUFFER_ALIGN);	return 0;}static int snd_vt1724_capture_pro_open(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	runtime->private_data = &vt1724_capture_pro_reg;	ice->capture_pro_substream = substream;	runtime->hw = snd_vt1724_2ch_stereo;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);	set_rate_constraints(ice, substream);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,				   VT1724_BUFFER_ALIGN);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,				   VT1724_BUFFER_ALIGN);	return 0;}static int snd_vt1724_playback_pro_close(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	if (PRO_RATE_RESET)		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);	ice->playback_pro_substream = NULL;	return 0;}static int snd_vt1724_capture_pro_close(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	if (PRO_RATE_RESET)		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);	ice->capture_pro_substream = NULL;	return 0;}static snd_pcm_ops_t snd_vt1724_playback_pro_ops = {	.open =		snd_vt1724_playback_pro_open,	.close =	snd_vt1724_playback_pro_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_vt1724_pcm_hw_params,	.hw_free =	snd_vt1724_pcm_hw_free,	.prepare =	snd_vt1724_playback_pro_prepare,	.trigger =	snd_vt1724_pcm_trigger,	.pointer =	snd_vt1724_playback_pro_pointer,};static snd_pcm_ops_t snd_vt1724_capture_pro_ops = {	.open =		snd_vt1724_capture_pro_open,	.close =	snd_vt1724_capture_pro_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_vt1724_pcm_hw_params,	.hw_free =	snd_vt1724_pcm_hw_free,	.prepare =	snd_vt1724_pcm_prepare,	.trigger =	snd_vt1724_pcm_trigger,	.pointer =	snd_vt1724_pcm_pointer,};static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device){	snd_pcm_t *pcm;	int err;	err = snd_pcm_new(ice->card, "ICE1724", device, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_vt1724_playback_pro_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_vt1724_capture_pro_ops);	pcm->private_data = ice;	pcm->info_flags = 0;	strcpy(pcm->name, "ICE1724");	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(ice->pci), 256*1024, 256*1024);	ice->pcm_pro = pcm;	return 0;}/* * SPDIF PCM */static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {	.addr = VT1724_MT_PDMA4_ADDR,	.size = VT1724_MT_PDMA4_SIZE,	.count = VT1724_MT_PDMA4_COUNT,	.start = VT1724_PDMA4_START,};static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {	.addr = VT1724_MT_RDMA1_ADDR,	.size = VT1724_MT_RDMA1_SIZE,	.count = VT1724_MT_RDMA1_COUNT,	.start = VT1724_RDMA1_START,};/* update spdif control bits; call with reg_lock */static void update_spdif_bits(ice1712_t *ice, unsigned int val){	unsigned char cbit, disabled;	cbit = inb(ICEREG1724(ice, SPDIF_CFG));	disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;	if (cbit != disabled)		outb(disabled, ICEREG1724(ice, SPDIF_CFG));	outw(val, ICEMT1724(ice, SPDIF_CTRL));	if (cbit != disabled)		outb(cbit, ICEREG1724(ice, SPDIF_CFG));	outw(val, ICEMT1724(ice, SPDIF_CTRL));}/* update SPDIF control bits according to the given rate */static void update_spdif_rate(ice1712_t *ice, unsigned int rate){	unsigned int val, nval;	unsigned long flags;	spin_lock_irqsave(&ice->reg_lock, flags);	nval = val = inw(ICEMT1724(ice, SPDIF_CTRL));	nval &= ~(7 << 12);	switch (rate) {	case 44100: break;	case 48000: nval |= 2 << 12; break;	case 32000: nval |= 3 << 12; break;	}	if (val != nval)		update_spdif_bits(ice, nval);	spin_unlock_irqrestore(&ice->reg_lock, flags);}static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	if (! ice->force_pdma4)		update_spdif_rate(ice, substream->runtime->rate);	return snd_vt1724_pcm_prepare(substream);}static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	runtime->private_data = &vt1724_playback_spdif_reg;	ice->playback_con_substream = substream;	if (ice->force_pdma4) {		runtime->hw = snd_vt1724_2ch_stereo;		set_rate_constraints(ice, substream);

⌨️ 快捷键说明

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