This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x aplay error

I'm using a beaglebone black with an external audio codec. I have created a codec driver and added the following dai link into the davinci_evm machine driver

static struct snd_soc_dai_link zl380xx_evm_dai = {

.name = "zl380xx",
.stream_name = "mycodec",
.codec_dai_name = "mycodec-dai",
.init = mycodec_dac_init,    /*just a return 0 statement*/
.ops = &evm_ops,
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_IB_NF,
};

after insmod both my codec driver and the davinci_evm machine driver, I got a proper link and I can see the related sound card created properly

[ 4000.759739] davinci_evm ocp:sound: mycodec-dai <-> 48038000.mcasp mapping ok

However, whenever I tried to play an audio file I got the error below.  The Sitara processor is configured as TDM slave.

And I have a scope connected to the related P9.29 and P9.31 pins of the beagle bone, I can see the correct clock I2S clock and WS signals on the related pins.

Any idea to the root cause of this error?

root@beaglebone:/home# aplay -D hw:0,0 -r 16000 test16k.wav
Playing WAVE 'test16k.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Stereo
aplay: set_params:1297: Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 16000
PERIOD_TIME: 125000
PERIOD_SIZE: 2000
PERIOD_BYTES: 8000
PERIODS: 4
BUFFER_TIME: 500000
BUFFER_SIZE: 8000
BUFFER_BYTES: 32000
TICK_TIME: 0


[ 4053.874685] davinci_evm ocp:sound: ASoC: machine hw_params failed: -524

I'm using a debian distro on the beaglebone black with kernel

root@beaglebone:/home# uname -r
4.4.9-ti-r25

Here is the dts overlay that I have successfully loaded into the board

/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
/plugin/;

/ {
compatible = "ti,beaglebone-black";
part-number = "BB-AUDI-03";
version = "00A0";

/* state the resources this cape uses */
exclusive-use =
/* the pin header uses */
"P9.28", /* mcasp0: mcasp0_axr2 - TX*/
"P9.29", /* mcasp0: mcasp0_fsx - WS*/
"P9.30", /* mcasp0: mcasp0_axr0 - RX*/
"P9.31", /* mcasp0: mcasp0_aclkx - BCLK*/
/* the hardware IP uses */
"mcasp0";

fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {

mcasp0_pins: mcasp0_pins {
pinctrl-single,pins = <
0x198 0x20 /* mcasp0_axr0 , MODE0 | INPUT */
0x19c 0x02 /* mcasp0_axr2, MODE2 | OUTPUT*/
0x194 0x20 /* mcasp0_fsx, MODE0 | inPUT */
0x190 0x20 /* mcasp0_aclkr.mcasp0_aclkx, MODE0 | inPUT_PULLDOWN */
>;
};
};
};

fragment@2 {
target = <&ocp>;
__overlay__ {

/* dummy node for mycodec - to keep it sperate from SPI and to avoid warning*/
#address-cells = <1>;
#size-cells = <1>;

mycodec: mycodec@0 {
compatible = "ti,mycodec";
status = "okay";
};
};
};

fragment@3 {
target = <&mcasp0>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&mcasp0_pins>;

status = "okay";

op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
num-serializer = <16>;
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
2 0 1 0
0 0 0 0
0 0 0 0
0 0 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
};

fragment@4 {
target = <&ocp>;
__overlay__ {
sound {
compatible = "ti,mycodec-evm-audio";
ti,model = "DAC";
ti,audio-codec = <&mycodec>;
ti,mcasp-controller = <&mcasp0>;
ti,codec-clock-rate = <12288000>;

};
};
};
};

  • Please note that this forum supports only the TI distributed Linux SDK: www.ti.com/.../PROCESSOR-SDK-AM335X Debian is not supported by TI. Can you try with the latest SDK from TI?
  • We also using the same code on our platform based on the same Ti Sitara processor and a yocto filesystem built on the TI SDK that you pointed me to and we are both getting the same error.
  • I think the issue is related to the clock setting in the hw_params.
    My codec is being used as a master I2S device, it generates both the clock and WS signals. The sitara is the slave.
    My codec is generating the proper clocks and I can see them on the related pins of the Sitara.
    are the clock settings in the hw_params correct?


    static int evm_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
    {
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    struct snd_soc_card *soc_card = rtd->card;
    int ret = 0;
    unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
    snd_soc_card_get_drvdata(soc_card))->sysclk;

    /* set the codec system clock */
    ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    if (ret < 0)
    return ret;

    /* set the CPU system clock */
    ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    if (ret < 0)
    return ret;

    return 0;
    }
  • Hi,

    My codec is being used as a master I2S device, it generates both the clock and WS signals. The sitara is the slave.
    My codec is generating the proper clocks and I can see them on the related pins of the Sitara.


    You need to indicate this in davinci-evm.c, in the <codec>_evm_dai (the dai-link strucuture) there is a .dai_fmt parameter which indicates this, i.e.:
    .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    SND_SOC_DAIFMT_IB_NF,
    In your case you should use:
    SND_SOC_DAIFMT_CBM_CFM (indicates that codec is clock and frame master)

    Also currently in your code the following line:
    ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    shows that you will be using the internal 24 MHz clock as sysclk for the McASP, rather than using an external oscillator.

    Best Regards,
    Yordan
  • I have done all that, and still getting that same error.

    I think the reason for this error is that ALSA doesn't know how to divide that system clock. The machine code needs a call to snd_soc_dai_set_clkdiv()

    But I don't know what that clock divider should be.

    ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, divider id?, divider?);