Skip to content

Commit

Permalink
ASoC: arizona: Disable AIF TX/RX before configuring it
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Richard Fitzgerald authored and Mark Brown committed Jul 22, 2014
1 parent c8badda commit bedd4b1
Showing 1 changed file with 69 additions and 18 deletions.
87 changes: 69 additions & 18 deletions sound/soc/codecs/arizona.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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];
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit bedd4b1

Please sign in to comment.