ASoC: rt5677: Use specific r/w function for DSP mode
In DSP mode, the register r/w should use the specific function to access that is invoked by address mapping of the DSP. The MX-65[1] is for switching DSP or codec mode. Signed-off-by: Oder Chiou <oder_chiou@realtek.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
d65fd3a42e
commit
19ba484d7b
|
@ -541,49 +541,51 @@ static bool rt5677_readable_register(struct device *dev, unsigned int reg)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rt5677_dsp_mode_i2c_write_addr - Write value to address on DSP mode.
|
* rt5677_dsp_mode_i2c_write_addr - Write value to address on DSP mode.
|
||||||
* @codec: SoC audio codec device.
|
* @rt5677: Private Data.
|
||||||
* @addr: Address index.
|
* @addr: Address index.
|
||||||
* @value: Address data.
|
* @value: Address data.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Returns 0 for success or negative error code.
|
* Returns 0 for success or negative error code.
|
||||||
*/
|
*/
|
||||||
static int rt5677_dsp_mode_i2c_write_addr(struct snd_soc_codec *codec,
|
static int rt5677_dsp_mode_i2c_write_addr(struct rt5677_priv *rt5677,
|
||||||
unsigned int addr, unsigned int value, unsigned int opcode)
|
unsigned int addr, unsigned int value, unsigned int opcode)
|
||||||
{
|
{
|
||||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
struct snd_soc_codec *codec = rt5677->codec;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&rt5677->dsp_cmd_lock);
|
mutex_lock(&rt5677->dsp_cmd_lock);
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_ADDR_MSB, addr >> 16);
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_MSB,
|
||||||
|
addr >> 16);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_ADDR_LSB,
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_LSB,
|
||||||
addr & 0xffff);
|
addr & 0xffff);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_DATA_MSB,
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_MSB,
|
||||||
value >> 16);
|
value >> 16);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set data msb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set data msb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_DATA_LSB,
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_LSB,
|
||||||
value & 0xffff);
|
value & 0xffff);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set data lsb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set data lsb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_OP_CODE, opcode);
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_OP_CODE,
|
||||||
|
opcode);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set op code value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set op code value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -597,42 +599,45 @@ err:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rt5677_dsp_mode_i2c_read_addr - Read value from address on DSP mode.
|
* rt5677_dsp_mode_i2c_read_addr - Read value from address on DSP mode.
|
||||||
* @codec: SoC audio codec device.
|
* rt5677: Private Data.
|
||||||
* @addr: Address index.
|
* @addr: Address index.
|
||||||
* @value: Address data.
|
* @value: Address data.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* Returns 0 for success or negative error code.
|
* Returns 0 for success or negative error code.
|
||||||
*/
|
*/
|
||||||
static int rt5677_dsp_mode_i2c_read_addr(
|
static int rt5677_dsp_mode_i2c_read_addr(
|
||||||
struct snd_soc_codec *codec, unsigned int addr, unsigned int *value)
|
struct rt5677_priv *rt5677, unsigned int addr, unsigned int *value)
|
||||||
{
|
{
|
||||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
struct snd_soc_codec *codec = rt5677->codec;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int msb, lsb;
|
unsigned int msb, lsb;
|
||||||
|
|
||||||
mutex_lock(&rt5677->dsp_cmd_lock);
|
mutex_lock(&rt5677->dsp_cmd_lock);
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_ADDR_MSB, addr >> 16);
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_MSB,
|
||||||
|
addr >> 16);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set addr msb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_ADDR_LSB,
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_ADDR_LSB,
|
||||||
addr & 0xffff);
|
addr & 0xffff);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set addr lsb value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(rt5677->regmap, RT5677_DSP_I2C_OP_CODE , 0x0002);
|
ret = regmap_write(rt5677->regmap_physical, RT5677_DSP_I2C_OP_CODE,
|
||||||
|
0x0002);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set op code value: %d\n", ret);
|
dev_err(codec->dev, "Failed to set op code value: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
regmap_read(rt5677->regmap, RT5677_DSP_I2C_DATA_MSB, &msb);
|
regmap_read(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_MSB, &msb);
|
||||||
regmap_read(rt5677->regmap, RT5677_DSP_I2C_DATA_LSB, &lsb);
|
regmap_read(rt5677->regmap_physical, RT5677_DSP_I2C_DATA_LSB, &lsb);
|
||||||
*value = (msb << 16) | lsb;
|
*value = (msb << 16) | lsb;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -643,17 +648,17 @@ err:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rt5677_dsp_mode_i2c_write - Write register on DSP mode.
|
* rt5677_dsp_mode_i2c_write - Write register on DSP mode.
|
||||||
* @codec: SoC audio codec device.
|
* rt5677: Private Data.
|
||||||
* @reg: Register index.
|
* @reg: Register index.
|
||||||
* @value: Register data.
|
* @value: Register data.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Returns 0 for success or negative error code.
|
* Returns 0 for success or negative error code.
|
||||||
*/
|
*/
|
||||||
static int rt5677_dsp_mode_i2c_write(struct snd_soc_codec *codec,
|
static int rt5677_dsp_mode_i2c_write(struct rt5677_priv *rt5677,
|
||||||
unsigned int reg, unsigned int value)
|
unsigned int reg, unsigned int value)
|
||||||
{
|
{
|
||||||
return rt5677_dsp_mode_i2c_write_addr(codec, 0x18020000 + reg * 2,
|
return rt5677_dsp_mode_i2c_write_addr(rt5677, 0x18020000 + reg * 2,
|
||||||
value, 0x0001);
|
value, 0x0001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,57 +666,33 @@ static int rt5677_dsp_mode_i2c_write(struct snd_soc_codec *codec,
|
||||||
* rt5677_dsp_mode_i2c_read - Read register on DSP mode.
|
* rt5677_dsp_mode_i2c_read - Read register on DSP mode.
|
||||||
* @codec: SoC audio codec device.
|
* @codec: SoC audio codec device.
|
||||||
* @reg: Register index.
|
* @reg: Register index.
|
||||||
|
* @value: Register data.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Returns Register value.
|
* Returns 0 for success or negative error code.
|
||||||
*/
|
*/
|
||||||
static unsigned int rt5677_dsp_mode_i2c_read(
|
static int rt5677_dsp_mode_i2c_read(
|
||||||
struct snd_soc_codec *codec, unsigned int reg)
|
struct rt5677_priv *rt5677, unsigned int reg, unsigned int *value)
|
||||||
{
|
{
|
||||||
unsigned int value = 0;
|
int ret = rt5677_dsp_mode_i2c_read_addr(rt5677, 0x18020000 + reg * 2,
|
||||||
|
value);
|
||||||
|
|
||||||
rt5677_dsp_mode_i2c_read_addr(codec, 0x18020000 + reg * 2, &value);
|
*value &= 0xffff;
|
||||||
|
|
||||||
return value;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void rt5677_set_dsp_mode(struct snd_soc_codec *codec, bool on)
|
||||||
* rt5677_dsp_mode_i2c_update_bits - update register on DSP mode.
|
|
||||||
* @codec: audio codec
|
|
||||||
* @reg: register index.
|
|
||||||
* @mask: register mask
|
|
||||||
* @value: new value
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Returns 1 for change, 0 for no change, or negative error code.
|
|
||||||
*/
|
|
||||||
static int rt5677_dsp_mode_i2c_update_bits(struct snd_soc_codec *codec,
|
|
||||||
unsigned int reg, unsigned int mask, unsigned int value)
|
|
||||||
{
|
{
|
||||||
unsigned int old, new;
|
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||||
int change, ret;
|
|
||||||
|
|
||||||
ret = rt5677_dsp_mode_i2c_read(codec, reg);
|
if (on) {
|
||||||
if (ret < 0) {
|
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x2);
|
||||||
dev_err(codec->dev, "Failed to read reg: %d\n", ret);
|
rt5677->is_dsp_mode = true;
|
||||||
goto err;
|
} else {
|
||||||
|
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x0);
|
||||||
|
rt5677->is_dsp_mode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
old = ret;
|
|
||||||
new = (old & ~mask) | (value & mask);
|
|
||||||
change = old != new;
|
|
||||||
if (change) {
|
|
||||||
ret = rt5677_dsp_mode_i2c_write(codec, reg, new);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(codec->dev,
|
|
||||||
"Failed to write reg: %d\n", ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return change;
|
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
|
static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
|
||||||
|
@ -733,9 +714,14 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
|
||||||
RT5677_LDO1_SEL_MASK, 0x0);
|
RT5677_LDO1_SEL_MASK, 0x0);
|
||||||
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
|
regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2,
|
||||||
RT5677_PWR_LDO1, RT5677_PWR_LDO1);
|
RT5677_PWR_LDO1, RT5677_PWR_LDO1);
|
||||||
regmap_write(rt5677->regmap, RT5677_GLB_CLK2, 0x0080);
|
regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK1,
|
||||||
|
RT5677_MCLK_SRC_MASK, RT5677_MCLK2_SRC);
|
||||||
|
regmap_update_bits(rt5677->regmap, RT5677_GLB_CLK2,
|
||||||
|
RT5677_PLL2_PR_SRC_MASK | RT5677_DSP_CLK_SRC_MASK,
|
||||||
|
RT5677_PLL2_PR_SRC_MCLK2 | RT5677_DSP_CLK_SRC_BYPASS);
|
||||||
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff);
|
regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x07ff);
|
||||||
regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07ff);
|
regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x07fd);
|
||||||
|
rt5677_set_dsp_mode(codec, true);
|
||||||
|
|
||||||
ret = request_firmware(&rt5677->fw1, RT5677_FIRMWARE1,
|
ret = request_firmware(&rt5677->fw1, RT5677_FIRMWARE1,
|
||||||
codec->dev);
|
codec->dev);
|
||||||
|
@ -751,8 +737,7 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
|
||||||
release_firmware(rt5677->fw2);
|
release_firmware(rt5677->fw2);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt5677_dsp_mode_i2c_update_bits(codec, RT5677_PWR_DSP1, 0x1,
|
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x1, 0x0);
|
||||||
0x0);
|
|
||||||
|
|
||||||
regcache_cache_bypass(rt5677->regmap, false);
|
regcache_cache_bypass(rt5677->regmap, false);
|
||||||
regcache_cache_only(rt5677->regmap, true);
|
regcache_cache_only(rt5677->regmap, true);
|
||||||
|
@ -762,9 +747,9 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
|
||||||
regcache_cache_only(rt5677->regmap, false);
|
regcache_cache_only(rt5677->regmap, false);
|
||||||
regcache_cache_bypass(rt5677->regmap, true);
|
regcache_cache_bypass(rt5677->regmap, true);
|
||||||
|
|
||||||
rt5677_dsp_mode_i2c_update_bits(codec, RT5677_PWR_DSP1, 0x1,
|
regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x1, 0x1);
|
||||||
0x1);
|
rt5677_set_dsp_mode(codec, false);
|
||||||
rt5677_dsp_mode_i2c_write(codec, RT5677_PWR_DSP1, 0x0001);
|
regmap_write(rt5677->regmap, RT5677_PWR_DSP1, 0x0001);
|
||||||
|
|
||||||
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
|
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
|
||||||
|
|
||||||
|
@ -4019,6 +4004,32 @@ static int rt5677_resume(struct snd_soc_codec *codec)
|
||||||
#define rt5677_resume NULL
|
#define rt5677_resume NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int rt5677_read(void *context, unsigned int reg, unsigned int *val)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = context;
|
||||||
|
struct rt5677_priv *rt5677 = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
if (rt5677->is_dsp_mode)
|
||||||
|
rt5677_dsp_mode_i2c_read(rt5677, reg, val);
|
||||||
|
else
|
||||||
|
regmap_read(rt5677->regmap_physical, reg, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rt5677_write(void *context, unsigned int reg, unsigned int val)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = context;
|
||||||
|
struct rt5677_priv *rt5677 = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
if (rt5677->is_dsp_mode)
|
||||||
|
rt5677_dsp_mode_i2c_write(rt5677, reg, val);
|
||||||
|
else
|
||||||
|
regmap_write(rt5677->regmap_physical, reg, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define RT5677_STEREO_RATES SNDRV_PCM_RATE_8000_96000
|
#define RT5677_STEREO_RATES SNDRV_PCM_RATE_8000_96000
|
||||||
#define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
#define RT5677_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
|
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
|
||||||
|
@ -4144,6 +4155,17 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5677 = {
|
||||||
.num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes),
|
.num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config rt5677_regmap_physical = {
|
||||||
|
.name = "physical",
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 16,
|
||||||
|
|
||||||
|
.max_register = RT5677_VENDOR_ID2 + 1,
|
||||||
|
.readable_reg = rt5677_readable_register,
|
||||||
|
|
||||||
|
.cache_type = REGCACHE_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config rt5677_regmap = {
|
static const struct regmap_config rt5677_regmap = {
|
||||||
.reg_bits = 8,
|
.reg_bits = 8,
|
||||||
.val_bits = 16,
|
.val_bits = 16,
|
||||||
|
@ -4153,6 +4175,8 @@ static const struct regmap_config rt5677_regmap = {
|
||||||
|
|
||||||
.volatile_reg = rt5677_volatile_register,
|
.volatile_reg = rt5677_volatile_register,
|
||||||
.readable_reg = rt5677_readable_register,
|
.readable_reg = rt5677_readable_register,
|
||||||
|
.reg_read = rt5677_read,
|
||||||
|
.reg_write = rt5677_write,
|
||||||
|
|
||||||
.cache_type = REGCACHE_RBTREE,
|
.cache_type = REGCACHE_RBTREE,
|
||||||
.reg_defaults = rt5677_reg,
|
.reg_defaults = rt5677_reg,
|
||||||
|
@ -4309,7 +4333,16 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
||||||
msleep(10);
|
msleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap);
|
rt5677->regmap_physical = devm_regmap_init_i2c(i2c,
|
||||||
|
&rt5677_regmap_physical);
|
||||||
|
if (IS_ERR(rt5677->regmap_physical)) {
|
||||||
|
ret = PTR_ERR(rt5677->regmap_physical);
|
||||||
|
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt5677->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5677_regmap);
|
||||||
if (IS_ERR(rt5677->regmap)) {
|
if (IS_ERR(rt5677->regmap)) {
|
||||||
ret = PTR_ERR(rt5677->regmap);
|
ret = PTR_ERR(rt5677->regmap);
|
||||||
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
|
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
|
||||||
|
|
|
@ -1628,7 +1628,7 @@ enum {
|
||||||
struct rt5677_priv {
|
struct rt5677_priv {
|
||||||
struct snd_soc_codec *codec;
|
struct snd_soc_codec *codec;
|
||||||
struct rt5677_platform_data pdata;
|
struct rt5677_platform_data pdata;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap, *regmap_physical;
|
||||||
const struct firmware *fw1, *fw2;
|
const struct firmware *fw1, *fw2;
|
||||||
struct mutex dsp_cmd_lock;
|
struct mutex dsp_cmd_lock;
|
||||||
|
|
||||||
|
@ -1646,6 +1646,7 @@ struct rt5677_priv {
|
||||||
#endif
|
#endif
|
||||||
bool dsp_vad_en;
|
bool dsp_vad_en;
|
||||||
struct regmap_irq_chip_data *irq_data;
|
struct regmap_irq_chip_data *irq_data;
|
||||||
|
bool is_dsp_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __RT5677_H__ */
|
#endif /* __RT5677_H__ */
|
||||||
|
|
Loading…
Reference in New Issue