📄 rme96.c
字号:
} snd_rme96_playback_stop(rme96); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (RME96_ISPLAYING(rme96)) { snd_rme96_playback_stop(rme96); } break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (!RME96_ISPLAYING(rme96)) { snd_rme96_playback_start(rme96, 1); } break; default: return -EINVAL; } return 0;}static intsnd_rme96_capture_trigger(struct snd_pcm_substream *substream, int cmd){ struct rme96 *rme96 = snd_pcm_substream_chip(substream); switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (!RME96_ISRECORDING(rme96)) { if (substream != rme96->capture_substream) { return -EBUSY; } snd_rme96_capture_start(rme96, 0); } break; case SNDRV_PCM_TRIGGER_STOP: if (RME96_ISRECORDING(rme96)) { if (substream != rme96->capture_substream) { return -EBUSY; } snd_rme96_capture_stop(rme96); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (RME96_ISRECORDING(rme96)) { snd_rme96_capture_stop(rme96); } break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (!RME96_ISRECORDING(rme96)) { snd_rme96_capture_start(rme96, 1); } break; default: return -EINVAL; } return 0;}static snd_pcm_uframes_tsnd_rme96_playback_pointer(struct snd_pcm_substream *substream){ struct rme96 *rme96 = snd_pcm_substream_chip(substream); return snd_rme96_playback_ptr(rme96);}static snd_pcm_uframes_tsnd_rme96_capture_pointer(struct snd_pcm_substream *substream){ struct rme96 *rme96 = snd_pcm_substream_chip(substream); return snd_rme96_capture_ptr(rme96);}static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .open = snd_rme96_playback_spdif_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_rme96_playback_hw_params, .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, .copy = snd_rme96_playback_copy, .silence = snd_rme96_playback_silence, .mmap = snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .open = snd_rme96_capture_spdif_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_rme96_capture_hw_params, .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, .copy = snd_rme96_capture_copy, .mmap = snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme96_playback_adat_ops = { .open = snd_rme96_playback_adat_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_rme96_playback_hw_params, .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, .copy = snd_rme96_playback_copy, .silence = snd_rme96_playback_silence, .mmap = snd_pcm_lib_mmap_iomem,};static struct snd_pcm_ops snd_rme96_capture_adat_ops = { .open = snd_rme96_capture_adat_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_rme96_capture_hw_params, .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, .copy = snd_rme96_capture_copy, .mmap = snd_pcm_lib_mmap_iomem,};static voidsnd_rme96_free(void *private_data){ struct rme96 *rme96 = (struct rme96 *)private_data; if (rme96 == NULL) { return; } if (rme96->irq >= 0) { snd_rme96_playback_stop(rme96); snd_rme96_capture_stop(rme96); rme96->areg &= ~RME96_AR_DAC_EN; writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); free_irq(rme96->irq, (void *)rme96); rme96->irq = -1; } if (rme96->iobase) { iounmap(rme96->iobase); rme96->iobase = NULL; } if (rme96->port) { pci_release_regions(rme96->pci); rme96->port = 0; } pci_disable_device(rme96->pci);}static voidsnd_rme96_free_spdif_pcm(struct snd_pcm *pcm){ struct rme96 *rme96 = (struct rme96 *) pcm->private_data; rme96->spdif_pcm = NULL;}static voidsnd_rme96_free_adat_pcm(struct snd_pcm *pcm){ struct rme96 *rme96 = (struct rme96 *) pcm->private_data; rme96->adat_pcm = NULL;}static int __devinitsnd_rme96_create(struct rme96 *rme96){ struct pci_dev *pci = rme96->pci; int err; rme96->irq = -1; spin_lock_init(&rme96->lock); if ((err = pci_enable_device(pci)) < 0) return err; if ((err = pci_request_regions(pci, "RME96")) < 0) return err; rme96->port = pci_resource_start(rme96->pci, 0); if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); return -ENOMEM; } if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, "RME96", rme96)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme96->irq = pci->irq; /* read the card's revision number */ pci_read_config_byte(pci, 8, &rme96->rev); /* set up ALSA pcm device for S/PDIF */ if ((err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, 1, 1, &rme96->spdif_pcm)) < 0) { return err; } rme96->spdif_pcm->private_data = rme96; rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm; strcpy(rme96->spdif_pcm->name, "Digi96 IEC958"); snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_spdif_ops); snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_spdif_ops); rme96->spdif_pcm->info_flags = 0; /* set up ALSA pcm device for ADAT */ if (pci->device == PCI_DEVICE_ID_RME_DIGI96) { /* ADAT is not available on the base model */ rme96->adat_pcm = NULL; } else { if ((err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, 1, 1, &rme96->adat_pcm)) < 0) { return err; } rme96->adat_pcm->private_data = rme96; rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm; strcpy(rme96->adat_pcm->name, "Digi96 ADAT"); snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_adat_ops); snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops); rme96->adat_pcm->info_flags = 0; } rme96->playback_periodsize = 0; rme96->capture_periodsize = 0; /* make sure playback/capture is stopped, if by some reason active */ snd_rme96_playback_stop(rme96); snd_rme96_capture_stop(rme96); /* set default values in registers */ rme96->wcreg = RME96_WCR_FREQ_1 | /* set 44.1 kHz playback */ RME96_WCR_SEL | /* normal playback */ RME96_WCR_MASTER | /* set to master clock mode */ RME96_WCR_INP_0; /* set coaxial input */ rme96->areg = RME96_AR_FREQPAD_1; /* set 44.1 kHz analog capture */ writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); /* reset the ADC */ writel(rme96->areg | RME96_AR_PD2, rme96->iobase + RME96_IO_ADDITIONAL_REG); writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); /* reset and enable the DAC (order is important). */ snd_rme96_reset_dac(rme96); rme96->areg |= RME96_AR_DAC_EN; writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); /* reset playback and record buffer pointers */ writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); /* reset volume */ rme96->vol[0] = rme96->vol[1] = 0; if (RME96_HAS_ANALOG_OUT(rme96)) { snd_rme96_apply_dac_volume(rme96); } /* init switch interface */ if ((err = snd_rme96_create_switches(rme96->card, rme96)) < 0) { return err; } /* init proc interface */ snd_rme96_proc_init(rme96); return 0;}/* * proc interface */static void snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ int n; struct rme96 *rme96 = (struct rme96 *)entry->private_data; rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); snd_iprintf(buffer, rme96->card->longname); snd_iprintf(buffer, " (index #%d)\n", rme96->card->number + 1); snd_iprintf(buffer, "\nGeneral settings\n"); if (rme96->wcreg & RME96_WCR_IDIS) { snd_iprintf(buffer, " period size: N/A (interrupts " "disabled)\n"); } else if (rme96->wcreg & RME96_WCR_ISEL) { snd_iprintf(buffer, " period size: 2048 bytes\n"); } else { snd_iprintf(buffer, " period size: 8192 bytes\n"); } snd_iprintf(buffer, "\nInput settings\n"); switch (snd_rme96_getinputtype(rme96)) { case RME96_INPUT_OPTICAL: snd_iprintf(buffer, " input: optical"); break; case RME96_INPUT_COAXIAL: snd_iprintf(buffer, " input: coaxial"); break; case RME96_INPUT_INTERNAL: snd_iprintf(buffer, " input: internal"); break; case RME96_INPUT_XLR: snd_iprintf(buffer, " input: XLR"); break; case RME96_INPUT_ANALOG: snd_iprintf(buffer, " input: analog"); break; } if (snd_rme96_capture_getrate(rme96, &n) < 0) { snd_iprintf(buffer, "\n sample rate: no valid signal\n"); } else { if (n) { snd_iprintf(buffer, " (8 channels)\n"); } else { snd_iprintf(buffer, " (2 channels)\n"); } snd_iprintf(buffer, " sample rate: %d Hz\n", snd_rme96_capture_getrate(rme96, &n)); } if (rme96->wcreg & RME96_WCR_MODE24_2) { snd_iprintf(buffer, " sample format: 24 bit\n"); } else { snd_iprintf(buffer, " sample format: 16 bit\n"); } snd_iprintf(buffer, "\nOutput settings\n"); if (rme96->wcreg & RME96_WCR_SEL) { snd_iprintf(buffer, " output signal: normal playback\n"); } else { snd_iprintf(buffer, " output signal: same as input\n"); } snd_iprintf(buffer, " sample rate: %d Hz\n", snd_rme96_playback_getrate(rme96)); if (rme96->wcreg & RME96_WCR_MODE24) { snd_iprintf(buffer, " sample format: 24 bit\n"); } else { snd_iprintf(buffer, " sample format: 16 bit\n"); } if (rme96->areg & RME96_AR_WSEL) { snd_iprintf(buffer, " sample clock source: word clock\n"); } else if (rme96->wcreg & RME96_WCR_MASTER) { snd_iprintf(buffer, " sample clock source: internal\n"); } else if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to analog input setting)\n"); } else if (snd_rme96_capture_getrate(rme96, &n) < 0) { snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to no valid signal)\n"); } else { snd_iprintf(buffer, " sample clock source: autosync\n"); } if (rme96->wcreg & RME96_WCR_PRO) { snd_iprintf(buffer, " format: AES/EBU (professional)\n"); } else { snd_iprintf(buffer, " format: IEC958 (consumer)\n"); } if (rme96->wcreg & RME96_WCR_EMP) { snd_iprintf(buffer, " emphasis: on\n"); } else { snd_iprintf(buffer, " emphasis: off\n"); } if (rme96->wcreg & RME96_WCR_DOLBY) { snd_iprintf(buffer, " non-audio (dolby): on\n"); } else { snd_iprintf(buffer, " non-audio (dolby): off\n"); } if (RME96_HAS_ANALOG_IN(rme96)) { snd_iprintf(buffer, "\nAnalog output settings\n"); switch (snd_rme96_getmontracks(rme96)) { case RME96_MONITOR_TRACKS_1_2: snd_iprintf(buffer, " monitored ADAT tracks: 1+2\n"); break; case RME96_MONITOR_TRACKS_3_4: snd_iprintf(buffer, " monitored ADAT tracks: 3+4\n"); break; case RME96_MONITOR_TRACKS_5_6: snd_iprintf(buffer, " monitored ADAT tracks: 5+6\n"); break; case RME96_MONITOR_TRACKS_7_8: snd_iprintf(buffer, " monitored ADAT tracks: 7+8\n"); break; } switch (snd_rme96_getattenuation(rme96)) { case RME96_ATTENUATION_0: snd_iprintf(buffer, " attenuation: 0 dB\n"); break; case RME96_ATTENUATION_6: snd_iprintf(buffer, " attenuation: -6 dB\n"); break; case RME96_ATTENUATION_12: snd_iprintf(buffer, " attenuation: -12 dB\n"); break; case RME96_ATTENUATION_18: snd_iprintf(buffer, " attenuation: -18 dB\n"); break; } snd_iprintf(buffer, " volume left: %u\n", rme96->vol[0]); snd_iprintf(buffer, " volume right: %u\n", rme96->vol[1]); }}static void __devinit snd_rme96_proc_init(struct rme96 *rme96){ struct snd_info_entry *entry; if (! snd_card_proc_new(rme96->card, "rme96", &entry)) snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read);}/* * control interface */#define snd_rme96_info_loopback_control snd_ctl_boolean_mono_infostatic intsnd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); spin_lock_irq(&rme96->lock); ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1; spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); unsigned int val; int change; val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL; spin_lock_irq(&rme96->lock); val = (rme96->wcreg & ~RME96_WCR_SEL) | val; change = val != rme96->wcreg; rme96->wcreg = val; writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER); spin_unlock_irq(&rme96->lock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -