Commit f9dfbf91 authored by Axel Lin's avatar Axel Lin Committed by Mark Brown

ASoC: tlv320aic23: convert to soc-cache

Signed-off-by: default avatarAxel Lin <axel.lin@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent a6f096f3
...@@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = { ...@@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = {
0x0000, 0x0000, 0x0000, 0x0000, /* 12 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
}; };
/*
* read tlv320aic23 register cache
*/
static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
*codec, unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg >= ARRAY_SIZE(tlv320aic23_reg))
return -1;
return cache[reg];
}
/*
* write tlv320aic23 register cache
*/
static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
u8 reg, u16 value)
{
u16 *cache = codec->reg_cache;
if (reg >= ARRAY_SIZE(tlv320aic23_reg))
return;
cache[reg] = value;
}
/*
* write to the tlv320aic23 register space
*/
static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* TLV320AIC23 has 7 bit address and 9 bits of data
* so we need to switch one data bit into reg and rest
* of data into val
*/
if (reg > 9 && reg != 15) {
printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
return -1;
}
data[0] = (reg << 1) | (value >> 8 & 0x01);
data[1] = value & 0xff;
tlv320aic23_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
value, reg);
return -EIO;
}
static const char *rec_src_text[] = { "Line", "Mic" }; static const char *rec_src_text[] = { "Line", "Mic" };
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
...@@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
*/ */
val = (val >= 4) ? 4 : (3 - val); val = (val >= 4) ? 4 : (3 - val);
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0); reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0);
tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
return 0; return 0;
} }
...@@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u16 val; u16 val;
val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0); val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
val = val >> 6; val = val >> 6;
val = (val >= 4) ? 4 : (3 - val); val = (val >= 4) ? 4 : (3 - val);
ucontrol->value.integer.value[0] = val; ucontrol->value.integer.value[0] = val;
...@@ -232,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { ...@@ -232,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
/* AIC23 driver data */ /* AIC23 driver data */
struct aic23 { struct aic23 {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
void *control_data;
int mclk; int mclk;
int requested_adc; int requested_adc;
int requested_dac; int requested_dac;
...@@ -344,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac) ...@@ -344,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac)
static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk, static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
u32 *sample_rate_adc, u32 *sample_rate_dac) u32 *sample_rate_adc, u32 *sample_rate_dac)
{ {
int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE); int src = snd_soc_read(codec, TLV320AIC23_SRATE);
int sr = (src >> 2) & 0x0f; int sr = (src >> 2) & 0x0f;
int val = (mclk / bosr_usb_divisor_table[src & 3]); int val = (mclk / bosr_usb_divisor_table[src & 3]);
int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
...@@ -368,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, ...@@ -368,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
__func__, sample_rate_adc, sample_rate_dac); __func__, sample_rate_adc, sample_rate_dac);
return -EINVAL; return -EINVAL;
} }
tlv320aic23_write(codec, TLV320AIC23_SRATE, data); snd_soc_write(codec, TLV320AIC23_SRATE, data);
#ifdef DEBUG #ifdef DEBUG
{ {
u32 adc, dac; u32 adc, dac;
...@@ -407,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, ...@@ -407,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
if (ret < 0) if (ret < 0)
return ret; return ret;
iface_reg = iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
tlv320aic23_read_reg_cache(codec,
TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
break; break;
...@@ -423,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, ...@@ -423,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
iface_reg |= (0x03 << 2); iface_reg |= (0x03 << 2);
break; break;
} }
tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
return 0; return 0;
} }
...@@ -435,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, ...@@ -435,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
/* set active */ /* set active */
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
return 0; return 0;
} }
...@@ -450,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, ...@@ -450,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
/* deactivate */ /* deactivate */
if (!codec->active) { if (!codec->active) {
udelay(50); udelay(50);
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
} }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
aic23->requested_dac = 0; aic23->requested_dac = 0;
...@@ -463,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) ...@@ -463,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 reg; u16 reg;
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT); reg = snd_soc_read(codec, TLV320AIC23_DIGT);
if (mute) if (mute)
reg |= TLV320AIC23_DACM_MUTE; reg |= TLV320AIC23_DACM_MUTE;
else else
reg &= ~TLV320AIC23_DACM_MUTE; reg &= ~TLV320AIC23_DACM_MUTE;
tlv320aic23_write(codec, TLV320AIC23_DIGT, reg); snd_soc_write(codec, TLV320AIC23_DIGT, reg);
return 0; return 0;
} }
...@@ -481,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -481,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 iface_reg; u16 iface_reg;
iface_reg = iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
...@@ -516,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -516,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
} }
tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
return 0; return 0;
} }
...@@ -532,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -532,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f; u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* vref/mid, osc on, dac unmute */ /* vref/mid, osc on, dac unmute */
reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \ reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
TLV320AIC23_DAC_OFF); TLV320AIC23_DAC_OFF);
tlv320aic23_write(codec, TLV320AIC23_PWR, reg); snd_soc_write(codec, TLV320AIC23_PWR, reg);
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* everything off except vref/vmid, */ /* everything off except vref/vmid, */
tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \ snd_soc_write(codec, TLV320AIC23_PWR,
TLV320AIC23_CLK_OFF); reg | TLV320AIC23_CLK_OFF);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
/* everything off, dac mute, inactive */ /* everything off, dac mute, inactive */
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff); snd_soc_write(codec, TLV320AIC23_PWR, 0xffff);
break; break;
} }
codec->dapm.bias_level = level; codec->dapm.bias_level = level;
...@@ -598,13 +538,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec, ...@@ -598,13 +538,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec,
static int tlv320aic23_resume(struct snd_soc_codec *codec) static int tlv320aic23_resume(struct snd_soc_codec *codec)
{ {
u16 reg; snd_soc_cache_sync(codec);
/* Sync reg_cache with the hardware */
for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) {
u16 val = tlv320aic23_read_reg_cache(codec, reg);
tlv320aic23_write(codec, reg, val);
}
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
...@@ -613,46 +547,52 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) ...@@ -613,46 +547,52 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
static int tlv320aic23_probe(struct snd_soc_codec *codec) static int tlv320aic23_probe(struct snd_soc_codec *codec)
{ {
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
int reg; int ret;
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
codec->control_data = aic23->control_data;
codec->hw_write = (hw_write_t)i2c_master_send; ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
codec->hw_read = NULL; if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
/* Reset codec */ /* Reset codec */
tlv320aic23_write(codec, TLV320AIC23_RESET, 0); snd_soc_write(codec, TLV320AIC23_RESET, 0);
/* Write the register default value to cache for reserved registers,
* so the write to the these registers are suppressed by the cache
* restore code when it skips writes of default registers.
*/
snd_soc_cache_write(codec, 0x0A, 0);
snd_soc_cache_write(codec, 0x0B, 0);
snd_soc_cache_write(codec, 0x0C, 0);
snd_soc_cache_write(codec, 0x0D, 0);
snd_soc_cache_write(codec, 0x0E, 0);
/* power on device */ /* power on device */
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
/* Unmute input */ /* Unmute input */
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL); snd_soc_update_bits(codec, TLV320AIC23_LINVOL,
tlv320aic23_write(codec, TLV320AIC23_LINVOL, TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
(reg & (~TLV320AIC23_LIM_MUTED)) |
(TLV320AIC23_LRS_ENABLED));
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL); snd_soc_update_bits(codec, TLV320AIC23_RINVOL,
tlv320aic23_write(codec, TLV320AIC23_RINVOL, TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
(reg & (~TLV320AIC23_LIM_MUTED)) |
TLV320AIC23_LRS_ENABLED);
reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG); snd_soc_update_bits(codec, TLV320AIC23_ANLG,
tlv320aic23_write(codec, TLV320AIC23_ANLG, TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
(reg) & (~TLV320AIC23_BYPASS_ON) & 0);
(~TLV320AIC23_MICM_MUTED));
/* Default output volume */ /* Default output volume */
tlv320aic23_write(codec, TLV320AIC23_LCHNVOL, snd_soc_write(codec, TLV320AIC23_LCHNVOL,
TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
TLV320AIC23_OUT_VOL_MASK); snd_soc_write(codec, TLV320AIC23_RCHNVOL,
tlv320aic23_write(codec, TLV320AIC23_RCHNVOL, TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
TLV320AIC23_DEFAULT_OUT_VOL &
TLV320AIC23_OUT_VOL_MASK);
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
snd_soc_add_controls(codec, tlv320aic23_snd_controls, snd_soc_add_controls(codec, tlv320aic23_snd_controls,
ARRAY_SIZE(tlv320aic23_snd_controls)); ARRAY_SIZE(tlv320aic23_snd_controls));
...@@ -674,8 +614,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { ...@@ -674,8 +614,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.remove = tlv320aic23_remove, .remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend, .suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume, .resume = tlv320aic23_resume,
.read = tlv320aic23_read_reg_cache,
.write = tlv320aic23_write,
.set_bias_level = tlv320aic23_set_bias_level, .set_bias_level = tlv320aic23_set_bias_level,
.dapm_widgets = tlv320aic23_dapm_widgets, .dapm_widgets = tlv320aic23_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
...@@ -702,7 +640,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, ...@@ -702,7 +640,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(i2c, aic23); i2c_set_clientdata(i2c, aic23);
aic23->control_data = i2c;
aic23->control_type = SND_SOC_I2C; aic23->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,
......
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