[alsa-devel] [PATCH v2 RESEND] ASoC: wm9081: Use snd_soc_update_bits for read-modify-write
Use snd_soc_update_bits for read-modify-write register access instead of open-coding it using snd_soc_read and snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- RESEND: I just found I doesn't set my mail client properly to show correct sender, so here is a resend.
v2: For Initial cold start ( change bias level from SND_SOC_BIAS_OFF to SND_SOC_BIAS_STANDBY ), the v1 does not set VMID_SEL[1:0] bits correctly for Normal bias enable & soft start off. In v2 we also clear VMID_SEL[1:0] bits for Normal bias enable & soft start off. We did clear VMID_SEL[1:0] bits in SND_SOC_BIAS_OFF, thus we know the VMID_SEL[1:0] bits status is 0b00 in this case.
sound/soc/codecs/wm9081.c | 82 +++++++++++++++++++------------------------- 1 files changed, 35 insertions(+), 47 deletions(-)
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 66092ef..9c38ddb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -766,84 +766,73 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = { static int wm9081_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 reg; - switch (level) { case SND_SOC_BIAS_ON: break;
case SND_SOC_BIAS_PREPARE: /* VMID=2*40k */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); - reg &= ~WM9081_VMID_SEL_MASK; - reg |= 0x2; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_VMID_CONTROL, + WM9081_VMID_SEL_MASK, 0x2);
/* Normal bias current */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg &= ~WM9081_STBY_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_STBY_BIAS_ENA, 0); break;
case SND_SOC_BIAS_STANDBY: /* Initial cold start */ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { /* Disable LINEOUT discharge */ - reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); - reg &= ~WM9081_LINEOUT_DISCH; - snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, + WM9081_LINEOUT_DISCH, 0);
/* Select startup bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_BIAS_SRC | WM9081_BIAS_ENA, + WM9081_BIAS_SRC | WM9081_BIAS_ENA);
/* VMID 2*4k; Soft VMID ramp enable */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); - reg |= WM9081_VMID_RAMP | 0x6; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); - + snd_soc_update_bits(codec, WM9081_VMID_CONTROL, + WM9081_VMID_RAMP | 0x6, + WM9081_VMID_RAMP | 0x6); mdelay(100);
/* Normal bias enable & soft start off */ - reg |= WM9081_BIAS_ENA; - reg &= ~WM9081_VMID_RAMP; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_VMID_CONTROL, + WM9081_VMID_RAMP | WM9081_BIAS_ENA | + WM9081_VMID_SEL_MASK, + WM9081_BIAS_ENA);
/* Standard bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg &= ~WM9081_BIAS_SRC; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_BIAS_SRC, 0); }
/* VMID 2*240k */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg &= ~WM9081_VMID_SEL_MASK; - reg |= 0x04; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_VMID_SEL_MASK, 0x04);
/* Standby bias current on */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg |= WM9081_STBY_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_STBY_BIAS_ENA, + WM9081_STBY_BIAS_ENA); break;
case SND_SOC_BIAS_OFF: /* Startup bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); - reg |= WM9081_BIAS_SRC; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, + WM9081_BIAS_SRC, WM9081_BIAS_SRC);
/* Disable VMID and biases with soft ramping */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); - reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA); - reg |= WM9081_VMID_RAMP; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_VMID_CONTROL, + WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK | + WM9081_BIAS_ENA, WM9081_VMID_RAMP);
/* Actively discharge LINEOUT */ - reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); - reg |= WM9081_LINEOUT_DISCH; - snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg); + snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, + WM9081_LINEOUT_DISCH, + WM9081_LINEOUT_DISCH); break; }
@@ -1242,11 +1231,10 @@ static int wm9081_probe(struct snd_soc_codec *codec) wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Enable zero cross by default */ - reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); - snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); - reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); - snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, - reg | WM9081_SPKPGAZC); + snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, + WM9081_LINEOUTZC, WM9081_LINEOUTZC); + snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA, + WM9081_SPKPGAZC, WM9081_SPKPGAZC);
snd_soc_add_controls(codec, wm9081_snd_controls, ARRAY_SIZE(wm9081_snd_controls));
On 19 October 2011 04:06, Axel Lin axel.lin@gmail.com wrote:
Use snd_soc_update_bits for read-modify-write register access instead of open-coding it using snd_soc_read and snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com
RESEND: I just found I doesn't set my mail client properly to show correct sender, so here is a resend.
v2: For Initial cold start ( change bias level from SND_SOC_BIAS_OFF to SND_SOC_BIAS_STANDBY ), the v1 does not set VMID_SEL[1:0] bits correctly for Normal bias enable & soft start off. In v2 we also clear VMID_SEL[1:0] bits for Normal bias enable & soft start off. We did clear VMID_SEL[1:0] bits in SND_SOC_BIAS_OFF, thus we know the VMID_SEL[1:0] bits status is 0b00 in this case.
The mechanics look OK, but best for Mark to check with the hardware.
Acked-by: Liam Girdwood lrg@ti.com
sound/soc/codecs/wm9081.c | 82 +++++++++++++++++++------------------------- 1 files changed, 35 insertions(+), 47 deletions(-)
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 66092ef..9c38ddb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -766,84 +766,73 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = { static int wm9081_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) {
- u16 reg;
switch (level) { case SND_SOC_BIAS_ON: break;
case SND_SOC_BIAS_PREPARE: /* VMID=2*40k */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg &= ~WM9081_VMID_SEL_MASK;
- reg |= 0x2;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
- WM9081_VMID_SEL_MASK, 0x2);
/* Normal bias current */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_STBY_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_STBY_BIAS_ENA, 0);
break;
case SND_SOC_BIAS_STANDBY: /* Initial cold start */ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { /* Disable LINEOUT discharge */
- reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
- reg &= ~WM9081_LINEOUT_DISCH;
- snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
- WM9081_LINEOUT_DISCH, 0);
/* Select startup bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_BIAS_SRC | WM9081_BIAS_ENA,
- WM9081_BIAS_SRC | WM9081_BIAS_ENA);
/* VMID 2*4k; Soft VMID ramp enable */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg |= WM9081_VMID_RAMP | 0x6;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
- WM9081_VMID_RAMP | 0x6,
- WM9081_VMID_RAMP | 0x6);
mdelay(100);
/* Normal bias enable & soft start off */
- reg |= WM9081_BIAS_ENA;
- reg &= ~WM9081_VMID_RAMP;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
- WM9081_VMID_RAMP | WM9081_BIAS_ENA |
- WM9081_VMID_SEL_MASK,
- WM9081_BIAS_ENA);
/* Standard bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_BIAS_SRC;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_BIAS_SRC, 0);
}
/* VMID 2*240k */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_VMID_SEL_MASK;
- reg |= 0x04;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_VMID_SEL_MASK, 0x04);
/* Standby bias current on */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_STBY_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_STBY_BIAS_ENA,
- WM9081_STBY_BIAS_ENA);
break;
case SND_SOC_BIAS_OFF: /* Startup bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_BIAS_SRC;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
- snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
- WM9081_BIAS_SRC, WM9081_BIAS_SRC);
/* Disable VMID and biases with soft ramping */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
- reg |= WM9081_VMID_RAMP;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
- WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK |
- WM9081_BIAS_ENA, WM9081_VMID_RAMP);
/* Actively discharge LINEOUT */
- reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
- reg |= WM9081_LINEOUT_DISCH;
- snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
- WM9081_LINEOUT_DISCH,
- WM9081_LINEOUT_DISCH);
break; }
@@ -1242,11 +1231,10 @@ static int wm9081_probe(struct snd_soc_codec *codec) wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Enable zero cross by default */
- reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
- snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
- reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
- snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
- reg | WM9081_SPKPGAZC);
- snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
- WM9081_LINEOUTZC, WM9081_LINEOUTZC);
- snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA,
- WM9081_SPKPGAZC, WM9081_SPKPGAZC);
snd_soc_add_controls(codec, wm9081_snd_controls, ARRAY_SIZE(wm9081_snd_controls)); -- 1.7.5.4
On Wed, Oct 19, 2011 at 11:06:27AM +0800, Axel Lin wrote:
/* Normal bias enable & soft start off */
reg |= WM9081_BIAS_ENA;
reg &= ~WM9081_VMID_RAMP;
snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
WM9081_VMID_RAMP | WM9081_BIAS_ENA |
WM9081_VMID_SEL_MASK,
WM9081_BIAS_ENA);
This looks (and sounds) wrong - the original code didn't touch VMID_SEL_MASK for this update but the new version will clear VMID_SEL_MASK. Even with that fixed there still seems to be some issue here, though.
2011/11/5 Mark Brown broonie@opensource.wolfsonmicro.com:
On Wed, Oct 19, 2011 at 11:06:27AM +0800, Axel Lin wrote:
/* Normal bias enable & soft start off */
- reg |= WM9081_BIAS_ENA;
- reg &= ~WM9081_VMID_RAMP;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
- snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
- WM9081_VMID_RAMP | WM9081_BIAS_ENA |
- WM9081_VMID_SEL_MASK,
- WM9081_BIAS_ENA);
This looks (and sounds) wrong - the original code didn't touch VMID_SEL_MASK for this update but the new version will clear VMID_SEL_MASK. Even with that fixed there still seems to be some issue here, though.
Hi Mark,
I just re-check current code, and I think current code (before converting to snd_soc_update_bits) is broken. See below 2 patches: ( I'm sending the patch now) ASoC: wm9081: Fix reading wrong register for setting VMID 2*240k ASoC: wm9081: Don't write WM9081_BIAS_ENA bit to WM9081_VMID_CONTROL register
Would you mind to test if above 2 patches works. If it works, I'll send a new patch to use snd_soc_update_bits for read-modify-write.
Thanks, Axel
participants (3)
-
Axel Lin
-
Girdwood, Liam
-
Mark Brown