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

ASoC: codecs: wm8753: Fix register cache incoherency

The multi-component patch(commit f0fba2ad) moved the allocation of the
register cache from the driver to the ASoC core. Most drivers where adjusted to
this, but the wm8753 driver still uses its own register cache for its
private functions, while functions from the ASoC core use the generic cache.
Furthermore the generic cache uses zero-based numbering while the wm8753 cache
uses one-based numbering.
Thus we end up with two from each other incoherent caches, which leads to undefined
behaviour and crashes.
This patch fixes the issue by changing the wm8753 driver to use the generic
register cache in its private functions.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent da280f51
...@@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, ...@@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
* are using 2 wire for device control, so we cache them instead. * are using 2 wire for device control, so we cache them instead.
*/ */
static const u16 wm8753_reg[] = { static const u16 wm8753_reg[] = {
0x0008, 0x0000, 0x000a, 0x000a, 0x0000, 0x0008, 0x0000, 0x000a,
0x0033, 0x0000, 0x0007, 0x00ff, 0x000a, 0x0033, 0x0000, 0x0007,
0x00ff, 0x000f, 0x000f, 0x007b, 0x00ff, 0x00ff, 0x000f, 0x000f,
0x0000, 0x0032, 0x0000, 0x00c3, 0x007b, 0x0000, 0x0032, 0x0000,
0x00c3, 0x00c0, 0x0000, 0x0000, 0x00c3, 0x00c3, 0x00c0, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0055,
0x0005, 0x0050, 0x0055, 0x0050,
0x0055, 0x0050, 0x0055, 0x0079,
0x0079, 0x0079, 0x0079, 0x0079,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0097, 0x0097, 0x0000, 0x0004, 0x0055, 0x0005, 0x0050, 0x0055,
0x0000, 0x0083, 0x0024, 0x01ba, 0x0050, 0x0055, 0x0050, 0x0055,
0x0000, 0x0083, 0x0024, 0x01ba, 0x0079, 0x0079, 0x0079, 0x0079,
0x0000, 0x0000, 0x0000 0x0079, 0x0000, 0x0000, 0x0000,
0x0000, 0x0097, 0x0097, 0x0000,
0x0004, 0x0000, 0x0083, 0x0024,
0x01ba, 0x0000, 0x0083, 0x0024,
0x01ba, 0x0000, 0x0000, 0x0000
}; };
/* codec private data */ /* codec private data */
...@@ -88,57 +88,10 @@ struct wm8753_priv { ...@@ -88,57 +88,10 @@ struct wm8753_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
unsigned int sysclk; unsigned int sysclk;
unsigned int pcmclk; unsigned int pcmclk;
u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
int dai_func; int dai_func;
}; };
/* #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
* read wm8753 register cache
*/
static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
return -1;
return cache[reg - 1];
}
/*
* write wm8753 register cache
*/
static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
return;
cache[reg - 1] = value;
}
/*
* write to the WM8753 register space
*/
static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8753_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
/* /*
* WM8753 Controls * WM8753 Controls
...@@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol, ...@@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); int mode = snd_soc_read(codec, WM8753_IOCTL);
ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
return 0; return 0;
...@@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, ...@@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); int mode = snd_soc_read(codec, WM8753_IOCTL);
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
...@@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, ...@@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
if (pll_id == WM8753_PLL1) { if (pll_id == WM8753_PLL1) {
offset = 0; offset = 0;
enable = 0x10; enable = 0x10;
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;
} else { } else {
offset = 4; offset = 4;
enable = 0x8; enable = 0x8;
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;
} }
if (!freq_in || !freq_out) { if (!freq_in || !freq_out) {
/* disable PLL */ /* disable PLL */
wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
wm8753_write(codec, WM8753_CLOCK, reg); snd_soc_write(codec, WM8753_CLOCK, reg);
return 0; return 0;
} else { } else {
u16 value = 0; u16 value = 0;
...@@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, ...@@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
/* set up N and K PLL divisor ratios */ /* set up N and K PLL divisor ratios */
/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
/* bits 8:0 = PLL_K[17:9] */ /* bits 8:0 = PLL_K[17:9] */
value = (pll_div.k & 0x03fe00) >> 9; value = (pll_div.k & 0x03fe00) >> 9;
wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
/* bits 8:0 = PLL_K[8:0] */ /* bits 8:0 = PLL_K[8:0] */
value = pll_div.k & 0x0001ff; value = pll_div.k & 0x0001ff;
wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
/* set PLL as input and enable */ /* set PLL as input and enable */
wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
(pll_div.div2 << 3)); (pll_div.div2 << 3));
wm8753_write(codec, WM8753_CLOCK, reg | enable); snd_soc_write(codec, WM8753_CLOCK, reg | enable);
} }
return 0; return 0;
} }
...@@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
/* interface format */ /* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
...@@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
return 0; return 0;
} }
...@@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
/* bit size */ /* bit size */
switch (params_format(params)) { switch (params_format(params)) {
...@@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
/* sample rate */ /* sample rate */
if (params_rate(params) * 384 == wm8753->pcmclk) if (params_rate(params) * 384 == wm8753->pcmclk)
srate |= 0x80; srate |= 0x80;
wm8753_write(codec, WM8753_SRATE1, srate); snd_soc_write(codec, WM8753_SRATE1, srate);
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
return 0; return 0;
} }
...@@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -958,8 +911,8 @@ static int wm8753_pcm_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 voice, ioctl; u16 voice, ioctl;
voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
...@@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
wm8753_write(codec, WM8753_IOCTL, ioctl); snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0; return 0;
} }
...@@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, ...@@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) { switch (div_id) {
case WM8753_PCMDIV: case WM8753_PCMDIV:
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f;
wm8753_write(codec, WM8753_CLOCK, reg | div); snd_soc_write(codec, WM8753_CLOCK, reg | div);
break; break;
case WM8753_BCLKDIV: case WM8753_BCLKDIV:
reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7;
wm8753_write(codec, WM8753_SRATE2, reg | div); snd_soc_write(codec, WM8753_SRATE2, reg | div);
break; break;
case WM8753_VXCLKDIV: case WM8753_VXCLKDIV:
reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f;
wm8753_write(codec, WM8753_SRATE2, reg | div); snd_soc_write(codec, WM8753_SRATE2, reg | div);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
/* interface format */ /* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
...@@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
return 0; return 0;
} }
...@@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1085,8 +1038,8 @@ static int wm8753_i2s_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 ioctl, hifi; u16 ioctl, hifi;
hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
...@@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
wm8753_write(codec, WM8753_IOCTL, ioctl); snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0; return 0;
} }
...@@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
int coeff; int coeff;
/* is digital filter coefficient valid ? */ /* is digital filter coefficient valid ? */
...@@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
return coeff; return coeff;
} }
wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
coeff_div[coeff].usb); coeff_div[coeff].usb);
/* bit size */ /* bit size */
...@@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
break; break;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
return 0; return 0;
} }
...@@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as pcmclk */ /* set clk source as pcmclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock); snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
...@@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as pcmclk */ /* set clk source as pcmclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock); snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
...@@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as mclk */ /* set clk source as mclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock | 0x4); snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
...@@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int wm8753_mute(struct snd_soc_dai *dai, int mute) static int wm8753_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
/* the digital mute covers the HiFi and Voice DAC's on the WM8753. /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
* make sure we check if they are not both active when we mute */ * make sure we check if they are not both active when we mute */
if (mute && wm8753->dai_func == 1) { if (mute && wm8753->dai_func == 1) {
if (!codec->active) if (!codec->active)
wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
} else { } else {
if (mute) if (mute)
wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
else else
wm8753_write(codec, WM8753_DAC, mute_reg); snd_soc_write(codec, WM8753_DAC, mute_reg);
} }
return 0; return 0;
...@@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) ...@@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
static int wm8753_set_bias_level(struct snd_soc_codec *codec, static int wm8753_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* set vmid to 50k and unmute dac */ /* set vmid to 50k and unmute dac */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
/* set vmid to 5k for quick power up */ /* set vmid to 5k for quick power up */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* mute dac and set vmid to 500k, enable VREF */ /* mute dac and set vmid to 500k, enable VREF */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8753_write(codec, WM8753_PWR1, 0x0001); snd_soc_write(codec, WM8753_PWR1, 0x0001);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, ...@@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
else else
dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
} }
wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
} }
static void wm8753_work(struct work_struct *work) static void wm8753_work(struct work_struct *work)
...@@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) ...@@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8753_resume(struct snd_soc_codec *codec) static int wm8753_resume(struct snd_soc_codec *codec)
{ {
u16 *reg_cache = codec->reg_cache;
int i; int i;
u8 data[2];
u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */ /* Sync reg_cache with the hardware */
for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
if (i + 1 == WM8753_RESET) if (i == WM8753_RESET)
continue; continue;
/* No point in writing hardware default values back */ /* No point in writing hardware default values back */
if (cache[i] == wm8753_reg[i]) if (reg_cache[i] == wm8753_reg[i])
continue; continue;
data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); snd_soc_write(codec, i, reg_cache[i]);
data[1] = cache[i] & 0x00ff;
codec->hw_write(codec->control_data, data, 2);
} }
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
...@@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork) ...@@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork)
static int wm8753_probe(struct snd_soc_codec *codec) static int wm8753_probe(struct snd_soc_codec *codec)
{ {
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
int ret = 0, reg; int ret;
INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
...@@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec) ...@@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec)
msecs_to_jiffies(caps_charge)); msecs_to_jiffies(caps_charge));
/* set the update bits */ /* set the update bits */
reg = wm8753_read_reg_cache(codec, WM8753_LDAC); snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LDAC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RDAC); snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
wm8753_write(codec, WM8753_RDAC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LADC); snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LADC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RADC); snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
wm8753_write(codec, WM8753_RADC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
snd_soc_add_controls(codec, wm8753_snd_controls, snd_soc_add_controls(codec, wm8753_snd_controls,
ARRAY_SIZE(wm8753_snd_controls)); ARRAY_SIZE(wm8753_snd_controls));
......
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