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

📄 emufx.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int change = 0;		spin_lock_irqsave(&emu->reg_lock, flags);	for (i = 0; i < ctl->vcount; i++) {		nval = ucontrol->value.integer.value[i];		if (nval < ctl->min)			nval = ctl->min;		if (nval > ctl->max)			nval = ctl->max;		if (nval != ctl->value[i])			change = 1;		val = ctl->value[i] = nval;		switch (ctl->translation) {		case EMU10K1_GPR_TRANSLATION_NONE:			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val);			break;		case EMU10K1_GPR_TRANSLATION_TABLE100:			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]);			break;		case EMU10K1_GPR_TRANSLATION_BASS:			snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error);			for (j = 0; j < 5; j++)				snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);			break;		case EMU10K1_GPR_TRANSLATION_TREBLE:			snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error);			for (j = 0; j < 5; j++)				snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);			break;		case EMU10K1_GPR_TRANSLATION_ONOFF:			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);			break;		}	}      __error:	spin_unlock_irqrestore(&emu->reg_lock, flags);	return change;}/* *   Interrupt handler */static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu){	snd_emu10k1_fx8010_irq_t *irq, *nirq;	irq = emu->fx8010.irq_handlers;	while (irq) {		nirq = irq->next;	/* irq ptr can be removed from list */		if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {			if (irq->handler)				irq->handler(emu, irq->private_data);			snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);		}		irq = nirq;	}}int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,						   snd_fx8010_irq_handler_t *handler,						   unsigned char gpr_running,						   void *private_data,						   snd_emu10k1_fx8010_irq_t **r_irq){	snd_emu10k1_fx8010_irq_t *irq;	unsigned long flags;		snd_runtime_check(emu, return -EINVAL);	snd_runtime_check(handler, return -EINVAL);	irq = kmalloc(sizeof(*irq), GFP_ATOMIC);	if (irq == NULL)		return -ENOMEM;	irq->handler = handler;	irq->gpr_running = gpr_running;	irq->private_data = private_data;	irq->next = NULL;	spin_lock_irqsave(&emu->fx8010.irq_lock, flags);	if (emu->fx8010.irq_handlers == NULL) {		emu->fx8010.irq_handlers = irq;		emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;		snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);	} else {		irq->next = emu->fx8010.irq_handlers;		emu->fx8010.irq_handlers = irq;	}	spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);	if (r_irq)		*r_irq = irq;	return 0;}int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,					      snd_emu10k1_fx8010_irq_t *irq){	snd_emu10k1_fx8010_irq_t *tmp;	unsigned long flags;		snd_runtime_check(irq, return -EINVAL);	spin_lock_irqsave(&emu->fx8010.irq_lock, flags);	if ((tmp = emu->fx8010.irq_handlers) == irq) {		emu->fx8010.irq_handlers = tmp->next;		if (emu->fx8010.irq_handlers == NULL) {			snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);			emu->dsp_interrupt = NULL;		}	} else {		while (tmp && tmp->next != irq)			tmp = tmp->next;		if (tmp)			tmp->next = tmp->next->next;	}	spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);	kfree(irq);	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)   * 2 + 0] = ((x & 0x3ff) << 10) | (y & 0x3ff);	icode->code[(*ptr)++ * 2 + 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 < 1024, return);	set_bit(*ptr, icode->code_valid);	icode->code[(*ptr)   * 2 + 0] = ((x & 0x7ff) << 12) | (y & 0x7ff);	icode->code[(*ptr)++ * 2 + 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)static 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 int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int gpr;	u32 val;	for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {		if (!test_bit(gpr, icode->gpr_valid))			continue;		if (get_user(val, &icode->gpr_map[gpr]))			return -EFAULT;		snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);	}	return 0;}static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int gpr;	u32 val;	for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {		set_bit(gpr, icode->gpr_valid);		val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);		if (put_user(val, &icode->gpr_map[gpr]))			return -EFAULT;	}	return 0;}static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int tram;	u32 addr, val;	for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {		if (!test_bit(tram, icode->tram_valid))			continue;		if (get_user(val, &icode->tram_data_map[tram]) ||		    get_user(addr, &icode->tram_addr_map[tram]))			return -EFAULT;		snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);		if (!emu->audigy) {			snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);		} else {			snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12);			snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20);		}	}	return 0;}static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	int tram;	u32 val, addr;	memset(icode->tram_valid, 0, sizeof(icode->tram_valid));	for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {		set_bit(tram, icode->tram_valid);		val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);		if (!emu->audigy) {			addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);		} else {			addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;			addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;		}		if (put_user(val, &icode->tram_data_map[tram]) ||		    put_user(addr, &icode->tram_addr_map[tram]))			return -EFAULT;	}	return 0;}static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	u32 pc, lo, hi;	for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {		if (!test_bit(pc / 2, icode->code_valid))			continue;		if (get_user(lo, &icode->code[pc + 0]) ||		    get_user(hi, &icode->code[pc + 1]))			return -EFAULT;		snd_emu10k1_efx_write(emu, pc + 0, lo);		snd_emu10k1_efx_write(emu, pc + 1, hi);	}	return 0;}static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	u32 pc;	memset(icode->code_valid, 0, sizeof(icode->code_valid));	for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {		set_bit(pc / 2, icode->code_valid);		if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))			return -EFAULT;		if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))			return -EFAULT;	}	return 0;}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){	unsigned int i;	snd_ctl_elem_id_t __user *_id;	snd_ctl_elem_id_t id;	emu10k1_fx8010_control_gpr_t __user *_gctl;	emu10k1_fx8010_control_gpr_t 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++, _gctl++) {		if (copy_from_user(&gctl, _gctl, sizeof(gctl)))			return -EFAULT;		if (snd_emu10k1_look_for_ctl(emu, &gctl.id))			continue;		down_read(&emu->card->controls_rwsem);		if (snd_ctl_find_id(emu->card, &gctl.id) != NULL) {			up_read(&emu->card->controls_rwsem);			return -EEXIST;		}		up_read(&emu->card->controls_rwsem);		if (gctl.id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&		    gctl.id.iface != SNDRV_CTL_ELEM_IFACE_PCM)			return -EINVAL;	}	for (i = 0, _gctl = icode->gpr_list_controls;	     i < icode->gpr_list_control_count; i++, _gctl++) {	     	/* FIXME: we need to check the WRITE access */		if (copy_from_user(&gctl, _gctl, sizeof(gctl)))			return -EFAULT;	}	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 int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode){	unsigned int i, j;	emu10k1_fx8010_control_gpr_t __user *_gctl;	emu10k1_fx8010_control_gpr_t gctl;	snd_emu10k1_fx8010_ctl_t *ctl, nctl;	snd_kcontrol_new_t knew;	snd_kcontrol_t *kctl;	snd_ctl_elem_value_t *val;	int err = 0;	val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);	if (!val)		return -ENOMEM;	for (i = 0, _gctl = icode->gpr_add_controls;	     i < icode->gpr_add_control_count; i++, _gctl++) {		if (copy_from_user(&gctl, _gctl, sizeof(gctl))) {			err = -EFAULT;

⌨️ 快捷键说明

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