Adding a new DAC
From Ubicom Developer
Contents |
Introduction
The purpose of this page is to describe the process of adding a new audio DAC to the existing Ubicom reference design. This document walks through the different hardware and software pieces that may need to be changed in order to support a new DAC.
Board Requirements
Most audio DACs share common interfaces and signals. This section walks through some of the different board level requirements.
Interfaces
Two types of interfaces commonly found on audio DACs are I2S and I2C. I2S is a standard interface for communicating digital audio and I2C is a common standard for inter-chip communication. A third interface type can be S/PDIF, though this interface either does not require a DAC or is an interface with a high-end DAC.
I2S & I2C
I2S has three signals:
1. SCLK - bit clock (sample width * sample rate)
2. LRCLK - word clock (sample rate)
3. SDIN - serial audio data
- note: SCLK and LRCLK should be on the same port.
I2C has two signals:
1. SCL - clock
2. SDA - serial data
I2C also has one other requirement. Because I2C is a master/slave bus, the slave device must have its own address. This address can be found from the datasheet of the DAC or can even be changed based on pull-ups/downs placed on the board. In the picture above, there are two pins on the DAC to allow for four different addresses.
S/PDIF
SPIDF is a format that can be used as either a direct output from the system (through either an optical transmitter or electrical connector) or an interface with a higher end DAC. In the case of S/PDIF, the clock is embedded into the data signal, requiring only one output pin to implement the interface.
DAC clocking
The DAC, however, must have its own clock to run its internal circuitry. Some have internal PLLs that multiply off of an external signal (the LRCLK for instance) and some require an external master clock to drive the DAC's internal circuitry. If the new part requires an external signal, the appropriate clock pins must be used on the Ubicom IP7K.
MCLK options (please note that these pins must be available):
1. PA5 - PWM0. Divided off the IO clock frequency (typically set at 500MHz).
2. PE4 - PWM1. Divided off the IO clock frequency (typically set at 500MHz).
3. PD0 - PWM2. Divided off the IO clock frequency (typically set at 500MHz).
4. PA7 - CLKDIV. Divided off the core clock frequency (see tables below).
Frequency Requirements
The Ubicom IP7K is quite flexible and allows for several clocking schema for I2S. I2S does not specify the exact setup and hold times for the different signals, so the designer must understand if their DAC supports the asymmetric clock scheme outlined below. The DACs used in the Ubicom reference design all support asymmetric timing.
The table below shows the Asymmetric I2S output from IP7K. This means that the duty cycle of the LRCLK and SCLK are not exactly 50%. The output will be very close to symmetrical (within 5%) and guaranteed to not be less than 44%.
| Ubicom Processor | I2S Sample Rates | Required Core Clock Frequency |
| IP7540 | 44100 & 48000 | 394MHz |
| IP7550 | 44100 & 48000 | 501MHz |
| IP7560 | 44100 & 48000 | 542MHz |
The table below outlines the different frequencies if the DAC requires symmetric timing.
| Ubicom Processor | I2S Sample Rates | Required Core Clock Frequency |
| IP7540 | 44100 | 383MHz |
| IP7540 | 48000 | 393MHz |
| IP7550 | 44100 | 496MHz |
| IP7550 | 48000 | 467/492MHz |
| IP7560 | 44100 & 48000 | 542MHz |
| Ubicom Processor | SPDIF Samples Rates | Required Core Clock Frequency |
| IP7540 | 44100 | 361MHz |
| IP7540 | 48000 | 393MHz |
| IP7550 | 44100 | 497MHz |
| IP7550 | 48000 | 492MHz |
| IP7560 | 44100 & 48000 | 541MHz |
Ultra Parameters
This section is outlines the parameters that must be set in the ultra project (or board file) in order to achieve the appropriate I2S timing. For details on how to edit the ultra portion of the Ubicom distro, please read this.
| Ubicom Processor | Audio Rate | HRT Spacing | I2S Sample Rate |
| IP7540 | 44100 48000 | 16 | 44100/48000 |
| IP7550 | 44100 48000 | 32 | 44100/48000 |
| IP7560 | 44100 48000 | 32 | 44100/48000 |
| Ubicom Processor | Audio Rate | HRT Spacing | I2S Sample Rate |
| IP7540 | 17 | 8 | 44100 |
| IP7540 | 16 | 8 | 48000 |
| IP7550 | 11 | 16 | 44100 |
| IP7550 | [19] 5 | [8] 32 | 48000 - [467] 492 |
| IP7560 | 6 | 32 | 44100 |
| IP7560 | 11 | 16 | 48000 |
| Ubicom Processor | Audio Rate | HRT Spacing | SPDIF Sample Rate |
| IP7540 | 4 | 16 | 44100 |
| IP7540 | 4 | 16 | 48000 |
| IP7550 | 11 | 8 | 44100 |
| IP7550 | 5 | 16 | 48000 |
| IP7560 | 11 & 12 | 8 | 44100 & 48000 |
Linux Driver Work
This section outlines the changes needed within the Ubicom Linux Distribution in order for ALSA to recognize the new audio DAC.
An ALSA driver must be written in order for Linux to correctly initialize the audio DAC. This document will not go into detail on how to write a driver. Please see the following files for examples on how to write a DAC driver (the datasheet must be consulted closely for the register and data settings).
~/ubicom-distro/linux-2.6.x/sound/ubicom32/ubi32-generic.c
~/ubicom-distro/linux-2.6.x/sound/ubicom32/ubi32-cs4350.c
~/ubicom-distro/linux-2.6.x/sound/ubicom32/ubi32-cs4384.c
~/ubicom-distro/linux-2.6.x/arch/ubicom32/include/asm/ubi32-cs4384.h - contains platform options for mclk
The Linux board file must be changed in order to initialize the appropriate ALSA driver. The two key components are the I2C device address and the audio_device_alloc.
- Note: the new audio DAC must be correctly configured in linux_menuconfig and compiled into the kernel. Please run \> make linux_menuconfig from the distro root directory to select the appropriate sound card driver.
~/ubicom-distro/linux-2.6.x/arch/ubicom32/mach-ip7k/board-ip7500iap.c
...
static struct i2c_board_info __initdata ip7500iap_i2c_board_info[] = {
/*
* U6, GENERIC DAC, address 0x4B
*/
{
.type = "generic",
.addr = 0x4B,
},
...
/*
* ip7500iap_init
* Called to add the devices which we have on this board
*/
static int __init ip7500iap_init(void)
{
...
/*
* Bring up audio devices
*/
platform_add_devices(ip7500iap_devices, ARRAY_SIZE(ip7500iap_devices));
audio_dev = audio_device_alloc("snd-ubi32-generic", "audio", "audio-i2sout", sizeof(struct ubi32_generic_platform_data));
if (audio_dev) {
ip7500iap_i2c_board_info[0].platform_data = audio_dev;
}
...
If the Audio DAC requires the IP7K to supply a master clock, the following additions must be made to the linux board file:
~/ubicom-distro/linux-2.6.x/arch/ubicom32/mach-ip7k/board-ip7500av.c
...
#include <asm/ubi32-pcm.h>
#include <asm/ubi32-cs4384.h>
...
/*
* List of possible mclks we can generate. This depends on the CPU frequency.
*/
static struct ubi32_cs4384_mclk_entry ip7500av_cs4384_mclk_entries[] = {
{
.rate = 12288000,
.div = 44,
},
{
.rate = 11289600,
.div = 48,
},
};
...
/*
* ip7500av_init
* Called to add the devices which we have on this board
*/
static int __init ip7500av_init(void)
{
struct platform_device *audio_dev;
struct ubi32_cs4384_platform_data *cs4384_pd;
/*
* CS4384 DAC
*/
audio_dev = audio_device_alloc("snd-ubi32-cs4384", "audio", "audio-i2sout", sizeof(struct ubi32_cs4384_platform_data));
if (audio_dev) {
/*
* Attempt to figure out a good divisor. This will only work
* assuming the core frequency is compatible.
*/
int i;
unsigned int freq = processor_frequency();
for (i = 0; i < ARRAY_SIZE(ip7500av_cs4384_mclk_entries); i++) \
{
unsigned int div;
unsigned int rate = ip7500av_cs4384_mclk_entries[i].rat\
e / 1000;
div = ((freq / rate) + 500) / 1000;
ip7500av_cs4384_mclk_entries[i].div = div;
printk("CS4384 mclk %d rate %u000Hz div %u act %u\n", i\
, rate, div, freq / div);
}
cs4384_pd = audio_device_priv(audio_dev);
cs4384_pd->mclk_src = UBI32_CS4384_MCLK_PWM_0;
cs4384_pd->n_mclk = ARRAY_SIZE(ip7500av_cs4384_mclk_entries);
cs4384_pd->mclk_entries = ip7500av_cs4384_mclk_entries;
ip7500av_i2c_board_info[0].platform_data = audio_dev;
}
...
Porting Confirmation
If the processor is able to communicate with the DAC over I2C, then the following boot messages will confirm proper porting (assuming the same coding/debugs are used in the new audio DAC as in the Ubicom reference drivers):
[ 2.960000] Advanced Linux Sound Architecture Driver Version 1.0.18rc3. [ 2.960000] Ubi32PCM: channels_min:1 channels_max:2 [ 2.960000] Ubi32PCM: rates:80000055 min:5512 max:44100 count:24 fmts:000000000000000c (playback) [ 2.970000] ALSA device list: [ 2.970000] #0: Ubi32-Generic at sendirq=14.0 recvirq=13.0 regs=400ffd7c


