Welcome to AVR32 Linux... Users Groups

AtmelAbdacDriver

The ABDAC ALSA sound driver was submitted for the initial review to the ALSA developmen list, see this email thread http://mailman.alsa-project.org/pipermail/alsa-devel/2009-February/014500.html This mean however that you need to be working on a Linux kernel version 2.6.29-rc3 or later, and have patches for DW DMAC cyclic DMA API which can be grabbed from http://avr32linux.org/archives/kernel/2009-February/002088.html + http://avr32linux.org/archives/kernel/2009-February/002087.html

How to enable it

Board code

You need to add a small snippet of board code to add the platform device for you board. This could be something like the following:

#include <mach/board.h>
static struct at32_abdac_pdata __initdata abdac0_data = {
};

And then later in the postcore_initcall(...) add:

at32_add_device_abdac(0, &abdac0_data);

See the file arch/avr32/mach-at32ap/include/mach/board.h for more information about the struct aat32_abdac_pdata passed to the machine code.

Select the driver in the kernel config

In menuconfig the driver is located in

Device Drivers  --->
  Sound card support  --->
    Advanced Linux Sound Architecture  --->
      AVR32 devices  --->
        Atmel AVR32 Audio Bitstream DAC (ABDAC) support

After selecting it as builtin or module do a compile and install to target. When the driver probes it will examine which features are available in the external codec and setup mixer, playback and capture accordingly.

Enhancing the sample rate accuracy to a specific bitrate

It is recommended to use a sample rate clock with a frequency matching most sound files. Today most sound files uses either 44.1 kHz or 48 kHz. The example below shows how to setup PLL1 to provide a suitable frequency to the generic clock providing the sample rate to the ABDAC module.

Add the following helper function in your board code:

static int __init set_abdac_rate(struct platform_device *pdev)
{
   int retval;
   struct clk *osc1;
   struct clk *pll1;
   struct clk *abdac;

   if (pdev == NULL)
      return -ENXIO;

   osc1 = clk_get(NULL, "osc1");
   if (IS_ERR(osc1)) {
      retval = PTR_ERR(osc1);
      goto out;
   }

   pll1 = clk_get(NULL, "pll1");
   if (IS_ERR(pll1)) {
      retval = PTR_ERR(pll1);
      goto out_osc1;
   }

   abdac = clk_get(&pdev->dev, "sample_clk");
   if (IS_ERR(abdac)) {
      retval = PTR_ERR(abdac);
      goto out_pll1;
   }

   retval = clk_set_parent(pll1, osc1);
   if (retval != 0)
      goto out_abdac;

   /*
    * Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in
    * power of 2, to a value above 80 MHz. Power of 2 so it is possible
    * for the generic clock to divide it down again and 80 MHz is the
    * lowest frequency for the PLL.
    */
   retval = clk_round_rate(pll1, 48000 * 256 * 16);
   if (retval < 0)
      goto out_abdac;

   retval = clk_set_rate(pll1, retval);
   if (retval != 0)
      goto out_abdac;

   retval = clk_set_parent(abdac, pll1);
   if (retval != 0)
      goto out_abdac;

out_abdac:
   clk_put(abdac);
out_pll1:
   clk_put(pll1);
out_osc1:
   clk_put(osc1);
out:
   return retval;
}

And then use it when adding the platform device in the postcore_initcall(...):

set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
r1 - 2009-02-04 - 12:30:21 - HansChristianEgtvedt
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.
Atmel®, AVR® and others are registered trademarks or trademarks of Atmel Corporation or its subsidiaries.
All other trademarks are the property of their respective owners.
Syndicate this site RSSATOM