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.

Linux/AM3352: McASP configuration for dummy codec

Part Number: AM3352
Other Parts Discussed in Thread: TLV320AIC33, AM3358,

Tool/software: Linux

Hi,

I am trying to make an 8 slot tdm rx/tx with mcasp.  We are going to connect a  fpga, so we don't need a codec. Below shows my dts file.  I used a dummy codec but i was not able to get the davince-mcasp.c file to print out any logs.  It appears that the dummy codec doesn't make the connection to the mcasp drivers. Any ideas why the connection is missing?

    codec_test: codec_test {
        compatible = "linux,snd-soc-dummy";
        #sound-dai-cells = <0>;
        status="okay";
    };

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "AM335x-TDM";
//        simple-audio-card,format = "dsp_a";
        simple-audio-card,format = "dsp_b";
//        simple-audio-card,format = "i2c";
        simple-audio-card,frame-master = <&sound_master>;
        simple-audio-card,bitclock-master = <&sound_master>;
//        simple-audio-card,bitclock-inversion;
//        system-clock-frequency = <24000000>;
//        system-clock-direction = "out";
        status="okay";

        sound_master: simple-audio-card,cpu {
            sound-dai = <&mcasp0>;
            system-clock-frequency = <24000000>;
            system-clock-direction = "out";

            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };

        sound_master1: simple-audio-card,codec {
//            sound-dai = <&tlv320aic3x>;
            sound-dai = <&codec_test>;
        };
    };

    mcasp0_pins: mcasp0_pins {
        pinctrl-single,pins = < /**/
            0x120 ( PIN_INPUT_PULLDOWN  | MUX_MODE6 ) /* (N18) gmii1_txd2.mcasp0_ahclkx */
            0x12c ( PIN_INPUT_PULLDOWN  | MUX_MODE6 ) /* (N19) gmii1_txclk.mcasp0_aclkx */
            0x130 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (M19) gmii1_rxclk.mcasp0_fsx */
            0x134 ( PIN_OUTPUT_PULLDOWN | MUX_MODE6 ) /* (N17) gmii1_col.mcasp0_axr0 */
            0x138 ( PIN_INPUT_PULLDOWN  | MUX_MODE6 ) /* (N16) gmii1_rxd0.mcasp0_axr1 */
        >;

&i2c0 {
    pinctrl-names = "default";
    pinctrl-0 = <&i2c0_pins>;
    clock-frequency = <100000>;
    status = "okay";

    tlv320aic3x: tlv320aic3x@1b {
        compatible = "ti,tlv320aic3x";
        reg = <0x1b>;
        #sound-dai-cells = <0>;

        status = "okay";
    };

/*    tlv320aic33: tlv320aic33@1b {
        compatible = "ti,tlv320aic33";
        reg = <0x1b>;
        #sound-dai-cells = <0>;

        status = "okay";
    }; */

};

&mcasp0 {
    #sound-dai-cells = <0>;
    pinctrl-names = "default";
    pinctrl-0 = <&mcasp0_pins>;

    status = "okay";

    op-mode = <0>;          /* 0: MCASP_IIS_MODE, 1: DIT */
    tdm-slots = <8>;

    /* 4 serializers */
    serial-dir = <        /* 0: INACTIVE, 1: TX, 2: RX */
        1 2 0 0        /* AXR0 AXR1 AXR2 AXR3 */
    >;
    tx-num-evt = <32>;
    rx-num-evt = <32>;
};

Rob

  • Hi Rob,

    Refer to the below e2e thread regarding dummy codec configuration:

    e2e.ti.com/.../2461361
    e2e.ti.com/.../2464720

    Regards,
    Pavel
  • I had already looked through all of those posts before I asked for help. They only helped as an overview.

    We are using am3352 and the am3358 controllers. The mcasp peripheral has built-in tdm functionality, so it was chosen.

    Here is what I needed to do. My project required a 8 slot tdm and no codec. I implemented the dts using simple-card sound device. First I configured my kernel config with:

    CONFIG_SND
    CONFIG_SND_SIMPLE_CARD
    CONFIG_SND_HWDEP
    CONFIG_SND_TIMER
    CONFIG_SND_PCM
    CONFIG_SND_RAWMIDI
    CONFIG_SND_SOC
    CONFIG_SND_EDMA_SOC
    CONFIG_SND_DAVINCI_SOC
    CONFIG_SND_DAVINCI_SOC_MCASP

    The davinci soc sound drivers were chosen for the mcasp.

    Next, the dts file needed to be modified. I have not worked with the Linux kernel since the 2.6.32 version. The dts and CONFIG_OF (open firmware) implementation was new to me. The dts is driver configuration file for the kernel at boot. The CONFIG_OF parses the parameters in the dts (really the dtb). Here the links for the dts parameters in the kernel (github.com/.../devicetree). I found looking through the dtsi files, kernel docs and post about the dts online very helpful. The dts file gets compiled into the dtb (device tree blob/block). The dtb is the file used at boot. It is useful to decompile the dtb; it shows exactly what you are configuring. The dtsi files are include files which also have useful info about your processor.

    Also, ti's pin mux tool is very useful for configuring pins in the dts file.

    Here is my dts for mcasp:

    / {

    codec_test: codec_test {
    compatible = "linux,snd-soc-dummy";
    #sound-dai-cells = <0>;
    status="okay";
    };


    // am335x is the clock master (mclk, bit and frame clks)
    // sound {
    // compatible = "simple-audio-card";
    // simple-audio-card,name = "AM335x-TDM";
    // simple-audio-card,format = "dsp_b";
    // simple-audio-card,frame-master = <&sound_master>;
    // simple-audio-card,bitclock-master = <&sound_master>;
    // status="okay";
    //
    // sound_master: simple-audio-card,cpu {
    // sound-dai = <&mcasp0>;
    // system-clock-frequency = <24000000>;
    // system-clock-direction = "out";
    //
    // dai-tdm-slot-num = <8>;
    // dai-tdm-slot-width = <16>;
    // };
    //
    // simple-audio-card,codec {
    // sound-dai = <&codec_test>;
    // };
    // };
    // };

    // am335x is the clock slave (bit and frame clks, mclk not needed)
    sound {
    compatible = "simple-audio-card";
    simple-audio-card,name = "AM335x-TDM";
    simple-audio-card,format = "dsp_b";
    simple-audio-card,frame-master = <&sound_master>;
    simple-audio-card,bitclock-master = <&sound_master>;
    status="okay";

    simple-audio-card,cpu {
    sound-dai = <&mcasp0>;
    system-clock-direction = "in";
    // bitclock-inversion;

    dai-tdm-slot-num = <8>;
    dai-tdm-slot-width = <16>;
    };

    sound_master: simple-audio-card,codec {
    sound-dai = <&codec_test>;
    };

    };
    };

    &am33xx_pinmux {
    pinctrl-names = "default";
    pinctrl-0 = <&triac_pins>, <&clkout1_pin>,
    <&universal_in_pins>, <&unused_pins>;

    mcasp0_pins: mcasp0_pins {
    pinctrl-single,pins = < /**/
    // clk master
    /* 0x120 ( PIN_OUTPUT_PULLDOWN | MUX_MODE6 ) /* (N18) gmii1_txd2.mcasp0_ahclkx */
    /* 0x12c ( PIN_OUTPUT_PULLDOWN | MUX_MODE6 ) /* (N19) gmii1_txclk.mcasp0_aclkx */
    /* 0x130 ( PIN_OUTPUT_PULLDOWN | MUX_MODE6 ) /* (M19) gmii1_rxclk.mcasp0_fsx */

    // clk slave
    0x120 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (N18) gmii1_txd2.mcasp0_ahclkx */
    0x12c ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (N19) gmii1_txclk.mcasp0_aclkx */
    0x130 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (M19) gmii1_rxclk.mcasp0_fsx */

    // data lines
    0x134 ( PIN_OUTPUT_PULLDOWN | MUX_MODE6 ) /* (N17) gmii1_col.mcasp0_axr0 */
    0x138 ( PIN_INPUT_PULLDOWN | MUX_MODE6 ) /* (N16) gmii1_rxd0.mcasp0_axr1 */
    >; /**/

    };
    };

    &mcasp0 {
    #sound-dai-cells = <0>;
    pinctrl-names = "default";
    pinctrl-0 = <&mcasp0_pins>;

    status = "okay";

    op-mode = <0>; /* 0: MCASP_IIS_MODE, 1: DIT */
    tdm-slots = <8>;

    /* 4 serializers */
    serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
    1 2 0 0 /* AXR0 AXR1 AXR2 AXR3 */
    >;
    tx-num-evt = <32>;
    rx-num-evt = <32>;
    };

    In each driver, there is a CONFIG_OF section that parses the dtb for the driver. The function name usually has _of at the end of the name. Look here to see if the parameters in the kernel docs are implemented.

    There are 2 patches that I needed to apply for this configuration for the above dts:

    This patch allows the system-clock-direction = "in | out". By default it is "in", but the am335x clock master mode wouldn't work unless this patch is applied.
    www.spinics.net/.../msg46431.html

    This patch extends the linux-soc-dummy so a codec isn't needed.
    patchwork.kernel.org/.../

    Howto use alsa with many channels:
    I used a non-interleaved implementation. I didn't add all the code, since there are many examples on the internet. I was not able to change the parameters on the embedded linux like I can on my pc. I assume this is limitations in the embedded world. The parameters listed below are the only ones that I could change.

    devName = "plughw:0,0"; // i could not use "hw:0,0"
    snd_pcm_open(&hndl, devNam.c_str(), SND_PCM_STREAM_PLAYBACK, 0);

    ret = snd_pcm_hw_params_set_rate_resample(hndl, pHwParms, 1); // this had to be 1 or it doesn't work

    ret = snd_pcm_hw_params_set_access(mhndl, pHwParms, SND_PCM_ACCESS_RW_INTERLEAVED);

    ret = snd_pcm_hw_params_set_format(hndl, pHwParms, SND_PCM_FORMAT_S16_LE);

    ret = snd_pcm_hw_params_set_channels(hndl, pHwParms, 8);

    samp = 24000;
    ret = snd_pcm_hw_params_set_rate_near(hndl, pHwParms, &samp, NULL); // had to use near or couldn't set sample rate

    // it would not let me set/get buffer size or periods, so i picked values that were allowed in the driver. Maybe, min/max functions associated with periods and buffer size would work. I didn't try.

    bufSiz = 64k;
    persiods = 16;
    frame = bufSiz / periods;
    uint8_t *pBuf[8];
    ret = snd_pcm_writen(m_Hndl, pBuf, frame);