diff options
author | Daniel Baluta <daniel.baluta@nxp.com> | 2018-03-08 18:55:32 +0200 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:50:36 +0800 |
commit | 8ffa567575a3c73a9e80e348f74ca043c93409d4 (patch) | |
tree | 27cf3abc10404aebeafc0189aa6f2982debdf39a | |
parent | 3be16c7bc4e9796f1bbce5bfc726211356d8ba6e (diff) |
MLK-17734-1: ASoC: fsl: imx-ak5558: Fix TDM mode for 8kHz / 16Khz
In order for TDM to correctly work we need that MCLK and
BCLK to follow the values in Table 9.
Thus,
* TDM128: BCLK = 128fs, MCLK = 128-1024fs
* TDM256: BCLK = 256fs, MCLK = 256-1024fs
* TDM512: BCLK = 512fs, MCLK = 512-1024fs
We assume only support TDM256 for the moment.
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
-rw-r--r-- | sound/soc/fsl/imx-ak5558.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/sound/soc/fsl/imx-ak5558.c b/sound/soc/fsl/imx-ak5558.c index 36b31f5357c9..70075db8034e 100644 --- a/sound/soc/fsl/imx-ak5558.c +++ b/sound/soc/fsl/imx-ak5558.c @@ -57,6 +57,17 @@ static const struct imx_ak5558_fs_mul fs_mul[] = { { .min = 768000, .max = 768000, .mul = 2 * 32 }, }; +/* + * MCLK and BCLK selection based on TDM mode + * because of SAI we also add the restriction: MCLK >= 2 * BCLK + * (Table 9 from datasheet) + */ +static const struct imx_ak5558_fs_mul fs_mul_tdm[] = { + { .min = 128, .max = 128, .mul = 256 }, + { .min = 256, .max = 256, .mul = 512 }, + { .min = 512, .max = 512, .mul = 1024 }, +}; + static struct snd_soc_dapm_widget imx_ak5558_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line In", NULL), }; @@ -83,13 +94,26 @@ static unsigned long ak5558_get_mclk_rate(struct snd_pcm_substream *substream, struct imx_ak5558_data *data = snd_soc_card_get_drvdata(rtd->card); unsigned int rate = params_rate(params); unsigned int freq = data->freq; + int mode; int i; - for (i = 0; i < ARRAY_SIZE(fs_mul); i++) { - if (rate < fs_mul[i].min || rate > fs_mul[i].max) - continue; - freq = rate * fs_mul[i].mul; - break; + if (data->tdm_mode) { + mode = data->slots * data->slot_width; + + for (i = 0; i < ARRAY_SIZE(fs_mul_tdm); i++) { + /* min = max = slots * slots_width */ + if (mode != fs_mul_tdm[i].min) + continue; + freq = rate * fs_mul_tdm[i].mul; + break; + } + } else { + for (i = 0; i < ARRAY_SIZE(fs_mul); i++) { + if (rate < fs_mul[i].min || rate > fs_mul[i].max) + continue; + freq = rate * fs_mul[i].mul; + break; + } } return freq; @@ -129,9 +153,13 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, } if (data->tdm_mode) { + /* 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, - 8, 32); + data->slots, data->slot_width); if (ret) { dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret); return ret; @@ -145,9 +173,13 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, return ret; } } else { + /* normal mode (I2S) */ + data->slots = 2; + data->slot_width = params_physical_width(params); + ret = snd_soc_dai_set_tdm_slot(cpu_dai, BIT(channels) - 1, BIT(channels) - 1, - 2, params_physical_width(params)); + data->slots, data->slot_width); if (ret) { dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret); return ret; |