ASoC: ti: davinci-i2s: Add handling of BP_FC format
authorBastien Curutchet <bastien.curutchet@bootlin.com>
Tue, 2 Apr 2024 07:12:08 +0000 (09:12 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 9 Apr 2024 15:58:39 +0000 (16:58 +0100)
McBSP is able to drive bit clock and consume frame clock but BP_FC
format is not handled by McBSP driver.

Add BP_FC format support.
When BP_FC is selected:
  - CLKX and CLKR are configured as outputs
  - The sample rate generator is configured to be able to provide bit
    clock.

Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Link: https://msgid.link/r/20240402071213.11671-9-bastien.curutchet@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/ti/davinci-i2s.c

index f9a67c2bc2f553aedc706527e6f6e298be38d1d9..e51f05cda941032a7abe3275001d94c2e64accd2 100644 (file)
@@ -310,6 +310,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;
                pcr |= DAVINCI_MCBSP_PCR_SCLKME;
                break;
+       case SND_SOC_DAIFMT_BP_FC:
+               /* cpu is bitclock provider */
+               pcr = DAVINCI_MCBSP_PCR_CLKXM |
+                       DAVINCI_MCBSP_PCR_CLKRM;
+               break;
+
        case SND_SOC_DAIFMT_BC_FC:
                if (dev->tdm_slots || dev->slot_width) {
                        dev_err(dev->dev, "TDM is not supported for BC_FC format\n");
@@ -500,6 +506,23 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                clk_div &= 0xFF;
                srgr |= clk_div;
                break;
+       case SND_SOC_DAIFMT_BP_FC:
+               if (dev->ext_clk) {
+                       freq = clk_get_rate(dev->ext_clk);
+               } else {
+                       freq = clk_get_rate(dev->clk);
+                       srgr = DAVINCI_MCBSP_SRGR_CLKSM;
+               }
+               if (dev->tdm_slots && dev->slot_width) {
+                       clk_div = freq / (params->rate_num * params->rate_den)
+                                / (dev->tdm_slots * dev->slot_width) - 1;
+               } else {
+                       clk_div = freq / (mcbsp_word_length * 16) /
+                                 params->rate_num * params->rate_den;
+               }
+               clk_div &= 0xFF;
+               srgr |= clk_div;
+               break;
        case SND_SOC_DAIFMT_BC_FC:
                /* Clock and frame sync given from external sources */
                i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);