]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: codecs: va-macro: Rework version checking
authorKonrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Wed, 15 Oct 2025 07:57:15 +0000 (13:27 +0530)
committerMark Brown <broonie@kernel.org>
Thu, 16 Oct 2025 15:33:44 +0000 (16:33 +0100)
Open-code some of the registers to make the checks anywhere near human-
readable. Error out if the version is unsupported or if the VA macro
isn't supposed to be present within this LPASS instance (since we can
check for that now).

Note that previously v2.0 and v2.1 assignments were swapped, but v2.1
does not even seem to exist (as opposed to v2.0.1) and there is no
difference in SW handling anyway.

[Prasad Kumpatla: fixed a spelling error and resolved a checkpatch
warning related to return value handling]

Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
Signed-off-by: Prasad Kumpatla <prasad.kumpatla@oss.qualcomm.com>
Link: https://patch.msgid.link/20251015-knp-audio-v2-v3-1-e0e3e4167d87@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/lpass-va-macro.c

index 2e1b77973a3e98cbbf1427b10c386ad630dd994f..eb4981255f2b3cd6528066660e69331c6b0dcb5d 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #define CDC_VA_TOP_CSR_I2S_CLK                 (0x00A8)
 #define CDC_VA_TOP_CSR_I2S_RESET               (0x00AC)
 #define CDC_VA_TOP_CSR_CORE_ID_0               (0x00C0)
+ #define CORE_ID_0_REV_MAJ                     GENMASK(7, 0)
 #define CDC_VA_TOP_CSR_CORE_ID_1               (0x00C4)
+#define CORE_ID_1_HAS_WSAMACRO                 BIT(3)
+#define CORE_ID_1_HAS_RXMACRO                  BIT(2)
+#define CORE_ID_1_HAS_TXMACRO                  BIT(1)
+#define CORE_ID_1_HAS_VAMACRO                  BIT(0)
 #define CDC_VA_TOP_CSR_CORE_ID_2               (0x00C8)
+ #define CORE_ID_2_REV_MIN                     GENMASK(7, 4)
+ #define CORE_ID_2_REV_STEP                    GENMASK(3, 0)
 #define CDC_VA_TOP_CSR_CORE_ID_3               (0x00CC)
 #define CDC_VA_TOP_CSR_SWR_MIC_CTL0            (0x00D0)
 #define CDC_VA_TOP_CSR_SWR_MIC_CTL1            (0x00D4)
@@ -1462,39 +1470,63 @@ undefined_rate:
        return dmic_sample_rate;
 }
 
-static void va_macro_set_lpass_codec_version(struct va_macro *va)
+static int va_macro_set_lpass_codec_version(struct va_macro *va)
 {
-       int core_id_0 = 0, core_id_1 = 0, core_id_2 = 0;
        int version = LPASS_CODEC_VERSION_UNKNOWN;
+       u32 maj, min, step;
+       u32 val;
 
-       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_0, &core_id_0);
-       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_1, &core_id_1);
-       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_2, &core_id_2);
+       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_0, &val);
+       maj = FIELD_GET(CORE_ID_0_REV_MAJ, val);
 
-       if ((core_id_0 == 0x01) && (core_id_1 == 0x0F))
-               version = LPASS_CODEC_VERSION_2_0;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && core_id_2 == 0x01)
+       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_1, &val);
+       if (!FIELD_GET(CORE_ID_1_HAS_VAMACRO, val)) {
+               dev_err(va->dev, "This is not a VA macro instance\n");
+               return -ENODEV;
+       }
+
+       regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_2, &val);
+       min = FIELD_GET(CORE_ID_2_REV_MIN, val);
+       step = FIELD_GET(CORE_ID_2_REV_STEP, val);
+
+       if (maj == 1) {
                version = LPASS_CODEC_VERSION_2_0;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0E))
-               version = LPASS_CODEC_VERSION_2_1;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51))
-               version = LPASS_CODEC_VERSION_2_5;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x60 || core_id_2 == 0x61))
-               version = LPASS_CODEC_VERSION_2_6;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x70 || core_id_2 == 0x71))
-               version = LPASS_CODEC_VERSION_2_7;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81))
-               version = LPASS_CODEC_VERSION_2_8;
-       if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x90 || core_id_2 == 0x91))
-               version = LPASS_CODEC_VERSION_2_9;
-
-       if (version == LPASS_CODEC_VERSION_UNKNOWN)
-               dev_warn(va->dev, "Unknown Codec version, ID: %02x / %02x / %02x\n",
-                        core_id_0, core_id_1, core_id_2);
+       } else if (maj == 2) {
+               switch (min) {
+               case 0:
+                       version = LPASS_CODEC_VERSION_2_0;
+                       break;
+               case 5:
+                       version = LPASS_CODEC_VERSION_2_5;
+                       break;
+               case 6:
+                       version = LPASS_CODEC_VERSION_2_6;
+                       break;
+               case 7:
+                       version = LPASS_CODEC_VERSION_2_7;
+                       break;
+               case 8:
+                       version = LPASS_CODEC_VERSION_2_8;
+                       break;
+               case 9:
+                       version = LPASS_CODEC_VERSION_2_9;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (version == LPASS_CODEC_VERSION_UNKNOWN) {
+               dev_err(va->dev, "VA Macro v%u.%u.%u is not supported\n",
+                       maj, min, step);
+               return -EOPNOTSUPP;
+       }
 
        lpass_macro_set_codec_version(version);
 
        dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version));
+
+       return 0;
 }
 
 static int va_macro_probe(struct platform_device *pdev)
@@ -1594,10 +1626,14 @@ static int va_macro_probe(struct platform_device *pdev)
         * old version of codecs do not have a reliable way to determine the
         * version from registers, get them from soc specific data
         */
-       if (data->version)
+       if (data->version) {
                lpass_macro_set_codec_version(data->version);
-       else /* read version from register */
-               va_macro_set_lpass_codec_version(va);
+       } else {
+               /* read version from register */
+               ret = va_macro_set_lpass_codec_version(va);
+               if (ret)
+                       return ret;
+       }
 
        if (va->has_swr_master) {
                /* Set default CLK div to 1 */