📄 echoaudio.c
字号:
.tlv = {.p = db_scale_input_gain},};#endif /* ECHOCARD_HAS_INPUT_GAIN */#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL/************ Analog output nominal level (+4dBu / -10dBV) ***************/static int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = num_analog_busses_out(chip); uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int c; chip = snd_kcontrol_chip(kcontrol); for (c = 0; c < num_analog_busses_out(chip); c++) ucontrol->value.integer.value[c] = chip->nominal_level[c]; return 0;}static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int c, changed; changed = 0; chip = snd_kcontrol_chip(kcontrol); spin_lock_irq(&chip->lock); for (c = 0; c < num_analog_busses_out(chip); c++) { if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) { set_nominal_level(chip, c, ucontrol->value.integer.value[c]); changed = 1; } } if (changed) update_output_line_level(chip); spin_unlock_irq(&chip->lock); return changed;}static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = { .name = "Line Playback Switch (-10dBV)", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_echo_output_nominal_info, .get = snd_echo_output_nominal_get, .put = snd_echo_output_nominal_put,};#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL/*************** Analog input nominal level (+4dBu / -10dBV) ***************/static int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = num_analog_busses_in(chip); uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int c; chip = snd_kcontrol_chip(kcontrol); for (c = 0; c < num_analog_busses_in(chip); c++) ucontrol->value.integer.value[c] = chip->nominal_level[bx_analog_in(chip) + c]; return 0;}static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int c, changed; changed = 0; chip = snd_kcontrol_chip(kcontrol); spin_lock_irq(&chip->lock); for (c = 0; c < num_analog_busses_in(chip); c++) { if (chip->nominal_level[bx_analog_in(chip) + c] != ucontrol->value.integer.value[c]) { set_nominal_level(chip, bx_analog_in(chip) + c, ucontrol->value.integer.value[c]); changed = 1; } } if (changed) update_output_line_level(chip); /* "Output" is not a mistake * here. */ spin_unlock_irq(&chip->lock); return changed;}static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = { .name = "Line Capture Switch (-10dBV)", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_echo_input_nominal_info, .get = snd_echo_input_nominal_get, .put = snd_echo_input_nominal_put,};#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */#ifdef ECHOCARD_HAS_MONITOR/******************* Monitor mixer *******************/static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = ECHOGAIN_MINOUT; uinfo->value.integer.max = ECHOGAIN_MAXOUT; uinfo->dimen.d[0] = num_busses_out(chip); uinfo->dimen.d[1] = num_busses_in(chip); return 0;}static int snd_echo_mixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)] [ucontrol->id.index % num_busses_in(chip)]; return 0;}static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int changed, gain; short out, in; changed = 0; chip = snd_kcontrol_chip(kcontrol); out = ucontrol->id.index / num_busses_in(chip); in = ucontrol->id.index % num_busses_in(chip); gain = ucontrol->value.integer.value[0]; if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) return -EINVAL; if (chip->monitor_gain[out][in] != gain) { spin_lock_irq(&chip->lock); set_monitor_gain(chip, out, in, gain); update_output_line_level(chip); spin_unlock_irq(&chip->lock); changed = 1; } return changed;}static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = { .name = "Monitor Mixer Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, .info = snd_echo_mixer_info, .get = snd_echo_mixer_get, .put = snd_echo_mixer_put, .tlv = {.p = db_scale_output_gain},};#endif /* ECHOCARD_HAS_MONITOR */#ifdef ECHOCARD_HAS_VMIXER/******************* Vmixer *******************/static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = ECHOGAIN_MINOUT; uinfo->value.integer.max = ECHOGAIN_MAXOUT; uinfo->dimen.d[0] = num_busses_out(chip); uinfo->dimen.d[1] = num_pipes_out(chip); return 0;}static int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)] [ucontrol->id.index % num_pipes_out(chip)]; return 0;}static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int gain, changed; short vch, out; changed = 0; chip = snd_kcontrol_chip(kcontrol); out = ucontrol->id.index / num_pipes_out(chip); vch = ucontrol->id.index % num_pipes_out(chip); gain = ucontrol->value.integer.value[0]; if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) return -EINVAL; if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) { spin_lock_irq(&chip->lock); set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]); update_vmixer_level(chip); spin_unlock_irq(&chip->lock); changed = 1; } return changed;}static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = { .name = "VMixer Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, .info = snd_echo_vmixer_info, .get = snd_echo_vmixer_get, .put = snd_echo_vmixer_put, .tlv = {.p = db_scale_output_gain},};#endif /* ECHOCARD_HAS_VMIXER */#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH/******************* Digital mode switch *******************/static int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *names[4] = { "S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical", "S/PDIF Cdrom" }; struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->value.enumerated.items = chip->num_digital_modes; uinfo->count = 1; if (uinfo->value.enumerated.item >= chip->num_digital_modes) uinfo->value.enumerated.item = chip->num_digital_modes - 1; strcpy(uinfo->value.enumerated.name, names[ chip->digital_mode_list[uinfo->value.enumerated.item]]); return 0;}static int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int i, mode; chip = snd_kcontrol_chip(kcontrol); mode = chip->digital_mode; for (i = chip->num_digital_modes - 1; i >= 0; i--) if (mode == chip->digital_mode_list[i]) { ucontrol->value.enumerated.item[0] = i; break; } return 0;}static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int changed; unsigned short emode, dmode; changed = 0; chip = snd_kcontrol_chip(kcontrol); emode = ucontrol->value.enumerated.item[0]; if (emode >= chip->num_digital_modes) return -EINVAL; dmode = chip->digital_mode_list[emode]; if (dmode != chip->digital_mode) { /* mode_mutex is required to make this operation atomic wrt pcm_digital_*_open() and set_input_clock() functions. */ down(&chip->mode_mutex); /* Do not allow the user to change the digital mode when a pcm device is open because it also changes the number of channels and the allowed sample rates */ if (atomic_read(&chip->opencount)) { changed = -EAGAIN; } else { changed = set_digital_mode(chip, dmode); /* If we had to change the clock source, report it */ if (changed > 0 && chip->clock_src_ctl) { snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->clock_src_ctl->id); DE_ACT(("SDM() =%d\n", changed)); } if (changed >= 0) changed = 1; /* No errors */ } up(&chip->mode_mutex); } return changed;}static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = { .name = "Digital mode Switch", .iface = SNDRV_CTL_ELEM_IFACE_CARD, .info = snd_echo_digital_mode_info, .get = snd_echo_digital_mode_get, .put = snd_echo_digital_mode_put,};#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */#ifdef ECHOCARD_HAS_DIGITAL_IO/******************* S/PDIF mode switch *******************/static int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *names[2] = {"Consumer", "Professional"}; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->value.enumerated.items = 2; uinfo->count = 1; if (uinfo->value.enumerated.item) uinfo->value.enumerated.item = 1; strcpy(uinfo->value.enumerated.name, names[uinfo->value.enumerated.item]); return 0;}static int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = !!chip->professional_spdif; return 0;}static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int mode; chip = snd_kcontrol_chip(kcontrol); mode = !!ucontrol->value.enumerated.item[0]; if (mode != chip->professional_spdif) { spin_lock_irq(&chip->lock); set_professional_spdif(chip, mode); spin_unlock_irq(&chip->lock); return 1; } return 0;}static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = { .name = "S/PDIF mode Switch", .iface = SNDRV_CTL_ELEM_IFACE_CARD, .info = snd_echo_spdif_mode_info, .get = snd_echo_spdif_mode_get, .put = snd_echo_spdif_mode_put,};#endif /* ECHOCARD_HAS_DIGITAL_IO */#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK/******************* Select input clock source *******************/static int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *names[8] = { "Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync", "ESync96", "MTC" }; struct echoaudio *chip; chip = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->value.enumerated.items = chip->num_clock_sources; uinfo->count = 1; if (uinfo->value.enumerated.item >= chip->num_clock_sources) uinfo->value.enumerated.item = chip->num_clock_sources - 1; strcpy(uinfo->value.enumerated.name, names[ chip->clock_source_list[uinfo->value.enumerated.item]]); return 0;}static int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int i, clock; chip = snd_kcontrol_chip(kcontrol); clock = chip->input_clock; for (i = 0; i < chip->num_clock_sources; i++) if (clock == chip->clock_source_list[i]) ucontrol->value.enumerated.item[0] = i; return 0;}static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip; int changed; unsigned int eclock, dclock; changed = 0; chip = snd_kcontrol_chip(kcontrol); eclock = ucontrol->value.enumerated.item[0]; if (eclock >= chip->input_clock_types) return -EINVAL; dclock = chip->clock_source_list[eclock]; if (chip->input_clock != dclock) { down(&chip->mode_mutex); spin_lock_irq(&chip->lock); if ((changed = set_input_clock(chip, dclock)) == 0) changed = 1; /* no errors */ spin_unlock_irq(&chip->lock); up(&chip->mode_mutex); } if (changed < 0) DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed)); return changed;}static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { .name = "Sample Clock Source", .iface = SNDRV_CTL_ELEM_IFACE_PCM, .info = snd_echo_clock_source_info, .get = snd_echo_clock_source_get, .put = snd_echo_clock_source_put,};#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */#ifdef ECHOCARD_HAS_PHANTOM_POWER/******************* Phantom power switch *******************/#define snd_echo_phantom_power_info snd_ctl_boolean_mono_infostatic int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = chip->phantom_power; return 0;}static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct echoaudio *chip = snd_kcontrol_chip(kcontrol); int power, changed = 0; power = !!ucontrol->value.integer.value[0]; if (chip->phantom_power != power) { spin_lock_irq(&chip->lock); changed = set_phantom_power(chip, power); spin_unlock_irq(&chip->lock); if (changed == 0) changed = 1; /* no errors */ } return changed;}static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { .name = "Phantom power Switch", .iface = SNDRV_CTL_ELEM_IFACE_CARD, .info = snd_echo_phantom_power_info, .get = snd_echo_phantom_power_get, .put = snd_echo_phantom_power_put,};#endif /* ECHOCARD_HAS_PHANTOM_POWER */#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE/******************* Digital input automute switch *******************/#define snd_echo_automute_info snd_ctl_boolean_mono_info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -