[alsa-devel] Problem with MX27 ASoC audio

Randolph Chung rchung42 at gmail.com
Thu Aug 12 12:15:47 CEST 2010

I have a target that uses iMX27(L) + tlv320aic3x. The kernel tree is
HEAD of linux-arm from about a week ago.

Simple playback and recording (using aplay and arecord) work fine.
However, I've run into a strange problem when both playback and
capture streams are opened at the same time.

Consider the attached test program. The capture device is setup with a
period time of 10ms, and the program reads samples in a loop. The
expected result is that I get a sample every 10ms. This works fine if
the playback device is *not* opened (more specifically, if the
hw_params are not set). However if the playback device is opened (#if
1 code) then I get samples every 20ms, which seems very wrong.

I have tried using both DMA and FIQ ssi-pcm interfaces and both give
the same strange result. With the FIQ driver, if I instrument the
timer callback, the timer triggers every 10ms but there is only enough
data every 20ms.

The codec is being driven with a 13MHz MCLK (output from MX27) and the
BCLK and WCLK come from the codec. They seem to have the correct

Any ideas? Can anybody else with MX27 hardware verify if my test
program also fails on their target?


/* Test program */

#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>

int main(int argc, char **argv)
    int err = -1;
    char buf[4096];
    unsigned long period_size;
    snd_pcm_t *in_handle = NULL, *out_handle;
    snd_pcm_hw_params_t *hwparams;

    if (snd_pcm_open(&in_handle, "hw:0,0", SND_PCM_STREAM_CAPTURE, 0) < 0) {
        printf("Cannot open capture device\n");
        return -1;
    snd_pcm_hw_params_any(in_handle, hwparams);
    snd_pcm_hw_params_set_access(in_handle, hwparams,
    snd_pcm_hw_params_set_format(in_handle, hwparams, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(in_handle, hwparams, 1);
    snd_pcm_hw_params_set_rate(in_handle, hwparams, 8000, 0);
    snd_pcm_hw_params_set_period_time(in_handle, hwparams, 10000, 0);
    snd_pcm_hw_params_get_period_size(hwparams, &period_size, 0);
    snd_pcm_hw_params(in_handle, hwparams);

    if (snd_pcm_open(&out_handle, "hw:0,0", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        printf("Cannot open playback device\n");
        return -1;
#if 1
    snd_pcm_hw_params_any(out_handle, hwparams);
    snd_pcm_hw_params_set_access(out_handle, hwparams,
    snd_pcm_hw_params_set_format(out_handle, hwparams, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(out_handle, hwparams, 1);
    snd_pcm_hw_params_set_rate(out_handle, hwparams, 8000, 0);
    snd_pcm_hw_params_set_period_time(out_handle, hwparams, 10000, 0);
    snd_pcm_hw_params(out_handle, hwparams);

    printf("period size = %u\n", period_size);

    printf("Config done, start loop\n");
    while (1) {
        struct timeval tv;
        int ret = snd_pcm_readi(in_handle, buf, period_size);
        if (ret < 0)
        gettimeofday(&tv, NULL);
        printf("[%u.%06u] snd_pcm_readi() return %d\n",
            tv.tv_sec, tv.tv_usec, ret);

    return 0;

More information about the Alsa-devel mailing list