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));