Commit bedd4b19 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

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: default avatarDimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent c8badda8
...@@ -1209,6 +1209,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, ...@@ -1209,6 +1209,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
return 0; 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, static int arizona_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -1224,6 +1245,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, ...@@ -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_width = arizona->tdm_width[dai->id - 1];
int tdm_slots = arizona->tdm_slots[dai->id - 1]; int tdm_slots = arizona->tdm_slots[dai->id - 1];
int bclk, lrclk, wl, frame, bclk_target; int bclk, lrclk, wl, frame, bclk_target;
bool reconfig;
unsigned int aif_tx_state, aif_rx_state;
if (params_rate(params) % 8000) if (params_rate(params) % 8000)
rates = &arizona_44k1_bclk_rates[0]; rates = &arizona_44k1_bclk_rates[0];
...@@ -1274,28 +1297,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, ...@@ -1274,28 +1297,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
wl = snd_pcm_format_width(params_format(params)); wl = snd_pcm_format_width(params_format(params));
frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; 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); ret = arizona_hw_params_rate(substream, params, dai);
if (ret != 0) if (ret != 0)
return ret; goto restore_aif;
regmap_update_bits_async(arizona->regmap, if (reconfig) {
base + ARIZONA_AIF_BCLK_CTRL, regmap_update_bits_async(arizona->regmap,
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); base + ARIZONA_AIF_BCLK_CTRL,
regmap_update_bits_async(arizona->regmap, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
base + ARIZONA_AIF_TX_BCLK_RATE, regmap_update_bits_async(arizona->regmap,
ARIZONA_AIF1TX_BCPF_MASK, lrclk); base + ARIZONA_AIF_TX_BCLK_RATE,
regmap_update_bits_async(arizona->regmap, ARIZONA_AIF1TX_BCPF_MASK, lrclk);
base + ARIZONA_AIF_RX_BCLK_RATE, regmap_update_bits_async(arizona->regmap,
ARIZONA_AIF1RX_BCPF_MASK, lrclk); base + ARIZONA_AIF_RX_BCLK_RATE,
regmap_update_bits_async(arizona->regmap, ARIZONA_AIF1RX_BCPF_MASK, lrclk);
base + ARIZONA_AIF_FRAME_CTRL_1, regmap_update_bits_async(arizona->regmap,
ARIZONA_AIF1TX_WL_MASK | base + ARIZONA_AIF_FRAME_CTRL_1,
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); ARIZONA_AIF1TX_WL_MASK |
regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
ARIZONA_AIF1RX_WL_MASK | regmap_update_bits(arizona->regmap,
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); 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) static const char *arizona_dai_clk_str(int clk_id)
......
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