bricolodu13
Posts: 38
Joined: Tue Aug 07, 2012 2:05 pm

Re: STICKY: The I2S sound thread.

Wed Jul 10, 2019 11:15 am

Hi Hias,

It's working now.

I had an old asound.conf that was on the way, sorry :oops: !

I finally got it working with my yesterday code:

Code: Select all

                                codec_port: port {
                                        codec_endpoint: endpoint {
                                                remote-endpoint = <&cpu_endpoint>;
                                                bitclock-master;
                                                frame-master;
                                        };
Thank you very much for your help.

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Thu Jul 18, 2019 2:16 am

I switched to an AD1934 DAC chip since it has integrated PLL and it works on the Raspberry Pi 3B+ !

Now I want to use TDM to get more than a single stereo output (up to 4 stereo outs on AD1934), so I setup my DAC in TDM mode and write the data like this :

Ch1 L | Ch1 R | Ch2 L | Ch2R (two stereo 48khz channels in a 96khz stream)

But I only get the sound from channel 1, I think it's because the Raspberry's I2S system isn't configured to generate the appropriate LRCK signal for TDM so my DAC just won't get all the data.

I looked at a few posts telling about custom overlays to setup the system in TDM mode, I compiled the following example but it seems to have no effect at all :

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2837","brcm,bcm2837B0","brcm,bcm2708", "brcm,bcm2709";


    [email protected] {
        target-path = "/";
        __overlay__ {
            dual_soundcard: dual-soundcard {
                compatible = "simple-audio-card";
                simple-audio-card,name = "Dual";

                status="okay";

                capture_link: simple-audio-card,[email protected] {
                    format = "i2s";
                    bitclock-master = <&r_codec_dai>;
                    frame-master = <&r_codec_dai>;

                    r_cpu_dai: cpu {
                        sound-dai = <&i2s>;

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

                    r_codec_dai: codec {
                        sound-dai = <&codec_in>;
                    };
                };

                playback_link: simple-audio-card,[email protected] {
                    format = "i2s";
                    bitclock-master = <&p_codec_dai>;
                    frame-master = <&p_codec_dai>;

                    p_cpu_dai: cpu {
                        sound-dai = <&i2s>;

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

                    p_codec_dai: codec {
                        sound-dai = <&codec_out>;
                    };
                };
            };
        };
    };

    [email protected] {
        target-path = "/";
        __overlay__ {
            codec_out: spdif-transmitter {
                #address-cells = <0>;
                #size-cells = <0>;
                #sound-dai-cells = <0>;
                compatible = "linux,spdif-dit";
                status = "okay";
            };
            codec_in: spdif-receiver {
                #address-cells = <0>;
                #size-cells = <0>;
                #sound-dai-cells = <0>;
                compatible = "linux,spdif-dir";
                status = "okay";
            };
        };
    };

    [email protected] {
        target = <&i2s>;
        __overlay__ {
            #sound-dai-cells = <0>;
            status = "okay";
        };
    };

};
The documentation on the net is really awful : somewhere I read the DTB file should be put at the root folder, at other places they say to put it in "boot/overlays/"... sometimes it's .dtb other times it's .dtbo. It isn't even clear if the overlay must be referenced in /config.txt or /boot/config.txt.

I added "bcm2837" and "bcm2837B0" in the "compatible" variable because it seemed strange to me that my CPU (RPI 3B+) isn't referenced but I have no idea if I'm doing it right.

May someone tell me how to do this properly ?
I'm using the rasberry with bare metal code, but it should not be a problem since overlays are loaded before by start.elf ?

HiassofT
Posts: 200
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Thu Jul 18, 2019 10:46 am

With bare metal code you can completely ignore the DT overlays, unless you have some code to interpret the FDT passed in from the bootloader. With Linux the DT overlays are used to configure the linux drivers.

Concerning TDM: While the bcm I2S block offers very flexible configuration it doesn't support more than 2 channels per frame -it's stereo only. Some people have used quirks to use it in multichannel configuration (while the base hardware is still running in stereo) but this is tricky and can lead to channel swaps/shifts if the clocks aren't started at very precise moments.

so long,

Hias

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Thu Jul 18, 2019 6:05 pm

Yeah it seems complicated. I've tried to run I2S at 192Khz to write four 48Khz frames, while slowing down Frame Sync Length by a factor of 4 (FSLEN register, I guess it controls LRCLK ? => broadcom datasheet p.131 https://www.raspberrypi.org/documentati ... herals.pdf )

To match the expected format for my DAC :
Image
https://www.analog.com/media/en/technic ... AD1934.pdf p.14

But I get no sound doing that.
In this mode my DAC seems a bit special since TDM LRCLK isn't just a pulse it's a stretched variant of the I2S (stereo) LRCLK, a square wave. It gave me some hope initially but maybe i'm misunderstanding.

Unfortunately I have no scope to see the signals... I ordered one, should receive it next week :)

HiassofT
Posts: 200
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Fri Jul 19, 2019 9:37 am

Setting up the interface at four-times stereo rate is a good start.

If you run the bcm2835-i2s in clock slave mode FSLEN doesn't matter, it only check for the leading LRCLK edge. Just set it up as usual (eg 1 for DSP mode or sample length for I2S).

There is a quirk in bcm2835-i2s, once it's seen a LRCLK edge it'll keep transmitting data even if the LRCLK edge is missing on subsequent frames. So you can eg drive it with a LRCLK signal set up for 8 samples instead of 2 - this is what the audioinjector octo card seems to be doing.

The downside of this is that the bcm2835-i2s won't properly sync to LRCLK. When starting clocks at the exact specific moments it seems to be doable though (haven't really looked into the latter myself).

If you run bcm2835-i2s in (frame clock) master mode you could use an external divide-by-4 circuit (eg 2 flip-flops) on the LRCLK signal so 4 stereo frames will be combined into one 8-channel frame. Again you must take care yourself that the polarity and phase of the divided signal is correct (eg reset the divider and/or keep LRCLK high) before the first stereo sample is transmitted.

so long,

Hias

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Fri Jul 19, 2019 11:18 am

I use the raspberry in Master mode for the sake of simplicity ^^
I received my scope and it helped a lot. For some reason, chosing a Frame Sync Length (FSLEN) greater than the Frame Length (FLEN) causes LRCLK to stop working.
However, I can get the 256 BCLK per LRCLK if I just increase both FLEN and FSLEN, so i'll do a test to see if I can talk to my DAC now.

Normal I2S mode :
Image

Increased only FSLEN... oops ! :
Image

Both FLEN and FSLEN increased :
Image

Yellow = LRCLK
Pink = BCLK
Blue = Data

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Fri Jul 19, 2019 11:36 am

Seems that I can only transfer the first 32 bits of the frame despite I set its length to 128. Or i'm missing something. Maybe the clock divider trick you explained is the only way to go

HiassofT
Posts: 200
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Fri Jul 19, 2019 11:40 am

No, you are not missing anything. bcm2835-i2s will only transfer (max) 2 samples/channels per frame - this is what I meant with "stereo only".

You'll have to use one of the tricks I posted to pack 4 stereo frames into an 8-channel one.

so long,

Hias

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Fri Jul 19, 2019 11:44 am

Thanks that make sense, i'ill try that asap.

Learning by trial & error :P :ugeek:

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Mon Jul 22, 2019 7:42 pm

-
Last edited by okenido on Tue Aug 06, 2019 11:26 am, edited 1 time in total.

okenido
Posts: 57
Joined: Thu Aug 02, 2018 11:47 am

Re: STICKY: The I2S sound thread.

Wed Jul 24, 2019 6:30 pm

-
Last edited by okenido on Tue Aug 06, 2019 11:25 am, edited 1 time in total.

User avatar
egawtry
Posts: 3
Joined: Tue Dec 04, 2018 6:22 pm
Location: Minnesota, USA

Re: STICKY: The I2S sound thread.

Thu Aug 01, 2019 5:48 pm

I have been searching and searching for an answer for this one (2 months so far), and I keep getting the runaround.

I have a working I2S send/recv at 192KHz with external clock. How the heck do I switch the sampling rate (96, 48, 44.1, etc)? I have been assuming it is via I2C, but nothing I do sends any data on the I2C bus when the sampling rate changes. I finally got it coded in the device tree to lock it out (UU on i2cdetect). i2cdump does send a signal when the sound driver is disabled.

I am not worried about what is in the output, only that something is available to detect when the sampling rate wants to change.

Could someone please help?

Thank You,
-Erik

Here is the device tree:

Code: Select all

/dts-v1/;
/plugin/;

// Device Tree Overlay for generic I2S audio output on Raspberry Pi

/ {
    compatible = "brcm,bcm2708";

    [email protected] {
        target = <&sound>;
        __overlay__ {

            compatible = "simple-audio-card";
            simple-audio-card,name = "Danville-dspElite-Soundcard";
		//audio-codec = <&pcm5122>;		// Breaks it
			
            status="okay";
            capture_link: simple-audio-card,[email protected] {
                format = "i2s";
				
                bitclock-master = <&r_codec_dai>;
                frame-master = <&r_codec_dai>;

                r_cpu_dai: cpu {
                                sound-dai = <&i2s>;

				                 // TDM slot configuration - BCLK ratio: 64 x Fs (2 x 32 bit) 
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
                
				};

                r_codec_dai: codec {
                    sound-dai = <&codec_in>;
                };
            };
            playback_link: simple-audio-card,[email protected] {
                format = "i2s";
				
                bitclock-master = <&p_codec_dai>;
                frame-master = <&p_codec_dai>;

                p_cpu_dai: cpu {
                                sound-dai = <&i2s>;

				                 // TDM slot configuration - BCLK ratio: 64 x Fs (2 x 32 bit) 
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
                
				};

                p_codec_dai: codec {
                    sound-dai = <&codec_out>;
                };
            };
        };
    };

    [email protected] {
        target-path = "/";
        __overlay__ {
            codec_out: spdif-transmitter {
                #address-cells = <0>;
                #size-cells = <0>;
                #sound-dai-cells = <0>;
                compatible = "linux,spdif-dit";
                status = "okay";
            };
	    codec_in: spdif-receiver {
                #address-cells = <0>;
                #size-cells = <0>;
                #sound-dai-cells = <0>;
		compatible = "linux,spdif-dir";
                status = "okay";
		};
	    };
    };

    [email protected] {
        target = <&i2s>;
        __overlay__ {
            #sound-dai-cells = <0>;
            status = "okay";
        };
    };
    
	[email protected] {
		target = <&i2c1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;
			status = "okay";

			[email protected] {
				#sound-dai-cells = <0>;
				compatible = "ti,pcm5122";
				reg = <0x52>;
				AVDD-supply = <&vdd_3v3_reg>;
				DVDD-supply = <&vdd_3v3_reg>;
				CPVDD-supply = <&vdd_3v3_reg>;
				status = "okay";
			};
		};
	};

};

HiassofT
Posts: 200
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Thu Aug 01, 2019 10:56 pm

You need to have a codec driver that handles sample rate / clock switching (in .hwparams).

That stuff is very specific to the codec / clock generator you are using (some use I2C, some SPI, some a bunch of GPIOs) so unless you are using some codec that's already supported in linux you need to write one that's matching your hardware.

so long,

Hias

User avatar
egawtry
Posts: 3
Joined: Tue Dec 04, 2018 6:22 pm
Location: Minnesota, USA

Re: STICKY: The I2S sound thread.

Mon Aug 05, 2019 3:38 pm

Hias,

You are the first person to give me an actual idea in months of trying. Please explain. Is there a help link somewhere hidden on ".hwparams"?

Thanks,
-Erik

HiassofT
Posts: 200
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Mon Aug 05, 2019 7:35 pm

Have a look at the kernel documentation - Documentation/sound in the kernel tree or online here: https://www.kernel.org/doc/html/v4.19/sound/index.html

"Writing an ALSA driver" is a good start, it contains also info what hw_parans should do and how ALSA in general works.

The ASoC sections may also be of interest to you, especially the "ASoC Codec Driver Class" section.

Also have a look at the codec drivers in sound/soc/codecs - eg cs4349.c (which is a rather simple one).

Edit: These slides contain a nice introduction into ASoC https://elinux.org/images/b/b5/Belloni-alsa-asoc.pdf and are worth a read as well.

so long,

Hias

Return to “Interfacing (DSI, CSI, I2C, etc.)”