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

📄 ice1724.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	} else		runtime->hw = snd_vt1724_spdif;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);	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_spdif_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_con_substream = NULL;	return 0;}static int snd_vt1724_capture_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_capture_spdif_reg;	ice->capture_con_substream = substream;	if (ice->force_rdma1) {		runtime->hw = snd_vt1724_2ch_stereo;		set_rate_constraints(ice, substream);	} else		runtime->hw = snd_vt1724_spdif;	snd_pcm_set_sync(substream);	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);	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_spdif_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_con_substream = NULL;	return 0;}static snd_pcm_ops_t snd_vt1724_playback_spdif_ops = {	.open =		snd_vt1724_playback_spdif_open,	.close =	snd_vt1724_playback_spdif_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_vt1724_pcm_hw_params,	.hw_free =	snd_vt1724_pcm_hw_free,	.prepare =	snd_vt1724_playback_spdif_prepare,	.trigger =	snd_vt1724_pcm_trigger,	.pointer =	snd_vt1724_pcm_pointer,};static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {	.open =		snd_vt1724_capture_spdif_open,	.close =	snd_vt1724_capture_spdif_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_spdif(ice1712_t * ice, int device){	char *name;	snd_pcm_t *pcm;	int play, capt;	int err;	if (ice->force_pdma4 ||	    (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_OUT_INT)) {		play = 1;		ice->has_spdif = 1;	} else		play = 0;	if (ice->force_rdma1 ||	    (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_IN)) {		capt = 1;		ice->has_spdif = 1;	} else		capt = 0;	if (! play && ! capt)		return 0; /* no spdif device */	if (ice->force_pdma4 || ice->force_rdma1)		name = "ICE1724 Secondary";	else		name = "IEC1724 IEC958";	err = snd_pcm_new(ice->card, name, device, play, capt, &pcm);	if (err < 0)		return err;	if (play)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,				&snd_vt1724_playback_spdif_ops);	if (capt)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,				&snd_vt1724_capture_spdif_ops);	pcm->private_data = ice;	pcm->info_flags = 0;	strcpy(pcm->name, name);	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(ice->pci), 64*1024, 64*1024);	ice->pcm = pcm;	return 0;}/* * independent surround PCMs */static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {	{		.addr = VT1724_MT_PDMA1_ADDR,		.size = VT1724_MT_PDMA1_SIZE,		.count = VT1724_MT_PDMA1_COUNT,		.start = VT1724_PDMA1_START,	},	{		.addr = VT1724_MT_PDMA2_ADDR,		.size = VT1724_MT_PDMA2_SIZE,		.count = VT1724_MT_PDMA2_COUNT,		.start = VT1724_PDMA2_START,	},	{		.addr = VT1724_MT_PDMA3_ADDR,		.size = VT1724_MT_PDMA3_SIZE,		.count = VT1724_MT_PDMA3_COUNT,		.start = VT1724_PDMA3_START,	},};static int snd_vt1724_playback_indep_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	unsigned char val;	spin_lock_irq(&ice->reg_lock);	val = 3 - substream->number;	if (inb(ICEMT1724(ice, BURST)) < val)		outb(val, ICEMT1724(ice, BURST));	spin_unlock_irq(&ice->reg_lock);	return snd_vt1724_pcm_prepare(substream);}static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	down(&ice->open_mutex);	/* already used by PDMA0? */	if (ice->pcm_reserved[substream->number]) {		up(&ice->open_mutex);		return -EBUSY; /* FIXME: should handle blocking mode properly */	}	up(&ice->open_mutex);	runtime->private_data = &vt1724_playback_dma_regs[substream->number];	ice->playback_con_substream_ds[substream->number] = 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);	return 0;}static int snd_vt1724_playback_indep_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_con_substream_ds[substream->number] = NULL;	ice->pcm_reserved[substream->number] = NULL;	return 0;}static snd_pcm_ops_t snd_vt1724_playback_indep_ops = {	.open =		snd_vt1724_playback_indep_open,	.close =	snd_vt1724_playback_indep_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_vt1724_pcm_hw_params,	.hw_free =	snd_vt1724_pcm_hw_free,	.prepare =	snd_vt1724_playback_indep_prepare,	.trigger =	snd_vt1724_pcm_trigger,	.pointer =	snd_vt1724_pcm_pointer,};static int __devinit snd_vt1724_pcm_indep(ice1712_t * ice, int device){	snd_pcm_t *pcm;	int play;	int err;	play = ice->num_total_dacs / 2 - 1;	if (play <= 0)		return 0;	err = snd_pcm_new(ice->card, "ICE1724 Surrounds", device, play, 0, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,			&snd_vt1724_playback_indep_ops);	pcm->private_data = ice;	pcm->info_flags = 0;	strcpy(pcm->name, "ICE1724 Surround PCM");	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(ice->pci), 64*1024, 64*1024);	ice->pcm_ds = pcm;	return 0;}/* *  Mixer section */static int __devinit snd_vt1724_ac97_mixer(ice1712_t * ice){	int err;	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) {		ac97_bus_t *pbus;		ac97_template_t ac97;		static ac97_bus_ops_t ops = {			.write = snd_vt1724_ac97_write,			.read = snd_vt1724_ac97_read,		};		/* cold reset */		outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));		mdelay(5); /* FIXME */		outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));		if ((err = snd_ac97_bus(ice->card, 0, &ops, NULL, &pbus)) < 0)			return err;		memset(&ac97, 0, sizeof(ac97));		ac97.private_data = ice;		if ((err = snd_ac97_mixer(pbus, &ac97, &ice->ac97)) < 0)			printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n");		else			return 0;	}	/* I2S mixer only */	strcat(ice->card->mixername, "ICE1724 - multitrack");	return 0;}/* * */static inline unsigned int eeprom_triple(ice1712_t *ice, int idx){	return (unsigned int)ice->eeprom.data[idx] | \		((unsigned int)ice->eeprom.data[idx + 1] << 8) | \		((unsigned int)ice->eeprom.data[idx + 2] << 16);}static void snd_vt1724_proc_read(snd_info_entry_t *entry, 				 snd_info_buffer_t * buffer){	ice1712_t *ice = entry->private_data;	unsigned int idx;	snd_iprintf(buffer, "%s\n\n", ice->card->longname);	snd_iprintf(buffer, "EEPROM:\n");	snd_iprintf(buffer, "  Subvendor        : 0x%x\n", ice->eeprom.subvendor);	snd_iprintf(buffer, "  Size             : %i bytes\n", ice->eeprom.size);	snd_iprintf(buffer, "  Version          : %i\n", ice->eeprom.version);	snd_iprintf(buffer, "  System Config    : 0x%x\n", ice->eeprom.data[ICE_EEP2_SYSCONF]);	snd_iprintf(buffer, "  ACLink           : 0x%x\n", ice->eeprom.data[ICE_EEP2_ACLINK]);	snd_iprintf(buffer, "  I2S              : 0x%x\n", ice->eeprom.data[ICE_EEP2_I2S]);	snd_iprintf(buffer, "  S/PDIF           : 0x%x\n", ice->eeprom.data[ICE_EEP2_SPDIF]);	snd_iprintf(buffer, "  GPIO direction   : 0x%x\n", ice->eeprom.gpiodir);	snd_iprintf(buffer, "  GPIO mask        : 0x%x\n", ice->eeprom.gpiomask);	snd_iprintf(buffer, "  GPIO state       : 0x%x\n", ice->eeprom.gpiostate);	for (idx = 0x12; idx < ice->eeprom.size; idx++)		snd_iprintf(buffer, "  Extra #%02i        : 0x%x\n", idx, ice->eeprom.data[idx]);	snd_iprintf(buffer, "\nRegisters:\n");	snd_iprintf(buffer, "  PSDOUT03 : 0x%08x\n", (unsigned)inl(ICEMT1724(ice, ROUTE_PLAYBACK)));	for (idx = 0x0; idx < 0x20 ; idx++)		snd_iprintf(buffer, "  CCS%02x    : 0x%02x\n", idx, inb(ice->port+idx));	for (idx = 0x0; idx < 0x30 ; idx++)		snd_iprintf(buffer, "  MT%02x     : 0x%02x\n", idx, inb(ice->profi_port+idx));}static void __devinit snd_vt1724_proc_init(ice1712_t * ice){	snd_info_entry_t *entry;	if (! snd_card_proc_new(ice->card, "ice1724", &entry))		snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read);}/* * */static int snd_vt1724_eeprom_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;	uinfo->count = sizeof(ice1712_eeprom_t);	return 0;}static int snd_vt1724_eeprom_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	ice1712_t *ice = snd_kcontrol_chip(kcontrol);		memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom));	return 0;}static snd_kcontrol_new_t snd_vt1724_eeprom __devinitdata = {	.iface = SNDRV_CTL_ELEM_IFACE_CARD,	.name = "ICE1724 EEPROM",	.access = SNDRV_CTL_ELEM_ACCESS_READ,	.info = snd_vt1724_eeprom_info,	.get = snd_vt1724_eeprom_get};/* */static int snd_vt1724_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga){	unsigned int val;	val = diga->status[0] & 0x03; /* professional, non-audio */	if (val & 0x01) {		/* professional */		if ((diga->status[0] & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)			val |= 1U << 3;		switch (diga->status[0] & IEC958_AES0_PRO_FS) {		case IEC958_AES0_PRO_FS_44100:			break;		case IEC958_AES0_PRO_FS_32000:			val |= 3U << 12;			break;		default:			val |= 2U << 12;			break;		}	} else {		/* consumer */		val |= diga->status[1] & 0x04; /* copyright */		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS)== IEC958_AES0_CON_EMPHASIS_5015)			val |= 1U << 3;		val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */		val |= (unsigned int)(diga->status[3] & IEC958_AES3_CON_FS) << 12; /* fs */	}	return val;}static void decode_spdif_bits(snd_aes_iec958_t *diga, unsigned int val){	memset(diga->status, 0, sizeof(diga->status));	diga->status[0] = val & 0x03; /* professional, non-audio */	if (val & 0x01) {		/* professional */		if (val & (1U << 3))			diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015;		switch ((val >> 12) & 0x7) {		case 0:			break;		case 2:			diga->status[0] |= IEC958_AES0_PRO_FS_32000;			break;		default:			diga->status[0] |= IEC958_AES0_PRO_FS_48000;			break;		}	} else {		/* consumer */		diga->status[0] |= val & (1U << 2); /* copyright */		if (val & (1U << 3))			diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015;		diga->status[1] |= (val >> 4) & 0x3f; /* category */		diga->status[3] |= (val >> 12) & 0x07; /* fs */	}}static int snd_vt1724_spdif_default_get(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	ice1712_t *ice = snd_kcontrol_chip(kcontrol);	unsigned int val;	val = inw(ICEMT1724(ice, SPDIF_CTRL));	decode_spdif_bits(&ucontrol->value.iec958, val);	return 0;}static int snd_vt1724_spdif_default_put(snd_kcontrol_t * kcontrol,					 snd_ctl_elem_value_t * ucontrol){	ice1712_t *ice = snd_kcontrol_chip(kcontrol);	unsigned int val, old;	val = encode_spdif_bits(&ucontrol->value.iec958);	spin_lock_irq(&ice->reg_lock);	old = inw(ICEMT1724(ice, SPDIF_CTRL));	if (val != old)		update_spdif_bits(ice, val);	spin_unlock_irq(&ice->reg_lock);	return (val != old);}static snd_kcontrol_new_t snd_vt1724_spdif_default __devinitdata ={	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),	.info =		snd_vt1724_spdif_info,	.get =		snd_vt1724_spdif_default_get,	.put =		snd_vt1724_spdif_default_put};static int snd_vt1724_spdif_maskc_get(snd_kcontrol_t * kcontrol,				       snd_ctl_elem_value_t * ucontrol){	ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO |						     IEC958_AES0_PROFESSIONAL |						     IEC958_AES0_CON_NOT_COPYRIGHT |						     IEC958_AES0_CON_EMPHASIS;	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL |						     IEC958_AES1_CON_CATEGORY;	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;

⌨️ 快捷键说明

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