summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-09-24 16:44:05 +0800
committerShengjiu Wang <shengjiu.wang@nxp.com>2019-12-29 13:26:32 +0800
commit0885728776125a1f442efefe6eaad9b3426b51cf (patch)
tree129458b9c57c54fbf313e21d1150cf7fac60839f
parent1ed8c746fe32b7fd084649bede80fc0ed9ef9293 (diff)
MLK-22620: ASoC: imx-ak5558: Force tdm mode for ASRC case
In order to support the odd channels for ASRC case, we force to enable TDM mode. In non-tdm case, we enable multi lane to support multi channels, but limitation is odd multi channels can't be supported. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
-rw-r--r--sound/soc/fsl/imx-ak5558.c77
1 files changed, 70 insertions, 7 deletions
diff --git a/sound/soc/fsl/imx-ak5558.c b/sound/soc/fsl/imx-ak5558.c
index 98a057dc91a4..f2d692282420 100644
--- a/sound/soc/fsl/imx-ak5558.c
+++ b/sound/soc/fsl/imx-ak5558.c
@@ -200,6 +200,66 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+/* In order to support odd channels, force tdm mode for FE-BE case */
+static int imx_aif_hw_params_be(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct device *dev = card->dev;
+ struct imx_ak5558_data *data = snd_soc_card_get_drvdata(card);
+ unsigned int channels = params_channels(params);
+ unsigned long mclk_freq;
+ unsigned int fmt;
+ int ret;
+
+ fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ /* support TDM256 (8 slots * 32 bits/per slot) */
+ data->slots = 8;
+ data->slot_width = 32;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+ BIT(channels) - 1, BIT(channels) - 1,
+ data->slots, data->slot_width);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai,
+ BIT(channels) - 1, BIT(channels) - 1,
+ 8, 32);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ mclk_freq = ak5558_get_mclk_rate(substream, params);
+ ret = snd_soc_dai_set_sysclk(cpu_dai, FSL_SAI_CLK_MAST1, mclk_freq,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ dev_err(dev, "failed to set cpu_dai mclk1 rate %lu\n",
+ mclk_freq);
+
+ return ret;
+}
+
static int imx_ak5558_hw_rule_rate(struct snd_pcm_hw_params *p,
struct snd_pcm_hw_rule *r)
{
@@ -253,12 +313,15 @@ static int imx_aif_startup(struct snd_pcm_substream *substream)
if (ret)
return ret;
- constraint_channels.list = ak5558_channels;
- constraint_channels.count = ARRAY_SIZE(ak5558_channels);
- ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- &constraint_channels);
- if (ret < 0)
- return ret;
+ if (!data->tdm_mode) {
+ constraint_channels.list = ak5558_channels;
+ constraint_channels.count = ARRAY_SIZE(ak5558_channels);
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraint_channels);
+ if (ret < 0)
+ return ret;
+ }
return snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, imx_ak5558_hw_rule_rate, data,
@@ -271,7 +334,7 @@ static struct snd_soc_ops imx_aif_ops = {
};
static struct snd_soc_ops imx_aif_ops_be = {
- .hw_params = imx_aif_hw_params,
+ .hw_params = imx_aif_hw_params_be,
};
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,