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

📄 emufx.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];	spin_lock(&emu->reg_lock);	pcm->opened = 0;	spin_unlock(&emu->reg_lock);	return 0;}static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {	open:			snd_emu10k1_fx8010_playback_open,	close:			snd_emu10k1_fx8010_playback_close,	ioctl:			snd_pcm_lib_ioctl,	hw_params:		snd_emu10k1_fx8010_playback_hw_params,	hw_free:		snd_emu10k1_fx8010_playback_hw_free,	prepare:		snd_emu10k1_fx8010_playback_prepare,	trigger:		snd_emu10k1_fx8010_playback_trigger,	copy:			snd_emu10k1_fx8010_playback_copy,	pointer:		snd_emu10k1_fx8010_playback_pointer,};static void snd_emu10k1_fx8010_pcm_free(snd_pcm_t *pcm){	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);	emu->pcm_fx8010 = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 8, 0, &pcm)) < 0)		return err;	pcm->private_data = emu;	pcm->private_free = snd_emu10k1_fx8010_pcm_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);	pcm->info_flags = 0;	strcpy(pcm->name, "EMU10K1 FX8010");	emu->pcm_fx8010 = pcm;		snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 0);	if (rpcm)		*rpcm = pcm;	return 0;}/************************************************************************* * EMU10K1 effect manager *************************************************************************/static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,				 u32 op, u32 r, u32 a, u32 x, u32 y){	snd_assert(*ptr < 512, return);	set_bit(*ptr, &icode->code_valid);	icode->code[*ptr    ][0] = ((x & 0x3ff) << 10) | (y & 0x3ff);	icode->code[(*ptr)++][1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);}#define OP(icode, ptr, op, r, a, x, y) \	snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,					u32 op, u32 r, u32 a, u32 x, u32 y){	snd_assert(*ptr < 512, return);	set_bit(*ptr, &icode->code_valid);	icode->code[*ptr    ][0] = ((x & 0x7ff) << 12) | (y & 0x7ff);	icode->code[(*ptr)++][1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);}#define A_OP(icode, ptr, op, r, a, x, y) \	snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data){	pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;	snd_emu10k1_ptr_write(emu, pc, 0, data);}unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc){	pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;	return snd_emu10k1_ptr_read(emu, pc, 0);}static void snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int gpr;	for (gpr = 0; gpr < 0x100; gpr++) {		if (!test_bit(gpr, &icode->gpr_valid))			continue;		snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, icode->gpr_map[gpr]);	}}static void snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int gpr;	for (gpr = 0; gpr < 0x100; gpr++) {		set_bit(gpr, &icode->gpr_valid);		icode->gpr_map[gpr] = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);	}}static void snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int tram;	for (tram = 0; tram < 0xa0; tram++) {		if (!test_bit(tram, &icode->tram_valid))			continue;		snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, icode->tram_data_map[tram]);		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram]);	}}static void snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int tram;	for (tram = 0; tram < 0xa0; tram++) {		set_bit(tram, &icode->tram_valid);		icode->tram_data_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);		icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);	}}static void snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	u32 pc;	for (pc = 0; pc < 512; pc++) {		if (!test_bit(pc, &icode->code_valid))			continue;		snd_emu10k1_efx_write(emu, pc * 2, icode->code[pc][0]);		snd_emu10k1_efx_write(emu, pc * 2 + 1, icode->code[pc][1]);	}}static void snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	u32 pc;	for (pc = 0; pc < 512; pc++) {		set_bit(pc, &icode->code_valid);		icode->code[pc][0] = snd_emu10k1_efx_read(emu, pc * 2);		icode->code[pc][1] = snd_emu10k1_efx_read(emu, pc * 2 + 1);	}}static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ctl_elem_id_t *id){	snd_emu10k1_fx8010_ctl_t *ctl;	snd_kcontrol_t *kcontrol;	struct list_head *list;		list_for_each(list, &emu->fx8010.gpr_ctl) {		ctl = emu10k1_gpr_ctl(list);		kcontrol = ctl->kcontrol;		if (kcontrol->id.iface == id->iface &&		    !strcmp(kcontrol->id.name, id->name) &&		    kcontrol->id.index == id->index)			return ctl;	}	return NULL;}static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int i;	snd_ctl_elem_id_t *_id, id;	emu10k1_fx8010_control_gpr_t *_gctl, gctl;		for (i = 0, _id = icode->gpr_del_controls;	     i < icode->gpr_del_control_count; i++, _id++) {	     	if (copy_from_user(&id, _id, sizeof(id)))	     		return -EFAULT;		if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)			return -ENOENT;	}	for (i = 0, _gctl = icode->gpr_add_controls;	     i < icode->gpr_add_control_count; i++) {		if (copy_from_user(&gctl, _gctl, sizeof(gctl)))			return -EFAULT;		if (snd_emu10k1_look_for_ctl(emu, &gctl.id))			continue;		if (snd_ctl_find_id(emu->card, &gctl.id) != NULL)			return -EEXIST;		if (gctl.id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&		    gctl.id.iface != SNDRV_CTL_ELEM_IFACE_PCM)			return -EINVAL;	}	return 0;}static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl){	snd_emu10k1_fx8010_ctl_t *ctl;		ctl = (snd_emu10k1_fx8010_ctl_t *)kctl->private_value;	kctl->private_value = 0;	list_del(&ctl->list);	kfree(ctl);}static void snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int i, j;	emu10k1_fx8010_control_gpr_t *_gctl, gctl;	snd_emu10k1_fx8010_ctl_t *ctl, nctl;	snd_kcontrol_new_t knew;	snd_kcontrol_t *kctl;	snd_ctl_elem_value_t val;	for (i = 0, _gctl = icode->gpr_add_controls;	     i < icode->gpr_add_control_count; i++, _gctl++) {		if (copy_from_user(&gctl, _gctl, sizeof(gctl)))			return;		snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||		                  gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, continue);		snd_runtime_check(gctl.id.name[0] != '\0', continue);		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.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];			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 (snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu)) < 0) {				kfree(ctl);				continue;			}			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);	}}static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int i;	snd_ctl_elem_id_t *_id, id;	snd_emu10k1_fx8010_ctl_t *ctl;		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, continue);		ctl = snd_emu10k1_look_for_ctl(emu, &id);		snd_runtime_check(ctl == NULL, continue);		snd_ctl_remove(emu->card, ctl->kcontrol);	}}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;	strncpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)-1);	emu->fx8010.name[sizeof(emu->fx8010.name)-1] = '\0';	/* 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 */	snd_emu10k1_del_controls(emu, icode);	snd_emu10k1_gpr_poke(emu, icode);	snd_emu10k1_tram_poke(emu, icode);	snd_emu10k1_code_poke(emu, icode);	snd_emu10k1_add_controls(emu, icode);	/* 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){	down(&emu->fx8010.lock);	strncpy(icode->name, emu->fx8010.name, sizeof(icode->name)-1);	emu->fx8010.name[sizeof(emu->fx8010.name)-1] = '\0';	/* ok, do the main job */	snd_emu10k1_gpr_peek(emu, icode);	snd_emu10k1_tram_peek(emu, icode);	snd_emu10k1_code_peek(emu, icode);	up(&emu->fx8010.lock);	return 0;}static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm){	int err = 0, i;	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;		}

⌨️ 快捷键说明

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