Commit a3a1ec66 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Mark Brown

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: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent a35daac7
...@@ -22,9 +22,14 @@ ...@@ -22,9 +22,14 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <asm/unaligned.h>
#include "sigmadsp.h" #include "sigmadsp.h"
#include "adau1701.h" #include "adau1701.h"
#define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i))
#define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i))
#define ADAU1701_DSPCTRL 0x081c #define ADAU1701_DSPCTRL 0x081c
#define ADAU1701_SEROCTL 0x081e #define ADAU1701_SEROCTL 0x081e
#define ADAU1701_SERICTL 0x081f #define ADAU1701_SERICTL 0x081f
...@@ -42,6 +47,7 @@ ...@@ -42,6 +47,7 @@
#define ADAU1701_DSPCTRL_CR (1 << 2) #define ADAU1701_DSPCTRL_CR (1 << 2)
#define ADAU1701_DSPCTRL_DAM (1 << 3) #define ADAU1701_DSPCTRL_DAM (1 << 3)
#define ADAU1701_DSPCTRL_ADM (1 << 4) #define ADAU1701_DSPCTRL_ADM (1 << 4)
#define ADAU1701_DSPCTRL_IST (1 << 5)
#define ADAU1701_DSPCTRL_SR_48 0x00 #define ADAU1701_DSPCTRL_SR_48 0x00
#define ADAU1701_DSPCTRL_SR_96 0x01 #define ADAU1701_DSPCTRL_SR_96 0x01
#define ADAU1701_DSPCTRL_SR_192 0x02 #define ADAU1701_DSPCTRL_SR_192 0x02
...@@ -102,6 +108,7 @@ struct adau1701 { ...@@ -102,6 +108,7 @@ struct adau1701 {
unsigned int pll_clkdiv; unsigned int pll_clkdiv;
unsigned int sysclk; unsigned int sysclk;
struct regmap *regmap; struct regmap *regmap;
struct i2c_client *client;
u8 pin_config[12]; u8 pin_config[12];
struct sigmadsp *sigmadsp; struct sigmadsp *sigmadsp;
...@@ -161,6 +168,7 @@ static bool adau1701_volatile_reg(struct device *dev, unsigned int reg) ...@@ -161,6 +168,7 @@ static bool adau1701_volatile_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case ADAU1701_DACSET: case ADAU1701_DACSET:
case ADAU1701_DSPCTRL:
return true; return true;
default: default:
return false; return false;
...@@ -240,6 +248,50 @@ static int adau1701_reg_read(void *context, unsigned int reg, ...@@ -240,6 +248,50 @@ static int adau1701_reg_read(void *context, unsigned int reg,
return 0; return 0;
} }
static int adau1701_safeload(struct sigmadsp *sigmadsp, unsigned int addr,
const uint8_t bytes[], size_t len)
{
struct i2c_client *client = to_i2c_client(sigmadsp->dev);
struct adau1701 *adau1701 = i2c_get_clientdata(client);
unsigned int val;
unsigned int i;
uint8_t buf[10];
int ret;
ret = regmap_read(adau1701->regmap, ADAU1701_DSPCTRL, &val);
if (ret)
return ret;
if (val & ADAU1701_DSPCTRL_IST)
msleep(50);
for (i = 0; i < len / 4; i++) {
put_unaligned_le16(ADAU1701_SAFELOAD_DATA(i), buf);
buf[2] = 0x00;
memcpy(buf + 3, bytes + i * 4, 4);
ret = i2c_master_send(client, buf, 7);
if (ret < 0)
return ret;
else if (ret != 7)
return -EIO;
put_unaligned_le16(ADAU1701_SAFELOAD_ADDR(i), buf);
put_unaligned_le16(addr + i, buf + 2);
ret = i2c_master_send(client, buf, 4);
if (ret < 0)
return ret;
else if (ret != 4)
return -EIO;
}
return regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL,
ADAU1701_DSPCTRL_IST, ADAU1701_DSPCTRL_IST);
}
static const struct sigmadsp_ops adau1701_sigmadsp_ops = {
.safeload = adau1701_safeload,
};
static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv, static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv,
unsigned int rate) unsigned int rate)
{ {
...@@ -684,6 +736,7 @@ static int adau1701_i2c_probe(struct i2c_client *client, ...@@ -684,6 +736,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
if (!adau1701) if (!adau1701)
return -ENOMEM; return -ENOMEM;
adau1701->client = client;
adau1701->regmap = devm_regmap_init(dev, NULL, client, adau1701->regmap = devm_regmap_init(dev, NULL, client,
&adau1701_regmap); &adau1701_regmap);
if (IS_ERR(adau1701->regmap)) if (IS_ERR(adau1701->regmap))
...@@ -740,8 +793,8 @@ static int adau1701_i2c_probe(struct i2c_client *client, ...@@ -740,8 +793,8 @@ static int adau1701_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, adau1701); i2c_set_clientdata(client, adau1701);
adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, NULL, adau1701->sigmadsp = devm_sigmadsp_init_i2c(client,
ADAU1701_FIRMWARE); &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE);
if (IS_ERR(adau1701->sigmadsp)) if (IS_ERR(adau1701->sigmadsp))
return PTR_ERR(adau1701->sigmadsp); return PTR_ERR(adau1701->sigmadsp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment