alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* How do I set up multiple codecs on one I2S - without TDM?
@ 2023-07-25 22:48 John Watts
  2023-07-27  9:45 ` Pierre-Louis Bossart
  2023-08-01 17:55 ` John Watts
  0 siblings, 2 replies; 4+ messages in thread
From: John Watts @ 2023-07-25 22:48 UTC (permalink / raw)
  To: alsa-devel

Hello there!

I have an interesting problem that I'm trying to solve. It will require
writing adding driver support but right now I'm struggling to understand
how I should go about it all.

As a background, this is with the Allwinner D1 or T113. It has a 16
channel I2S controller and each channel can be configured to use a
specific pin and TDM time slice. Even channels are low LRCLK, odd are
high LRCLK.

So for my situation I want to have six channels:

- Channel 0: Timeslot 0, Pin 0, LRCLK 0 -> ADC 1
- Channel 1: Timeslot 0, Pin 0, LRCLK 1 -> ADC 1
- Channel 2: Timeslot 0, Pin 1, LRCLK 0 -> ADC 2
- Channel 3: Timeslot 0, Pin 1, LRCLK 1 -> ADC 2
- Channel 4: Timeslot 0, Pin 2, LRCLK 0 -> ADC 3
- Channel 5: Timeslot 0, Pin 2, LRCLK 1 -> ADC 3

These ADCs are WM8782s, completely TDM unaware. If they were TDM aware
then I could run even more ADCs by having multiple separate TDMs going
on each pin.

I have tried to look online for I2S controllers that do the same thing
but haven't had much luck. The current driver for this controller only
supports TDM. So I will have to add support for this.

So my questions are: 
- How do I express this in terms of ALSA and sound card concepts?
- How do I express this in the device tree?

My immediate thought is that this is a situation where I have a card
with 3 dai-links between the I2S controller and each separate codec.
I have written this tree as a test:

    wm8782_1: stereo-adc {
    	compatible = "wlf,wm8782";
    	Vdda-supply = <&reg_vcc>;
    	Vdd-supply = <&reg_vcc>;
    	#sound-dai-cells = <0>;
    };
    
    wm8782_2: stereo-adc {
    	compatible = "wlf,wm8782";
    	Vdda-supply = <&reg_vcc>;
    	Vdd-supply = <&reg_vcc>;
    	#sound-dai-cells = <0>;
    };
    
    wm8782_3: stereo-adc {
    	compatible = "wlf,wm8782";
    	Vdda-supply = <&reg_vcc>;
    	Vdd-supply = <&reg_vcc>;
    	#sound-dai-cells = <0>;
    };
    
    sound {
    	compatible = "simple-audio-card";
    	simple-audio-card,name = "Testcard In";
    	simple-audio-card,format = "i2s";
    	simple-audio-card,bitclock-master = <&sound_cpu>;
    	simple-audio-card,frame-master = <&sound_cpu>;
    	simple-audio-card,mclk-fs = <128>;
    	#address-cells = <1>;
    	#size-cells = <0>;
    	simple-audio-card,dai-link@0 {
    		reg = <0>;
    		sound_cpu: cpu {
    			sound-dai = <&i2s2>;
    		};
    		codec {
    			sound-dai = <&wm8782_1>;
    		};
    	};
    	simple-audio-card,dai-link@1 {
    		reg = <1>;
    		cpu {
    			sound-dai = <&i2s2>;
    		};
    		codec {
    			sound-dai = <&wm8782_2>;
    		};
    	};
    	simple-audio-card,dai-link@2 {
    		reg = <2>;
    		cpu {
    			sound-dai = <&i2s2>;
    		};
    		codec {
    			sound-dai = <&wm8782_3>;
    		};
    	};
    };

But I get this kernel error:

    kobject_add_internal failed for 2034000.i2s-wm8782 with -EEXIST, don't try to register things with the same name
    asoc-simple-card: probe of sound failed with error -12

The WM8782 doesn't support TDM or multiplexing so I'm not exactly sure
if this is correct behaviour or my mistake configuring.

I tried adding TDM nodes which didn't help.

I also tried having a single link with multiple codecs on sound-dai
which did create a sound card but it was unclear to me if this was
ignoring the other codecs I had listed or not.

I also can't test this at this point as the sunxi codec driver assumes
that the number of channels is equal to TDM slots, which isn't true any
more.

Any pointers in the right direction would be a huge help.
Surely someone else has had this problem.

Thanks,
John.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How do I set up multiple codecs on one I2S - without TDM?
  2023-07-25 22:48 How do I set up multiple codecs on one I2S - without TDM? John Watts
@ 2023-07-27  9:45 ` Pierre-Louis Bossart
  2023-07-27  9:50   ` John Watts
  2023-08-01 17:55 ` John Watts
  1 sibling, 1 reply; 4+ messages in thread
From: Pierre-Louis Bossart @ 2023-07-27  9:45 UTC (permalink / raw)
  To: John Watts, alsa-devel

On 7/26/23 12:48 AM, John Watts wrote:
> Hello there!
> 
> I have an interesting problem that I'm trying to solve. It will require
> writing adding driver support but right now I'm struggling to understand
> how I should go about it all.
> 
> As a background, this is with the Allwinner D1 or T113. It has a 16
> channel I2S controller and each channel can be configured to use a
> specific pin and TDM time slice. Even channels are low LRCLK, odd are
> high LRCLK.
> 
> So for my situation I want to have six channels:
> 
> - Channel 0: Timeslot 0, Pin 0, LRCLK 0 -> ADC 1
> - Channel 1: Timeslot 0, Pin 0, LRCLK 1 -> ADC 1
> - Channel 2: Timeslot 0, Pin 1, LRCLK 0 -> ADC 2
> - Channel 3: Timeslot 0, Pin 1, LRCLK 1 -> ADC 2
> - Channel 4: Timeslot 0, Pin 2, LRCLK 0 -> ADC 3
> - Channel 5: Timeslot 0, Pin 2, LRCLK 1 -> ADC 3

It would help if you described what those different 'channels' are 
supposed to transmit. Usually channels mean a group of data that is 
rendered at the same time. It looks like you plan on transmitting 
independent streams that may be enabled/disabled separately.

Also you should describe if there are independent clocks or if all those 
6 'channels' are transmitted with a single pair of bit/frame clocks? 
That completely changes the model, in the former case you could 
represent independent DAIs/dailinks but in the latter case you really 
have a single muxed stream.



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How do I set up multiple codecs on one I2S - without TDM?
  2023-07-27  9:45 ` Pierre-Louis Bossart
@ 2023-07-27  9:50   ` John Watts
  0 siblings, 0 replies; 4+ messages in thread
From: John Watts @ 2023-07-27  9:50 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: alsa-devel

On Thu, Jul 27, 2023 at 11:45:01AM +0200, Pierre-Louis Bossart wrote:
> On 7/26/23 12:48 AM, John Watts wrote:
> > Hello there!
> > 
> > I have an interesting problem that I'm trying to solve. It will require
> > writing adding driver support but right now I'm struggling to understand
> > how I should go about it all.
> > 
> > As a background, this is with the Allwinner D1 or T113. It has a 16
> > channel I2S controller and each channel can be configured to use a
> > specific pin and TDM time slice. Even channels are low LRCLK, odd are
> > high LRCLK.
> > 
> > So for my situation I want to have six channels:
> > 
> > - Channel 0: Timeslot 0, Pin 0, LRCLK 0 -> ADC 1
> > - Channel 1: Timeslot 0, Pin 0, LRCLK 1 -> ADC 1
> > - Channel 2: Timeslot 0, Pin 1, LRCLK 0 -> ADC 2
> > - Channel 3: Timeslot 0, Pin 1, LRCLK 1 -> ADC 2
> > - Channel 4: Timeslot 0, Pin 2, LRCLK 0 -> ADC 3
> > - Channel 5: Timeslot 0, Pin 2, LRCLK 1 -> ADC 3
> 
> It would help if you described what those different 'channels' are supposed
> to transmit. Usually channels mean a group of data that is rendered at the
> same time. It looks like you plan on transmitting independent streams that
> may be enabled/disabled separately.
> 
> Also you should describe if there are independent clocks or if all those 6
> 'channels' are transmitted with a single pair of bit/frame clocks? That
> completely changes the model, in the former case you could represent
> independent DAIs/dailinks but in the latter case you really have a single
> muxed stream.

Hello,

These channels are intended for measuring vibration at various points in a
vehicle. Each channel is a vibration measurement.

These all use the same I2S clock, multiplexing is handled by having each ADC
connected to a different I2S pin.

John.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How do I set up multiple codecs on one I2S - without TDM?
  2023-07-25 22:48 How do I set up multiple codecs on one I2S - without TDM? John Watts
  2023-07-27  9:45 ` Pierre-Louis Bossart
@ 2023-08-01 17:55 ` John Watts
  1 sibling, 0 replies; 4+ messages in thread
From: John Watts @ 2023-08-01 17:55 UTC (permalink / raw)
  To: alsa-devel

I return days later with an answer, so I shall try and answer my own email.

On Wed, Jul 26, 2023 at 08:48:18AM +1000, John Watts wrote:
> So my questions are: 
> - How do I express this in terms of ALSA and sound card concepts?
> - How do I express this in the device tree?

After reading the following links:

https://lore.kernel.org/all/87fsw124wn.wl-kuninori.morimoto.gx@renesas.com/
https://lore.kernel.org/r/87ilbx1kh3.wl-kuninori.morimoto.gx@renesas.com

I found that this is a case of 1:N cpus to codecs, and this can be
solved using audio-graph-card2.

So I set up a device tree like this:

	wm8782_1: stereo-adc-1 {
		compatible = "wlf,wm8782";
		Vdda-supply = <&reg_vcc>;
		Vdd-supply = <&reg_vcc>;
		#sound-dai-cells = <0>;
		port {
			wm8782_1_ep: endpoint {
				remote-endpoint = <&card_ep_1>;
			};
		};
	};

	wm8782_2: stereo-adc-2 {
		compatible = "wlf,wm8782";
		Vdda-supply = <&reg_vcc>;
		Vdd-supply = <&reg_vcc>;
		#sound-dai-cells = <0>;
		port {
			wm8782_2_ep: endpoint {
				remote-endpoint = <&card_ep_2>;
			};
		};
	};

	wm8782_3: stereo-adc-3 {
		compatible = "wlf,wm8782";
		Vdda-supply = <&reg_vcc>;
		Vdd-supply = <&reg_vcc>;
		#sound-dai-cells = <0>;
		port {
			wm8782_3_ep: endpoint {
				remote-endpoint = <&card_ep_3>;
			};
		};
	};

	sound {
		compatible = "audio-graph-card2";
		links = <&i2s2_port>;
		multi {
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 {
					card_ep_0: endpoint {
						remote-endpoint = <&i2s2_ep>;
					};
				};
				port@1 {
					card_ep_1: endpoint {
						remote-endpoint = <&wm8782_1_ep>;
					};
				};
				port@2 {
					card_ep_2: endpoint {
						remote-endpoint = <&wm8782_2_ep>;
					};
				};
				port@3 {
					card_ep_3: endpoint {
						remote-endpoint = <&wm8782_3_ep>;
					};
				};
			};
		};
	};

	&i2s2 {
		pinctrl-0 = <&i2s2_pins>, <&i2s2_din_pins>;
		pinctrl-names = "default";
		status = "okay";
		i2s2_port: port {
			format = "i2s";
			mclk-fs = <128>;
			bitclock-master;
			frame-master;
			i2s2_ep: endpoint {
				remote-endpoint = <&card_ep_0>;
			};
		};
	};

Immediately I was able to record from the needed channels!
After tinkering with the driver registers I was even able to get it to
read the channels properly :)

I hope this helps somebody else in my situation.
John.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-08-04  9:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-25 22:48 How do I set up multiple codecs on one I2S - without TDM? John Watts
2023-07-27  9:45 ` Pierre-Louis Bossart
2023-07-27  9:50   ` John Watts
2023-08-01 17:55 ` John Watts

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).