aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2014-07-22 06:42:06 -0400
committerMark Brown <broonie@linaro.org>2014-07-22 18:22:19 -0400
commitbedd4b1993ecb7228f8e5d6673e25d4482bd302b (patch)
tree4d160e9d6573d72280fa83e6253c87f607b2f4f2
parentc8badda8eea6e9d142c8794519f6a57aa3ea3123 (diff)
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>
-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,
1209 return 0; 1209 return 0;
1210} 1210}
1211 1211
1212static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1213 int base, int bclk, int lrclk, int frame)
1214{
1215 int val;
1216
1217 val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1218 if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1219 return true;
1220
1221 val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1222 if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1223 return true;
1224
1225 val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1226 if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1227 ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1228 return true;
1229
1230 return false;
1231}
1232
1212static int arizona_hw_params(struct snd_pcm_substream *substream, 1233static int arizona_hw_params(struct snd_pcm_substream *substream,
1213 struct snd_pcm_hw_params *params, 1234 struct snd_pcm_hw_params *params,
1214 struct snd_soc_dai *dai) 1235 struct snd_soc_dai *dai)
@@ -1224,6 +1245,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
1224 int tdm_width = arizona->tdm_width[dai->id - 1]; 1245 int tdm_width = arizona->tdm_width[dai->id - 1];
1225 int tdm_slots = arizona->tdm_slots[dai->id - 1]; 1246 int tdm_slots = arizona->tdm_slots[dai->id - 1];
1226 int bclk, lrclk, wl, frame, bclk_target; 1247 int bclk, lrclk, wl, frame, bclk_target;
1248 bool reconfig;
1249 unsigned int aif_tx_state, aif_rx_state;
1227 1250
1228 if (params_rate(params) % 8000) 1251 if (params_rate(params) % 8000)
1229 rates = &arizona_44k1_bclk_rates[0]; 1252 rates = &arizona_44k1_bclk_rates[0];
@@ -1274,28 +1297,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
1274 wl = snd_pcm_format_width(params_format(params)); 1297 wl = snd_pcm_format_width(params_format(params));
1275 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; 1298 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
1276 1299
1300 reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1301
1302 if (reconfig) {
1303 /* Save AIF TX/RX state */
1304 aif_tx_state = snd_soc_read(codec,
1305 base + ARIZONA_AIF_TX_ENABLES);
1306 aif_rx_state = snd_soc_read(codec,
1307 base + ARIZONA_AIF_RX_ENABLES);
1308 /* Disable AIF TX/RX before reconfiguring it */
1309 regmap_update_bits_async(arizona->regmap,
1310 base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1311 regmap_update_bits(arizona->regmap,
1312 base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1313 }
1314
1277 ret = arizona_hw_params_rate(substream, params, dai); 1315 ret = arizona_hw_params_rate(substream, params, dai);
1278 if (ret != 0) 1316 if (ret != 0)
1279 return ret; 1317 goto restore_aif;
1280 1318
1281 regmap_update_bits_async(arizona->regmap, 1319 if (reconfig) {
1282 base + ARIZONA_AIF_BCLK_CTRL, 1320 regmap_update_bits_async(arizona->regmap,
1283 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); 1321 base + ARIZONA_AIF_BCLK_CTRL,
1284 regmap_update_bits_async(arizona->regmap, 1322 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1285 base + ARIZONA_AIF_TX_BCLK_RATE, 1323 regmap_update_bits_async(arizona->regmap,
1286 ARIZONA_AIF1TX_BCPF_MASK, lrclk); 1324 base + ARIZONA_AIF_TX_BCLK_RATE,
1287 regmap_update_bits_async(arizona->regmap, 1325 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1288 base + ARIZONA_AIF_RX_BCLK_RATE, 1326 regmap_update_bits_async(arizona->regmap,
1289 ARIZONA_AIF1RX_BCPF_MASK, lrclk); 1327 base + ARIZONA_AIF_RX_BCLK_RATE,
1290 regmap_update_bits_async(arizona->regmap, 1328 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1291 base + ARIZONA_AIF_FRAME_CTRL_1, 1329 regmap_update_bits_async(arizona->regmap,
1292 ARIZONA_AIF1TX_WL_MASK | 1330 base + ARIZONA_AIF_FRAME_CTRL_1,
1293 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); 1331 ARIZONA_AIF1TX_WL_MASK |
1294 regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2, 1332 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1295 ARIZONA_AIF1RX_WL_MASK | 1333 regmap_update_bits(arizona->regmap,
1296 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); 1334 base + ARIZONA_AIF_FRAME_CTRL_2,
1335 ARIZONA_AIF1RX_WL_MASK |
1336 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1337 }
1297 1338
1298 return 0; 1339restore_aif:
1340 if (reconfig) {
1341 /* Restore AIF TX/RX state */
1342 regmap_update_bits_async(arizona->regmap,
1343 base + ARIZONA_AIF_TX_ENABLES,
1344 0xff, aif_tx_state);
1345 regmap_update_bits(arizona->regmap,
1346 base + ARIZONA_AIF_RX_ENABLES,
1347 0xff, aif_rx_state);
1348 }
1349 return ret;
1299} 1350}
1300 1351
1301static const char *arizona_dai_clk_str(int clk_id) 1352static const char *arizona_dai_clk_str(int clk_id)