^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Digigram VX soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Common mixer part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/vx_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "vx_cmd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * write a codec data (24bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) if (snd_BUG_ON(!chip->ops->write_codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (chip->chip_status & VX_STAT_IS_STALE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) chip->ops->write_codec(chip, codec, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * Data type used to access the Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) union vx_codec_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #ifdef SNDRV_BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct w {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u16 h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u16 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) } w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct b {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u8 hh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u8 mh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u8 ml;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u8 ll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #else /* LITTLE_ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct w {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u16 l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u16 h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) } w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct b {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 ll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u8 ml;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u8 mh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 hh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SET_CDC_DATA_VAL(di,d) ((di).b.ll = (u8) (d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SET_CDC_DATA_INIT(di) ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * set up codec register and write the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @codec: the codec id, 0 or 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @reg: register index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @val: data value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) union vx_codec_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* DAC control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) SET_CDC_DATA_INIT(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) SET_CDC_DATA_REG(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) SET_CDC_DATA_VAL(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) vx_write_codec_reg(chip, codec, data.l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * vx_set_analog_output_level - set the output attenuation level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @codec: the output codec, 0 or 1. (1 for VXP440 only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @left: left output level, 0 = mute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @right: right output level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) left = chip->hw->output_level_max - left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) right = chip->hw->output_level_max - right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (chip->ops->akm_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * vx_toggle_dac_mute - mute/unmute DAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @mute: 0 = unmute, 1 = mute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define DAC_ATTEN_MIN 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define DAC_ATTEN_MAX 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void vx_toggle_dac_mute(struct vx_core *chip, int mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (i = 0; i < chip->hw->num_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (chip->ops->akm_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * vx_reset_codec - reset and initialize the codecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) void vx_reset_codec(struct vx_core *chip, int cold_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) chip->ops->reset_codec(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* AKM codecs should be initialized in reset_codec callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (! chip->ops->akm_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* initialize old codecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for (i = 0; i < chip->hw->num_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* DAC control register (change level when zero crossing + mute) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* ADC control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Port mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Clock control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* mute analog output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) for (i = 0; i < chip->hw->num_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) chip->output_level[i][0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) chip->output_level[i][1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) vx_set_analog_output_level(chip, i, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * change the audio input source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @src: the target source (VX_AUDIO_SRC_XXX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void vx_change_audio_source(struct vx_core *chip, int src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (chip->chip_status & VX_STAT_IS_STALE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) chip->ops->change_audio_source(chip, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * change the audio source if necessary and possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * returns 1 if the source is actually changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int vx_sync_audio_source(struct vx_core *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (chip->audio_source_target == chip->audio_source ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) chip->pcm_running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) vx_change_audio_source(chip, chip->audio_source_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) chip->audio_source = chip->audio_source_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * audio level, mute, monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct vx_audio_level {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned int has_level: 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned int has_monitor_level: 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned int has_mute: 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned int has_monitor_mute: 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned int mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned int monitor_mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) short level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) short monitor_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int vx_adjust_audio_level(struct vx_core *chip, int audio, int capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct vx_audio_level *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct vx_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (chip->chip_status & VX_STAT_IS_STALE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) rmh.Cmd[0] |= COMMAND_RECORD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Add Audio IO mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) rmh.Cmd[1] = 1 << audio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) rmh.Cmd[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (info->has_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) rmh.Cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) rmh.Cmd[2] |= info->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (info->has_monitor_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) rmh.Cmd[0] |= VALID_AUDIO_IO_MONITORING_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (info->has_mute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (info->mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (info->has_monitor_mute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* validate flag for M2 at least to unmute it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (info->monitor_mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return vx_send_msg(chip, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #if 0 // not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int vx_read_audio_level(struct vx_core *chip, int audio, int capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct vx_audio_level *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct vx_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) memset(info, 0, sizeof(*info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) rmh.Cmd[0] |= COMMAND_RECORD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* Add Audio IO mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) rmh.Cmd[1] = 1 << audio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) err = vx_send_msg(chip, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #endif // not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * set the monitoring level and mute state of the given audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * no more static, because must be called from vx_pcm to demute monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct vx_audio_level info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) info.has_monitor_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) info.monitor_level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) info.has_monitor_mute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) info.monitor_mute = !active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) chip->audio_monitor[audio] = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) chip->audio_monitor_active[audio] = active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * set the mute status of the given audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int vx_set_audio_switch(struct vx_core *chip, int audio, int active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct vx_audio_level info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) info.has_mute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) info.mute = !active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) chip->audio_active[audio] = active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * set the mute status of the given audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int vx_set_audio_gain(struct vx_core *chip, int audio, int capture, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct vx_audio_level info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) info.has_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) info.level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) chip->audio_gain[capture][audio] = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return vx_adjust_audio_level(chip, audio, capture, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * reset all audio levels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void vx_reset_audio_levels(struct vx_core *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unsigned int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct vx_audio_level info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) memset(chip->audio_gain, 0, sizeof(chip->audio_gain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) memset(chip->audio_active, 0, sizeof(chip->audio_active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) for (c = 0; c < 2; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (i = 0; i < chip->hw->num_ins * 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (c == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) info.has_monitor_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) info.has_mute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) info.has_monitor_mute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) info.has_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) info.level = CVAL_0DB; /* default: 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) vx_adjust_audio_level(chip, i, c, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) chip->audio_gain[c][i] = CVAL_0DB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) chip->audio_monitor[i] = CVAL_0DB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * VU, peak meter record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #define VU_METER_CHANNELS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct vx_vu_meter {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int saturated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int vu_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int peak_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * get the VU and peak meter values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @audio: the audio index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * @capture: 0 = playback, 1 = capture operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * @info: the array of vx_vu_meter records (size = 2).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int vx_get_audio_vu_meter(struct vx_core *chip, int audio, int capture, struct vx_vu_meter *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct vx_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (chip->chip_status & VX_STAT_IS_STALE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rmh.LgStat += 2 * VU_METER_CHANNELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) rmh.Cmd[0] |= COMMAND_RECORD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Add Audio IO mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) rmh.Cmd[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) for (i = 0; i < VU_METER_CHANNELS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) rmh.Cmd[1] |= 1 << (audio + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) err = vx_send_msg(chip, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* Read response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) info->vu_level = rmh.Stat[i + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) info->peak_level = rmh.Stat[i + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) info++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * control API entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * output level control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int vx_output_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) uinfo->value.integer.max = chip->hw->output_level_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int codec = kcontrol->id.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ucontrol->value.integer.value[0] = chip->output_level[codec][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ucontrol->value.integer.value[1] = chip->output_level[codec][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int codec = kcontrol->id.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) unsigned int val[2], vmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) vmax = chip->hw->output_level_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) val[0] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) val[1] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (val[0] > vmax || val[1] > vmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (val[0] != chip->output_level[codec][0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) val[1] != chip->output_level[codec][1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) vx_set_analog_output_level(chip, codec, val[0], val[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) chip->output_level[codec][0] = val[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) chip->output_level[codec][1] = val[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static const struct snd_kcontrol_new vx_control_output_level = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .info = vx_output_level_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .get = vx_output_level_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .put = vx_output_level_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* tlv will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * audio source select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static int vx_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static const char * const texts_mic[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) "Digital", "Line", "Mic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static const char * const texts_vx2[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) "Digital", "Analog"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (chip->type >= VX_TYPE_VXPOCKET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return snd_ctl_enum_info(uinfo, 1, 3, texts_mic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return snd_ctl_enum_info(uinfo, 1, 2, texts_vx2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ucontrol->value.enumerated.item[0] = chip->audio_source_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (chip->type >= VX_TYPE_VXPOCKET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (ucontrol->value.enumerated.item[0] > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (ucontrol->value.enumerated.item[0] > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) chip->audio_source_target = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) vx_sync_audio_source(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static const struct snd_kcontrol_new vx_control_audio_src = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .name = "Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .info = vx_audio_src_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .get = vx_audio_src_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .put = vx_audio_src_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * clock mode selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int vx_clock_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static const char * const texts[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) "Auto", "Internal", "External"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return snd_ctl_enum_info(uinfo, 1, 3, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ucontrol->value.enumerated.item[0] = chip->clock_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (ucontrol->value.enumerated.item[0] > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) chip->clock_mode = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) vx_set_clock(chip, chip->freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static const struct snd_kcontrol_new vx_control_clock_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .name = "Clock Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .info = vx_clock_mode_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .get = vx_clock_mode_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .put = vx_clock_mode_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * Audio Gain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int vx_audio_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) uinfo->value.integer.max = CVAL_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int capture = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int capture = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unsigned int val[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) val[0] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) val[1] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (val[0] > CVAL_MAX || val[1] > CVAL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (val[0] != chip->audio_gain[capture][audio] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) val[1] != chip->audio_gain[capture][audio+1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) vx_set_audio_gain(chip, audio, capture, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) vx_set_audio_gain(chip, audio+1, capture, val[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ucontrol->value.integer.value[0] = chip->audio_monitor[audio];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) unsigned int val[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) val[0] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) val[1] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (val[0] > CVAL_MAX || val[1] > CVAL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (val[0] != chip->audio_monitor[audio] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) val[1] != chip->audio_monitor[audio+1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) vx_set_monitor_level(chip, audio, val[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) chip->audio_monitor_active[audio]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) vx_set_monitor_level(chip, audio+1, val[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) chip->audio_monitor_active[audio+1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) #define vx_audio_sw_info snd_ctl_boolean_stereo_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ucontrol->value.integer.value[0] = chip->audio_active[audio];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ucontrol->value.integer.value[1] = chip->audio_active[audio+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ucontrol->value.integer.value[0] != chip->audio_active[audio] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) vx_set_audio_switch(chip, audio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) !!ucontrol->value.integer.value[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) vx_set_audio_switch(chip, audio+1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) !!ucontrol->value.integer.value[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) !!ucontrol->value.integer.value[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) !!ucontrol->value.integer.value[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static const struct snd_kcontrol_new vx_control_audio_gain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* name will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .info = vx_audio_gain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .get = vx_audio_gain_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .put = vx_audio_gain_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .tlv = { .p = db_scale_audio_gain },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static const struct snd_kcontrol_new vx_control_output_switch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .name = "PCM Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .info = vx_audio_sw_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .get = vx_audio_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) .put = vx_audio_sw_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static const struct snd_kcontrol_new vx_control_monitor_gain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .name = "Monitoring Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .info = vx_audio_gain_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) .get = vx_audio_monitor_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .put = vx_audio_monitor_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .tlv = { .p = db_scale_audio_gain },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static const struct snd_kcontrol_new vx_control_monitor_switch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .name = "Monitoring Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .info = vx_audio_sw_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .get = vx_monitor_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .put = vx_monitor_sw_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * IEC958 status bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static int vx_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static int vx_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ucontrol->value.iec958.status[0] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ucontrol->value.iec958.status[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) ucontrol->value.iec958.status[2] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ucontrol->value.iec958.status[3] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) val = (ucontrol->value.iec958.status[0] << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) (ucontrol->value.iec958.status[1] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) (ucontrol->value.iec958.status[2] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) (ucontrol->value.iec958.status[3] << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) mutex_lock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (chip->uer_bits != val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) chip->uer_bits = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) vx_set_iec958_status(chip, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) mutex_unlock(&chip->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static const struct snd_kcontrol_new vx_control_iec958_mask = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .info = vx_iec958_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .get = vx_iec958_mask_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static const struct snd_kcontrol_new vx_control_iec958 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .info = vx_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .get = vx_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .put = vx_iec958_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * VU meter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) #define METER_MAX 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) #define METER_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int vx_vu_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) uinfo->value.integer.max = METER_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static int vx_vu_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct vx_vu_meter meter[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int capture = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) vx_get_audio_vu_meter(chip, audio, capture, meter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct vx_vu_meter meter[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) int capture = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) vx_get_audio_vu_meter(chip, audio, capture, meter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) #define vx_saturation_info snd_ctl_boolean_stereo_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) struct vx_core *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) struct vx_vu_meter meter[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) int audio = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ucontrol->value.integer.value[0] = meter[0].saturated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ucontrol->value.integer.value[1] = meter[1].saturated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static const struct snd_kcontrol_new vx_control_vu_meter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) /* name will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .info = vx_vu_meter_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .get = vx_vu_meter_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static const struct snd_kcontrol_new vx_control_peak_meter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* name will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .info = vx_vu_meter_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .get = vx_peak_meter_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static const struct snd_kcontrol_new vx_control_saturation = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .name = "Input Saturation",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .info = vx_saturation_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .get = vx_saturation_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int snd_vx_mixer_new(struct vx_core *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) unsigned int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct snd_kcontrol_new temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct snd_card *card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) strcpy(card->mixername, card->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* output level controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) for (i = 0; i < chip->hw->num_outs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) temp = vx_control_output_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) temp.tlv.p = chip->hw->output_level_db_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* PCM volumes, switches, monitoring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) for (i = 0; i < chip->hw->num_outs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) int val = i * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) temp = vx_control_audio_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) temp.name = "PCM Playback Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) temp = vx_control_output_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) temp = vx_control_monitor_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) temp = vx_control_monitor_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) for (i = 0; i < chip->hw->num_outs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) temp = vx_control_audio_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) temp.name = "PCM Capture Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) temp.private_value = (i * 2) | (1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /* Audio source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* clock mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* IEC958 controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* VU, peak, saturation meters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) for (c = 0; c < 2; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) static const char * const dir[2] = { "Output", "Input" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) for (i = 0; i < chip->hw->num_ins; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) int val = (i * 2) | (c << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (c == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) temp = vx_control_saturation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) sprintf(name, "%s VU Meter", dir[c]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) temp = vx_control_vu_meter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) temp.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) sprintf(name, "%s Peak Meter", dir[c]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) temp = vx_control_peak_meter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) temp.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) temp.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) temp.private_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) vx_reset_audio_levels(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }