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

📄 emufx.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto __error;		}		snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||		                  gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);		snd_runtime_check(gctl.id.name[0] != '\0', err = -EINVAL; goto __error);		ctl = snd_emu10k1_look_for_ctl(emu, &gctl.id);		memset(&knew, 0, sizeof(knew));		knew.iface = gctl.id.iface;		knew.name = gctl.id.name;		knew.index = gctl.id.index;		knew.device = gctl.id.device;		knew.subdevice = gctl.id.subdevice;		knew.info = snd_emu10k1_gpr_ctl_info;		knew.get = snd_emu10k1_gpr_ctl_get;		knew.put = snd_emu10k1_gpr_ctl_put;		memset(&nctl, 0, sizeof(nctl));		nctl.vcount = gctl.vcount;		nctl.count = gctl.count;		for (j = 0; j < 32; j++) {			nctl.gpr[j] = gctl.gpr[j];			nctl.value[j] = ~gctl.value[j];	/* inverted, we want to write new value in gpr_ctl_put() */			val->value.integer.value[j] = gctl.value[j];		}		nctl.min = gctl.min;		nctl.max = gctl.max;		nctl.translation = gctl.translation;		if (ctl == NULL) {			ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);			if (ctl == NULL)				continue;			knew.private_value = (unsigned long)ctl;			memcpy(ctl, &nctl, sizeof(nctl));			if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {				kfree(ctl);				goto __error;			}			kctl->private_free = snd_emu10k1_ctl_private_free;			ctl->kcontrol = kctl;			list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);		} else {			/* overwrite */			nctl.list = ctl->list;			nctl.kcontrol = ctl->kcontrol;			memcpy(ctl, &nctl, sizeof(nctl));			snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |			                          SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);		}		snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);	}      __error:	kfree(val);	return err;}static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	unsigned int i;	snd_ctl_elem_id_t id;	snd_ctl_elem_id_t __user *_id;	snd_emu10k1_fx8010_ctl_t *ctl;	snd_card_t *card = emu->card;		for (i = 0, _id = icode->gpr_del_controls;	     i < icode->gpr_del_control_count; i++, _id++) {	     	snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, return -EFAULT);		down_write(&card->controls_rwsem);		ctl = snd_emu10k1_look_for_ctl(emu, &id);		if (ctl)			snd_ctl_remove(card, ctl->kcontrol);		up_write(&card->controls_rwsem);	}	return 0;}static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	unsigned int i = 0, j;	unsigned int total = 0;	emu10k1_fx8010_control_gpr_t gctl;	emu10k1_fx8010_control_gpr_t __user *_gctl;	snd_emu10k1_fx8010_ctl_t *ctl;	snd_ctl_elem_id_t *id;	struct list_head *list;	_gctl = icode->gpr_list_controls;		list_for_each(list, &emu->fx8010.gpr_ctl) {		ctl = emu10k1_gpr_ctl(list);		total++;		if (_gctl && i < icode->gpr_list_control_count) {			memset(&gctl, 0, sizeof(gctl));			id = &ctl->kcontrol->id;			gctl.id.iface = id->iface;			strlcpy(gctl.id.name, id->name, sizeof(gctl.id.name));			gctl.id.index = id->index;			gctl.id.device = id->device;			gctl.id.subdevice = id->subdevice;			gctl.vcount = ctl->vcount;			gctl.count = ctl->count;			for (j = 0; j < 32; j++) {				gctl.gpr[j] = ctl->gpr[j];				gctl.value[j] = ctl->value[j];			}			gctl.min = ctl->min;			gctl.max = ctl->max;			gctl.translation = ctl->translation;			if (copy_to_user(_gctl, &gctl, sizeof(gctl)))				return -EFAULT;			_gctl++;			i++;		}	}	icode->gpr_list_control_total = total;	return 0;}static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int err = 0;	down(&emu->fx8010.lock);	if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)		goto __error;	strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));	/* stop FX processor - this may be dangerous, but it's better to miss	   some samples than generate wrong ones - [jk] */	if (emu->audigy)		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);	else		snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);	/* ok, do the main job */	if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||	    (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||	    (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||	    (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||	    (err = snd_emu10k1_add_controls(emu, icode)) < 0)		goto __error;	/* start FX processor when the DSP code is updated */	if (emu->audigy)		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);	else		snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);      __error:	up(&emu->fx8010.lock);	return err;}static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int err;	down(&emu->fx8010.lock);	strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));	/* ok, do the main job */	err = snd_emu10k1_gpr_peek(emu, icode);	if (err >= 0)		err = snd_emu10k1_tram_peek(emu, icode);	if (err >= 0)		err = snd_emu10k1_code_peek(emu, icode);	if (err >= 0)		err = snd_emu10k1_list_controls(emu, icode);	up(&emu->fx8010.lock);	return err;}static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm){	unsigned int i;	int err = 0;	snd_emu10k1_fx8010_pcm_t *pcm;	if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)		return -EINVAL;	if (ipcm->channels > 32)		return -EINVAL;	pcm = &emu->fx8010.pcm[ipcm->substream];	down(&emu->fx8010.lock);	spin_lock_irq(&emu->reg_lock);	if (pcm->opened) {		err = -EBUSY;		goto __error;	}	if (ipcm->channels == 0) {	/* remove */		pcm->valid = 0;	} else {		/* FIXME: we need to add universal code to the PCM transfer routine */		if (ipcm->channels != 2) {			err = -EINVAL;			goto __error;		}		pcm->valid = 1;		pcm->opened = 0;		pcm->channels = ipcm->channels;		pcm->tram_start = ipcm->tram_start;		pcm->buffer_size = ipcm->buffer_size;		pcm->gpr_size = ipcm->gpr_size;		pcm->gpr_count = ipcm->gpr_count;		pcm->gpr_tmpcount = ipcm->gpr_tmpcount;		pcm->gpr_ptr = ipcm->gpr_ptr;		pcm->gpr_trigger = ipcm->gpr_trigger;		pcm->gpr_running = ipcm->gpr_running;		for (i = 0; i < pcm->channels; i++)			pcm->etram[i] = ipcm->etram[i];	}      __error:	spin_unlock_irq(&emu->reg_lock);	up(&emu->fx8010.lock);	return err;}static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm){	unsigned int i;	int err = 0;	snd_emu10k1_fx8010_pcm_t *pcm;	if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)		return -EINVAL;	pcm = &emu->fx8010.pcm[ipcm->substream];	down(&emu->fx8010.lock);	spin_lock_irq(&emu->reg_lock);	ipcm->channels = pcm->channels;	ipcm->tram_start = pcm->tram_start;	ipcm->buffer_size = pcm->buffer_size;	ipcm->gpr_size = pcm->gpr_size;	ipcm->gpr_ptr = pcm->gpr_ptr;	ipcm->gpr_count = pcm->gpr_count;	ipcm->gpr_tmpcount = pcm->gpr_tmpcount;	ipcm->gpr_trigger = pcm->gpr_trigger;	ipcm->gpr_running = pcm->gpr_running;	for (i = 0; i < pcm->channels; i++)		ipcm->etram[i] = pcm->etram[i];	ipcm->res1 = ipcm->res2 = 0;	ipcm->pad = 0;	spin_unlock_irq(&emu->reg_lock);	up(&emu->fx8010.lock);	return err;}#define SND_EMU10K1_GPR_CONTROLS	41#define SND_EMU10K1_INPUTS		10#define SND_EMU10K1_PLAYBACK_CHANNELS	8#define SND_EMU10K1_CAPTURE_CHANNELS	4static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval){	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;	strcpy(ctl->id.name, name);	ctl->vcount = ctl->count = 1;	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;	ctl->min = 0;	ctl->max = 100;	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;	}static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval){	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;	strcpy(ctl->id.name, name);	ctl->vcount = ctl->count = 2;	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;	ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;	ctl->min = 0;	ctl->max = 100;	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;}static void __devinit snd_emu10k1_init_mono_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval){	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;	strcpy(ctl->id.name, name);	ctl->vcount = ctl->count = 1;	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;	ctl->min = 0;	ctl->max = 1;	ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;}static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval){	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;	strcpy(ctl->id.name, name);	ctl->vcount = ctl->count = 2;	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;	ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;	ctl->min = 0;	ctl->max = 1;	ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;}/* * initial DSP configuration for Audigy */static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu){	int err, i, z, gpr, nctl;	const int playback = 10;	const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */	const int stereo_mix = capture + 2;	const int tmp = 0x88;	u32 ptr;	emu10k1_fx8010_code_t *icode = NULL;	emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;	mm_segment_t seg;	spin_lock_init(&emu->fx8010.irq_lock);	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||	    (icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||	    (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {		err = -ENOMEM;		goto __err;	}	icode->tram_data_map = icode->gpr_map + 512;	icode->tram_addr_map = icode->tram_data_map + 256;	icode->code = icode->tram_addr_map + 256;	/* clear free GPRs */	for (i = 0; i < 512; i++)		set_bit(i, icode->gpr_valid);			/* clear TRAM data & address lines */	for (i = 0; i < 256; i++)		set_bit(i, icode->tram_valid);	strcpy(icode->name, "Audigy DSP code for ALSA");	ptr = 0;	nctl = 0;	gpr = stereo_mix + 10;	/* stop FX processor */	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);	/* PCM front Playback Volume (independent from stereo mix) */	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);	gpr += 2;		/* PCM Surround Playback (independent from stereo mix) */	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);

⌨️ 快捷键说明

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