aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/sound/pci/emu10k1/emumixer.c
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2023-05-16 11:36:08 +0200
committerTakashi Iwai <tiwai@suse.de>2023-05-17 17:07:55 +0200
commit1fc710f06aa8f33abab4fdded9463eefdff7d390 (patch)
tree94e77f651e78b5b654dccb5af26686ad8510dacf /sound/pci/emu10k1/emumixer.c
parentALSA: emu10k1: fix return value of snd_emu1010_dac_pads_put() (diff)
downloadwireguard-linux-1fc710f06aa8f33abab4fdded9463eefdff7d390.tar.xz
wireguard-linux-1fc710f06aa8f33abab4fdded9463eefdff7d390.zip
ALSA: emu10k1: make E-MU I/O routing init data-driven
... and move it to the mixer init, as it's logically part of it. As a side effect, this fixes the initial values of the input destination mixer controls, which would have previously remained at "Silent" despite different defaults. This didn't really matter, though, as ALSA state restoration would hide that bug beyond first use. Note that this completely does away with clearing the output routing registers, as it was rather pointless - we just programmed the FPGA (resetting it first if necessary), so everything is zeroed anyway (that's documented by Xilinx, and as further evidence, some of the loops terminated too early, and we didn't bother clearing the high channels of the input routes at all, all with no observed adverse effects). As a drive-by, this also fixes some capture channel defaults - any EMU_SRC_*2 isn't a sensible value in 1x clock mode. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230516093612.3536508-7-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/emu10k1/emumixer.c')
-rw-r--r--sound/pci/emu10k1/emumixer.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index ef05d4f3316c..b3e5a842ac17 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -231,6 +231,20 @@ static const unsigned short emu1010_output_dst[] = {
};
static_assert(ARRAY_SIZE(emu1010_output_dst) == ARRAY_SIZE(emu1010_output_texts));
+static const unsigned short emu1010_output_dflt[] = {
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
+ EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5,
+ EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
+ EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
+};
+static_assert(ARRAY_SIZE(emu1010_output_dflt) == ARRAY_SIZE(emu1010_output_dst));
+
/* 1616(m) cardbus */
static const char * const snd_emu1616_output_texts[] = {
@@ -252,6 +266,17 @@ static const unsigned short emu1616_output_dst[] = {
};
static_assert(ARRAY_SIZE(emu1616_output_dst) == ARRAY_SIZE(snd_emu1616_output_texts));
+static const unsigned short emu1616_output_dflt[] = {
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
+ EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
+ EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
+ EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
+};
+static_assert(ARRAY_SIZE(emu1616_output_dflt) == ARRAY_SIZE(emu1616_output_dst));
+
/*
* Data destinations - FPGA outputs going to Alice2 (Audigy) for
* capture (EMU32 + I2S links)
@@ -311,11 +336,43 @@ static const unsigned short emu1010_input_dst[] = {
};
static_assert(ARRAY_SIZE(emu1010_input_dst) == ARRAY_SIZE(emu1010_input_texts));
+static const unsigned short emu1010_input_dflt[] = {
+ EMU_SRC_DOCK_MIC_A1,
+ EMU_SRC_DOCK_MIC_B1,
+ EMU_SRC_HAMOA_ADC_LEFT1,
+ EMU_SRC_HAMOA_ADC_RIGHT1,
+ EMU_SRC_DOCK_ADC1_LEFT1,
+ EMU_SRC_DOCK_ADC1_RIGHT1,
+ EMU_SRC_DOCK_ADC2_LEFT1,
+ EMU_SRC_DOCK_ADC2_RIGHT1,
+ /* Pavel Hofman - setting defaults for all capture channels.
+ * Defaults only, users will set their own values anyways, let's
+ * just copy/paste. */
+ EMU_SRC_DOCK_MIC_A1,
+ EMU_SRC_DOCK_MIC_B1,
+ EMU_SRC_HAMOA_ADC_LEFT1,
+ EMU_SRC_HAMOA_ADC_RIGHT1,
+ EMU_SRC_DOCK_ADC1_LEFT1,
+ EMU_SRC_DOCK_ADC1_RIGHT1,
+ EMU_SRC_DOCK_ADC2_LEFT1,
+ EMU_SRC_DOCK_ADC2_RIGHT1,
+
+ EMU_SRC_DOCK_ADC1_LEFT1,
+ EMU_SRC_DOCK_ADC1_RIGHT1,
+ EMU_SRC_DOCK_ADC2_LEFT1,
+ EMU_SRC_DOCK_ADC2_RIGHT1,
+ EMU_SRC_DOCK_ADC3_LEFT1,
+ EMU_SRC_DOCK_ADC3_RIGHT1,
+};
+static_assert(ARRAY_SIZE(emu1010_input_dflt) == ARRAY_SIZE(emu1010_input_dst));
+
struct snd_emu1010_routing_info {
const char * const *src_texts;
const unsigned short *src_regs;
const unsigned short *out_regs;
const unsigned short *in_regs;
+ const unsigned short *out_dflts;
+ const unsigned short *in_dflts;
unsigned n_srcs;
unsigned n_outs;
unsigned n_ins;
@@ -327,9 +384,11 @@ const struct snd_emu1010_routing_info emu1010_routing_info[] = {
.src_texts = emu1010_src_texts,
.n_srcs = ARRAY_SIZE(emu1010_src_texts),
+ .out_dflts = emu1010_output_dflt,
.out_regs = emu1010_output_dst,
.n_outs = ARRAY_SIZE(emu1010_output_dst),
+ .in_dflts = emu1010_input_dflt,
.in_regs = emu1010_input_dst,
.n_ins = ARRAY_SIZE(emu1010_input_dst),
},
@@ -339,9 +398,11 @@ const struct snd_emu1010_routing_info emu1010_routing_info[] = {
.src_texts = emu1616_src_texts,
.n_srcs = ARRAY_SIZE(emu1616_src_texts),
+ .out_dflts = emu1616_output_dflt,
.out_regs = emu1616_output_dst,
.n_outs = ARRAY_SIZE(emu1616_output_dst),
+ .in_dflts = emu1010_input_dflt,
.in_regs = emu1010_input_dst,
.n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
},
@@ -375,6 +436,28 @@ static void snd_emu1010_input_source_apply(struct snd_emu10k1 *emu,
emu_ri->in_regs[channel], emu_ri->src_regs[src]);
}
+static void snd_emu1010_apply_sources(struct snd_emu10k1 *emu)
+{
+ const struct snd_emu1010_routing_info *emu_ri =
+ &emu1010_routing_info[emu1010_idx(emu)];
+
+ for (unsigned i = 0; i < emu_ri->n_outs; i++)
+ snd_emu1010_output_source_apply(
+ emu, i, emu->emu1010.output_source[i]);
+ for (unsigned i = 0; i < emu_ri->n_ins; i++)
+ snd_emu1010_input_source_apply(
+ emu, i, emu->emu1010.input_source[i]);
+}
+
+static u8 emu1010_map_source(const struct snd_emu1010_routing_info *emu_ri,
+ unsigned val)
+{
+ for (unsigned i = 0; i < emu_ri->n_srcs; i++)
+ if (val == emu_ri->src_regs[i])
+ return i;
+ return 0;
+}
+
static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -1979,6 +2062,20 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
return err;
}
+ if (emu->card_capabilities->emu_model) {
+ unsigned i, emu_idx = emu1010_idx(emu);
+ const struct snd_emu1010_routing_info *emu_ri =
+ &emu1010_routing_info[emu_idx];
+
+ for (i = 0; i < emu_ri->n_ins; i++)
+ emu->emu1010.input_source[i] =
+ emu1010_map_source(emu_ri, emu_ri->in_dflts[i]);
+ for (i = 0; i < emu_ri->n_outs; i++)
+ emu->emu1010.output_source[i] =
+ emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
+ snd_emu1010_apply_sources(emu);
+ }
+
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
/* 1616(m) cardbus */
err = add_ctls(emu, &emu1010_output_source_ctl,