📄 emu8000.c
字号:
{AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},};/*exported*/ intsnd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, long len){ soundfont_reverb_fx_t rec; if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) { snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode); return -EINVAL; } if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) return -EFAULT; reverb_parm[mode] = rec; reverb_defined[mode] = 1; return 0;}/*exported*/ voidsnd_emu8000_update_reverb_mode(emu8000_t *emu){ int effect = emu->reverb_mode; int i; if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS || (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect])) return; for (i = 0; i < 28; i++) { int port; if (reverb_cmds[i].port == DATA1) port = EMU8000_DATA1(emu); else port = EMU8000_DATA2(emu); snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]); }}/*---------------------------------------------------------------- * mixer interface *----------------------------------------------------------------*//* * bass/treble */static int mixer_bass_treble_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 11; return 0;}static int mixer_bass_treble_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level; return 0;}static int mixer_bass_treble_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1; val1 = ucontrol->value.integer.value[0] % 12; spin_lock_irqsave(&emu->control_lock, flags); if (kcontrol->private_value) { change = val1 != emu->treble_level; emu->treble_level = val1; } else { change = val1 != emu->bass_level; emu->bass_level = val1; } spin_unlock_irqrestore(&emu->control_lock, flags); snd_emu8000_update_equalizer(emu); return change;}static snd_kcontrol_new_t mixer_bass_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Synth Tone Control - Bass", .info = mixer_bass_treble_info, .get = mixer_bass_treble_get, .put = mixer_bass_treble_put, .private_value = 0,};static snd_kcontrol_new_t mixer_treble_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Synth Tone Control - Treble", .info = mixer_bass_treble_info, .get = mixer_bass_treble_get, .put = mixer_bass_treble_put, .private_value = 1,};/* * chorus/reverb mode */static int mixer_chorus_reverb_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1); return 0;}static int mixer_chorus_reverb_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode; return 0;}static int mixer_chorus_reverb_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1; spin_lock_irqsave(&emu->control_lock, flags); if (kcontrol->private_value) { val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS; change = val1 != emu->chorus_mode; emu->chorus_mode = val1; } else { val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS; change = val1 != emu->reverb_mode; emu->reverb_mode = val1; } spin_unlock_irqrestore(&emu->control_lock, flags); if (change) { if (kcontrol->private_value) snd_emu8000_update_chorus_mode(emu); else snd_emu8000_update_reverb_mode(emu); } return change;}static snd_kcontrol_new_t mixer_chorus_mode_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Chorus Mode", .info = mixer_chorus_reverb_info, .get = mixer_chorus_reverb_get, .put = mixer_chorus_reverb_put, .private_value = 1,};static snd_kcontrol_new_t mixer_reverb_mode_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Reverb Mode", .info = mixer_chorus_reverb_info, .get = mixer_chorus_reverb_get, .put = mixer_chorus_reverb_put, .private_value = 0,};/* * FM OPL3 chorus/reverb depth */static int mixer_fm_depth_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0;}static int mixer_fm_depth_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth; return 0;}static int mixer_fm_depth_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu8000_t *emu = snd_kcontrol_chip(kcontrol); unsigned long flags; int change; unsigned short val1; val1 = ucontrol->value.integer.value[0] % 256; spin_lock_irqsave(&emu->control_lock, flags); if (kcontrol->private_value) { change = val1 != emu->fm_chorus_depth; emu->fm_chorus_depth = val1; } else { change = val1 != emu->fm_reverb_depth; emu->fm_reverb_depth = val1; } spin_unlock_irqrestore(&emu->control_lock, flags); if (change) snd_emu8000_init_fm(emu); return change;}static snd_kcontrol_new_t mixer_fm_chorus_depth_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "FM Chorus Depth", .info = mixer_fm_depth_info, .get = mixer_fm_depth_get, .put = mixer_fm_depth_put, .private_value = 1,};static snd_kcontrol_new_t mixer_fm_reverb_depth_control ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "FM Reverb Depth", .info = mixer_fm_depth_info, .get = mixer_fm_depth_get, .put = mixer_fm_depth_put, .private_value = 0,};static snd_kcontrol_new_t *mixer_defs[EMU8000_NUM_CONTROLS] = { &mixer_bass_control, &mixer_treble_control, &mixer_chorus_mode_control, &mixer_reverb_mode_control, &mixer_fm_chorus_depth_control, &mixer_fm_reverb_depth_control,};/* * create and attach mixer elements for WaveTable treble/bass controls */static int __initsnd_emu8000_create_mixer(snd_card_t *card, emu8000_t *emu){ int i, err = 0; snd_assert(emu != NULL && card != NULL, return -EINVAL); spin_lock_init(&emu->control_lock); memset(emu->controls, 0, sizeof(emu->controls)); for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) goto __error; } return 0;__error: for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { down_write(&card->controls_rwsem); if (emu->controls[i]) snd_ctl_remove(card, emu->controls[i]); up_write(&card->controls_rwsem); } return err;}/* * free resources */static int snd_emu8000_free(emu8000_t *hw){ release_and_free_resource(hw->res_port1); release_and_free_resource(hw->res_port2); release_and_free_resource(hw->res_port3); kfree(hw); return 0;}/* */static int snd_emu8000_dev_free(snd_device_t *device){ emu8000_t *hw = device->device_data; return snd_emu8000_free(hw);}/* * initialize and register emu8000 synth device. */int __initsnd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_device_t **awe_ret){ snd_seq_device_t *awe; emu8000_t *hw; int err; static snd_device_ops_t ops = { .dev_free = snd_emu8000_dev_free, }; if (awe_ret) *awe_ret = NULL; if (seq_ports <= 0) return 0; hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (hw == NULL) return -ENOMEM; spin_lock_init(&hw->reg_lock); hw->index = index; hw->port1 = port; hw->port2 = port + 0x400; hw->port3 = port + 0x800; if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) || !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) || !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) { snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3); snd_emu8000_free(hw); return -EBUSY; } hw->mem_size = 0; hw->card = card; hw->seq_ports = seq_ports; hw->bass_level = 5; hw->treble_level = 9; hw->chorus_mode = 2; hw->reverb_mode = 4; hw->fm_chorus_depth = 0; hw->fm_reverb_depth = 0; if (snd_emu8000_detect(hw) < 0) { snd_emu8000_free(hw); return -ENODEV; } snd_emu8000_init_hw(hw); if ((err = snd_emu8000_create_mixer(card, hw)) < 0) { snd_emu8000_free(hw); return err; } if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) { snd_emu8000_free(hw); return err; }#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, sizeof(emu8000_t*), &awe) >= 0) { strcpy(awe->name, "EMU-8000"); *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw; }#else awe = NULL;#endif if (awe_ret) *awe_ret = awe; return 0;}/* * exported stuff */EXPORT_SYMBOL(snd_emu8000_poke);EXPORT_SYMBOL(snd_emu8000_peek);EXPORT_SYMBOL(snd_emu8000_poke_dw);EXPORT_SYMBOL(snd_emu8000_peek_dw);EXPORT_SYMBOL(snd_emu8000_dma_chan);EXPORT_SYMBOL(snd_emu8000_init_fm);EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);EXPORT_SYMBOL(snd_emu8000_update_equalizer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -