📄 emumixer.c
字号:
.access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), .count = 3, .info = snd_emu10k1_spdif_info, .get = snd_emu10k1_spdif_get_mask};static struct snd_kcontrol_new snd_emu10k1_spdif_control ={ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .count = 3, .info = snd_emu10k1_spdif_info, .get = snd_emu10k1_spdif_get, .put = snd_emu10k1_spdif_put};static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route){ if (emu->audigy) { snd_emu10k1_ptr_write(emu, A_FXRT1, voice, snd_emu10k1_compose_audigy_fxrt1(route)); snd_emu10k1_ptr_write(emu, A_FXRT2, voice, snd_emu10k1_compose_audigy_fxrt2(route)); } else { snd_emu10k1_ptr_write(emu, FXRT, voice, snd_emu10k1_compose_send_routing(route)); }}static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume){ snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]); snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]); snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]); snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]); if (emu->audigy) { unsigned int val = ((unsigned int)volume[4] << 24) | ((unsigned int)volume[5] << 16) | ((unsigned int)volume[6] << 8) | (unsigned int)volume[7]; snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val); }}/* PCM stream controls */static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = emu->audigy ? 3*8 : 3*4; uinfo->value.integer.min = 0; uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; return 0;}static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int voice, idx; int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; spin_lock_irqsave(&emu->reg_lock, flags); for (voice = 0; voice < 3; voice++) for (idx = 0; idx < num_efx; idx++) ucontrol->value.integer.value[(voice * num_efx) + idx] = mix->send_routing[voice][idx] & mask; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, voice, idx, val; int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; spin_lock_irqsave(&emu->reg_lock, flags); for (voice = 0; voice < 3; voice++) for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; if (mix->send_routing[voice][idx] != val) { mix->send_routing[voice][idx] = val; change = 1; } } if (change && mix->epcm) { if (mix->epcm->voices[0] && mix->epcm->voices[1]) { update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, &mix->send_routing[1][0]); update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number, &mix->send_routing[2][0]); } else if (mix->epcm->voices[0]) { update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, &mix->send_routing[0][0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_send_routing_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "EMU10K1 PCM Send Routing", .count = 32, .info = snd_emu10k1_send_routing_info, .get = snd_emu10k1_send_routing_get, .put = snd_emu10k1_send_routing_put};static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = emu->audigy ? 3*8 : 3*4; uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0;}static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; int num_efx = emu->audigy ? 8 : 4; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < 3*num_efx; idx++) ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx]; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; int num_efx = emu->audigy ? 8 : 4; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < 3*num_efx; idx++) { val = ucontrol->value.integer.value[idx] & 255; if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { mix->send_volume[idx/num_efx][idx%num_efx] = val; change = 1; } } if (change && mix->epcm) { if (mix->epcm->voices[0] && mix->epcm->voices[1]) { update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, &mix->send_volume[1][0]); update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number, &mix->send_volume[2][0]); } else if (mix->epcm->voices[0]) { update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, &mix->send_volume[0][0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_send_volume_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "EMU10K1 PCM Send Volume", .count = 32, .info = snd_emu10k1_send_volume_info, .get = snd_emu10k1_send_volume_get, .put = snd_emu10k1_send_volume_put};static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 3; uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xffff; return 0;}static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; int idx; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < 3; idx++) ucontrol->value.integer.value[idx] = mix->attn[idx]; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int change = 0, idx, val; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < 3; idx++) { val = ucontrol->value.integer.value[idx] & 0xffff; if (mix->attn[idx] != val) { mix->attn[idx] = val; change = 1; } } if (change && mix->epcm) { if (mix->epcm->voices[0] && mix->epcm->voices[1]) { snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]); snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]); } else if (mix->epcm->voices[0]) { snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_attn_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "EMU10K1 PCM Volume", .count = 32, .info = snd_emu10k1_attn_info, .get = snd_emu10k1_attn_get, .put = snd_emu10k1_attn_put};/* Mutichannel PCM stream controls */static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = emu->audigy ? 8 : 4; uinfo->value.integer.min = 0; uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; return 0;}static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < num_efx; idx++) ucontrol->value.integer.value[idx] = mix->send_routing[0][idx] & mask; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; int num_efx = emu->audigy ? 8 : 4; int mask = emu->audigy ? 0x3f : 0x0f; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[idx] & mask; if (mix->send_routing[0][idx] != val) { mix->send_routing[0][idx] = val; change = 1; } } if (change && mix->epcm) { if (mix->epcm->voices[ch]) { update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, &mix->send_routing[0][0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "Multichannel PCM Send Routing", .count = 16, .info = snd_emu10k1_efx_send_routing_info, .get = snd_emu10k1_efx_send_routing_get, .put = snd_emu10k1_efx_send_routing_put};static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = emu->audigy ? 8 : 4; uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0;}static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; int idx; int num_efx = emu->audigy ? 8 : 4; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < num_efx; idx++) ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, idx, val; int num_efx = emu->audigy ? 8 : 4; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < num_efx; idx++) { val = ucontrol->value.integer.value[idx] & 255; if (mix->send_volume[0][idx] != val) { mix->send_volume[0][idx] = val; change = 1; } } if (change && mix->epcm) { if (mix->epcm->voices[ch]) { update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, &mix->send_volume[0][0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "Multichannel PCM Send Volume", .count = 16, .info = snd_emu10k1_efx_send_volume_info, .get = snd_emu10k1_efx_send_volume_get, .put = snd_emu10k1_efx_send_volume_put};static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xffff; return 0;}static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; unsigned long flags; spin_lock_irqsave(&emu->reg_lock, flags); ucontrol->value.integer.value[0] = mix->attn[0]; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ unsigned long flags; struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; int change = 0, val; spin_lock_irqsave(&emu->reg_lock, flags); val = ucontrol->value.integer.value[0] & 0xffff; if (mix->attn[0] != val) { mix->attn[0] = val; change = 1; } if (change && mix->epcm) { if (mix->epcm->voices[ch]) { snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); } } spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static struct snd_kcontrol_new snd_emu10k1_efx_attn_control ={ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "Multichannel PCM Volume", .count = 16, .info = snd_emu10k1_efx_attn_info, .get = snd_emu10k1_efx_attn_get, .put = snd_emu10k1_efx_attn_put};#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_infostatic int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); if (emu->audigy) ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -