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

    i2s_accurate_sck switch can be used to have a better approximate
    sampling frequency.
    The clock is an externally visible bit clock and it is named
    i2s continuous serial clock (I2S_SCK).
    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 |   33 ++++++++++++++++++++++++++++++
 sound/soc/davinci/davinci-i2s.c          |   24 +++++++++++++++++----
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/asp.h 
b/arch/arm/mach-davinci/include/mach/asp.h
index 0847d21..b12c69e 100644
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ b/arch/arm/mach-davinci/include/mach/asp.h
@@ -73,6 +73,39 @@ struct snd_platform_data {
         */
        int clk_input_pin;
 
+       /*
+        * This flag works when both clock and FS are outputs for the cpu
+        * and makes clock more accurate (FS is not symmetrical and the
+        * clock is very fast.
+        * The clock becoming faster is named
+        * i2s continuous serial clock (I2S_SCK) and it is an externally
+        * visible bit clock.
+        *
+        * first line : WordSelect
+        * second line : ContinuousSerialClock
+        * third line: SerialData
+        *
+        * SYMMETRICAL APPROACH:
+        *   _______________________          LEFT
+        * _|         RIGHT         |______________________|
+        *     _   _         _   _   _   _         _   _
+        *   _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_
+        *     _   _         _   _   _   _         _   _
+        *   _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_
+        *    \_/ \_/       \_/ \_/ \_/ \_/       \_/ \_/
+        *
+        * ACCURATE CLOCK APPROACH:
+        *   ______________          LEFT
+        * _|     RIGHT    |_______________________________|
+        *     _         _   _         _   _   _   _   _   _
+        *   _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| |
+        *     _         _   _          _      dummy cycles
+        *   _/ \_ ... _/ \_/ \_  ... _/ \__________________
+        *    \_/       \_/ \_/        \_/
+        *
+        */
+       bool i2s_accurate_sck;
+
        /* 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 ba5644b..b251bc9 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -155,6 +155,7 @@ 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,
@@ -447,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;
@@ -662,6 +675,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_sck = pdata->i2s_accurate_sck;
        }
        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