📄 rme96.c
字号:
return change;}static intsnd_rme96_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" }; struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; switch (rme96->pci->device) { case PCI_DEVICE_ID_RME_DIGI96: case PCI_DEVICE_ID_RME_DIGI96_8: uinfo->value.enumerated.items = 3; break; case PCI_DEVICE_ID_RME_DIGI96_8_PRO: uinfo->value.enumerated.items = 4; break; case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: if (rme96->rev > 4) { /* PST */ uinfo->value.enumerated.items = 4; texts[3] = _texts[4]; /* Analog instead of XLR */ } else { /* PAD */ uinfo->value.enumerated.items = 5; } 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_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); unsigned int items = 3; spin_lock_irq(&rme96->lock); ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); switch (rme96->pci->device) { case PCI_DEVICE_ID_RME_DIGI96: case PCI_DEVICE_ID_RME_DIGI96_8: items = 3; break; case PCI_DEVICE_ID_RME_DIGI96_8_PRO: items = 4; break; case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: if (rme96->rev > 4) { /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { ucontrol->value.enumerated.item[0] = RME96_INPUT_XLR; } items = 4; } else { items = 5; } break; default: snd_BUG(); break; } if (ucontrol->value.enumerated.item[0] >= items) { ucontrol->value.enumerated.item[0] = items - 1; } spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); unsigned int val; int change, items = 3; switch (rme96->pci->device) { case PCI_DEVICE_ID_RME_DIGI96: case PCI_DEVICE_ID_RME_DIGI96_8: items = 3; break; case PCI_DEVICE_ID_RME_DIGI96_8_PRO: items = 4; break; case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: if (rme96->rev > 4) { items = 4; } else { items = 5; } break; default: snd_BUG(); break; } val = ucontrol->value.enumerated.item[0] % items; /* special case for PST */ if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { if (val == RME96_INPUT_XLR) { val = RME96_INPUT_ANALOG; } } spin_lock_irq(&rme96->lock); change = (int)val != snd_rme96_getinputtype(rme96); snd_rme96_setinputtype(rme96, val); spin_unlock_irq(&rme96->lock); return change;}static intsnd_rme96_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[3] = { "AutoSync", "Internal", "Word" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; if (uinfo->value.enumerated.item > 2) { uinfo->value.enumerated.item = 2; } strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static intsnd_rme96_get_clockmode_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.enumerated.item[0] = snd_rme96_getclockmode(rme96); spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_put_clockmode_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.enumerated.item[0] % 3; spin_lock_irq(&rme96->lock); change = (int)val != snd_rme96_getclockmode(rme96); snd_rme96_setclockmode(rme96, val); spin_unlock_irq(&rme96->lock); return change;}static intsnd_rme96_info_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[4] = { "0 dB", "-6 dB", "-12 dB", "-18 dB" }; 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_rme96_get_attenuation_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.enumerated.item[0] = snd_rme96_getattenuation(rme96); spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_put_attenuation_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.enumerated.item[0] % 4; spin_lock_irq(&rme96->lock); change = (int)val != snd_rme96_getattenuation(rme96); snd_rme96_setattenuation(rme96, val); spin_unlock_irq(&rme96->lock); return change;}static intsnd_rme96_info_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[4] = { "1+2", "3+4", "5+6", "7+8" }; 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_rme96_get_montracks_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.enumerated.item[0] = snd_rme96_getmontracks(rme96); spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_put_montracks_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.enumerated.item[0] % 4; spin_lock_irq(&rme96->lock); change = (int)val != snd_rme96_getmontracks(rme96); snd_rme96_setmontracks(rme96, val); spin_unlock_irq(&rme96->lock); return change;}static u32 snd_rme96_convert_from_aes(struct snd_aes_iec958 *aes){ u32 val = 0; val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME96_WCR_PRO : 0; val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME96_WCR_DOLBY : 0; if (val & RME96_WCR_PRO) val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME96_WCR_EMP : 0; else val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME96_WCR_EMP : 0; return val;}static void snd_rme96_convert_to_aes(struct snd_aes_iec958 *aes, u32 val){ aes->status[0] = ((val & RME96_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | ((val & RME96_WCR_DOLBY) ? IEC958_AES0_NONAUDIO : 0); if (val & RME96_WCR_PRO) aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; else aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;}static int snd_rme96_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_rme96_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif); return 0;}static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&rme96->lock); change = val != rme96->wcreg_spdif; rme96->wcreg_spdif = val; spin_unlock_irq(&rme96->lock); return change;}static int snd_rme96_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_rme96_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream); return 0;}static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); int change; u32 val; val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&rme96->lock); change = val != rme96->wcreg_spdif_stream; rme96->wcreg_spdif_stream = val; rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); rme96->wcreg |= val; writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); spin_unlock_irq(&rme96->lock); return change;}static int snd_rme96_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_rme96_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 intsnd_rme96_dac_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = RME96_185X_MAX_OUT(rme96); return 0;}static intsnd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); spin_lock_irq(&rme96->lock); u->value.integer.value[0] = rme96->vol[0]; u->value.integer.value[1] = rme96->vol[1]; spin_unlock_irq(&rme96->lock); return 0;}static intsnd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u){ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); int change = 0; if (!RME96_HAS_ANALOG_OUT(rme96)) { return -EINVAL; } spin_lock_irq(&rme96->lock); if (u->value.integer.value[0] != rme96->vol[0]) { rme96->vol[0] = u->value.integer.value[0]; change = 1; } if (u->value.integer.value[1] != rme96->vol[1]) { rme96->vol[1] = u->value.integer.value[1]; change = 1; } if (change) { snd_rme96_apply_dac_volume(rme96); } spin_unlock_irq(&rme96->lock); return change;}static struct snd_kcontrol_new snd_rme96_controls[] = {{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = snd_rme96_control_spdif_info, .get = snd_rme96_control_spdif_get, .put = snd_rme96_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_rme96_control_spdif_stream_info, .get = snd_rme96_control_spdif_stream_get, .put = snd_rme96_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_rme96_control_spdif_mask_info, .get = snd_rme96_control_spdif_mask_get, .private_value = IEC958_AES0_NONAUDIO | 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_rme96_control_spdif_mask_info, .get = snd_rme96_control_spdif_mask_get, .private_value = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_EMPHASIS},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Connector", .info = snd_rme96_info_inputtype_control, .get = snd_rme96_get_inputtype_control, .put = snd_rme96_put_inputtype_control },{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Loopback Input", .info = snd_rme96_info_loopback_control, .get = snd_rme96_get_loopback_control, .put = snd_rme96_put_loopback_control},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Sample Clock Source", .info = snd_rme96_info_clockmode_control, .get = snd_rme96_get_clockmode_control, .put = snd_rme96_put_clockmode_control},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitor Tracks", .info = snd_rme96_info_montracks_control, .get = snd_rme96_get_montracks_control, .put = snd_rme96_put_montracks_control},{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Attenuation", .info = snd_rme96_info_attenuation_control, .get = snd_rme96_get_attenuation_control, .put =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -