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>
This commit is contained in:
Родитель
a35daac77a
Коммит
a3a1ec66d6
|
@ -22,9 +22,14 @@
|
|||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "sigmadsp.h"
|
||||
#include "adau1701.h"
|
||||
|
||||
#define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i))
|
||||
#define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i))
|
||||
|
||||
#define ADAU1701_DSPCTRL 0x081c
|
||||
#define ADAU1701_SEROCTL 0x081e
|
||||
#define ADAU1701_SERICTL 0x081f
|
||||
|
@ -42,6 +47,7 @@
|
|||
#define ADAU1701_DSPCTRL_CR (1 << 2)
|
||||
#define ADAU1701_DSPCTRL_DAM (1 << 3)
|
||||
#define ADAU1701_DSPCTRL_ADM (1 << 4)
|
||||
#define ADAU1701_DSPCTRL_IST (1 << 5)
|
||||
#define ADAU1701_DSPCTRL_SR_48 0x00
|
||||
#define ADAU1701_DSPCTRL_SR_96 0x01
|
||||
#define ADAU1701_DSPCTRL_SR_192 0x02
|
||||
|
@ -102,6 +108,7 @@ struct adau1701 {
|
|||
unsigned int pll_clkdiv;
|
||||
unsigned int sysclk;
|
||||
struct regmap *regmap;
|
||||
struct i2c_client *client;
|
||||
u8 pin_config[12];
|
||||
|
||||
struct sigmadsp *sigmadsp;
|
||||
|
@ -161,6 +168,7 @@ static bool adau1701_volatile_reg(struct device *dev, unsigned int reg)
|
|||
{
|
||||
switch (reg) {
|
||||
case ADAU1701_DACSET:
|
||||
case ADAU1701_DSPCTRL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -240,6 +248,50 @@ static int adau1701_reg_read(void *context, unsigned int reg,
|
|||
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,
|
||||
unsigned int rate)
|
||||
{
|
||||
|
@ -684,6 +736,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
|||
if (!adau1701)
|
||||
return -ENOMEM;
|
||||
|
||||
adau1701->client = client;
|
||||
adau1701->regmap = devm_regmap_init(dev, NULL, client,
|
||||
&adau1701_regmap);
|
||||
if (IS_ERR(adau1701->regmap))
|
||||
|
@ -740,8 +793,8 @@ static int adau1701_i2c_probe(struct i2c_client *client,
|
|||
|
||||
i2c_set_clientdata(client, adau1701);
|
||||
|
||||
adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, NULL,
|
||||
ADAU1701_FIRMWARE);
|
||||
adau1701->sigmadsp = devm_sigmadsp_init_i2c(client,
|
||||
&adau1701_sigmadsp_ops, ADAU1701_FIRMWARE);
|
||||
if (IS_ERR(adau1701->sigmadsp))
|
||||
return PTR_ERR(adau1701->sigmadsp);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче