^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) * Support for Digigram Lola PCI-e boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "lola.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int dir, int nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) pin->nid = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) val &= 0x00f00fff; /* test TYPE and bits 0..11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (val == 0x00400200) /* Type = 4, Digital = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pin->is_analog = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) pin->is_analog = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) pin->is_analog = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) dev_err(chip->card->dev, "Invalid wcaps 0x%x for 0x%x\n", val, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* analog parameters only following, so continue in case of Digital pin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (!pin->is_analog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (dir == PLAY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dev_err(chip->card->dev, "Can't read AMP-caps for 0x%x\n", nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (pin->amp_num_steps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* zero as mute state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pin->amp_num_steps++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) pin->amp_step_size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) pin->amp_offset = LOLA_AMP_OFFSET(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) dev_err(chip->card->dev, "Can't get MAX_LEVEL 0x%x\n", nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pin->max_level = val & 0x3ff; /* 10 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pin->config_default_reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pin->fixed_gain_list_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pin->cur_gain_step = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int lola_init_pins(struct lola *chip, int dir, int *nidp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int i, err, nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) nid = *nidp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (chip->pin[dir].pins[i].is_analog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) chip->pin[dir].num_analog_pins++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *nidp = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void lola_free_mixer(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) vfree(chip->mixer.array_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int lola_init_mixer_widget(struct lola *chip, int nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return err;
^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) if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_dbg(chip->card->dev, "No valid mixer widget\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) chip->mixer.nid = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) chip->mixer.caps = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) chip->mixer.array = (struct lola_mixer_array __iomem *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* reserve memory to copy mixer data for sleep mode transitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* mixer matrix sources are physical input data and play streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* mixer matrix destinations are record streams and physical output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* mixer matrix may have unused areas between PhysIn and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Play or Record and PhysOut zones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * +-+ 0-------8------16-------8------16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * | | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * |s| | INPUT | | INPUT | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * | |->| -> |unused | -> |unused |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * |r| |CAPTURE| | OUTPUT| |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * | | | MIX | | MIX | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * |c| 8--------------------------------
^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) * |g| |unused |unused |unused |unused |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * | | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * |a| | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * | | 16-------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * |i| | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * | | | PLAYBK| | PLAYBK| |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * |n|->| -> |unused | -> |unused |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * | | |CAPTURE| | OUTPUT| |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * | | | MIX | | MIX | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * |a| 8--------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * |r| | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * |r| | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * |a| |unused |unused |unused |unused |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * |y| | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * | | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * +++ 16--|---------------|------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * +---V---------------V-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * | dest_mix_gain_enable array |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * +-------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* example : MixerMatrix of LoLa280
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * +-+ 0-------8-2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * |s| | INPUT | | INPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * |r|->| -> | | ->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * |c| |CAPTURE| | <- OUTPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * | | | MIX | | MIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * |g| 8----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * |a| | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * |i| | PLAYBK| | PLAYBACK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * |n|->| -> | | ->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * | | |CAPTURE| | <- OUTPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * |a| | MIX | | MIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * |r| 8---|----|-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * |r| +---V----V-------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * |a| | dest_mix_gain_enable array |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * |y| +----------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_err(chip->card->dev, "Invalid mixer widget size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) (((1U << chip->mixer.src_stream_outs) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) << chip->mixer.src_stream_out_ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) (((1U << chip->mixer.dest_phys_outs) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) << chip->mixer.dest_phys_out_ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev_dbg(chip->card->dev, "Mixer src_mask=%x, dest_mask=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) chip->mixer.src_mask, chip->mixer.dest_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned short gain, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned int oldval, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!(chip->mixer.src_mask & (1 << id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) oldval = val = readl(&chip->mixer.array->src_gain_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) val |= (1 << id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) val &= ~(1 << id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* test if values unchanged */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if ((val == oldval) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) (gain == readw(&chip->mixer.array->src_gain[id])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) id, gain, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) writew(gain, &chip->mixer.array->src_gain[id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) writel(val, &chip->mixer.array->src_gain_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* inform micro-controller about the new source gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) LOLA_VERB_SET_SOURCE_GAIN, id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #if 0 /* not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned short *gains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if ((chip->mixer.src_mask & mask) != mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) for (i = 0; i < LOLA_MIXER_DIM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (mask & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) writew(*gains, &chip->mixer.array->src_gain[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) gains++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) writel(mask, &chip->mixer.array->src_gain_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* update for all srcs at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* update manually */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) for (i = 0; i < LOLA_MIXER_DIM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (mask & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) LOLA_VERB_SET_SOURCE_GAIN, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #endif /* not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static int lola_mixer_set_mapping_gain(struct lola *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned int src, unsigned int dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned short gain, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!(chip->mixer.src_mask & (1 << src)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) !(chip->mixer.dest_mask & (1 << dest)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) val |= (1 << src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) val &= ~(1 << src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) src, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #if 0 /* not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) unsigned int mask, unsigned short *gains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!(chip->mixer.dest_mask & (1 << id)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) (chip->mixer.src_mask & mask) != mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) for (i = 0; i < LOLA_MIXER_DIM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (mask & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) gains++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* update for all dests at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #endif /* not used */
^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) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int set_analog_volume(struct lola *chip, int dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) unsigned int idx, unsigned int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) bool external_call);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct lola_pin *pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int idx, max_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) pin = chip->pin[dir].pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) max_idx = chip->pin[dir].num_pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (idx = 0; idx < max_idx; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (pin[idx].is_analog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned int val = mute ? 0 : pin[idx].cur_gain_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* set volume and do not save the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) set_analog_volume(chip, dir, idx, val, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) void lola_save_mixer(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* mute analog output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (chip->mixer.array_saved) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* store contents of mixer array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) sizeof(*chip->mixer.array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */
^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) void lola_restore_mixer(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*lola_reset_setups(chip);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (chip->mixer.array_saved) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* restore contents of mixer array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) sizeof(*chip->mixer.array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* inform micro-controller about all restored values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * and ignore return values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0; i < chip->mixer.src_phys_ins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) LOLA_VERB_SET_SOURCE_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (i = 0; i < chip->mixer.src_stream_outs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) LOLA_VERB_SET_SOURCE_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) chip->mixer.src_stream_out_ofs + i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) for (i = 0; i < chip->mixer.dest_stream_ins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) LOLA_VERB_SET_DESTINATION_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) for (i = 0; i < chip->mixer.dest_phys_outs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) LOLA_VERB_SET_DESTINATION_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) chip->mixer.dest_phys_out_ofs + i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int set_analog_volume(struct lola *chip, int dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int idx, unsigned int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) bool external_call)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct lola_pin *pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (idx >= chip->pin[dir].num_pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) pin = &chip->pin[dir].pins[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!pin->is_analog || pin->amp_num_steps <= val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (external_call && pin->cur_gain_step == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (external_call)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) "set_analog_volume (dir=%d idx=%d, volume=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dir, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) err = lola_codec_write(chip, pin->nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (external_call)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) pin->cur_gain_step = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int success = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int n, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* SRC can be activated and the dwInputSRCMask is valid? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if ((chip->input_src_caps_mask & src_mask) != src_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /* handle all even Inputs - SRC is a stereo setting !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) unsigned int mask = 3U << n; /* handle the stereo case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) unsigned int new_src, src_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!(chip->input_src_caps_mask & mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* if one IO needs SRC, both stereo IO will get SRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) new_src = (src_mask & mask) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) src_state = (chip->input_src_mask & mask) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (src_state == new_src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) continue; /* nothing to change for this IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) LOLA_VERB_SET_SRC, new_src, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) success++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ret = lola_codec_flush(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) chip->input_src_mask = src_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int init_mixer_values(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* all sample rate converters on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* clear all mixer matrix settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* inform firmware about all updated matrix columns - capture part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) for (i = 0; i < chip->mixer.dest_stream_ins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) LOLA_VERB_SET_DESTINATION_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* inform firmware about all updated matrix columns - output part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) for (i = 0; i < chip->mixer.dest_phys_outs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) lola_codec_write(chip, chip->mixer.nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) LOLA_VERB_SET_DESTINATION_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) chip->mixer.dest_phys_out_ofs + i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* set all digital input source (master) gains to 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) for (i = 0; i < chip->mixer.src_phys_ins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* set all digital playback source (master) gains to 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) for (i = 0; i < chip->mixer.src_stream_outs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) lola_mixer_set_src_gain(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) i + chip->mixer.src_stream_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 336, true); /* 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int src = i % chip->mixer.src_phys_ins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) lola_mixer_set_mapping_gain(chip, src, i, 336, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) for (i = 0; i < chip->mixer.src_stream_outs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) int src = chip->mixer.src_stream_out_ofs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int dst = chip->mixer.dest_phys_out_ofs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) i % chip->mixer.dest_phys_outs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) lola_mixer_set_mapping_gain(chip, src, dst, 336, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * analog mixer control element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int dir = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) uinfo->count = chip->pin[dir].num_pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^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) static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) int dir = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) for (i = 0; i < chip->pin[dir].num_pins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ucontrol->value.integer.value[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) chip->pin[dir].pins[i].cur_gain_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int dir = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) for (i = 0; i < chip->pin[dir].num_pins; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) err = set_analog_volume(chip, dir, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ucontrol->value.integer.value[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned int size, unsigned int __user *tlv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int dir = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) unsigned int val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct lola_pin *pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (size < 4 * sizeof(unsigned int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) pin = &chip->pin[dir].pins[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) val2 = pin->amp_step_size * 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) val1 = -1 * (int)pin->amp_offset * (int)val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) #ifdef TLV_DB_SCALE_MUTE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) val2 |= TLV_DB_SCALE_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (put_user(2 * sizeof(unsigned int), tlv + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (put_user(val1, tlv + 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (put_user(val2, tlv + 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static struct snd_kcontrol_new lola_analog_mixer = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) SNDRV_CTL_ELEM_ACCESS_TLV_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .info = lola_analog_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .get = lola_analog_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .put = lola_analog_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) .tlv.c = lola_analog_vol_tlv,
^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 create_analog_mixer(struct lola *chip, int dir, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (!chip->pin[dir].num_pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* no analog volumes on digital only adapters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) lola_analog_mixer.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) lola_analog_mixer.private_value = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) snd_ctl_new1(&lola_analog_mixer, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * Hardware sample rate converter on digital input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int lola_input_src_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) uinfo->count = chip->pin[CAPT].num_pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) uinfo->value.integer.max = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int lola_input_src_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) for (i = 0; i < chip->pin[CAPT].num_pins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ucontrol->value.integer.value[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) !!(chip->input_src_mask & (1 << i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int lola_input_src_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) for (i = 0; i < chip->pin[CAPT].num_pins; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (ucontrol->value.integer.value[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) mask |= 1 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return lola_set_src_config(chip, mask, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static const struct snd_kcontrol_new lola_input_src_mixer = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .name = "Digital SRC Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) .info = lola_input_src_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .get = lola_input_src_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .put = lola_input_src_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * Lola16161 or Lola881 can have Hardware sample rate converters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * on its digital input pins
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int create_input_src_mixer(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!chip->input_src_caps_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) snd_ctl_new1(&lola_input_src_mixer, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * src gain mixer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) unsigned int count = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) uinfo->count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) uinfo->value.integer.max = 409;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) unsigned int ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) unsigned int count = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) unsigned int mask, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) mask = readl(&chip->mixer.array->src_gain_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) unsigned int idx = ofs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!(chip->mixer.src_mask & (1 << idx)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (mask & (1 << idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) val = readw(&chip->mixer.array->src_gain[idx]) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ucontrol->value.integer.value[i] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) unsigned int ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) unsigned int count = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) unsigned int idx = ofs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) unsigned short val = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) val--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err = lola_mixer_set_src_gain(chip, idx, val, !!val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static struct snd_kcontrol_new lola_src_gain_mixer = {
^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) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .info = lola_src_gain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) .get = lola_src_gain_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) .put = lola_src_gain_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .tlv.p = lola_src_gain_tlv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int create_src_gain_mixer(struct lola *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int num, int ofs, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) lola_src_gain_mixer.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) lola_src_gain_mixer.private_value = ofs + (num << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) snd_ctl_new1(&lola_src_gain_mixer, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) #if 0 /* not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * destination gain (matrix-like) mixer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) uinfo->count = src_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) uinfo->value.integer.max = 433;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 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 lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) unsigned int src_ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned int dst, mask, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) for (i = 0; i < src_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) unsigned int src = src_ofs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (!(chip->mixer.src_mask & (1 << src)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (mask & (1 << dst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ucontrol->value.integer.value[i] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct lola *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) unsigned int src_ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) unsigned int dst, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unsigned short gains[MAX_STREAM_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int i, num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) for (i = 0; i < src_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) unsigned short val = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) gains[num++] = val - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) mask |= 1 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mask <<= src_ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return lola_mixer_set_dest_gains(chip, dst, mask, gains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static struct snd_kcontrol_new lola_dest_gain_mixer = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .info = lola_dest_gain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .get = lola_dest_gain_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .put = lola_dest_gain_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .tlv.p = lola_dest_gain_tlv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int create_dest_gain_mixer(struct lola *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int src_num, int src_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int num, int ofs, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) lola_dest_gain_mixer.count = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) lola_dest_gain_mixer.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) lola_dest_gain_mixer.private_value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) snd_ctl_new1(&lola_dest_gain_mixer, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) #endif /* not used */
^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) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int lola_create_mixer(struct lola *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) err = create_analog_mixer(chip, PLAY, "Analog Playback Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) err = create_analog_mixer(chip, CAPT, "Analog Capture Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) err = create_input_src_mixer(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) "Digital Capture Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) chip->mixer.src_stream_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) "Digital Playback Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /* FIXME: buggy mixer matrix handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) err = create_dest_gain_mixer(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) chip->mixer.src_phys_ins, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) chip->mixer.dest_stream_ins, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) "Line Capture Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) err = create_dest_gain_mixer(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) chip->mixer.src_stream_outs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) chip->mixer.src_stream_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) chip->mixer.dest_stream_ins, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) "Stream-Loopback Capture Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) err = create_dest_gain_mixer(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) chip->mixer.src_phys_ins, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) chip->mixer.dest_phys_outs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) chip->mixer.dest_phys_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) "Line-Loopback Playback Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) err = create_dest_gain_mixer(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) chip->mixer.src_stream_outs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) chip->mixer.src_stream_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) chip->mixer.dest_phys_outs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) chip->mixer.dest_phys_out_ofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) "Stream Playback Volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) #endif /* FIXME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return init_mixer_values(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }