ASoC: davinci-mcasp: Set BCLK divider if McASP is BCLK master
authorJyri Sarha <jsarha@ti.com>
Mon, 27 Jan 2014 15:37:52 +0000 (17:37 +0200)
committerMark Brown <broonie@linaro.org>
Mon, 27 Jan 2014 20:45:57 +0000 (20:45 +0000)
Make BCLK divider setting implicite in hw_params call if McASP device
is the bit clock master on the audio serial bus.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
sound/soc/davinci/davinci-mcasp.c

index b7858bfa0295357bc5d3ca6d1328932595167b9e..ae328beb676a9fd00d94ad1c964d396b60089d15 100644 (file)
@@ -53,6 +53,9 @@ struct davinci_mcasp {
        u16     bclk_lrclk_ratio;
        int     streams;
 
+       int     sysclk_freq;
+       bool    bclk_master;
+
        /* McASP FIFO related */
        u8      txnumevt;
        u8      rxnumevt;
@@ -292,6 +295,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
                mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
                mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+               mcasp->bclk_master = 1;
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
@@ -303,6 +307,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
                mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
                mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+               mcasp->bclk_master = 0;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                /* codec is clock and frame master */
@@ -314,6 +319,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
                mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
                               ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
+               mcasp->bclk_master = 0;
                break;
 
        default:
@@ -405,6 +411,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
        }
 
+       mcasp->sysclk_freq = freq;
+
        return 0;
 }
 
@@ -607,6 +615,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        int channels;
        struct snd_interval *pcm_channels = hw_param_interval(params,
                                        SNDRV_PCM_HW_PARAM_CHANNELS);
+
+       /* If mcasp is BCLK master we need to set BCLK divider */
+       if (mcasp->bclk_master) {
+               unsigned int bclk_freq = snd_soc_params_to_bclk(params);
+               if (mcasp->sysclk_freq % bclk_freq != 0) {
+                       dev_err(mcasp->dev, "Can't produce requred BCLK\n");
+                       return -EINVAL;
+               }
+               davinci_mcasp_set_clkdiv(
+                       cpu_dai, 1, mcasp->sysclk_freq / bclk_freq);
+       }
+
        channels = pcm_channels->min;
 
        active_serializers = (channels + slots - 1) / slots;