diff options
| author | Mark Brown <broonie@kernel.org> | 2026-09-08 19:54:52 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-08 19:54:52 +0100 |
| commit | 8fa5ce4e95bda6d3a90761d07d171f9e3f2f9328 (patch) | |
| tree | 0236ef3ca7399fbb0ad403590e6a6346d9d2f117 | |
| parent | 5bb30783e4e5782349b5bfafbaf982bf86285302 (diff) | |
| parent | 322a9e0850b41a628b59c29be89f499acba9f1c8 (diff) | |
| download | linux-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.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/lpass-tx-macro.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/lpass-va-macro.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/lpass-wsa-macro.c | 46 |
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); |
