Linux ALSA device tree bindings for 3 x ADAU1761 and 2 x SAI

Hello,

I am working on bringup of a custom board that has three ADAU1761 codecs, and a NXP LS1028A SoC. The codecs are supposed to be configured in TDM8 mode and share a common playback I2S bus connected to SAI4, and a common capture I2S bus connected to SAI3.
What is the recommended way of modelling this setup in the Linux device tree ?

So far I have tried the following:

&i2c0 {
    status = "okay";
    
    i2c_codec1: adau1761@38 {
        compatible = "adi,adau1761";
        #sound-dai-cells=<0>;
        reg = <0x38>;
        tdm-offset = <0>;
        clocks = <&adau1761_mclk>;
        clock-names = "mclk";
    };
    
    i2c_codec2: adau1761@39 {
        compatible = "adi,adau1761";
        #sound-dai-cells=<0>;
        reg = <0x39>;
        tdm-offset = <16>;
        clocks = <&adau1761_mclk>;
        clock-names = "mclk";
    };
    
    i2c_codec3: adau1761@3a {
        compatible = "adi,adau1761";
        #sound-dai-cells=<0>;
        reg = <0x3a>;
        tdm-offset = <32>;
        clocks = <&adau1761_mclk>;
        clock-names = "mclk";
    };
};

At first I attempted creating three simple-audio-card's. That attempted failed since sharing the same cpu (SAI3 and SAI4) failed with no ALSA device as a result.

Then I attempted cerating a single simple-audio-card with a dai-link containing two cpu sub-nodes and three codec sub-nodes. ALSA enumerates this device, and I get the expected ADAU171 controls for a single codec. But how do I get the two other sets of ADAU171 controls? And how do I do the widgets and routing for this ?

Note: The widgets and routing below is just experimental.

sound {
        status = "okay";
        compatible = "simple-audio-card";
        simple-audio-card,format = "i2s";

        simple-audio-card,widgets =
            "Headphone", "O1 Headphone",
            "Headphone", "O2 Headphone",
            "Headphone", "O3 Headphone";

        simple-audio-card,routing =
            "Playback", "O1 Headphone",
            "Playback", "O2 Headphone",
            "Playback", "O3 Headphone";

        simple-audio-card,dai-link {
            format = "i2s";
            convert-channels = <8>;
            bitclock-master = <&snd_dai_playback>;
            frame-master = <&snd_dai_playback>;
            
            snd_dai_capture: cpu@0 {
                sound-dai = <&sai3>;
                dai-tdm-slot-num = <8>;
                dai-tdm-slot-width = <16>;
            };
            
            snd_dai_playback: cpu@1 {
                sound-dai = <&sai4>;
                dai-tdm-slot-num = <8>;
                dai-tdm-slot-width = <16>;
            };

            codec@0 {
                sound-dai = <&i2c_codec1>;
                frame-master;
                bitclock-master;
                system-clock-frequency = <25000000>;
            };
            codec@1 {
                sound-dai = <&i2c_codec2>;
                system-clock-frequency = <25000000>;
            };
            codec@2 {
                sound-dai = <&i2c_codec3>;
                system-clock-frequency = <25000000>;
            };
        };

    };

Parents
  • 0
    •  Analog Employees 
    on Mar 4, 2020 8:52 AM over 1 year ago

    Hi Rolf,

    Unfortunately I think that simple card driver is not flexible enough to accommodate such a particular case with multiple codecs attached to same DAI.

    Especially as you correctly stated that widgets/routing part where we have the same names for routes in codec drivers so we can't really address say Headphones out of codec 1/2/3.

    I think that you have to write a custom ALSA machine driver for this setup.

    Also please post a question on alsa-devel mailing list describing this setup so that Alsa specialists will answer you there.

    Regards,

    Bogdan

  • Hi Bogdan,

    Ok. Thank you for your reply.

    I will re-post in alsa-devel mailing list.

    By chance we came across a reply to a posting stating the following:

    "Unfortunately the ADAU1761 serial ports do not go to high impedance
    when unused channels are being output. The output line is driven at all
    times"

    Is this correct ? If so we will need to re-design our hardware ..

    Regards

    Rolf

  • 0
    •  Analog Employees 
    on Mar 4, 2020 4:42 PM over 1 year ago in reply to rpk

    Hello Bogdan,

    I support the ADAU1761 part and it is correct that it does not tri-state during unused slots. If you use the DSP in the part rather than just use it as a codec, then you can daisy chain the serial ports and have each part add its signal onto the TDM buss and send the incoming data out onto another channel so you end out with one TDM stream with 8 channels of data. The data would then have to be time aligned by the receiving processor. This would require loading in a DSP program into the device. I do not know if the driver is setup for that at all. 

    So another choice is a hardware change. The ADAU1372 should have a Linux driver available. That part is a newer part and so the serial port is more flexible and can tri-state during unused TDM slots. When using this feature you cannot use the CLKOUT pin because there is a known bug. The CLKOUT signal is gated when the TDM slot is tri-stated. That is usually not an issue since I would not expect you to need that clock output. 

    The big plus about this device is that there are ASRCs on the serial ports. So the converters run at a higher rate for lower latency and then is decimated down. The ASRC allows the codec to be on its own clock domain and the ASRC will simply follow the incoming sample rate. This is handy when switching to other signal sources and sample rates. There is no need to write to the codec to change the sample rate, it will do it automatically. 

    If your I/O needs are greater there may be other options. Fill me in on your application.

    Dave T

  • Hello Dave,

    Ok. Thank you for your reply. I have had a look at ADAU1372 but it is not pin compatible, and has no DSP. Additionally the bug you mentioned excludes it for our use. So we will stick with the ADAU1761. We are planning on solving the lacking tri-stating by using an OR gate provided that the ADC data line is guaranteed to always be driven low outside each ADAU's allocated time-slots. Do you think this will work?

    Rolf  

Reply
  • Hello Dave,

    Ok. Thank you for your reply. I have had a look at ADAU1372 but it is not pin compatible, and has no DSP. Additionally the bug you mentioned excludes it for our use. So we will stick with the ADAU1761. We are planning on solving the lacking tri-stating by using an OR gate provided that the ADC data line is guaranteed to always be driven low outside each ADAU's allocated time-slots. Do you think this will work?

    Rolf  

Children
  • 0
    •  Analog Employees 
    on Mar 5, 2020 8:30 PM over 1 year ago in reply to rpk

    Hello Rolf,

    Most people who use the 1761 with Linux do not use the DSP. They only use it as a codec. There are other parts that will have a DSP but nothing will be pin compatible. Then the CLKOUT bug is surprising that you would be using it. Again, in Linux based systems there is usually other master clock sources for the system so I am glad I mentioned it.

    Your OR gate solution might work. It will depend on how fast the gate can react and bring up the line. I am pretty certain the ADC will output zeros in the unused slots. I would have to check that but you can easily look at it on a scope as well.  This also means that the OR gate would be for all the data in every slot. If the timing is too slow then flipping the polarity of the bit clock on the receiver might give you more margin on the data timing. Something to experiment with. 

    This solution is certainly something that has to be tested and look at the timing on the gate's datasheet to see how it will behave over temperatures and silicon skews. Then see what margin you are seeing at room to get an idea if it will work for all conditions. 

    Dave T