summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/arizona.c
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2014-07-22 12:42:06 +0200
committerMark Brown <broonie@linaro.org>2014-07-23 00:22:19 +0200
commitbedd4b1993ecb7228f8e5d6673e25d4482bd302b (patch)
tree4d160e9d6573d72280fa83e6253c87f607b2f4f2 /sound/soc/codecs/arizona.c
parentASoC: arizona: Update handling for input change on an active FLL (diff)
downloadlinux-bedd4b1993ecb7228f8e5d6673e25d4482bd302b.tar.xz
linux-bedd4b1993ecb7228f8e5d6673e25d4482bd302b.zip
ASoC: arizona: Disable AIF TX/RX before configuring it
Changes to the AIF configuration registers only take effect when the AIF is disabled. If the configuration is being changed from the previous setup, temporarily disable the AIF. Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r--sound/soc/codecs/arizona.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index be3657ac52a4..9a730689a0ac 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1209,6 +1209,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
return 0;
}
+static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
+ int base, int bclk, int lrclk, int frame)
+{
+ int val;
+
+ val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
+ if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
+ return true;
+
+ val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
+ if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
+ return true;
+
+ val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
+ if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
+ ARIZONA_AIF1TX_SLOT_LEN_MASK)))
+ return true;
+
+ return false;
+}
+
static int arizona_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -1224,6 +1245,8 @@ 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;
+ bool reconfig;
+ unsigned int aif_tx_state, aif_rx_state;
if (params_rate(params) % 8000)
rates = &arizona_44k1_bclk_rates[0];
@@ -1274,28 +1297,56 @@ 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;
+ reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
+
+ if (reconfig) {
+ /* 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 reconfiguring it */
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
+ regmap_update_bits(arizona->regmap,
+ 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,
- ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
- regmap_update_bits_async(arizona->regmap,
- base + ARIZONA_AIF_TX_BCLK_RATE,
- ARIZONA_AIF1TX_BCPF_MASK, lrclk);
- regmap_update_bits_async(arizona->regmap,
- base + ARIZONA_AIF_RX_BCLK_RATE,
- ARIZONA_AIF1RX_BCPF_MASK, lrclk);
- regmap_update_bits_async(arizona->regmap,
- base + ARIZONA_AIF_FRAME_CTRL_1,
- ARIZONA_AIF1TX_WL_MASK |
- ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
- regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
- ARIZONA_AIF1RX_WL_MASK |
- ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+ if (reconfig) {
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_BCLK_CTRL,
+ ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_TX_BCLK_RATE,
+ ARIZONA_AIF1TX_BCPF_MASK, lrclk);
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_RX_BCLK_RATE,
+ ARIZONA_AIF1RX_BCPF_MASK, lrclk);
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_FRAME_CTRL_1,
+ ARIZONA_AIF1TX_WL_MASK |
+ ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
+ regmap_update_bits(arizona->regmap,
+ base + ARIZONA_AIF_FRAME_CTRL_2,
+ ARIZONA_AIF1RX_WL_MASK |
+ ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+ }
- return 0;
+restore_aif:
+ if (reconfig) {
+ /* Restore AIF TX/RX state */
+ regmap_update_bits_async(arizona->regmap,
+ base + ARIZONA_AIF_TX_ENABLES,
+ 0xff, aif_tx_state);
+ regmap_update_bits(arizona->regmap,
+ base + ARIZONA_AIF_RX_ENABLES,
+ 0xff, aif_rx_state);
+ }
+ return ret;
}
static const char *arizona_dai_clk_str(int clk_id)