Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: adau1701: Implement sigmadsp safeload

The safeload feature allows to load up to 5 parameter memory registers
atomically. This is helpful for switching between e.g. filter settings
without causing any glitches.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Lars-Peter Clausen and committed by
Mark Brown
a3a1ec66 a35daac7

+55 -2
+55 -2
sound/soc/codecs/adau1701.c
··· 22 22 #include <sound/pcm_params.h> 23 23 #include <sound/soc.h> 24 24 25 + #include <asm/unaligned.h> 26 + 25 27 #include "sigmadsp.h" 26 28 #include "adau1701.h" 29 + 30 + #define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i)) 31 + #define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i)) 27 32 28 33 #define ADAU1701_DSPCTRL 0x081c 29 34 #define ADAU1701_SEROCTL 0x081e ··· 47 42 #define ADAU1701_DSPCTRL_CR (1 << 2) 48 43 #define ADAU1701_DSPCTRL_DAM (1 << 3) 49 44 #define ADAU1701_DSPCTRL_ADM (1 << 4) 45 + #define ADAU1701_DSPCTRL_IST (1 << 5) 50 46 #define ADAU1701_DSPCTRL_SR_48 0x00 51 47 #define ADAU1701_DSPCTRL_SR_96 0x01 52 48 #define ADAU1701_DSPCTRL_SR_192 0x02 ··· 108 102 unsigned int pll_clkdiv; 109 103 unsigned int sysclk; 110 104 struct regmap *regmap; 105 + struct i2c_client *client; 111 106 u8 pin_config[12]; 112 107 113 108 struct sigmadsp *sigmadsp; ··· 168 161 { 169 162 switch (reg) { 170 163 case ADAU1701_DACSET: 164 + case ADAU1701_DSPCTRL: 171 165 return true; 172 166 default: 173 167 return false; ··· 247 239 248 240 return 0; 249 241 } 242 + 243 + static int adau1701_safeload(struct sigmadsp *sigmadsp, unsigned int addr, 244 + const uint8_t bytes[], size_t len) 245 + { 246 + struct i2c_client *client = to_i2c_client(sigmadsp->dev); 247 + struct adau1701 *adau1701 = i2c_get_clientdata(client); 248 + unsigned int val; 249 + unsigned int i; 250 + uint8_t buf[10]; 251 + int ret; 252 + 253 + ret = regmap_read(adau1701->regmap, ADAU1701_DSPCTRL, &val); 254 + if (ret) 255 + return ret; 256 + 257 + if (val & ADAU1701_DSPCTRL_IST) 258 + msleep(50); 259 + 260 + for (i = 0; i < len / 4; i++) { 261 + put_unaligned_le16(ADAU1701_SAFELOAD_DATA(i), buf); 262 + buf[2] = 0x00; 263 + memcpy(buf + 3, bytes + i * 4, 4); 264 + ret = i2c_master_send(client, buf, 7); 265 + if (ret < 0) 266 + return ret; 267 + else if (ret != 7) 268 + return -EIO; 269 + 270 + put_unaligned_le16(ADAU1701_SAFELOAD_ADDR(i), buf); 271 + put_unaligned_le16(addr + i, buf + 2); 272 + ret = i2c_master_send(client, buf, 4); 273 + if (ret < 0) 274 + return ret; 275 + else if (ret != 4) 276 + return -EIO; 277 + } 278 + 279 + return regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, 280 + ADAU1701_DSPCTRL_IST, ADAU1701_DSPCTRL_IST); 281 + } 282 + 283 + static const struct sigmadsp_ops adau1701_sigmadsp_ops = { 284 + .safeload = adau1701_safeload, 285 + }; 250 286 251 287 static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv, 252 288 unsigned int rate) ··· 736 684 if (!adau1701) 737 685 return -ENOMEM; 738 686 687 + adau1701->client = client; 739 688 adau1701->regmap = devm_regmap_init(dev, NULL, client, 740 689 &adau1701_regmap); 741 690 if (IS_ERR(adau1701->regmap)) ··· 793 740 794 741 i2c_set_clientdata(client, adau1701); 795 742 796 - adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, NULL, 797 - ADAU1701_FIRMWARE); 743 + adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, 744 + &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); 798 745 if (IS_ERR(adau1701->sigmadsp)) 799 746 return PTR_ERR(adau1701->sigmadsp); 800 747