ASoC: arizona: Disable AIF TX/RX before configuring it
diff mbox

Message ID 20140716121029.GA22222@opensource.wolfsonmicro.com
State New, archived
Headers show

Commit Message

Richard Fitzgerald July 16, 2014, 12:10 p.m. UTC
If we don't disable the AIF TX/RX then we may fall into a
situation where the new AIF settings are ignored by the device.
For example, this problem manifests when switching between
different sample rates.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/arizona.c |   20 ++++++++++++++++++--
 1 files changed, 18 insertions(+), 2 deletions(-)

Comments

Mark Brown July 17, 2014, 7:42 p.m. UTC | #1
On Wed, Jul 16, 2014 at 01:10:39PM +0100, Richard Fitzgerald wrote:

> If we don't disable the AIF TX/RX then we may fall into a
> situation where the new AIF settings are ignored by the device.
> For example, this problem manifests when switching between
> different sample rates.

So, what this does is momentarily disable the AIF when reconfiguring.
That will glitch any running audio, making me wonder if the driver
shouldn't be returning an error or at least complaining if it has to
reconfigure instead.  What's the use case where this might get
triggered?
Richard Fitzgerald July 21, 2014, 9:01 a.m. UTC | #2
On Thu, Jul 17, 2014 at 08:42:15PM +0100, Mark Brown wrote:
> On Wed, Jul 16, 2014 at 01:10:39PM +0100, Richard Fitzgerald wrote:
> 
> > If we don't disable the AIF TX/RX then we may fall into a
> > situation where the new AIF settings are ignored by the device.
> > For example, this problem manifests when switching between
> > different sample rates.
> 
> So, what this does is momentarily disable the AIF when reconfiguring.
> That will glitch any running audio, making me wonder if the driver
> shouldn't be returning an error or at least complaining if it has to
> reconfigure instead.  What's the use case where this might get
> triggered?

The case being fixed is like this:

aplay 48kHz.wav; aplay 96kHz.wav

The second open happens before pmdown_time so the AIF is still enabled.
Writes to the AIF config registers only take effect if the AIF is disabled.
Without this patch, the 96kHz.wav will play at 48kHz
Takashi Iwai July 21, 2014, 9:04 a.m. UTC | #3
At Mon, 21 Jul 2014 10:01:22 +0100,
Richard Fitzgerald wrote:
> 
> On Thu, Jul 17, 2014 at 08:42:15PM +0100, Mark Brown wrote:
> > On Wed, Jul 16, 2014 at 01:10:39PM +0100, Richard Fitzgerald wrote:
> > 
> > > If we don't disable the AIF TX/RX then we may fall into a
> > > situation where the new AIF settings are ignored by the device.
> > > For example, this problem manifests when switching between
> > > different sample rates.
> > 
> > So, what this does is momentarily disable the AIF when reconfiguring.
> > That will glitch any running audio, making me wonder if the driver
> > shouldn't be returning an error or at least complaining if it has to
> > reconfigure instead.  What's the use case where this might get
> > triggered?
> 
> The case being fixed is like this:
> 
> aplay 48kHz.wav; aplay 96kHz.wav
> 
> The second open happens before pmdown_time so the AIF is still enabled.
> Writes to the AIF config registers only take effect if the AIF is disabled.
> Without this patch, the 96kHz.wav will play at 48kHz

If the glitch really matters, the driver can minimize by checking the
change of sample rate and doing temporary turn on/off only when
required.


Takashi
Richard Fitzgerald July 21, 2014, 10:33 a.m. UTC | #4
On Mon, Jul 21, 2014 at 11:04:56AM +0200, Takashi Iwai wrote:
> At Mon, 21 Jul 2014 10:01:22 +0100,
> Richard Fitzgerald wrote:
> > 
> > On Thu, Jul 17, 2014 at 08:42:15PM +0100, Mark Brown wrote:
> > > On Wed, Jul 16, 2014 at 01:10:39PM +0100, Richard Fitzgerald wrote:
> > > 
> > > > If we don't disable the AIF TX/RX then we may fall into a
> > > > situation where the new AIF settings are ignored by the device.
> > > > For example, this problem manifests when switching between
> > > > different sample rates.
> > > 
> > > So, what this does is momentarily disable the AIF when reconfiguring.
> > > That will glitch any running audio, making me wonder if the driver
> > > shouldn't be returning an error or at least complaining if it has to
> > > reconfigure instead.  What's the use case where this might get
> > > triggered?
> > 
> > The case being fixed is like this:
> > 
> > aplay 48kHz.wav; aplay 96kHz.wav
> > 
> > The second open happens before pmdown_time so the AIF is still enabled.
> > Writes to the AIF config registers only take effect if the AIF is disabled.
> > Without this patch, the 96kHz.wav will play at 48kHz
> 
> If the glitch really matters, the driver can minimize by checking the
> change of sample rate and doing temporary turn on/off only when
> required.
> 
> 
> Takashi

That's a fair point.
Mark Brown July 21, 2014, 4:24 p.m. UTC | #5
On Mon, Jul 21, 2014 at 11:33:27AM +0100, Richard Fitzgerald wrote:
> On Mon, Jul 21, 2014 at 11:04:56AM +0200, Takashi Iwai wrote:
> > Richard Fitzgerald wrote:

> > > The case being fixed is like this:

> > > aplay 48kHz.wav; aplay 96kHz.wav

> > > The second open happens before pmdown_time so the AIF is still enabled.
> > > Writes to the AIF config registers only take effect if the AIF is disabled.
> > > Without this patch, the 96kHz.wav will play at 48kHz

> > If the glitch really matters, the driver can minimize by checking the
> > change of sample rate and doing temporary turn on/off only when
> > required.

> That's a fair point.

The case I was particularly worrying about here was simultaneous
playback and capture - we won't be changing rates here since these
devices currently require symmetry which is enforced via constraints but
we are likely to at least be starting multiple streams close to each
other frequently.

Patch
diff mbox

diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index fb30c82..270e7ad 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1249,6 +1249,7 @@  static int arizona_hw_params(struct snd_pcm_substream *substream,
 	int tdm_width = arizona->tdm_width[dai->id - 1];
 	int tdm_slots = arizona->tdm_slots[dai->id - 1];
 	int bclk, lrclk, wl, frame, bclk_target;
+	unsigned int aif_tx_state, aif_rx_state;
 
 	if (params_rate(params) % 8000)
 		rates = &arizona_44k1_bclk_rates[0];
@@ -1299,9 +1300,18 @@  static int arizona_hw_params(struct snd_pcm_substream *substream,
 	wl = snd_pcm_format_width(params_format(params));
 	frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
 
+	/* Save AIF TX/RX state */
+	aif_tx_state = snd_soc_read(codec, base + ARIZONA_AIF_TX_ENABLES);
+	aif_rx_state = snd_soc_read(codec, base + ARIZONA_AIF_RX_ENABLES);
+	/* Disable AIF TX/RX before configuring it */
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_ENABLES,
+			    0xff, 0x0);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_ENABLES,
+			    0xff, 0x0);
+
 	ret = arizona_hw_params_rate(substream, params, dai);
 	if (ret != 0)
-		return ret;
+		goto restore_aif;
 
 	regmap_update_bits_async(arizona->regmap,
 				 base + ARIZONA_AIF_BCLK_CTRL,
@@ -1320,7 +1330,13 @@  static int arizona_hw_params(struct snd_pcm_substream *substream,
 			   ARIZONA_AIF1RX_WL_MASK |
 			   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
 
-	return 0;
+restore_aif:
+	/* Restore AIF TX/RX state */
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_ENABLES,
+			    0xff, aif_tx_state);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_ENABLES,
+			    0xff, aif_rx_state);
+	return ret;
 }
 
 static const char *arizona_dai_clk_str(int clk_id)