]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/soc/davinci/davinci-i2s.c
Merge git://git.infradead.org/users/dwmw2/libraid-2.6 into for-linus
[mv-sheeva.git] / sound / soc / davinci / davinci-i2s.c
index c8f038cb4c5e5a154519cd2bc17d2c80960f5aea..9e8932abf158b7f8d22660081fd73183a73a4469 100644 (file)
@@ -122,6 +122,7 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
 };
 
 struct davinci_mcbsp_dev {
+       struct device *dev;
        struct davinci_pcm_dma_params   dma_params[2];
        void __iomem                    *base;
 #define MOD_DSP_A      0
@@ -153,6 +154,8 @@ struct davinci_mcbsp_dev {
 
        unsigned int fmt;
        int clk_div;
+       int clk_input_pin;
+       bool i2s_accurate_sck;
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -279,11 +282,26 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                        DAVINCI_MCBSP_PCR_CLKRM;
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
-               /* McBSP CLKR pin is the input for the Sample Rate Generator.
-                * McBSP FSR and FSX are driven by the Sample Rate Generator. */
-               pcr = DAVINCI_MCBSP_PCR_SCLKME |
-                       DAVINCI_MCBSP_PCR_FSXM |
-                       DAVINCI_MCBSP_PCR_FSRM;
+               pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;
+               /*
+                * Selection of the clock input pin that is the
+                * input for the Sample Rate Generator.
+                * McBSP FSR and FSX are driven by the Sample Rate
+                * Generator.
+                */
+               switch (dev->clk_input_pin) {
+               case MCBSP_CLKS:
+                       pcr |= DAVINCI_MCBSP_PCR_CLKXM |
+                               DAVINCI_MCBSP_PCR_CLKRM;
+                       break;
+               case MCBSP_CLKR:
+                       pcr |= DAVINCI_MCBSP_PCR_SCLKME;
+                       break;
+               default:
+                       dev_err(dev->dev, "bad clk_input_pin\n");
+                       return -EINVAL;
+               }
+
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                /* codec is master */
@@ -430,11 +448,23 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                       DAVINCI_MCBSP_SRGR_CLKSM;
                srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
                                                8 - 1);
-               /* symmetric waveforms */
-               clk_div = freq / (mcbsp_word_length * 16) /
-                         params->rate_num * params->rate_den;
-               srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
-                                               16 - 1);
+               if (dev->i2s_accurate_sck) {
+                       clk_div = 256;
+                       do {
+                               framesize = (freq / (--clk_div)) /
+                               params->rate_num *
+                                       params->rate_den;
+                       } while (((framesize < 33) || (framesize > 4095)) &&
+                                (clk_div));
+                       clk_div--;
+                       srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
+               } else {
+                       /* symmetric waveforms */
+                       clk_div = freq / (mcbsp_word_length * 16) /
+                                 params->rate_num * params->rate_den;
+                       srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
+                                                       16 - 1);
+               }
                clk_div &= 0xFF;
                srgr |= clk_div;
                break;
@@ -618,6 +648,8 @@ static int davinci_i2s_probe(struct platform_device *pdev)
        struct snd_platform_data *pdata = pdev->dev.platform_data;
        struct davinci_mcbsp_dev *dev;
        struct resource *mem, *ioarea, *res;
+       enum dma_event_q asp_chan_q = EVENTQ_0;
+       enum dma_event_q ram_chan_q = EVENTQ_1;
        int ret;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -644,7 +676,17 @@ static int davinci_i2s_probe(struct platform_device *pdev)
                        pdata->sram_size_playback;
                dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
                        pdata->sram_size_capture;
+               dev->clk_input_pin = pdata->clk_input_pin;
+               dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
+               asp_chan_q = pdata->asp_chan_q;
+               ram_chan_q = pdata->ram_chan_q;
        }
+
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q   = asp_chan_q;
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q   = ram_chan_q;
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q    = asp_chan_q;
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q    = ram_chan_q;
+
        dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                ret = -ENODEV;
@@ -676,6 +718,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
                goto err_free_mem;
        }
        dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
+       dev->dev = &pdev->dev;
 
        davinci_i2s_dai.private_data = dev;
        davinci_i2s_dai.capture.dma_data = dev->dma_params;