I2s-out overlay to enable i2s0

Thanks for the hint.
I check the source of adau1701 driver. It seems to me that it is using primary I2C to communicate with the DSP and load a image to it. On success it will the dynamically load da sound-dai.

I think yes, this is usable on later development when I have an image to upload. But I haven’t atm.

So I’m primary looking to get the simple_card with i2s_8ch_0 and dummy_codec working in 8ch mode, so that ‘aplay -c8’ or speaker-test -c8 will use all 8 channels.

It seems to me, that this combination is still using 2 channel 32 bits regardless of the settings in the simple-audio node. I have try dai-tdm-lots<8>, dai-tdm-slot-size<16> but it is still ignored.
Only parameter format = “dsp_b”; is working.
I have attached a logic-analysator to check the tdm.

speaker-test -c2 is working and all other -cX drops a error -EIO

that is my current dt-part:

i2s_tdm: i2s_8ch_0 … // set label here

tdm_sound {
compatible = “simple-audio-card”;
simple-audio-card,name = “rockpis-tdm”;
simple-audio-card,format = “dsp_b”;
simple-audio-card,mclk-fs = < 0x100 >;
simple-audio-card,bitclock-master = <&i2s_tdm>;
simple-audio-card,frame-master = <&i2s_tdm>;
status = “okay”;

        simple-audio-card,cpu {
            sound-dai = < &i2s_tdm 0>;
            system-clock-frequency = <12288000 >;
            system-clock-direction = "out";
            dai-tdm-slot-num = <8>;
            dai-tdm-slot-with = <16>;
        dailink0_master: simple-audio-card,codec {
            sound-dai = <&dummy_codec>;
            dai-tdm-slot-num = <8>;
            dai-tdm-slot-with = <16>;

dummy_codec: dummy-codec {
        status = "okay";
        compatible = "rockchip,dummy-codec";
        #sound-dai-cells = < 0x00 >;
        clocks = <0x02 0x4c>;
        clock-names = "mclk";
        phandle = < 0x139 >;

All is enumerated without error, but its only 2 channel 32 bit not 8 channel 16 bit. That is the problem I’m unable to solve.

I did following:

I was on 143-55 as you. Read in the forum that there is also a 143-57 avail. So I did a
apt-get install kernel-latest

After booting the new kernel, I check the overlays now present.
There is now a new overlay there called rk3308-i2s-out.dtbo

When activating this, I can do aplay -c2 test.wav and see a 2 channel i2s stream on the desired pins.
Without that overlay, i2s pins stay idle, assuming apaly will use the internal dac, which I’m not so interesting in ( maybe later ).

Yes I uploaded that to radxas repository as well as the spdif-out overlay but I think our friend ash want to use the simple_card overlay to get rid of the multicodec stuff.

you are right, simple_card should work for him.

When you also have a rk3308-8ch-tdm-out.dtbo in your pockets, I’m very interesting in. :wink:

I think I will write a small program using the alsa api, so that I have a better control of the parameters.
The hardware can, the device tree should work but there are to less debug information what is really going on.Possible that is caused by missing alsa settings.

Sure. If I only had little more free time.
Just a question. When you loading your i2s_tdm: i2s_8ch_0 overlay do you get a master clock out on GPIO 68?

Oh I feel so silly. Thanks for all the pointers, and sorry to have wasted your time!

Yes, masterclock and Frame in dsp_b mode and also data, but only 2ch.
My measurement shows framesync = 48Khz, clock = 3.072 Mhz, dsp_b mode ( pulse sync + 1 bit delay )

Meanwhile I have change my DT to 6.144 Mhz and mckl-fs = 128 to fit to 8 channel 16 bits
(8chan * 16 bits * 48Khz = 6.144 Mhz)
But changes to mclk-fs, clock-frequency are still ignored.

The first thing I have to find out is, why the clock frequency is ignored or possible overwritten by alsa.

No no dont feel that. I hope it wasnt my way to tell things that made you feel that. A lot of things in our heads can lead to some mistakes but we are here to help each other right?

1 Like

Aa let me explain.
many DACs require a master clock (mclk) besides the serial clock (sclk) and word clock (lrclk) ro make the internal oversampling to realize digital filtering etc. I know that that clock is not a part of the I2S standard but.
When you look at the pinout of PiS that clock (mclk) should be traced out to
sclk to
12 GPIO2_A5 I2S0_8CH_SCLK_TX 69
lrclk to
22 GPIO2_A7 I2S0_8CH_LRCK_TX 71
data to
18 GPIO2_B1 I2S0_8CH_SDO0 73
so the driver should output all those clocks. The dummy-codec is patched to output the mclk and you can see in your dump that it gets that clock successfully.

[ 1.658822] dummy_codec dummy-codec: get mclk success

But can you see it on the instrument? that was my question.

Ok, I take a look if there are more clocks active this evening.

But I think the device supports this mode:
19.3.11 TDM left shift mode2 (PCM format). Using only one Pin
SDI0/SDO0 for all 8 channels

That is different to
19.3.1 I2S normal mode which has 2 channels but can have 4 IO Pins
SDI0-3/SDO0-3 = 4 * 2 channels
I think you mean this mode.

I like to setup the PiS for the waveform like in chapter 19.3.11. Have all 8 channel with only one IO Pin, so that all 8 channels are transmitted/received within one frame. For that It needs only 4 wires. Clock, Sync, In, Out

Ok Thats what I mean. I experienced the same behavior before that simple-card ignoring the clock setting when I was working with nanopi but in those cases it was the sunxi I2S driver itself that failed.
Please check the mclk when you have time.

I am playing with music streaming devices and in most cases when you start playing or stopping tracks the I2S driver start and stop the clocks and therefor it outputs pops and clicks very annoying.
So I have modified the rockchip I2S driver to keep the clocks always on.
The modified driver is in my github account same place as the overlays if someone needs that…
You can also find there a kernel I have build (deb packages) that gets rid of all those loop devices.

I have check the clocks:
I2S0_8CH_MCLK: n.a
I2S0_8CH_SCLK_TX: 3.078 Mhz
I2S0_8CH_LRCK_TX: 48 Khz

When reading the DT-docs for i2s-tdm then you are right it is splitting using multiple IO lines
There is nothing about tdm slots.

But, the confusing thing is the doc for rockcip-i2s:

  • clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
  • clock-names: should contain followings:
    • “i2s_hclk”: clock for I2S BUS
    • “i2s_clk” : clock for I2S controller
  • rockchip,playback-channels: max playback channels, if not set, 8 channels default.
  • rockchip,capture-channels: max capture channels, if not set, 2 channels default.
  • rockchip,bclk-fs: configure the i2s bclk fs.

8 channel as default ??? for a device which can handle only 2 channels. Have they mixed up the device driver ? So that the i2s_8ch should use rockchip-i2s and the i2s_2ch should use the rockchip-i2s-tdm

I think, I try to set the driver to rk3066-i2s

not working -22
Now i try to use i2s_0
not functional. is not on the header, so it can not work

It confirms what I thought. I have tested the 2channel driver with the same result as you very obvious since it is not hardware connected.
As I said before I did some work with the tdm driver to keep the clocks on constantly I will go back and try to maybe find some answers

For whatever reason, I got it working now.
My DT so far:

   i2s_tdm: i2s@ff300000 {
            compatible = "rockchip,rk3308-i2s-tdm";
            reg = < 0x00 0xff300000 0x00 0x1000 >;
            interrupts = < 0x00 0x30 0x04 >;
            clocks = < 0x02 0x4c 0x02 0x4e 0x02 0xa4 0x02 0x6e 0x02 0x6f 0x02 0x03 0x02 0x04 >;
            clock-names = "mclk_tx\0mclk_rx\0hclk\0mclk_tx_src\0mclk_rx_src\0mclk_root0\0mclk_root1";
            dmas = < 0x25 0x00 0x25 0x01 >;
            dma-names = "tx\0rx";
            resets = < 0x02 0x89 0x02 0x8a >;
            reset-names = "tx-m\0rx-m";
            rockchip,cru = < 0x02 >;
            rockchip,grf = < 0x4b >;
            pinctrl-names = "default";
            pinctrl-0 = < 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a >;
            status = "okay";
            rockchip,clk-trm = <1>;
            rockchip,bclk-fs = <128>;
            #sound-dai-cells = <0>;
            phandle = < 0xbe >;

   tdm_sound {
            compatible = "simple-audio-card";
            simple-audio-card,name = "rockpis-tdm";
            simple-audio-card,format = "dsp_b";
            simple-audio-card,mclk-fs = < 128 >;
            simple-audio-card,bitclock-master = <&tdm_snd_cpu>;
            simple-audio-card,frame-master = <&tdm_snd_cpu>;
            status = "okay";

            tdm_snd_cpu: simple-audio-card,cpu {
                dai-tdm-slot-num = <8>;
                dai-tdm-slot-width = <16>;
                sound-dai = <&i2s_tdm>;

            tdm_snd_codec: simple-audio-card,codec {
                sound-dai = <&dummy_tdm_codec>;

    dummy_tdm_codec: dummy-codec {
            status = "okay";
            compatible = "rockchip,dummy-codec";
            #sound-dai-cells = < 0x00 >;
            phandle = < 0x139 >;

I have check that with speaker-test -c 8 -s [1-8] to see that all channels run independently.
Saw on logic analyser:
Clock: 6.144 Mhz
Sync: 48Khz

Only the channels seems to mixed up between speaker-test and the position on tdm. but this can be changed by alsa settings.

Hurra. Now I have drink a box of beer and hopefully radxa pay it :smile::beers:

1 Like

Nice Not giving up too easy pays off sometimes.
If you dont want to mess with the dtb you can use this.


I loaded that on my armbian image and it seems to work. It should work on radxas image as well.

Yes this DT stuff is hard to understand. I think the main issue was to set the clock master to the dummy-codec. I found this somewhere in an other rockship DT.
The overlay is a better solution, right. But i was easier for my to mod the base dtb :wink:

armbian was my first attempt using this board. But I have stopped using It, because of not working USB and USB-otg. Is this working now ?
I prefer a newer kernel,because there is a patch out for USB-Audio 2.0 which is mandatory for me. With armbian, I think i will only compile that. With raxda image, I will have to backport it. Also my own stuff was from rasberian which is also using a newer kernel.
When USB on armbian is working, than it would save me a lot of unwanted work

Yes I can confirm that. I tested my overlay yesterday on latest armbian with current kernel and since the dummy codec was not precompiled there I used the pcm5102a codec.

The card comes up fine but 8-ch didnt work so I was on my way to dive in to TDM driver.
But loading the same overlay using the dummy codec on armbian with legacy kernel seems to work fine.
So the trick was to get the codec to set the clock right.

@eragefe I had some time today and decided to test my original goal of i2s with the 5.x kernel :slight_smile:

Would you have some pointers for me w.t.r simple-card.

I’ll port of the dummy-codec over soon, but is there anything else that might also need porting?

# This is with the new Armbian build
# Armbian_20.11_Rockpi-s_buster_current_5.9.10_minimal.img
root@rockpi-s:~# uname -a
Linux rockpi-s 5.9.10-rockchip64 #20.11 SMP PREEMPT Mon Nov 23 13:36:07 CET 2020 aarch64 GNU/Linux
# dmesg
[    8.818446] rk3308-acodec ff560000.acodec: Don't need hp-ctl gpio
[    8.818488] rk3308-acodec ff560000.acodec: Don't need spk-ctl gpio
[    8.818522] rk3308-acodec ff560000.acodec: Don't need pa-drv gpio
[    8.818529] rk3308-acodec ff560000.acodec: De-pop as much as possible
[    8.818658] rk3308-acodec ff560000.acodec: Don't need micbias-en gpio
[    8.818704] rk3308-acodec ff560000.acodec: no vmicbias regulator found
[    8.818715] rk3308-acodec ff560000.acodec: Check ext_micbias: 0
[    8.818751] The acodec version is: a
[    8.888772] asoc-simple-card acodec-sound: ASoC: no DMI vendor name!
[    8.901359] asoc-simple-card sound_i2s: ASoC: no DMI vendor name!
[    8.907407] rockchip-i2s-tdm ff300000.i2s: Trying to bind component to card "i2s_8ch_0" but is already bound to card "SimpleDAC"
[    8.907426] asoc-simple-card sound: ASoC: failed to instantiate card -19

And here is the overlay file.

root@rockpi-s:~# cat /boot/overlay-user/simple_card.dts
// Definitions for DummyDAC

/ {
        compatible = "radxa,rockpis", "rockchip,rk3308";

        fragment@0 {
                target = <&i2s_8ch_0>;

                __overlay__ {
                        #sound-dai-cells = <0>;
                        status = "okay";

        fragment@1 {
                target-path = "/";

                __overlay__ {
                        i2s0_out: i2s0-out {
                                #sound-dai-cells = <0>;
                                compatible = "ti,pcm5102a";
                                status = "okay";

                        sound_i2s {
                                simple-audio-card,name = "SimpleDAC";
                                compatible = "simple-audio-card";
                                simple-audio-card,format = "i2s";
                                simple-audio-card,bitclock-master = <&cpu_dai>;
                                simple-audio-card,frame-master = <&cpu_dai>;
                                simple-audio-card,mclk-fs = <256>;
                                status = "okay";

                                cpu_dai: simple-audio-card,cpu {
                                sound-dai = <&i2s_8ch_0>;

                                codec_dai: simple-audio-card,codec {
                                sound-dai = <&i2s0_out>;

The cards register, even though dmesg show signs of impending trouble…

root@rockpi-s:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: rockchiprk3308a [rockchip,rk3308-acodec], device 0: ff320000.i2s-rk3308-hifi rk3308-hifi-0 [ff320000.i2s-rk3308-hifi rk3308-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: SimpleDAC [SimpleDAC], device 0: ff300000.i2s-pcm5102a-hifi pcm5102a-hifi-0 [ff300000.i2s-pcm5102a-hifi pcm5102a-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
# speaker-test leads to a nice kernel panic
[  475.652740] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[  475.653255] Modules linked in: 8723ds cfg80211 rfkill zstd snd_soc_pcm5102a snd_soc_rk3308 snd_soc_simple_card snd_soc_rockchip_i2s_tdm snd_soc_simple_card_utils snd_soc_core snd_pcm_dmaengine snd_pcm snd_timer snd soundcore cpufreq_dt zram ip_tables x_tables autofs4 realtek dwmac_rk stmmac_platform stmmac mdio_xpcs
[  475.655832] CPU: 2 PID: 1935 Comm: speaker-test Not tainted 5.9.10-rockchip64 #20.11
[  475.656522] Hardware name: Radxa ROCK Pi S (DT)
[  475.656943] pstate: a0000005 (NzCv daif -PAN -UAO BTYPE=--)
[  475.657614] pc : dapm_update_dai_unlocked.isra.0+0x40/0x108 [snd_soc_core]
[  475.658369] lr : snd_soc_dapm_update_dai+0x40/0x68 [snd_soc_core]
[  475.658917] sp : ffff8000130bba10
[  475.659225] x29: ffff8000130bba10 x28: ffff0000161b0000
[  475.659717] x27: ffff0000133e4d1c x26: 0000000000000000
[  475.660206] x25: ffff0000133e4c24 x24: ffff0000161b0000
[  475.660695] x23: ffff0000133e4c00 x22: ffff0000128c8cd8
[  475.661184] x21: ffff0000128c8c00 x20: 0000000000000002
[  475.661673] x19: ffffffffffffffd8 x18: 0000000000000000
[  475.662160] x17: 0000000000000000 x16: 0000000000000000
[  475.662647] x15: 0000000000000000 x14: 0000000000000000
[  475.663137] x13: 0000000000000000 x12: 0000000000000001
[  475.663625] x11: 0000000000000004 x10: 0101010101010101
[  475.664114] x9 : 0000000000000001 x8 : 7f7f7f7f7f7f7f7f
[  475.664603] x7 : 0000000000000000 x6 : 0000000000000000
[  475.665091] x5 : 0000000000000000 x4 : 0000000000000000
[  475.665579] x3 : ffff0000163d7148 x2 : ffff000014046480
[  475.666067] x1 : ffff0000133e4c00 x0 : 0000000000000000
[  475.666557] Call trace:
[  475.666930]  dapm_update_dai_unlocked.isra.0+0x40/0x108 [snd_soc_core]
[  475.667647]  snd_soc_dapm_update_dai+0x40/0x68 [snd_soc_core]
[  475.668300]  soc_pcm_hw_params+0x32c/0x5a8 [snd_soc_core]
[  475.668864]  snd_pcm_hw_params+0xf0/0x400 [snd_pcm]
[  475.669371]  snd_pcm_common_ioctl+0x2d8/0x1078 [snd_pcm]
[  475.669914]  snd_pcm_ioctl+0x30/0x48 [snd_pcm]
[  475.670337]  __arm64_sys_ioctl+0xa8/0xf0
[  475.670710]  el0_svc_common.constprop.0+0x70/0x188
[  475.671154]  do_el0_svc+0x24/0x90
[  475.671471]  el0_sync_handler+0x90/0x198
[  475.671835]  el0_sync+0x158/0x180
[  475.672168] Code: f84d8ed3 eb1302df d100a273 540001a0 (f9400a61)
[  475.672726] ---[ end trace a07ab07415ed41c6 ]---

Is it not possible to have both the Audio jack and the I2S output active at the same time? If I read your 8ch_simple_card seems to disable the i2s_8ch_2 node that the audio codec maps to?

EDIT: The 8ch_simple_card also has a similar kernel panic when trying speaker-test -c2

Yes you are right there. The overlay disables the audio codec.
The dtb in armbian latest you using implementing several simple-card nodes
analog-sound {
compatible = “simple-audio-card”;
simple-audio-card,format = “i2s”;
simple-audio-card,mclk-fs = <0x100>;
simple-audio-card,name = “Analog”;
status = “disabled”;
phandle = <0x6f>;

            simple-audio-card,cpu {
                    sound-dai = <0x07>;

            simple-audio-card,codec {
                    sound-dai = <0x08>;

thats why you see those error messages in your dump.

BUT first I have to understand what you want to do.
Play something that you want to output both at the i2s pins and the analog output simultaneously?

If this is the case and you can register both cards correctly (maybe I can assist with that) then I guess you could send the stream to card1 and pipe it to card0.
Usually people do that to connect an input and an output device to send sound from a mic to a loudspeaker for example.

Anyway I did some testing yesterday and if you use this overlay everything works fine.

and with both cards


Welcome to Armbian 20.11 Focal with Linux 5.9.10-rockchip64

System load: 4% Up time: 0 min
Memory usage: 33% of 213M IP:
CPU temp: 34°C Usage of /: 6% of 15G

[ Menu-driven system configuration (beta): sudo apt update && sudo apt install armbian-config ]

Last login: Thu Dec 3 02:15:34 2020 from
root@rockpi-s:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: rockchiprk3308a [rockchip,rk3308-acodec], device 0: ff320000.i2s-rk3308-hifi rk3308-hifi-0 [ff320000.i2s-rk3308-hifi rk3308-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: SimpleDAC [SimpleDAC], device 0: ff300000.i2s-pcm5102a-hifi pcm5102a-hifi-0 [ff300000.i2s-pcm5102a-hifi pcm5102a-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
root@rockpi-s:~# speaker-test -c2 -D plughw:1

speaker-test 1.2.2

Playback device is plughw:1
Stream parameters are 48000Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 128 to 131072
Period size range from 64 to 65536
Using max buffer size 131072
Periods = 4
was set period_size = 32768
was set buffer_size = 131072
0 - Front Left
1 - Front Right
Time per period = 2.776536
0 - Front Left
1 - Front Right
Time per period = 5.460972
0 - Front Left
^C 1 - Front Right
Time per period = 0.830656
root@rockpi-s:~# speaker-test -c2 -D plughw:0

speaker-test 1.2.2

Playback device is plughw:0
Stream parameters are 48000Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 128 to 131072
Period size range from 64 to 65536
Using max buffer size 131072
Periods = 4
was set period_size = 32768
was set buffer_size = 131072
0 - Front Left
1 - Front Right
Time per period = 2.749659
0 - Front Left
1 - Front Right
^CTime per period = 4.607317

1 Like