summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-09-08 19:54:52 +0100
committerMark Brown <broonie@kernel.org>2026-09-08 19:54:52 +0100
commit8fa5ce4e95bda6d3a90761d07d171f9e3f2f9328 (patch)
tree0236ef3ca7399fbb0ad403590e6a6346d9d2f117
parent5bb30783e4e5782349b5bfafbaf982bf86285302 (diff)
parent322a9e0850b41a628b59c29be89f499acba9f1c8 (diff)
downloadlinux-next-8fa5ce4e95bda6d3a90761d07d171f9e3f2f9328.tar.gz
linux-next-8fa5ce4e95bda6d3a90761d07d171f9e3f2f9328.zip
ASoC: codecs: lpass-macros: switch regcache to REGCACHE_MAPLE
Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> says: Move all four LPASS codec macros (rx/tx/va/wsa) from REGCACHE_FLAT to REGCACHE_MAPLE, and fix a latent v2.5 Compander1 addressing bug that the flat cache had been absorbing. REGCACHE_FLAT hides missing-default reads by returning the zero- initialised cache slot instead of doing a bus read. The caller can't tell that value apart from a real hardware value, so any un-defaulted, readable, non-volatile register that gets read silently returns wrong data. Since commit e062bdfdd6ad ("regmap: warn users about uninitialized flat cache") regmap dev_warn_once()s the first such miss, but any subsequent miss stays silent. REGCACHE_MAPLE reports a cache miss as -ENOENT and the regmap core falls back to a real bus read, so the caller always gets the true hardware value. All four macros are switched in the same series for consistency. The switch surfaced a latent bug in wsa_macro_set_spkr_mode() on v2.5+ silicon: two Compander1 register addresses moved on that generation and the driver was writing to the v2.1 addresses on all versions, taking a silent bus error. Patch 1/6 fixes that and is tagged Cc: stable. Series contents: 1/6: wsa-macro: use v2.5 Compander1 addresses on v2.5+ silicon (fix, tagged for stable). 2/6: rx-macro + wsa-macro: sort concatenated reg_defaults before regmap init so regmap does not sort a copy at runtime. 3/6: wsa-macro: switch cache to REGCACHE_MAPLE. 4/6, 5/6, 6/6: rx-macro / tx-macro / va-macro: cache switch, same rationale as 3/6. Tested on Glymur (SC8480XP CRD, WCD9378 SDCA compute mode + WSA8845 speakers): HPH playback, mic capture and WSA speaker playback all work with the full series applied; the "using zero-initialized flat cache" and "Unsorted reg_defaults" warnings both disappear from the boot log. Link: https://patch.msgid.link/20260908082806.648797-1-srinivas.kandagatla@oss.qualcomm.com
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c4
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c2
-rw-r--r--sound/soc/codecs/lpass-va-macro.c2
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c46
4 files changed, 33 insertions, 21 deletions
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 2e74ec1a52f8..c41eb8de6160 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -1673,7 +1673,7 @@ static const struct regmap_config rx_regmap_config = {
.reg_bits = 16,
.val_bits = 32, /* 8 but with 32 bit read/write */
.reg_stride = 4,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_MAPLE,
.max_register = RX_MAX_OFFSET,
.writeable_reg = rx_is_writeable_register,
.volatile_reg = rx_is_volatile_register,
@@ -3852,6 +3852,8 @@ static int rx_macro_probe(struct platform_device *pdev)
return -EINVAL;
}
+ regcache_sort_defaults(reg_defaults, def_count);
+
struct regmap_config *reg_config __free(kfree) = kmemdup(&rx_regmap_config,
sizeof(*reg_config),
GFP_KERNEL);
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index 4ac8a11f3062..6deaaabe43af 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -602,7 +602,7 @@ static const struct regmap_config tx_regmap_config = {
.reg_bits = 16,
.val_bits = 32,
.reg_stride = 4,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_MAPLE,
.max_register = TX_MAX_OFFSET,
.reg_defaults = tx_defaults,
.num_reg_defaults = ARRAY_SIZE(tx_defaults),
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index a3b3af0d7db3..03d6434a4a12 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -454,7 +454,7 @@ static const struct regmap_config va_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = va_defaults,
.num_reg_defaults = ARRAY_SIZE(va_defaults),
.max_register = VA_MAX_OFFSET,
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index f6ef7f188b1a..4242366601a5 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -1109,7 +1109,7 @@ static const struct regmap_config wsa_regmap_config = {
.reg_bits = 16,
.val_bits = 32, /* 8 but with 32 bit read/write */
.reg_stride = 4,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_MAPLE,
/* .reg_defaults and .num_reg_defaults set in probe() */
.max_register = WSA_MAX_OFFSET,
.writeable_reg = wsa_is_writeable_register,
@@ -1129,27 +1129,35 @@ static const struct regmap_config wsa_regmap_config = {
int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode)
{
struct wsa_macro *wsa = snd_soc_component_get_drvdata(component);
+ unsigned int comp1_ctl3, comp1_ctl7;
+ u8 comp_val, boost_val;
wsa->spkr_mode = mode;
- switch (mode) {
- case WSA_MACRO_SPKR_MODE_1:
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00);
- snd_soc_component_update_bits(component, CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44);
- snd_soc_component_update_bits(component, CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44);
- break;
- default:
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01);
- snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01);
- snd_soc_component_update_bits(component, CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58);
- snd_soc_component_update_bits(component, CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58);
- break;
+ /* Compander1 CTL3/CTL7 moved on v2.5+ silicon. */
+ if (wsa->codec_version >= LPASS_CODEC_VERSION_2_5) {
+ comp1_ctl3 = CDC_2_5_WSA_COMPANDER1_CTL3;
+ comp1_ctl7 = CDC_2_5_WSA_COMPANDER1_CTL7;
+ } else {
+ comp1_ctl3 = CDC_WSA_COMPANDER1_CTL3;
+ comp1_ctl7 = CDC_WSA_COMPANDER1_CTL7;
}
+
+ if (mode == WSA_MACRO_SPKR_MODE_1) {
+ comp_val = 0x00;
+ boost_val = 0x44;
+ } else {
+ comp_val = 0x80;
+ boost_val = 0x58;
+ }
+
+ snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL3, 0x80, comp_val);
+ snd_soc_component_update_bits(component, comp1_ctl3, 0x80, comp_val);
+ snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL7, 0x01, comp_val ? 0x01 : 0x00);
+ snd_soc_component_update_bits(component, comp1_ctl7, 0x01, comp_val ? 0x01 : 0x00);
+ snd_soc_component_update_bits(component, CDC_WSA_BOOST0_BOOST_CTL, 0x7C, boost_val);
+ snd_soc_component_update_bits(component, CDC_WSA_BOOST1_BOOST_CTL, 0x7C, boost_val);
+
return 0;
}
EXPORT_SYMBOL(wsa_macro_set_spkr_mode);
@@ -2755,6 +2763,8 @@ static int wsa_macro_probe(struct platform_device *pdev)
return -EINVAL;
}
+ regcache_sort_defaults(reg_defaults, def_count);
+
struct regmap_config *reg_config __free(kfree) = kmemdup(&wsa_regmap_config,
sizeof(*reg_config),
GFP_KERNEL);