From: Raffaele Recalcati <raffaele.recalc...@bticino.it>

    i2s_accurate_clock switch can be used to have a better approximate
    frequency.
    The trade off is between more accurate clock (fast clock)
    and less accurate clock (slow clock).
    The waveform will be not symmetric.
    Probably it is possible to get a better algorithm for calculating
    the divider, trying to keep a slower clock as possible.

    This patch has been developed against the
        http://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci.git
    git tree and has been tested on bmx board (similar to dm365 evm, but using
    uda1345 as external audio codec).

Signed-off-by: Raffaele Recalcati <raffaele.recalc...@bticino.it>
Signed-off-by: Davide Bonfanti <davide.bonfa...@bticino.it>
---
 arch/arm/mach-davinci/include/mach/asp.h |    7 +++++++
 sound/soc/davinci/davinci-i2s.c          |   20 ++++++++++++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/asp.h 
b/arch/arm/mach-davinci/include/mach/asp.h
index 0847d21..21c886e 100644
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ b/arch/arm/mach-davinci/include/mach/asp.h
@@ -73,6 +73,13 @@ struct snd_platform_data {
         */
        int clk_input_pin;
 
+       /*
+        * This define works when both clock and FS are output for the cpu
+        * and makes clock more accurate (FS is not symmetrical and the
+        * clock is very fast.
+        */
+       bool i2s_accurate_clock;
+
        /* McASP specific fields */
        int tdm_slots;
        u8 op_mode;
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 17f594f..2fb1209 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -154,6 +154,7 @@ struct davinci_mcbsp_dev {
        unsigned int fmt;
        int clk_div;
        int clk_input_pin;
+       bool i2s_accurate_clock;
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -447,6 +448,24 @@ 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);
+               if (dev->i2s_accurate_clock) {
+                       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);
+               }
+
                /* symmetric waveforms */
                clk_div = freq / (mcbsp_word_length * 16) /
                          params->rate_num * params->rate_den;
@@ -662,6 +681,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
                dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
                        pdata->sram_size_capture;
                dev->clk_input_pin = pdata->clk_input_pin;
+               dev->i2s_accurate_clock = pdata->i2s_accurate_clock;
        }
        dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
-- 
1.7.0.4

_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to