📄 pcxhr_mixer.c
字号:
static struct snd_kcontrol_new snd_pcxhr_pcm_vol ={ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* name will be filled later */ /* count will be filled later */ .info = pcxhr_digital_vol_info, /* shared */ .get = pcxhr_pcm_vol_get, .put = pcxhr_pcm_vol_put,};static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ down(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; up(&chip->mgr->mixer_mutex); return 0;}static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; down(&chip->mgr->mixer_mutex); j = idx; for (i = 0; i < 2; i++) { if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) { chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i]; changed = 1; } } if (changed) pcxhr_update_playback_stream_level(chip, idx); up(&chip->mgr->mixer_mutex); return changed;}static struct snd_kcontrol_new pcxhr_control_pcm_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", .count = PCXHR_PLAYBACK_STREAMS, .info = pcxhr_sw_info, /* shared */ .get = pcxhr_pcm_sw_get, .put = pcxhr_pcm_sw_put};/* * monitoring level control */static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); down(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; up(&chip->mgr->mixer_mutex); return 0;}static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; down(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; if(chip->monitoring_active[i]) /* do only when monitoring is unmuted */ /* update monitoring volume and mute */ pcxhr_update_audio_pipe_level(chip, 0, i); changed = 1; } } up(&chip->mgr->mixer_mutex); return changed;}static struct snd_kcontrol_new pcxhr_control_monitor_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Volume", .info = pcxhr_digital_vol_info, /* shared */ .get = pcxhr_monitor_vol_get, .put = pcxhr_monitor_vol_put,};/* * monitoring switch control */static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); down(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_active[0]; ucontrol->value.integer.value[1] = chip->monitoring_active[1]; up(&chip->mgr->mixer_mutex); return 0;}static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; down(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { chip->monitoring_active[i] = ucontrol->value.integer.value[i]; changed |= (1<<i); /* mask 0x01 and 0x02 */ } } if(changed & 0x01) /* update left monitoring volume and mute */ pcxhr_update_audio_pipe_level(chip, 0, 0); if(changed & 0x02) /* update right monitoring volume and mute */ pcxhr_update_audio_pipe_level(chip, 0, 1); up(&chip->mgr->mixer_mutex); return (changed != 0);}static struct snd_kcontrol_new pcxhr_control_monitor_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Switch", .info = pcxhr_sw_info, /* shared */ .get = pcxhr_monitor_sw_get, .put = pcxhr_monitor_sw_put};/* * audio source select */#define PCXHR_SOURCE_AUDIO01_UER 0x000100#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200#define PCXHR_SOURCE_AUDIO23_UER 0x000400#define PCXHR_SOURCE_AUDIO45_UER 0x001000#define PCXHR_SOURCE_AUDIO67_UER 0x040000static int pcxhr_set_audio_source(struct snd_pcxhr* chip){ struct pcxhr_rmh rmh; unsigned int mask, reg; unsigned int codec; int err, use_src, changed; switch (chip->chip_idx) { case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break; case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break; case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break; case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break; default: return -EINVAL; } reg = 0; /* audio source from analog plug */ use_src = 0; /* do not activate codec SRC */ if (chip->audio_capture_source != 0) { reg = mask; /* audio source from digital plug */ if (chip->audio_capture_source == 2) use_src = 1; } /* set the input source */ pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed); /* resync them (otherwise channel inversion possible) */ if (changed) { pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS); rmh.cmd[0] |= (1 << chip->chip_idx); err = pcxhr_send_msg(chip->mgr, &rmh); if (err) return err; } pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */ rmh.cmd_len = 3; rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; rmh.cmd[1] = codec; rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54); err = pcxhr_send_msg(chip->mgr, &rmh); if(err) return err; rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49); err = pcxhr_send_msg(chip->mgr, &rmh); return err;}static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[3] = {"Analog", "Digital", "Digi+SRC"}; 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 int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = chip->audio_capture_source; return 0;}static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int ret = 0; down(&chip->mgr->mixer_mutex); if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { chip->audio_capture_source = ucontrol->value.enumerated.item[0]; pcxhr_set_audio_source(chip); ret = 1; } up(&chip->mgr->mixer_mutex); return ret;}static struct snd_kcontrol_new pcxhr_control_audio_src = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = pcxhr_audio_src_info, .get = pcxhr_audio_src_get, .put = pcxhr_audio_src_put,};/* * clock type selection * enum pcxhr_clock_type { * PCXHR_CLOCK_TYPE_INTERNAL = 0, * PCXHR_CLOCK_TYPE_WORD_CLOCK, * PCXHR_CLOCK_TYPE_AES_SYNC, * PCXHR_CLOCK_TYPE_AES_1, * PCXHR_CLOCK_TYPE_AES_2, * PCXHR_CLOCK_TYPE_AES_3, * PCXHR_CLOCK_TYPE_AES_4, * }; */static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[7] = { "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4" }; struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int clock_items = 3 + mgr->capture_chips; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = clock_items; if (uinfo->value.enumerated.item >= clock_items) uinfo->value.enumerated.item = clock_items-1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = mgr->use_clock_type; return 0;}static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int rate, ret = 0; down(&mgr->mixer_mutex); if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { down(&mgr->setup_mutex); mgr->use_clock_type = ucontrol->value.enumerated.item[0]; if (mgr->use_clock_type) pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); else rate = mgr->sample_rate; if (rate) { pcxhr_set_clock(mgr, rate); if (mgr->sample_rate) mgr->sample_rate = rate; } up(&mgr->setup_mutex); ret = 1; /* return 1 even if the set was not done. ok ? */ } up(&mgr->mixer_mutex); return ret;}static struct snd_kcontrol_new pcxhr_control_clock_type = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Clock Mode", .info = pcxhr_clock_type_info, .get = pcxhr_clock_type_get, .put = pcxhr_clock_type_put,};/* * clock rate control * specific control that scans the sample rates on the external plugs */static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 3 + mgr->capture_chips; uinfo->value.integer.min = 0; /* clock not present */ uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */ return 0;}static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -