📄 emupcm.c
字号:
emu10k1_t *emu = snd_pcm_substream_chip(substream); emu10k1_pcm_t *epcm; emu10k1_pcm_mixer_t *mix; snd_pcm_runtime_t *runtime = substream->runtime; int i, err; epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL); if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->type = PLAYBACK_EMUVOICE; epcm->substream = substream; runtime->private_data = epcm; runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_playback; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { snd_magic_kfree(epcm); return err; } if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) { snd_magic_kfree(epcm); return err; } mix = &emu->pcm_mixer[substream->number]; for (i = 0; i < 4; i++) mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i; memset(&mix->send_volume, 0, sizeof(mix->send_volume)); mix->send_volume[0][0] = mix->send_volume[0][1] = mix->send_volume[1][0] = mix->send_volume[2][1] = 255; mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; mix->epcm = epcm; snd_emu10k1_pcm_mixer_notify(emu->card, mix, 1); return 0;}static int snd_emu10k1_playback_close(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number]; mix->epcm = NULL; snd_emu10k1_pcm_mixer_notify(emu->card, mix, 0); return 0;}static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; emu10k1_pcm_t *epcm; epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL); if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->type = CAPTURE_AC97ADC; epcm->substream = substream; epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL; epcm->capture_inte = INTE_ADCBUFENABLE; epcm->capture_ba_reg = ADCBA; epcm->capture_bs_reg = ADCBS; epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX; runtime->private_data = epcm; runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_capture; emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt; emu->pcm_capture_substream = substream; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates); return 0;}static int snd_emu10k1_capture_close(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu->capture_interrupt = NULL; emu->pcm_capture_substream = NULL; return 0;}static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu10k1_pcm_t *epcm; snd_pcm_runtime_t *runtime = substream->runtime; epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL); if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->type = CAPTURE_AC97MIC; epcm->substream = substream; epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL; epcm->capture_inte = INTE_MICBUFENABLE; epcm->capture_ba_reg = MICBA; epcm->capture_bs_reg = MICBS; epcm->capture_idx_reg = MICIDX; substream->runtime->private_data = epcm; substream->runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_capture; runtime->hw.rates = SNDRV_PCM_RATE_8000; runtime->hw.rate_min = runtime->hw.rate_max = 8000; runtime->hw.channels_min = 1; emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt; emu->pcm_capture_mic_substream = substream; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); return 0;}static int snd_emu10k1_capture_mic_close(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu->capture_interrupt = NULL; emu->pcm_capture_mic_substream = NULL; return 0;}static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu10k1_pcm_t *epcm; snd_pcm_runtime_t *runtime = substream->runtime; unsigned long flags; int nefx = emu->audigy ? 64 : 32; int idx; epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL); if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->type = CAPTURE_EFX; epcm->substream = substream; epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL; epcm->capture_inte = INTE_EFXBUFENABLE; epcm->capture_ba_reg = FXBA; epcm->capture_bs_reg = FXBS; epcm->capture_idx_reg = FXIDX; substream->runtime->private_data = epcm; substream->runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_capture; runtime->hw.rates = SNDRV_PCM_RATE_48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000; spin_lock_irqsave(&emu->reg_lock, flags); runtime->hw.channels_min = runtime->hw.channels_max = 0; for (idx = 0; idx < nefx; idx++) { if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) { runtime->hw.channels_min++; runtime->hw.channels_max++; } } epcm->capture_cr_val = emu->efx_voices_mask[0]; epcm->capture_cr_val2 = emu->efx_voices_mask[1]; spin_unlock_irqrestore(&emu->reg_lock, flags); emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt; emu->pcm_capture_efx_substream = substream; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); return 0;}static int snd_emu10k1_capture_efx_close(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu->capture_interrupt = NULL; emu->pcm_capture_efx_substream = NULL; return 0;}static snd_pcm_ops_t snd_emu10k1_playback_ops = { open: snd_emu10k1_playback_open, close: snd_emu10k1_playback_close, ioctl: snd_pcm_lib_ioctl, hw_params: snd_emu10k1_playback_hw_params, hw_free: snd_emu10k1_playback_hw_free, prepare: snd_emu10k1_playback_prepare, trigger: snd_emu10k1_playback_trigger, pointer: snd_emu10k1_playback_pointer,};static snd_pcm_ops_t snd_emu10k1_capture_ops = { open: snd_emu10k1_capture_open, close: snd_emu10k1_capture_close, ioctl: snd_pcm_lib_ioctl, hw_params: snd_emu10k1_capture_hw_params, hw_free: snd_emu10k1_capture_hw_free, prepare: snd_emu10k1_capture_prepare, trigger: snd_emu10k1_capture_trigger, pointer: snd_emu10k1_capture_pointer,};static void snd_emu10k1_pcm_free(snd_pcm_t *pcm){ emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return); emu->pcm = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_emu10k1_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, 32, 1, &pcm)) < 0) return err; pcm->private_data = emu; pcm->private_free = snd_emu10k1_pcm_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops); pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strcpy(pcm->name, "EMU10K1"); emu->pcm = pcm; snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 128*1024); if (rpcm) *rpcm = pcm; return 0;}static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = { open: snd_emu10k1_capture_mic_open, close: snd_emu10k1_capture_mic_close, ioctl: snd_pcm_lib_ioctl, hw_params: snd_emu10k1_capture_hw_params, hw_free: snd_emu10k1_capture_hw_free, prepare: snd_emu10k1_capture_prepare, trigger: snd_emu10k1_capture_trigger, pointer: snd_emu10k1_capture_pointer,};static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm){ emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return); emu->pcm_mic = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_emu10k1_pcm_mic(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 mic", device, 0, 1, &pcm)) < 0) return err; pcm->private_data = emu; pcm->private_free = snd_emu10k1_pcm_mic_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops); pcm->info_flags = 0; strcpy(pcm->name, "EMU10K1 MIC"); emu->pcm_mic = pcm; snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 64*1024); if (rpcm) *rpcm = pcm; return 0;}static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){ emu10k1_t *emu = snd_kcontrol_chip(kcontrol); int nefx = emu->audigy ? 64 : 32; uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = nefx; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu10k1_t *emu = snd_kcontrol_chip(kcontrol); unsigned long flags; int nefx = emu->audigy ? 64 : 32; int idx; spin_lock_irqsave(&emu->reg_lock, flags); for (idx = 0; idx < nefx; idx++) ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0; spin_unlock_irqrestore(&emu->reg_lock, flags); return 0;}static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ emu10k1_t *emu = snd_kcontrol_chip(kcontrol); unsigned long flags; unsigned int nval[2], bits; int nefx = emu->audigy ? 64 : 32; int change, idx; nval[0] = nval[1] = 0; for (idx = 0, bits = 0; idx < nefx; idx++) if (ucontrol->value.integer.value[idx]) { nval[idx / 32] |= 1 << (idx % 32); bits++; } if (bits != 1 && bits != 2 && bits != 4 && bits != 8) return -EINVAL; spin_lock_irqsave(&emu->reg_lock, flags); change = (nval[0] != emu->efx_voices_mask[0]) || (nval[1] != emu->efx_voices_mask[1]); emu->efx_voices_mask[0] = nval[0]; emu->efx_voices_mask[1] = nval[1]; spin_unlock_irqrestore(&emu->reg_lock, flags); return change;}static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = { iface: SNDRV_CTL_ELEM_IFACE_PCM, name: "EFX voices mask", info: snd_emu10k1_pcm_efx_voices_mask_info, get: snd_emu10k1_pcm_efx_voices_mask_get, put: snd_emu10k1_pcm_efx_voices_mask_put};static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = { open: snd_emu10k1_capture_efx_open, close: snd_emu10k1_capture_efx_close, ioctl: snd_pcm_lib_ioctl, hw_params: snd_emu10k1_capture_hw_params, hw_free: snd_emu10k1_capture_hw_free, prepare: snd_emu10k1_capture_prepare, trigger: snd_emu10k1_capture_trigger, pointer: snd_emu10k1_capture_pointer,};static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm){ emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return); emu->pcm_efx = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}int __devinit snd_emu10k1_pcm_efx(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 efx", device, 0, 1, &pcm)) < 0) return err; pcm->private_data = emu; pcm->private_free = snd_emu10k1_pcm_efx_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops); pcm->info_flags = 0; strcpy(pcm->name, "EMU10K1 EFX"); emu->pcm_efx = pcm; if (rpcm) *rpcm = pcm; emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; emu->efx_voices_mask[1] = 0; snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu)); snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 64*1024); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -