aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2015-01-06 09:17:20 -0500
committerMark Brown <broonie@kernel.org>2015-01-07 13:01:57 -0500
commitce64c8b9cf5be2a93508af4667110dbe90904557 (patch)
treec0feb3d4ff8f66ef466419845d23c6859201117d
parent9cb2a25ce68aec15d5d940f5d3040bd66ca688c7 (diff)
ASoC: Add helper function for changing the DAI link format
For some setups it is necessary to change the DAI link format at runtime. This patch factors out the code that does the initial static DAI link format configuration into a separate helper function which can be used board drivers as well. This allows board drivers that have to change the DAI link format at runtime to reuse it instead of having to manually change the format on all DAIs. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--include/sound/soc.h3
-rw-r--r--sound/soc/soc-core.c125
2 files changed, 72 insertions, 56 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index b4fca9aed2a2..edd4a0a11ccf 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -429,6 +429,9 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
429void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); 429void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
430void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); 430void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
431 431
432int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
433 unsigned int dai_fmt);
434
432/* Utility functions to get clock rates from various things */ 435/* Utility functions to get clock rates from various things */
433int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); 436int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
434int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); 437int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 985052b3fbed..80ea358d3ad7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1427,11 +1427,75 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
1427 return 0; 1427 return 0;
1428} 1428}
1429 1429
1430/**
1431 * snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
1432 * @rtd: The runtime for which the DAI link format should be changed
1433 * @dai_fmt: The new DAI link format
1434 *
1435 * This function updates the DAI link format for all DAIs connected to the DAI
1436 * link for the specified runtime.
1437 *
1438 * Note: For setups with a static format set the dai_fmt field in the
1439 * corresponding snd_dai_link struct instead of using this function.
1440 *
1441 * Returns 0 on success, otherwise a negative error code.
1442 */
1443int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
1444 unsigned int dai_fmt)
1445{
1446 struct snd_soc_dai **codec_dais = rtd->codec_dais;
1447 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1448 unsigned int i;
1449 int ret;
1450
1451 for (i = 0; i < rtd->num_codecs; i++) {
1452 struct snd_soc_dai *codec_dai = codec_dais[i];
1453
1454 ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
1455 if (ret != 0 && ret != -ENOTSUPP) {
1456 dev_warn(codec_dai->dev,
1457 "ASoC: Failed to set DAI format: %d\n", ret);
1458 return ret;
1459 }
1460 }
1461
1462 /* Flip the polarity for the "CPU" end of a CODEC<->CODEC link */
1463 if (cpu_dai->codec) {
1464 unsigned int inv_dai_fmt;
1465
1466 inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK;
1467 switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1468 case SND_SOC_DAIFMT_CBM_CFM:
1469 inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
1470 break;
1471 case SND_SOC_DAIFMT_CBM_CFS:
1472 inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
1473 break;
1474 case SND_SOC_DAIFMT_CBS_CFM:
1475 inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
1476 break;
1477 case SND_SOC_DAIFMT_CBS_CFS:
1478 inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
1479 break;
1480 }
1481
1482 dai_fmt = inv_dai_fmt;
1483 }
1484
1485 ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
1486 if (ret != 0 && ret != -ENOTSUPP) {
1487 dev_warn(cpu_dai->dev,
1488 "ASoC: Failed to set DAI format: %d\n", ret);
1489 return ret;
1490 }
1491
1492 return 0;
1493}
1494
1430static int snd_soc_instantiate_card(struct snd_soc_card *card) 1495static int snd_soc_instantiate_card(struct snd_soc_card *card)
1431{ 1496{
1432 struct snd_soc_codec *codec; 1497 struct snd_soc_codec *codec;
1433 struct snd_soc_dai_link *dai_link; 1498 int ret, i, order;
1434 int ret, i, order, dai_fmt;
1435 1499
1436 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); 1500 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
1437 1501
@@ -1542,60 +1606,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
1542 card->num_dapm_routes); 1606 card->num_dapm_routes);
1543 1607
1544 for (i = 0; i < card->num_links; i++) { 1608 for (i = 0; i < card->num_links; i++) {
1545 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; 1609 if (card->dai_link[i].dai_fmt)
1546 dai_link = &card->dai_link[i]; 1610 snd_soc_runtime_set_dai_fmt(&card->rtd[i],
1547 dai_fmt = dai_link->dai_fmt; 1611 card->dai_link[i].dai_fmt);
1548
1549 if (dai_fmt) {
1550 struct snd_soc_dai **codec_dais = rtd->codec_dais;
1551 int j;
1552
1553 for (j = 0; j < rtd->num_codecs; j++) {
1554 struct snd_soc_dai *codec_dai = codec_dais[j];
1555
1556 ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
1557 if (ret != 0 && ret != -ENOTSUPP)
1558 dev_warn(codec_dai->dev,
1559 "ASoC: Failed to set DAI format: %d\n",
1560 ret);
1561 }
1562 }
1563
1564 /* If this is a regular CPU link there will be a platform */
1565 if (dai_fmt &&
1566 (dai_link->platform_name || dai_link->platform_of_node)) {
1567 ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
1568 dai_fmt);
1569 if (ret != 0 && ret != -ENOTSUPP)
1570 dev_warn(card->rtd[i].cpu_dai->dev,
1571 "ASoC: Failed to set DAI format: %d\n",
1572 ret);
1573 } else if (dai_fmt) {
1574 /* Flip the polarity for the "CPU" end */
1575 dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
1576 switch (dai_link->dai_fmt &
1577 SND_SOC_DAIFMT_MASTER_MASK) {
1578 case SND_SOC_DAIFMT_CBM_CFM:
1579 dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
1580 break;
1581 case SND_SOC_DAIFMT_CBM_CFS:
1582 dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
1583 break;
1584 case SND_SOC_DAIFMT_CBS_CFM:
1585 dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
1586 break;
1587 case SND_SOC_DAIFMT_CBS_CFS:
1588 dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
1589 break;
1590 }
1591
1592 ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
1593 dai_fmt);
1594 if (ret != 0 && ret != -ENOTSUPP)
1595 dev_warn(card->rtd[i].cpu_dai->dev,
1596 "ASoC: Failed to set DAI format: %d\n",
1597 ret);
1598 }
1599 } 1612 }
1600 1613
1601 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), 1614 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),