Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }