]> www.infradead.org Git - users/hch/misc.git/commitdiff
ASoC: codecs: lpass-wsa-macro: Fix speaker quality distortion
authorKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Sun, 31 Aug 2025 15:14:02 +0000 (17:14 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 4 Sep 2025 16:51:57 +0000 (17:51 +0100)
Commit bb4a0f497bc1 ("ASoC: codecs: lpass: Drop unused
AIF_INVALID first DAI identifier") removed first entry in enum with DAI
identifiers, because it looked unused.  Turns out that there is a
relation between DAI ID and "WSA RX0 Mux"-like kcontrols (which use
"rx_mux_text" array).  That "rx_mux_text" array used first three entries
of DAI IDs enum, with value '0' being invalid.

The value passed tp "WSA RX0 Mux"-like kcontrols was used as DAI ID and
set to configure active channel count and mask, which are arrays indexed
by DAI ID.

After removal of first AIF_INVALID DAI identifier, this kcontrol was
updating wrong entries in active channel count and mask arrays which was
visible in reduced quality (distortions) during speaker playback on
several boards like Lenovo T14s laptop and Qualcomm SM8550-based boards.

Reported-by: Alexey Klimov <alexey.klimov@linaro.org>
Fixes: bb4a0f497bc1 ("ASoC: codecs: lpass: Drop unused AIF_INVALID first DAI identifier")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Tested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Message-ID: <20250831151401.30897-2-krzysztof.kozlowski@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/lpass-wsa-macro.c

index da6adb3de21d77c91c2bc227685d4322ae560353..d7eec9fdaf9c655cb60ffa597ec7d70e41302796 100644 (file)
@@ -368,6 +368,7 @@ static struct interp_sample_rate int_mix_sample_rate_val[] = {
        {192000, 0x6},  /* 192K */
 };
 
+/* Matches also rx_mux_text */
 enum {
        WSA_MACRO_AIF1_PB,
        WSA_MACRO_AIF_MIX1_PB,
@@ -465,6 +466,7 @@ static const char *const rx_mix_ec_text[] = {
        "ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
 };
 
+/* Order must match WSA_MACRO_MAX_DAIS enum (offset by 1) */
 static const char *const rx_mux_text[] = {
        "ZERO", "AIF1_PB", "AIF_MIX1_PB"
 };
@@ -2207,6 +2209,7 @@ static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
        u32 rx_port_value = ucontrol->value.integer.value[0];
        u32 bit_input;
        u32 aif_rst;
+       unsigned int dai_id;
        struct wsa_macro *wsa = snd_soc_component_get_drvdata(component);
 
        aif_rst = wsa->rx_port_value[widget->shift];
@@ -2224,17 +2227,22 @@ static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
 
        switch (rx_port_value) {
        case 0:
-               if (wsa->active_ch_cnt[aif_rst]) {
-                       clear_bit(bit_input,
-                                 &wsa->active_ch_mask[aif_rst]);
-                       wsa->active_ch_cnt[aif_rst]--;
+               /*
+                * active_ch_cnt and active_ch_mask use DAI IDs (WSA_MACRO_MAX_DAIS).
+                * active_ch_cnt == 0 was tested in if() above.
+                */
+               dai_id = aif_rst - 1;
+               if (wsa->active_ch_cnt[dai_id]) {
+                       clear_bit(bit_input, &wsa->active_ch_mask[dai_id]);
+                       wsa->active_ch_cnt[dai_id]--;
                }
                break;
        case 1:
        case 2:
-               set_bit(bit_input,
-                       &wsa->active_ch_mask[rx_port_value]);
-               wsa->active_ch_cnt[rx_port_value]++;
+               /* active_ch_cnt and active_ch_mask use DAI IDs (WSA_MACRO_MAX_DAIS). */
+               dai_id = rx_port_value - 1;
+               set_bit(bit_input, &wsa->active_ch_mask[dai_id]);
+               wsa->active_ch_cnt[dai_id]++;
                break;
        default:
                dev_err(component->dev,