📄 au88x0_pcm.c
字号:
vortex_wt_allocroute(chip, stream->dma, 0); }#endif substream->runtime->private_data = NULL; spin_unlock_irq(&chip->lock); return snd_pcm_lib_free_pages(substream);}/* prepare callback */static int snd_vortex_pcm_prepare(snd_pcm_substream_t * substream){ vortex_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; stream_t *stream = (stream_t *) substream->runtime->private_data; int dma = stream->dma, fmt, dir; // set up the hardware with the current configuration. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dir = 1; else dir = 0; fmt = vortex_alsafmt_aspfmt(runtime->format); spin_lock_irq(&chip->lock); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { vortex_adbdma_setmode(chip, dma, 1, dir, fmt, 0 /*? */ , 0); vortex_adbdma_setstartbuffer(chip, dma, 0); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF) vortex_adb_setsrc(chip, dma, runtime->rate, dir); }#ifndef CHIP_AU8810 else { vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0); // FIXME: Set rate (i guess using vortex_wt_writereg() somehow). vortex_wtdma_setstartbuffer(chip, dma, 0); }#endif spin_unlock_irq(&chip->lock); return 0;}/* trigger callback */static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd){ vortex_t *chip = snd_pcm_substream_chip(substream); stream_t *stream = (stream_t *) substream->runtime->private_data; int dma = stream->dma; spin_lock(&chip->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: // do something to start the PCM engine //printk(KERN_INFO "vortex: start %d\n", dma); stream->fifo_enabled = 1; if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { vortex_adbdma_resetup(chip, dma); vortex_adbdma_startfifo(chip, dma); }#ifndef CHIP_AU8810 else { printk(KERN_INFO "vortex: wt start %d\n", dma); vortex_wtdma_startfifo(chip, dma); }#endif break; case SNDRV_PCM_TRIGGER_STOP: // do something to stop the PCM engine //printk(KERN_INFO "vortex: stop %d\n", dma); stream->fifo_enabled = 0; if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) vortex_adbdma_pausefifo(chip, dma); //vortex_adbdma_stopfifo(chip, dma);#ifndef CHIP_AU8810 else { printk(KERN_INFO "vortex: wt stop %d\n", dma); vortex_wtdma_stopfifo(chip, dma); }#endif break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: //printk(KERN_INFO "vortex: pause %d\n", dma); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) vortex_adbdma_pausefifo(chip, dma);#ifndef CHIP_AU8810 else vortex_wtdma_pausefifo(chip, dma);#endif break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: //printk(KERN_INFO "vortex: resume %d\n", dma); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) vortex_adbdma_resumefifo(chip, dma);#ifndef CHIP_AU8810 else vortex_wtdma_resumefifo(chip, dma);#endif break; default: spin_unlock(&chip->lock); return -EINVAL; } spin_unlock(&chip->lock); return 0;}/* pointer callback */static snd_pcm_uframes_t snd_vortex_pcm_pointer(snd_pcm_substream_t * substream){ vortex_t *chip = snd_pcm_substream_chip(substream); stream_t *stream = (stream_t *) substream->runtime->private_data; int dma = stream->dma; snd_pcm_uframes_t current_ptr = 0; spin_lock(&chip->lock); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) current_ptr = vortex_adbdma_getlinearpos(chip, dma);#ifndef CHIP_AU8810 else current_ptr = vortex_wtdma_getlinearpos(chip, dma);#endif //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr); spin_unlock(&chip->lock); return (bytes_to_frames(substream->runtime, current_ptr));}/* Page callback. *//*static struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset) { }*//* operators */static snd_pcm_ops_t snd_vortex_playback_ops = { .open = snd_vortex_pcm_open, .close = snd_vortex_pcm_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_vortex_pcm_hw_params, .hw_free = snd_vortex_pcm_hw_free, .prepare = snd_vortex_pcm_prepare, .trigger = snd_vortex_pcm_trigger, .pointer = snd_vortex_pcm_pointer, .page = snd_pcm_sgbuf_ops_page,};/** definitions of capture are omitted here...*/static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = { "AU88x0 ADB", "AU88x0 SPDIF", "AU88x0 A3D", "AU88x0 WT", "AU88x0 I2S",};static char *vortex_pcm_name[VORTEX_PCM_LAST] = { "adb", "spdif", "a3d", "wt", "i2s",};/* SPDIF kcontrol */static intsnd_vortex_spdif_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo){ static char *texts[] = { "32000", "44100", "48000" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static intsnd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ vortex_t *vortex = snd_kcontrol_chip(kcontrol); if (vortex->spdif_sr == 32000) ucontrol->value.enumerated.item[0] = 0; if (vortex->spdif_sr == 44100) ucontrol->value.enumerated.item[0] = 1; if (vortex->spdif_sr == 48000) ucontrol->value.enumerated.item[0] = 2; return 0;}static intsnd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ vortex_t *vortex = snd_kcontrol_chip(kcontrol); static unsigned int sr[3] = { 32000, 44100, 48000 }; //printk("vortex: spdif sr = %d\n", ucontrol->value.enumerated.item[0]); vortex->spdif_sr = sr[ucontrol->value.enumerated.item[0] % 3]; vortex_spdif_init(vortex, sr[ucontrol->value.enumerated.item[0] % 3], 1); return 1;}static snd_kcontrol_new_t vortex_spdif_kcontrol __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "SPDIF SR", .index = 0, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .private_value = 0, .info = snd_vortex_spdif_info, .get = snd_vortex_spdif_get, .put = snd_vortex_spdif_put};/* create a pcm device */static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr){ snd_pcm_t *pcm; int err, nr_capt; if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST)) return -ENODEV; /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the * same dma engine. WT uses it own separate dma engine whcih cant capture. */ if (idx == VORTEX_PCM_ADB) nr_capt = nr; else nr_capt = 0; if ((err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr, nr_capt, &pcm)) < 0) return err; strcpy(pcm->name, vortex_pcm_name[idx]); chip->pcm[idx] = pcm; // This is an evil hack, but it saves a lot of duplicated code. VORTEX_PCM_TYPE(pcm) = idx; pcm->private_data = chip; /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_vortex_playback_ops); if (idx == VORTEX_PCM_ADB) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_vortex_playback_ops); /* pre-allocation of Scatter-Gather buffers */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci_dev), 0x10000, 0x10000); if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) { snd_kcontrol_t *kcontrol; if ((kcontrol = snd_ctl_new1(&vortex_spdif_kcontrol, chip)) == NULL) return -ENOMEM; if ((err = snd_ctl_add(chip->card, kcontrol)) < 0) return err; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -