Rock Pi S I2S audio input

I’ve just received my Rock Pi S.
I intended to use the i2s inputs and outputs.
after checking this forum i have successfully preformed audio input from 2 microphones.
unfortunately i failed to record with more than 2.
i am using the dtbo file in the overlay folder (rockpis-i2s-out.dtbo):

/dts-v1/;
/plugin/;

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

        fragment@0 {
                target = <&i2s_8ch_2>;
                __overlay__ {
                        status = "disabled";
                };
        };

        fragment@1 {
                target = <&acodec>;
                __overlay__ {
                        status = "okay";
                };
        };

        fragment@2 {
                target = <&i2s_8ch_0>;
                __overlay__ {
                        rockchip,bclk-fs = <256>;
                        status = "okay";
                };
        };

        fragment@3 {
                target = <&acodec_sound>;
                __overlay__ {
                        rockchip,card-name = "i2sout";
                        rockchip,cpu = <&i2s_8ch_0>;
                        rockchip,codec = <&acodec>;
                };
        };
};

The issues is when i try to record with more than 2 the lrclk doesnt scale according to the channel selection and the extra channels come blank.

Hi
The format defined in the dtb is i2s you may need to change that according to your needs.
for ex. rockchip,format = “dsp_b”;

Maybe some pointers here?
I2s-out overlay to enable i2s0 ?

I tried changing it but unfortunately the clocks still wont change according to the number of channels
and i get this error:
arecord: pcm_read:2145: read error: Input/output error

i read this thread but they are only talking about i2s playback not recording. i tried following it and playback works great but recording wont work for more than 2 channels.

acodec is only 2 channel.
You may want to use dummy-codec for you use something like that

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 >;
    };

This is “8-Channel Master Mode” dsp_b format ( 1 bit delay ), 16 Bit.
To use 32 bit change mclk-fs to 256.

I can confirm, that playback and recording is working.
Have a ADAU1467 connected and use it for 8 channel in/out

Can you explain where are u getting <&i2s_tdm> from?

I Tried using <&i2s_8ch_0> instead but got :
Set mclk_rx: clk_i2s0_8ch_rx freq: 0 failed

You are right, forgot that I use alabel for that.
i2s_8ch_0 is the right one.

You can ignore the mclk_rx error, it is working also with this log:
It seems that the MCLK rx/tx is broken at all for i2s_8ch_0.

For 4*I2S you may change the dummy-codec to the multichannel-codec, but I have never test that.

The problem is i cant record everytime i start i get this error in ALSA:
arecord: set_params:1403: Unable to install hw params:

and this error in PortAudio:
OSError: [Errno -9999] Unanticipated host error

i saw another error in dmesg maybe it got anything to do with it:
rk-multicodecs acodec-sound: ASoC: CPU DAI (null) not registered

It is working here:
arecord -c8 -D hw:1,0 -f S16_LE -r 48000 ./test.wav
Aufnahme: WAVE ‘./test.wav’ : Signed 16 bit Little Endian, Rate: 48000 Hz, 8 Kanäle

aplay -l
[...]
Karte 1: i2s8ch0 [i2s_8ch_0], Gerät 0: ff300000.i2s-dummy_codec dummy_codec-0 []
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0

dmesg:
(Standardeingabe)-[ 1.465890] of_get_named_gpiod_flags: can’t parse ‘simple-audio-card,hp-det-gpio’ property of node ‘/tdm-sound[0]’
(Standardeingabe)-[ 1.465918] of_get_named_gpiod_flags: can’t parse ‘simple-audio-card,mic-det-gpio’ property of node ‘/tdm-sound[0]’
(Standardeingabe):[ 1.467361] asoc-simple-card tdm-sound: dummy_codec <-> ff300000.i2s mapping ok
(Standardeingabe)-[ 1.488491] ALSA device list:
(Standardeingabe)-[ 1.488812] #0: Loopback 1
(Standardeingabe):[ 1.489099] #1: i2s_8ch_0

That is my modded device tree. You may create a overlay ( I was to lazy for that ) by yourself.
Or recompile the device tree using my modded one.

cat rk3308-rock-pi-s-mod.dts 
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
 */

/dts-v1/;

#include <dt-bindings/input/input.h>
/* #include "rk3308.dtsi" */
#include "rk3308k.dtsi"

/ {
        model = "Radxa ROCK Pi S";
        compatible = "radxa,rockpis", "rockchip,rk3308";

        sdio_pwrseq: sdio-pwrseq {
                compatible = "mmc-pwrseq-simple";
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_enable_h>;

                /*
                 * On the module itself this is one of these (depending
                 * on the actual card populated):
                 * - SDIO_RESET_L_WL_REG_ON
                 * - PDN (power down when low)
                 */
                reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
        };

        vdd_core: vdd-core {
                compatible = "pwm-regulator";
                pwms = <&pwm0 0 5000 1>;
                regulator-name = "vdd_core";
                regulator-min-microvolt = <827000>;
                regulator-max-microvolt = <1340000>;
                regulator-init-microvolt = <1015000>;
                regulator-always-on;
                regulator-boot-on;
                regulator-settling-time-up-us = <250>;
                status = "okay";
        };

        vdd_log: vdd-log {
                compatible = "regulator-fixed";
                regulator-name = "vdd_log";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1050000>;
                regulator-max-microvolt = <1050000>;
        };

        vdd_1v0: vdd-1v0 {
                compatible = "regulator-fixed";
                regulator-name = "vdd_1v0";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1000000>;
                regulator-max-microvolt = <1000000>;
        };

        vccio_sdio: vcc_1v8: vcc-1v8 {
                compatible = "regulator-fixed";
                regulator-name = "vcc_1v8";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                vin-supply = <&vcc_io>;
        };

        vccio_sd: vccio-sd {
                compatible = "regulator-gpio";
                regulator-name = "vccio_sd";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <3300000>;
                states = <1800000 0x0
                          3300000 0x1>;
        };

        vcc_sd: vcc-sd {
                compatible = "regulator-fixed";
                gpio = <&gpio4 RK_PD6 GPIO_ACTIVE_LOW>;
                regulator-name = "vcc_sd";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };

        vcc_1v8_codec: vcc-1v8-codec {
                compatible = "regulator-fixed";
                regulator-name = "vcc_1v8_codec";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                vin-supply = <&vcc_io>;
        };

        vcc_ddr: vcc-ddr {
                compatible = "regulator-fixed";
                regulator-name = "vcc_ddr";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1500000>;
                regulator-max-microvolt = <1500000>;
        };

        vcc_3v3_codec: vcc_io: vcc-io {
                compatible = "regulator-fixed";
                regulator-name = "vcc_io";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };

        vccio_flash: vccio-flash {
                compatible = "regulator-fixed";
                regulator-name = "vccio_flash";
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
        };

        vcc_phy: vcc-phy-regulator {
                compatible = "regulator-fixed";
                regulator-name = "vcc_phy";
                regulator-always-on;
                regulator-boot-on;
        };

        vcc_otg_vbus: otg-vbus-regulator {
                compatible = "regulator-fixed";
                enable-active-high;
                gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&otg_vbus_drv>;
                regulator-name = "vcc_otg_vbus";
        };

        wireless-bluetooth {
                compatible = "bluetooth-platdata";
                uart_rts_gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
                pinctrl-names = "default", "rts_gpio";
                pinctrl-0 = <&uart4_rts>;
                pinctrl-1 = <&uart4_rts_gpio>;
                BT,power_gpio    = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
                BT,wake_host_irq = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
                status = "okay";
        };

        wireless-wlan {
                compatible = "wlan-platdata";
                rockchip,grf = <&grf>;
                clocks = <&cru SCLK_WIFI>;
                clock-names = "clk_wifi";
                ref-clock-frequency = <24000000>;
                pinctrl-names = "default";
                pinctrl-0 = <&wifi_wake_host>;
                wifi_chip_type = "rtl8723ds";
                WIFI,host_wake_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
                status = "okay";
        };

        gpio-leds {
                compatible = "gpio-leds";
                status = "okay";

                green-led {
                        label = "rockpis:green:power";
                        gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "default-on";
                        default-state = "on";
                };

                blue-led {
                        label = "rockpis:blue:user";
                        gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                        default-state = "on";
                };
        };

        acodec_sound: acodec-sound {
                compatible = "rockchip,multicodecs-card";
                rockchip,card-name = "rockchip,rk3308-acodec";
                rockchip,codec-hp-det;
                rockchip,mclk-fs = <256>;
                rockchip,cpu = <&i2s_8ch_2>;
                rockchip,codec = <&acodec>;
        };

        tdm_sound: tdm-sound {
                compatible = "simple-audio-card";
                simple-audio-card,name = "i2s_8ch_0";
                simple-audio-card,format = "dsp_b";
                simple-audio-card,mclk-fs = < 256 >;
                simple-audio-card,bitclock-master = <&tdm_snd_cpu>;
                simple-audio-card,frame-master = <&tdm_snd_cpu>;

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

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


        tdm_codec: dummy-codec {
                compatible = "rockchip,dummy-codec";
                #sound-dai-cells = <0>;
        };

};

&cpu0 {
        cpu-supply = <&vdd_core>;
};

&dmc {
        center-supply = <&vdd_log>;
        status = "okay";
};

&emmc {
        bus-width = <4>;
        cap-mmc-highspeed;
        //mmc-hs200-1_8v;
        supports-sd;
        disable-wp;
        non-removable;
        num-slots = <1>;
        status = "okay";
};

&sdmmc {
        max-frequeency = <150000000>;
        supports-sd;
        bus-width = <4>;
        cap-mmc-highspeed;
        cap-sd-highspeed;
        disable-wp;
        num-slots = <1>;
        vmmc-supply = <&vcc_sd>;
        vqmmc-supply = <&vccio_sd>;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
        ard-detect-delay = <800>;
        status = "okay";
};

&mac {
        phy-supply = <&vcc_phy>;
        clock_in_out = "output";
        assigned-clocks = <&cru SCLK_MAC>;
        assigned-clock-parents = <&cru SCLK_MAC_SRC>;
        snps,reset-gpio = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
        snps,reset-active-low;
        snps,reset-delays-us = <0 50000 50000>;
        status = "okay";
};

&io_domains {
        status = "okay";

        vccio0-supply = <&vcc_io>;
        vccio1-supply = <&vcc_io>;
        vccio2-supply = <&vcc_1v8>;
        vccio3-supply = <&vccio_flash>;
        vccio4-supply = <&vccio_sdio>;
        vccio5-supply = <&vcc_io>;
};


&i2s_8ch_0 {
    
        assigned-clocks = <&cru SCLK_I2S0_8CH_RX>;
        assigned-clock-parents = <&cru SCLK_I2S0_8CH_TX_MUX>;

        pinctrl-0 = <&i2s_8ch_0_sclktx
                    &i2s_8ch_0_sclkrx
                    &i2s_8ch_0_lrcktx
                    &i2s_8ch_0_lrckrx
                    &i2s_8ch_0_sdi0
                    &i2s_8ch_0_sdo0
                    &i2s_8ch_0_mclk>;

        rockchip,clk-trcm = < 1 >;
        rockchip,bclk-fs = < 256 >;
        #sound-dai-cells = <0>;
        status = "okay";
};

&i2s_8ch_2 {
        status = "disabled";
        #sound-dai-cells = <0>;
};

&pinctrl {
        pinctrl-names = "default";
        pinctrl-0 = <&rtc_32k>;

        buttons {
                mic_mute: mic-mute {
                        rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
        usb {
                otg_vbus_drv: otg-vbus-drv {
                        rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
        rotary {
                rotary_gpio: rotary-gpio {
                        rockchip,pins =
                                <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>,
                                <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
        sdio-pwrseq {
                wifi_enable_h: wifi-enable-h {
                        rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };

        wireless-wlan {
                wifi_wake_host: wifi-wake-host {
                        rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
};

&pwm0 {
        status = "okay";
        pinctrl-names = "active";
        pinctrl-0 = <&pwm0_pin_pull_down>;
};

&rockchip_suspend {
        rockchip,pwm-regulator-config = <
                (0
                | RKPM_PWM_REGULATOR
                )
        >;

        status = "okay";
};

&sdio {
        max-frequency = <110000000>;
        bus-width = <4>;
        cap-sd-highspeed;
        supports-sdio;
        ignore-pm-notify;
        keep-power-in-suspend;
        non-removable;
        mmc-pwrseq = <&sdio_pwrseq>;
        sd-uhs-sdr104;
        status = "okay";
};

&tsadc {
        rockchip,hw-tshut-mode = <0>;           /* 0:CRU */
        rockchip,hw-tshut-polarity = <1>;       /* 1:HIGH */
        status = "okay";
};

&u2phy {
        status = "okay";

        u2phy_host: host-port {
                phy-supply = <&vcc_otg_vbus>;
                status = "okay";
        };

        u2phy_otg: otg-port {
                vbus-supply = <&vcc_otg_vbus>;
                status = "okay";
        };
};

&uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart4_xfer &uart4_cts>;
        status = "disabled";
};

&usb20_otg {
        dr_mode = "peripheral";
        status = "okay";
};

&usb_host0_ehci {
        status = "okay";
};

&usb_host0_ohci{
        status = "okay";
};

&acodec {
        status = "disabled";
};

&thermal_zones {
        soc_thermal {
                thermal-sensors = <&tsadc 0>;
        };
};

&wdt {
        status = "okay";
};

&saradc {
        status = "okay";
        vref-supply = <&vcc_1v8>;
};

Ive tried using your tree, the problem i had was i was missing. this line:
rockchip,clk-trcm = < 1 >; which set the active lrclk, 1 means both tx and rx
but when i set it to 1 (both) it doesnt output the rx-lrclk for recording, only tx-lrclk for playback.
when i set it to 2 ( only rx ) or 0 ( only tx) it works great

so i can record now which is great but do you have any idea how can i get both to work?

tx-lrclk are in sync normally. You can use it for both rx and tx. so it is regardless which of the clk’s you are using.
Looking at the register descriptions tells how to get them both working at the same time, but i assume that this may not be implemented ( looks complicated too ), because no one need this.

sorry it took so long to replay, the problem is when if i set the clk-trcm in tk-only mode and try to record i don’t get any lr-clocks, and the opposite also.

I use record/playback at the same time. Playback to move Audio to DSP and record for receiving audio from headset microphone using pcm8102 attached also to the DSP.
Playback stated as service just after start and record on demand, when plug in the headset.
When you need both syn working, the you may look at the driver rockchip-tdm.c what’s going on

Can you give me the hardware connection such as what are the pins did you use .?