📄 emupcm.c
字号:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0, &emu->efx_pcm_mixer[0]); for (i = 1; i < NUM_EFX_PLAYBACK; i++) snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0, &emu->efx_pcm_mixer[i]); snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0); snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); for (i = 1; i < NUM_EFX_PLAYBACK; i++) snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0); epcm->running = 1; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: epcm->running = 0; for (i = 0; i < NUM_EFX_PLAYBACK; i++) { snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]); } snd_emu10k1_playback_stop_voice(emu, epcm->extra); break; default: result = -EINVAL; break; } spin_unlock(&emu->reg_lock); return result;}static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; emu10k1_pcm_t *epcm = runtime->private_data; unsigned int ptr; if (!epcm->running) return 0; if (epcm->first_ptr) { udelay(50); // hack, it takes awhile until capture is started epcm->first_ptr = 0; } ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff; return bytes_to_frames(runtime, ptr);}/* * Playback support device description */static snd_pcm_hardware_t snd_emu10k1_playback ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000, .rate_min = 4000, .rate_max = 96000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (128*1024), .period_bytes_min = 64, .period_bytes_max = (128*1024), .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};/* * Capture support device description */static snd_pcm_hardware_t snd_emu10k1_capture ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (64*1024), .period_bytes_min = 384, .period_bytes_max = (64*1024), .periods_min = 2, .periods_max = 2, .fifo_size = 0,};/* * */static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, int idx, int activate){ snd_ctl_elem_id_t id; if (! kctl) return; if (activate) kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; else kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_build_ioff(&id, kctl, idx));}static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate){ snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate); snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate); snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);}static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activate){ snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate); snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate); snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);}static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime){ kfree(runtime->private_data);}static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream){ emu10k1_t *emu = snd_pcm_substream_chip(substream); emu10k1_pcm_mixer_t *mix; int i; for (i=0; i < NUM_EFX_PLAYBACK; i++) { mix = &emu->efx_pcm_mixer[i]; mix->epcm = NULL; snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0); } return 0;}static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream){ 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; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->type = PLAYBACK_EFX; epcm->substream = substream; emu->pcm_playback_efx_substream = substream; runtime->private_data = epcm; runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_efx_playback; for (i=0; i < NUM_EFX_PLAYBACK; i++) { mix = &emu->efx_pcm_mixer[i]; mix->send_routing[0][0] = i; memset(&mix->send_volume, 0, sizeof(mix->send_volume)); mix->send_volume[0][0] = 255; mix->attn[0] = 0xffff; mix->epcm = epcm; snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1); } return 0;}static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream){ 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 = kzalloc(sizeof(*epcm), 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) { kfree(epcm); return err; } if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) { 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, substream->number, 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, substream->number, 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 = kzalloc(sizeof(*epcm), 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_BYTES, &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 = kzalloc(sizeof(*epcm), 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 = emu->audigy ? A_MICIDX : 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_BYTES, &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; int nefx = emu->audigy ? 64 : 32; int idx; epcm = kzalloc(sizeof(*epcm), 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_irq(&emu->reg_lock); 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_irq(&emu->reg_lock); 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_BYTES, &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, .page = snd_pcm_sgbuf_ops_page,};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,};/* EFX playback */static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = { .open = snd_emu10k1_efx_playback_open, .close = snd_emu10k1_efx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_emu10k1_playback_hw_params, .hw_free = snd_emu10k1_efx_playback_hw_free, .prepare = snd_emu10k1_efx_playback_prepare, .trigger = snd_emu10k1_efx_playback_trigger, .pointer = snd_emu10k1_efx_playback_pointer, .page = snd_pcm_sgbuf_ops_page,};static void snd_emu10k1_pcm_free(snd_pcm_t *pcm){ emu10k1_t *emu = pcm->private_data; 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; snd_pcm_substream_t *substream; 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, "ADC Capture/Standard PCM Playback"); emu->pcm = pcm; for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) return err; for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); if (rpcm) *rpcm = pcm; return 0;}int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; snd_pcm_substream_t *substream; int err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -