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.

How to define multiple audio devices in device tree sound node

Other Parts Discussed in Thread: PCM5102A, PCM3168A, PCM3168

Hi,

I have followed the following guide to port and connect a new audio card device (lets say TI PCM5102a Codec) to McASP for my Sitara based HW: http://processors.wiki.ti.com/index.php/Sitara_Linux_SDK_Audio_DAC_Example

I have the first audio card connected to McASP0 and I can stream audio data to it fine.

Now I am trying to port and register a second card that is connected to McASP1 (let's say the multiple channels TI PCM3168a Codec). I have the kernel driver in place in /sound/soc/codecs and sound/soc/davinci as guided by the example in TI link above, but, I am not sure how to define the second card in the sound node in my am335x device tree file (.dts). Here is my first sound card node in the device tree which works fine:

 pcm5102a: pcm5102a {
compatible = "ti,pcm5102a";
};
 
sound {
compatible = "ti,pcm5102a-evm-audio";
ti,model = "TI PCM5102A";
ti,audio-codec = <&pcm5102a>;
ti,mcasp-controller = <&mcasp0>;
ti,codec-clock-rate = <24000000>;

 };

Question: how to add the second audio card (connect to the second McASP port mcasp1 ) into the sound node in the kernel device tree? any examples?

  • Hi,

    I will ask the software team to help on this.
  • Hi,

    Have a look at the following thread: e2e.ti.com/.../1651425.

    Best Regards,
    Yordan
  • Thank you Yordan for referring me to the other thread. I did posted my question there and got my concern on defining 2 separate codecs under the sound node of the device tree resolved:

    solution was to do something like this:

    pcm5102a: pcm5102a {
    compatible = "ti,pcm5102a";
    };
     
    sound0:sound@0 {
    compatible = "ti,pcm5102a-evm-audio";
    ti,model = "TI PCM5102A";
    ti,audio-codec = <&pcm5102a>;
    ti,mcasp-controller = <&mcasp0>;
    ti,codec-clock-rate = <24000000>;
    };
     

    sound1:sound@1 {
    compatible = "ti,pcm3168a";
    };
     
    sound {
    compatible = "ti,pcm3168a-evm-audio";
    ti,model = "TI PCM3168A";
    ti,audio-codec = <&pcm3168a>;
    ti,mcasp-controller = <&mcasp1>;
    ti,codec-clock-rate = <24000000>;
    };
     

    My new question is regarding the mcasp1 node itself and its parameters definition; what I mean, is asking if the following settings are correct for configuring the TI PCM3168a codec (this codec provides 8OUTPUT and 6 INPUTS) for my requirements:

    &mcasp1 {

    pinctrl-names = "default", "sleep";

    pinctrl-0 = <&mcasp1_pins>;

    pinctrl-1 = <&mcasp1_sleep_pins>;

    status = "okay";

    op-mode = <0>; /* MCASP_IIS_MODE */

    tdm-slots = <10>; /* 8 slots for TX and 2 Slots for RX */

    /* 16 serializer */

    serial-dir = < /* 0:INACTIVE,  1:TX,    2:RX */

    1 0 2 0

    >;

    tx-num-evt = <32>;

    rx-num-evt = <32>;

    };

    My basic requirements for using this multichannel codec on Mcasp1 are:

    - Use mcasp1 data pin AXR0 for TX and AXR2 for RX

    - Setup TX for only 8 audio output channels (8 speakers)

    - Setup RX for only 2 audio inputs (2 Mics)

    - My audio data samples are 16bits/samples, so I will have 16*10 slots=160bits/frame (2 slots RX, 8 slots TX)

    - We are using the same bit clock and frame sync clocks for RX and TX

    1)  My main question is regarding the "tdm-slots = <10>;": Is this correct for handling 8 TX and 2 RX slots? How McASP will know which slots are TX and RX and sent TX streams to AXR0 while getting RX streams from AXR2?

    2) Is using   "op-mode = <0>; /* MCASP_IIS_MODE */"  make sense in this use case where we are dealing with multiple channels and I2S is known to be used only for stereo (2 chan) operation?

  • Hi,

    PEleph said:
    1)  My main question is regarding the "tdm-slots = <10>;": Is this correct for handling 8 TX and 2 RX slots? How McASP will know which slots are TX and RX and sent TX streams to AXR0 while getting RX streams from AXR2?

    The <serial-dir> parameter provides this information. In the settings you provide: 

    PEleph said:
    serial-dir = < /* 0:INACTIVE,  1:TX,    2:RX */

    1 0 2 0

    >;

    Only 4 serializers will be used   

    AXR0 as TX, AXR1 -> Inactive, AXR2 as RX, AXR3 -> Inactive

    Regarding your second question, op-mode can be either 0 or 1: 

    0: I2S mode, used for I2S, PCM and TDM protocols

    1: DIT mode, used for S/PDIF protocol 

    You need to determine which of the two is most suitable fro your use case. IMO you could use I2S mode. 

    Best Regards, 
    Yordan

    • op-mode

      • 0: I2S mode, used for I2S, PCM and TDM protocols

      • 1: DIT mode, used for S/PDIF protocol

  • PEleph said:
    1)  My main question is regarding the "tdm-slots = <10>;": Is this correct for handling 8 TX and 2 RX slots? How McASP will know which slots are TX and RX and sent TX streams to AXR0 while getting RX streams from AXR2?

    You're correct that the device tree does not provide a way to break down the 10 TDM slots as "8 TX" + "2 RX".  You can see how the code handles this by inspecting sound/soc/davinci/davinci-mcasp.c.  In particular, the "tdm-slots" variable from the device tree gets stored in a variable called "tdm_slots".  In mcasp_i2s_hw_param that variable gets used to derive a bitmask (called "mask") that ultimately is used to initialize both TXTDM_REG and RXTDM_REG.  So in short, the driver is assuming that RX and TX are the same.  It looks to me like you will have to modify the driver in order to independently specify the number of TX and RX slots.

  • I found an issue with overlaying the 2 sounds nodes for the 2 different sound cards I referred to, in my Nov 30th post of this thread.

    If I defined as recommended (sound0 and sound1 in separate nodes), I can successfully send data to sound0 underlying mcasp driver, but sending data to sound1 underlying driver does not get called by the underlying davinci-mcasp driver, even though the driver for sound1 got correctly loaded by the kernel and shows up when I list the audio devices with following cmd for example: "cat /proc/asound/devices."

    It looks like just defining sound0 and sound1 does not really overlay the 2 codecs to be used, just the first one (sound0) takes precedence! am I missing something else for properly overlaying the 2 sound nodes?

  • Can you temporarily remove sound0 altogether? Does sound1 work when it's the *only* codec in the system? (Hopefully that's something that can be tested independently.) It would be best if we could get sound1 functional in isolation before we attempt to get them both operational. I suspect the issue relates to the sound1/mcasp0 configuration rather than the overlay.
  • Brad,

    Yes, when ONLY one node is defined in dts (sound1 or sound0), it works; meaning, I can send and see (scope) data on the respective mcasp (mcasp0 or mcasp1) data pin. That is why I think there is issue with overlaying both nodes.

  • Do you have a script using devmem2 that dumps the McASP register configuration at run-time?  I think you may have made a simple one for an earlier issue we debugged.  Can you run it on McASP0 for the two cases (i.e. sound0+sound1 and sound1-only)?

  • Finally got both sound card working at the same time by properly calling the specific name of the card in from my audio playback application.

    I used to run following cmds to playback

    on sound0: aplay -D device="hw:0,0" test.wav

    and on sound1 card: aplay -D device="hw:1,0" test.wav

    cmd on sound1 would failed with "device not found" error! I realized that hw:1,0 was not defined in my kernel image, so I had to used the specific name of the device. However, device 0 (hw:0,0)is by default define in my kernel image, that why first cmd worked.

    so, to get sound1 running, correct cmd is:

    aplay -D device=PCM3168A test.wav

  • Hi PElph:
    I'm working in a project where i need to interface the PCM3168 with the beaglebone for 6 input and 8 output channel... I was wondering how you solved the tdm-slots question you had? Should i define tdm-slots=<16> or tdm-slots=<14>? And in the codec side, should i configure as Left justified TFM? cause i think the am335x just supports two slots per frame in i2s mode...

    Another question is if i should use S24_LE format? because in the pcm3168 datasheet i understood that if you use 24 bits, 32 bck are given per slot, so 4 bytes are transmitted? Should i use a 32 bit format instead? i know that both codec and processor should agree in how many bck are given per slot, but does the SO manages this?

    Could you share your files with me? They surely helps me to learn a lot
    Thanks
  • Pablo,

    You are confusing tdm-slots with serial-dir.  The serial-dir field is where you program the number of pins/serializers being used.  The PCM3168 has 3 output pins and 4 input pins.  The PCM3168 is transferring two channels of data per pin.  This corresponds to tdm-slots=2.  The serial-dir field is where you specify which serializers of the McASP are inputs and which are outputs.

    Note, however, that McASP0 and McASP1 have 4 serializers each.  So for example if you need all 7 serializers then you would need to put the 3 McASP inputs on McASP0 and the 4 McASP outputs on McASP1.

    Please start a new thread for your questions.  They are fundamentally different than the question/issue in this thread.

    Brad

  • Thanks for your answer:

    My intention is to use 4 channes on each serializer, not two... but if i used tdm-slots=4 and then arecord -c 6, it said no channels count available... I asked it here because he made that very same question in one of his posts, so i thought he could tell me how he finally solved that...

    I'll start a new post, Thanks again!

    Pablo