📄 rme32.c
字号:
break; case RME32_INPUT_XLR: snd_iprintf(buffer, " input: XLR"); break; } if (snd_rme32_capture_getrate(rme32, &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_rme32_capture_getrate(rme32, &n)); } snd_iprintf(buffer, "\nOutput settings\n"); if (rme32->wcreg & RME32_WCR_SEL) { snd_iprintf(buffer, " output signal: normal playback"); } else { snd_iprintf(buffer, " output signal: same as input"); } if (rme32->wcreg & RME32_WCR_MUTE) { snd_iprintf(buffer, " (muted)\n"); } else { snd_iprintf(buffer, "\n"); } /* master output frequency */ if (! ((!(rme32->wcreg & RME32_WCR_FREQ_0)) && (!(rme32->wcreg & RME32_WCR_FREQ_1)))) { snd_iprintf(buffer, " sample rate: %d Hz\n", snd_rme32_playback_getrate(rme32)); } if (rme32->rcreg & RME32_RCR_KMODE) { snd_iprintf(buffer, " sample clock source: AutoSync\n"); } else { snd_iprintf(buffer, " sample clock source: Internal\n"); } if (rme32->wcreg & RME32_WCR_PRO) { snd_iprintf(buffer, " format: AES/EBU (professional)\n"); } else { snd_iprintf(buffer, " format: IEC958 (consumer)\n"); } if (rme32->wcreg & RME32_WCR_EMP) { snd_iprintf(buffer, " emphasis: on\n"); } else { snd_iprintf(buffer, " emphasis: off\n"); }}static void __devinit snd_rme32_proc_init(struct rme32 * rme32){ struct snd_info_entry *entry; if (! snd_card_proc_new(rme32->card, "rme32", &entry)) snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read);}/* * control interface */#define snd_rme32_info_loopback_control snd_ctl_boolean_mono_infostatic intsnd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); spin_lock_irq(&rme32->lock); ucontrol->value.integer.value[0] = rme32->wcreg & RME32_WCR_SEL ? 0 : 1; spin_unlock_irq(&rme32->lock); return 0;}static intsnd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); unsigned int val; int change; val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL; spin_lock_irq(&rme32->lock); val = (rme32->wcreg & ~RME32_WCR_SEL) | val; change = val != rme32->wcreg; if (ucontrol->value.integer.value[0]) val &= ~RME32_WCR_MUTE; else val |= RME32_WCR_MUTE; rme32->wcreg = val; writel(val, rme32->iobase + RME32_IO_CONTROL_REGISTER); spin_unlock_irq(&rme32->lock); return change;}static intsnd_rme32_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; switch (rme32->pci->device) { case PCI_DEVICE_ID_RME_DIGI32: case PCI_DEVICE_ID_RME_DIGI32_8: uinfo->value.enumerated.items = 3; break; case PCI_DEVICE_ID_RME_DIGI32_PRO: uinfo->value.enumerated.items = 4; break; default: snd_BUG(); break; } if (uinfo->value.enumerated.item > uinfo->value.enumerated.items - 1) { uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; } strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static intsnd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); unsigned int items = 3; spin_lock_irq(&rme32->lock); ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); switch (rme32->pci->device) { case PCI_DEVICE_ID_RME_DIGI32: case PCI_DEVICE_ID_RME_DIGI32_8: items = 3; break; case PCI_DEVICE_ID_RME_DIGI32_PRO: items = 4; break; default: snd_BUG(); break; } if (ucontrol->value.enumerated.item[0] >= items) { ucontrol->value.enumerated.item[0] = items - 1; } spin_unlock_irq(&rme32->lock); return 0;}static intsnd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); unsigned int val; int change, items = 3; switch (rme32->pci->device) { case PCI_DEVICE_ID_RME_DIGI32: case PCI_DEVICE_ID_RME_DIGI32_8: items = 3; break; case PCI_DEVICE_ID_RME_DIGI32_PRO: items = 4; break; default: snd_BUG(); break; } val = ucontrol->value.enumerated.item[0] % items; spin_lock_irq(&rme32->lock); change = val != (unsigned int)snd_rme32_getinputtype(rme32); snd_rme32_setinputtype(rme32, val); spin_unlock_irq(&rme32->lock); return change;}static intsnd_rme32_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[4] = { "AutoSync", "Internal 32.0kHz", "Internal 44.1kHz", "Internal 48.0kHz" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) { uinfo->value.enumerated.item = 3; } strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static intsnd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); spin_lock_irq(&rme32->lock); ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32); spin_unlock_irq(&rme32->lock); return 0;}static intsnd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); unsigned int val; int change; val = ucontrol->value.enumerated.item[0] % 3; spin_lock_irq(&rme32->lock); change = val != (unsigned int)snd_rme32_getclockmode(rme32); snd_rme32_setclockmode(rme32, val); spin_unlock_irq(&rme32->lock); return change;}static u32 snd_rme32_convert_from_aes(struct snd_aes_iec958 * aes){ u32 val = 0; val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME32_WCR_PRO : 0; if (val & RME32_WCR_PRO) val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME32_WCR_EMP : 0; else val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME32_WCR_EMP : 0; return val;}static void snd_rme32_convert_to_aes(struct snd_aes_iec958 * aes, u32 val){ aes->status[0] = ((val & RME32_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0); if (val & RME32_WCR_PRO) aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; else aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;}static int snd_rme32_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_rme32_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); snd_rme32_convert_to_aes(&ucontrol->value.iec958, rme32->wcreg_spdif); return 0;}static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&rme32->lock); change = val != rme32->wcreg_spdif; rme32->wcreg_spdif = val; spin_unlock_irq(&rme32->lock); return change;}static int snd_rme32_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_rme32_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value * ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); snd_rme32_convert_to_aes(&ucontrol->value.iec958, rme32->wcreg_spdif_stream); return 0;}static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value * ucontrol){ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&rme32->lock); change = val != rme32->wcreg_spdif_stream; rme32->wcreg_spdif_stream = val; rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); rme32->wcreg |= val; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); spin_unlock_irq(&rme32->lock); return change;}static int snd_rme32_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value * ucontrol){ ucontrol->value.iec958.status[0] = kcontrol->private_value; return 0;}static struct snd_kcontrol_new snd_rme32_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), .info = snd_rme32_control_spdif_info, .get = snd_rme32_control_spdif_get, .put = snd_rme32_control_spdif_put }, { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), .info = snd_rme32_control_spdif_stream_info, .get = snd_rme32_control_spdif_stream_get, .put = snd_rme32_control_spdif_stream_put }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), .info = snd_rme32_control_spdif_mask_info, .get = snd_rme32_control_spdif_mask_get, .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_CON_EMPHASIS }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), .info = snd_rme32_control_spdif_mask_info, .get = snd_rme32_control_spdif_mask_get, .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_EMPHASIS }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Connector", .info = snd_rme32_info_inputtype_control, .get = snd_rme32_get_inputtype_control, .put = snd_rme32_put_inputtype_control }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Loopback Input", .info = snd_rme32_info_loopback_control, .get = snd_rme32_get_loopback_control, .put = snd_rme32_put_loopback_control }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Sample Clock Source", .info = snd_rme32_info_clockmode_control, .get = snd_rme32_get_clockmode_control, .put = snd_rme32_put_clockmode_control }};static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32){ int idx, err; struct snd_kcontrol *kctl; for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) { if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ rme32->spdif_ctl = kctl; } return 0;}/* * Card initialisation */static void snd_rme32_card_free(struct snd_card *card){ snd_rme32_free(card->private_data);}static int __devinitsnd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id){ static int dev; struct rme32 *rme32; struct snd_card *card; int err; if (dev >= SNDRV_CARDS) { return -ENODEV; } if (!enable[dev]) { dev++; return -ENOENT; } if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct rme32))) == NULL) return -ENOMEM; card->private_free = snd_rme32_card_free; rme32 = (struct rme32 *) card->private_data; rme32->card = card; rme32->pci = pci; snd_card_set_dev(card, &pci->dev); if (fullduplex[dev]) rme32->fullduplex_mode = 1; if ((err = snd_rme32_create(rme32)) < 0) { snd_card_free(card); return err; } strcpy(card->driver, "Digi32"); switch (rme32->pci->device) { case PCI_DEVICE_ID_RME_DIGI32: strcpy(card->shortname, "RME Digi32"); break; case PCI_DEVICE_ID_RME_DIGI32_8: strcpy(card->shortname, "RME Digi32/8"); break; case PCI_DEVICE_ID_RME_DIGI32_PRO: strcpy(card->shortname, "RME Digi32 PRO"); break; } sprintf(card->longname, "%s (Rev. %d) at 0x%lx, irq %d", card->shortname, rme32->rev, rme32->port, rme32->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); dev++; return 0;}static void __devexit snd_rme32_remove(struct pci_dev *pci){ snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL);}static struct pci_driver driver = { .name = "RME Digi32", .id_table = snd_rme32_ids, .probe = snd_rme32_probe, .remove = __devexit_p(snd_rme32_remove),};static int __init alsa_card_rme32_init(void){ return pci_register_driver(&driver);}static void __exit alsa_card_rme32_exit(void){ pci_unregister_driver(&driver);}module_init(alsa_card_rme32_init)module_exit(alsa_card_rme32_exit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -