Unverified Commit b2b6b2d8 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: makes CPU/Codec channel connection map more

Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

Current ASoC is supporting CPU/Codec = N:M (N < M) connection by using
ch_map idea. This patch-set expands it that all connection uses this idea,
and no longer N < M limit [1][2].

Link: https://lore.kernel.org/r/87fs6wuszr.wl-kuninori.morimoto.gx@renesas.com [1]
Link: https://lore.kernel.org/r/878r7yqeo4.wl-kuninori.morimoto.gx@renesas.com [2]

ASoC core code ([PATCH 1/5]) is same as v6 and it was tested by Pierre-Louis,
and Jerome. Big change on v7 is basically for Audio-Graph-Card2.
parents 9b3cd8eb 792846d9
Loading
Loading
Loading
Loading
+53 −3
Original line number Diff line number Diff line
@@ -655,8 +655,45 @@ struct snd_soc_dai_link_component {
	struct of_phandle_args *dai_args;
};

struct snd_soc_dai_link_codec_ch_map {
	unsigned int connected_cpu_id;
/*
 * [dai_link->ch_maps Image sample]
 *
 *-------------------------
 * CPU0 <---> Codec0
 *
 * ch-map[0].cpu = 0	ch-map[0].codec = 0
 *
 *-------------------------
 * CPU0 <---> Codec0
 * CPU1 <---> Codec1
 * CPU2 <---> Codec2
 *
 * ch-map[0].cpu = 0	ch-map[0].codec = 0
 * ch-map[1].cpu = 1	ch-map[1].codec = 1
 * ch-map[2].cpu = 2	ch-map[2].codec = 2
 *
 *-------------------------
 * CPU0 <---> Codec0
 * CPU1 <-+-> Codec1
 * CPU2 <-/
 *
 * ch-map[0].cpu = 0	ch-map[0].codec = 0
 * ch-map[1].cpu = 1	ch-map[1].codec = 1
 * ch-map[2].cpu = 2	ch-map[2].codec = 1
 *
 *-------------------------
 * CPU0 <---> Codec0
 * CPU1 <-+-> Codec1
 *	  \-> Codec2
 *
 * ch-map[0].cpu = 0	ch-map[0].codec = 0
 * ch-map[1].cpu = 1	ch-map[1].codec = 1
 * ch-map[2].cpu = 1	ch-map[2].codec = 2
 *
 */
struct snd_soc_dai_link_ch_map {
	unsigned int cpu;
	unsigned int codec;
	unsigned int ch_mask;
};

@@ -688,7 +725,9 @@ struct snd_soc_dai_link {
	struct snd_soc_dai_link_component *codecs;
	unsigned int num_codecs;

	struct snd_soc_dai_link_codec_ch_map *codec_ch_maps;
	/* num_ch_maps = max(num_cpu, num_codecs) */
	struct snd_soc_dai_link_ch_map *ch_maps;

	/*
	 * You MAY specify the link's platform/PCM/DMA driver, either by
	 * device name, or by DT/OF node, but not both. Some forms of link
@@ -775,6 +814,10 @@ struct snd_soc_dai_link {
#endif
};

static inline int snd_soc_link_num_ch_map(struct snd_soc_dai_link *link) {
	return max(link->num_cpus, link->num_codecs);
}

static inline struct snd_soc_dai_link_component*
snd_soc_link_to_cpu(struct snd_soc_dai_link *link, int n) {
	return &(link)->cpus[n];
@@ -808,6 +851,12 @@ snd_soc_link_to_platform(struct snd_soc_dai_link *link, int n) {
		     ((cpu) = snd_soc_link_to_cpu(link, i));		\
	     (i)++)

#define for_each_link_ch_maps(link, i, ch_map)			\
	for ((i) = 0;						\
	     ((i) < snd_soc_link_num_ch_map(link) &&		\
		      ((ch_map) = link->ch_maps + i));		\
	     (i)++)

/*
 * Sample 1 : Single CPU/Codec/Platform
 *
@@ -1163,6 +1212,7 @@ struct snd_soc_pcm_runtime {
	     ((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) &&	\
		     ((dai) = (rtd)->dais[i]);				\
	     (i)++)
#define for_each_rtd_ch_maps(rtd, i, ch_maps) for_each_link_ch_maps(rtd->dai_link, i, ch_maps)

void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);

+341 −39
Original line number Diff line number Diff line
@@ -58,12 +58,32 @@ / {
	 *			| |-> codec13
	 *			+-+
	 *
	 * [Multi-CPU/Codec]
	 * [Multi-CPU/Codec-0]
	 *		+-+		+-+
	 *	cpu1 <--| |<-@--------->| |-> codec1
	 *	cpu2 <--| |		| |-> codec2
	 *		+-+		+-+
	 *
	 * [Multi-CPU/Codec-1]
	 *
	 *		+-+		+-+
	 *		| |<-@--------->| |
	 *		| |		| |
	 *	cpu8 <--| |<----------->| |-> codec14
	 *	cpu9 <--| |<---+------->| |-> codec15
	 *		+-+	\------>| |-> codec16
	 *				+-+
	 *
	 * [Multi-CPU/Codec-2]
	 *
	 *		+-+		+-+
	 *		| |<-@--------->| |
	 *		| |		| |
	 *	cpu10 <-| |<----------->| |-> codec17
	 *	cpu11 <-| |<-----+----->| |-> codec18
	 *	cpu12 <-| |<----/	+-+
	 *		+-+
	 *
	 * [DPCM]
	 *
	 *	CPU3/CPU4 are converting rate to 44100
@@ -144,15 +164,38 @@ audio-graph-card2-custom-sample {
			 */
			 &cpu0

			/* [Semi-Multi] */
			/*
			 * [Semi-Multi]
			 * cpu7/codec12/codec13
			 */
			&sm0

			/*
			 * [Multi-CPU/Codec]: cpu side only
			 * [Multi-CPU/Codec-0]: cpu side only
			 * cpu1/cpu2/codec1/codec2
			 */
			 &mcpu0

			/*
			 * [Multi-CPU/Codec-1]: cpu side only
			 * cpu8/cpu9/codec14/codec15/codec16
			 *
			 * Because it will reach to the maximum of sound minor number,
			 * disable it so far.
			 * If you want to try it, please disable some other one instead.
			 */
			//&mcpu1

			/*
			 * [Multi-CPU/Codec-2]: cpu side only
			 * cpu10/cpu11/cpu12/codec17/codec18
			 *
			 * Because it will reach to the maximum of sound minor number,
			 * disable it so far.
			 * If you want to try it, please disable some other one instead.
			 */
			//&mcpu2

			/*
			 * [DPCM]: both FE / BE
			 * cpu3/cpu4/codec3
@@ -182,64 +225,259 @@ multi {
			#address-cells = <1>;
			#size-cells = <0>;

			/*
			 * [Multi-CPU-0]
			 *
			 *		+---+		+---+
			 *	cpu1 <--|A X|<-@------->|x a|-> codec1
			 *	cpu2 <--|B  |		|  b|-> codec2
			 *		+---+		+---+
			 */
			ports@0 {
				reg = <0>;
				#address-cells = <1>;
				#size-cells = <0>;
			/* [Multi-CPU] */
			mcpu0:	port@0 { reg = <0>; mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; };
				port@1 { reg = <1>; mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>;    }; };
				port@2 { reg = <2>; mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>;    }; };
			mcpu0:	port@0 { reg = <0>; mcpu00_ep: endpoint { remote-endpoint = <&mcodec00_ep>; };};/* (X) to pair */
				port@1 { reg = <1>; mcpu01_ep: endpoint { remote-endpoint = <&cpu1_ep>;     };};/* (A) Multi Element */
				port@2 { reg = <2>; mcpu02_ep: endpoint { remote-endpoint = <&cpu2_ep>;     };};/* (B) Multi Element */
			};

			/* [Multi-Codec] */
			/*
			 * [Multi-Codec-0]
			 *
			 *		+---+		+---+
			 *	cpu1 <--|A X|<-@------->|x a|-> codec1
			 *	cpu2 <--|B  |		|  b|-> codec2
			 *		+---+		+---+
			 */
			ports@1 {
				reg = <1>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>;  }; };
				port@1 { reg = <1>; mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
				port@2 { reg = <2>; mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; };
				port@0 { reg = <0>; mcodec00_ep: endpoint { remote-endpoint = <&mcpu00_ep>; };};/* (x) to pair */
				port@1 { reg = <1>; mcodec01_ep: endpoint { remote-endpoint = <&codec1_ep>; };};/* (a) Multi Element */
				port@2 { reg = <2>; mcodec02_ep: endpoint { remote-endpoint = <&codec2_ep>; };};/* (b) Multi Element */
			};

			/* [DPCM-Multi]::BE */
			/*
			 * [DPCM-Multi]::BE
			 *
			 *	FE			BE
			 *		  ****		+---+
			 *	cpu5 <-@--*  *-----@--->|x a|-> codec4
			 *	cpu6 <-@--*  *		|  b|-> codec5
			 *		  ****		+---+
			 */
			ports@2 {
				reg = <2>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mbe_ep:  endpoint { remote-endpoint = <&be10_ep>;  }; };
				port@1 { reg = <1>; mbe1_ep: endpoint { remote-endpoint = <&codec4_ep>; }; };
				port@2 { reg = <2>; mbe2_ep: endpoint { remote-endpoint = <&codec5_ep>; }; };
				port@0 { reg = <0>; mbe_ep:  endpoint { remote-endpoint = <&be10_ep>;   };};/* (x) to pair */
				port@1 { reg = <1>; mbe1_ep: endpoint { remote-endpoint = <&codec4_ep>; };};/* (a) Multi Element */
				port@2 { reg = <2>; mbe2_ep: endpoint { remote-endpoint = <&codec5_ep>; };};/* (b) Multi Element */
			};

			/* [Codec2Codec-Multi]::CPU */
			/*
			 * [Codec2Codec-Multi]::CPU
			 *
			 *		+---+
			 *	   +-@->|X A|-> codec8
			 *	   |	|  B|-> codec9
			 *	   |	+---+
			 *	   |	+---+
			 *	   +--->|x a|-> codec10
			 *		|  b|-> codec11
			 *		+---+
			 */
			ports@3 {
				reg = <3>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mc2c0_ep:  endpoint { remote-endpoint = <&c2cmf_ep>;  }; };
				port@1 { reg = <1>; mc2c00_ep: endpoint { remote-endpoint = <&codec8_ep>; }; };
				port@2 { reg = <2>; mc2c01_ep: endpoint { remote-endpoint = <&codec9_ep>; }; };
				port@0 { reg = <0>; mc2c0_ep:  endpoint { remote-endpoint = <&c2cmf_ep>;  };};/* (X) to pair */
				port@1 { reg = <1>; mc2c00_ep: endpoint { remote-endpoint = <&codec8_ep>; };};/* (A) Multi Element */
				port@2 { reg = <2>; mc2c01_ep: endpoint { remote-endpoint = <&codec9_ep>; };};/* (B) Multi Element */
			};

			/* [Codec2Codec-Multi]::Codec */
			/*
			 * [Codec2Codec-Multi]::Codec
			 *
			 *		+---+
			 *	   +-@->|X A|-> codec8
			 *	   |	|  B|-> codec9
			 *	   |	+---+
			 *	   |	+---+
			 *	   +--->|x a|-> codec10
			 *		|  b|-> codec11
			 *		+---+
			 */
			ports@4 {
				reg = <4>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mc2c1_ep:  endpoint { remote-endpoint = <&c2cmb_ep>;  }; };
				port@1 { reg = <1>; mc2c10_ep: endpoint { remote-endpoint = <&codec10_ep>; }; };
				port@2 { reg = <2>; mc2c11_ep: endpoint { remote-endpoint = <&codec11_ep>; }; };
				port@0 { reg = <0>; mc2c1_ep:  endpoint { remote-endpoint = <&c2cmb_ep>;   };};/* (x) to pair */
				port@1 { reg = <1>; mc2c10_ep: endpoint { remote-endpoint = <&codec10_ep>; };};/* (a) Multi Element */
				port@2 { reg = <2>; mc2c11_ep: endpoint { remote-endpoint = <&codec11_ep>; };};/* (b) Multi Element */
			};

			/* [Semi-Multi] */
			/*
			 * [Semi-Multi]
			 *
			 *			+---+
			 *	cpu7 <-@------->|X A|-> codec12
			 *			|  B|-> codec13
			 *			+---+
			 */
			ports@5 {
				reg = <5>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; smcodec0_ep: endpoint { remote-endpoint = <&cpu7_ep>;    }; };
				port@1 { reg = <1>; smcodec1_ep: endpoint { remote-endpoint = <&codec12_ep>; }; };
				port@2 { reg = <2>; smcodec2_ep: endpoint { remote-endpoint = <&codec13_ep>; }; };
				port@0 { reg = <0>; smcodec0_ep: endpoint { remote-endpoint = <&cpu7_ep>;    };};/* (X) to pair */
				port@1 { reg = <1>; smcodec1_ep: endpoint { remote-endpoint = <&codec12_ep>; };};/* (A) Multi Element */
				port@2 { reg = <2>; smcodec2_ep: endpoint { remote-endpoint = <&codec13_ep>; };};/* (B) Multi Element */
			};

			/*
			 * [Multi-CPU-1]
			 *
			 *		+---+		+---+
			 *		|  X|<-@------->|x  |
			 *		|   |		|   |
			 *	cpu8 <--|A 1|<--------->|3 a|-> codec14
			 *	cpu9 <--|B 2|<---+----->|4 b|-> codec15
			 *		+---+	  \---->|5 c|-> codec16
			 *				+---+
			 */
			ports@6 {
				reg = <6>;
				#address-cells = <1>;
				#size-cells = <0>;
			mcpu1:	port@0 { reg = <0>; mcpu10_ep: endpoint { remote-endpoint = <&mcodec10_ep>; };};    /* (X) to pair */
				port@1 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <1>;
					mcpu11_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&cpu8_ep>;       }; /* (A) Multi Element */
					mcpu11_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec11_ep_0>; }; /* (1) connected Codec */
				};
				port@2 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <2>;
					mcpu12_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&cpu9_ep>;       }; /* (B) Multi Element */
					mcpu12_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec12_ep_0>; }; /* (2) connected Codec */
					mcpu12_ep_1: endpoint@2 { reg = <2>; remote-endpoint = <&mcodec13_ep_0>; }; /* (2) connected Codec */
				};
			};

			/*
			 * [Multi-Codec-1]
			 *
			 *		+---+		+---+
			 *		|  X|<-@------->|x  |
			 *		|   |		|   |
			 *	cpu8 <--|A 1|<--------->|3 a|-> codec14
			 *	cpu9 <--|B 2|<---+----->|4 b|-> codec15
			 *		+---+	  \---->|5 c|-> codec16
			 *				+---+
			 */
			ports@7 {
				reg = <7>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mcodec10_ep: endpoint { remote-endpoint = <&mcpu10_ep>;  };};   /* (x) to pair */
				port@1 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <1>;
					mcodec11_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&codec14_ep>;  }; /* (a) Multi Element */
					mcodec11_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu11_ep_0>; }; /* (3) connected CPU */
				};
				port@2 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <2>;
					mcodec12_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&codec15_ep>;  }; /* (b) Multi Element */
					mcodec12_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu12_ep_0>; }; /* (4) connected CPU */
				};
				port@3 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <3>;
					mcodec13_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&codec16_ep>;  }; /* (c) Multi Element */
					mcodec13_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu12_ep_1>; }; /* (5) connected CPU */
				};
			};

			/*
			 * [Multi-CPU-2]
			 *
			 *		+---+		+---+
			 *		|  X|<-@------->|x  |
			 *		|   |		|   |
			 *	cpu10 <-|A 1|<--------->|4 a|-> codec17
			 *	cpu11 <-|B 2|<-----+--->|5 b|-> codec18
			 *	cpu12 <-|C 3|<----/	+---+
			 *		+---+
			 */
			ports@8 {
				reg = <8>;
				#address-cells = <1>;
				#size-cells = <0>;
			mcpu2:	port@0 { reg = <0>; mcpu20_ep: endpoint { remote-endpoint = <&mcodec20_ep>; };};    /* (X) to pair */
				port@1 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <1>;
					mcpu21_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&cpu10_ep>;      }; /* (A) Multi Element */
					mcpu21_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec21_ep_0>; }; /* (1) connected Codec */
				};
				port@2 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <2>;
					mcpu22_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&cpu11_ep>;      }; /* (B) Multi Element */
					mcpu22_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec22_ep_0>; }; /* (2) connected Codec */
				};
				port@3 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <3>;
					mcpu23_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&cpu12_ep>;      }; /* (C) Multi Element */
					mcpu23_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec22_ep_1>; }; /* (3) connected Codec */
				};
			};

			/*
			 * [Multi-Codec-2]
			 *
			 *		+---+		+---+
			 *		|  X|<-@------->|x  |
			 *		|   |		|   |
			 *	cpu10 <-|A 1|<--------->|4 a|-> codec17
			 *	cpu11 <-|B 2|<-----+--->|5 b|-> codec18
			 *	cpu12 <-|C 3|<----/	+---+
			 *		+---+
			 */
			ports@9 {
				reg = <9>;
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 { reg = <0>; mcodec20_ep: endpoint { remote-endpoint = <&mcpu20_ep>;  };};   /* (x) to pair */
				port@1 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <1>;
					mcodec21_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&codec17_ep>;  }; /* (a) Multi Element */
					mcodec21_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu21_ep_0>; }; /* (4) connected CPU */
				};
				port@2 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <2>;
					mcodec22_ep:   endpoint@0 { reg = <0>; remote-endpoint = <&codec18_ep>;  }; /* (b) Multi Element */
					mcodec22_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu22_ep_0>; }; /* (5) connected CPU */
					mcodec22_ep_1: endpoint@2 { reg = <2>; remote-endpoint = <&mcpu23_ep_0>; }; /* (5) connected CPU */
				};
			};
		};

@@ -252,11 +490,27 @@ ports@0 {

				#address-cells = <1>;
				#size-cells = <0>;
			/* [DPCM]::FE */
				/*
				 * [DPCM]::FE
				 *
				 *	FE				BE
				 *			****
				 *	cpu3 <-@(fe00)--*  *--(be0)@--> codec3
				 *	cpu4 <-@(fe01)--*  *		(44.1kHz)
				 *			****
				 */
			fe00:	port@0 { reg = <0>; fe00_ep: endpoint { remote-endpoint = <&cpu3_ep>; }; };
			fe01:	port@1 { reg = <1>; fe01_ep: endpoint { remote-endpoint = <&cpu4_ep>; }; };

			/* [DPCM-Multi]::FE */
				/*
				 * [DPCM-Multi]::FE
				 *
				 *		FE			BE
				 *			****		+-+
				 *	cpu5 <-@(fe10)--*  *---(be1)@-->| |-> codec4
				 *	cpu6 <-@(fe11)--*  *		| |-> codec5
				 *			****		+-+
				 */
			fe10:	port@2 { reg = <2>; fe10_ep: endpoint { remote-endpoint = <&cpu5_ep>; }; };
			fe11:	port@3 { reg = <3>; fe11_ep: endpoint { remote-endpoint = <&cpu6_ep>; }; };
			};
@@ -266,10 +520,26 @@ ports@1 {

				#address-cells = <1>;
				#size-cells = <0>;
			/* [DPCM]::BE */
				/*
				 * [DPCM]::BE
				 *
				 *	FE				BE
				 *			****
				 *	cpu3 <-@(fe00)--*  *--(be0)@--> codec3
				 *	cpu4 <-@(fe01)--*  *		(44.1kHz)
				 *			****
				 */
			be0:	port@0 { reg = <0>; be00_ep: endpoint { remote-endpoint = <&codec3_ep>; }; };

			/* [DPCM-Multi]::BE */
				/*
				 * [DPCM-Multi]::BE
				 *
				 *		FE			BE
				 *			****		+-+
				 *	cpu5 <-@(fe10)--*  *---(be1)@-->| |-> codec4
				 *	cpu6 <-@(fe11)--*  *		| |-> codec5
				 *			****		+-+
				 */
			be1:	port@1 { reg = <1>; be10_ep: endpoint { remote-endpoint = <&mbe_ep>; }; };
			};
		};
@@ -277,7 +547,13 @@ ports@1 {
		codec2codec {
			#address-cells = <1>;
			#size-cells = <0>;
			/* [Codec2Codec] */
			/*
			 * [Codec2Codec]
			 *
			 *	+-@(c2c)-> codec6
			 *	|
			 *	+--------> codec7
			 */
			ports@0 {
				reg = <0>;

@@ -289,7 +565,18 @@ ports@0 {
				port@1 { reg = <1>; c2cb_ep: endpoint { remote-endpoint = <&codec7_ep>; }; };
			};

			/* [Codec2Codec-Multi] */
			/*
			 * [Codec2Codec-Multi]
			 *
			 *			+-+
			 *	   +-@(c2c_m)-->| |-> codec8
			 *	   |		| |-> codec9
			 *	   |		+-+
			 *	   |		+-+
			 *	   +----------->| |-> codec10
			 *			| |-> codec11
			 *			+-+
			 */
			ports@1 {
				reg = <1>;

@@ -323,9 +610,9 @@ ports {
			/* [Normal] */
			cpu0: port@0 { reg = <0>; cpu0_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };

			/* [Multi-CPU] */
			      port@1 { reg = <1>; cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
			      port@2 { reg = <2>; cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
			/* [Multi-CPU-0] */
			      port@1 { reg = <1>; cpu1_ep: endpoint { remote-endpoint = <&mcpu01_ep>; }; };
			      port@2 { reg = <2>; cpu2_ep: endpoint { remote-endpoint = <&mcpu02_ep>; }; };

			/* [DPCM]::FE */
			      port@3 { reg = <3>; cpu3_ep: endpoint { remote-endpoint = <&fe00_ep>; }; };
@@ -337,6 +624,14 @@ ports {

			/* [Semi-Multi] */
			sm0:  port@7 { reg = <7>; cpu7_ep: endpoint { remote-endpoint = <&smcodec0_ep>; }; };

			/* [Multi-CPU-1] */
			      port@8 { reg = <8>; cpu8_ep: endpoint { remote-endpoint = <&mcpu11_ep>;   }; };
			      port@9 { reg = <9>; cpu9_ep: endpoint { remote-endpoint = <&mcpu12_ep>;   }; };
			/* [Multi-CPU-2] */
			      port@a { reg = <10>; cpu10_ep: endpoint { remote-endpoint = <&mcpu21_ep>; }; };
			      port@b { reg = <11>; cpu11_ep: endpoint { remote-endpoint = <&mcpu22_ep>; }; };
			      port@c { reg = <12>; cpu12_ep: endpoint { remote-endpoint = <&mcpu23_ep>; }; };
		};
	};

@@ -363,9 +658,9 @@ ports {
			/* [Normal] */
			port@0  { reg = <0>; codec0_ep:  endpoint { remote-endpoint = <&cpu0_ep>; }; };

			/* [Multi-Codec] */
			port@1  { reg = <1>; codec1_ep:  endpoint { remote-endpoint = <&mcodec1_ep>; }; };
			port@2  { reg = <2>; codec2_ep:  endpoint { remote-endpoint = <&mcodec2_ep>; }; };
			/* [Multi-Codec-0] */
			port@1  { reg = <1>; codec1_ep:  endpoint { remote-endpoint = <&mcodec01_ep>; }; };
			port@2  { reg = <2>; codec2_ep:  endpoint { remote-endpoint = <&mcodec02_ep>; }; };

			/* [DPCM]::BE */
			port@3  {
@@ -395,6 +690,13 @@ port@3 {
			port@c { reg = <12>; codec12_ep: endpoint { remote-endpoint = <&smcodec1_ep>; }; };
			port@d { reg = <13>; codec13_ep: endpoint { remote-endpoint = <&smcodec2_ep>; }; };

			/* [Multi-Codec-1] */
			port@e  { reg = <14>; codec14_ep: endpoint { remote-endpoint = <&mcodec11_ep>; }; };
			port@f  { reg = <15>; codec15_ep: endpoint { remote-endpoint = <&mcodec12_ep>; }; };
			port@10 { reg = <16>; codec16_ep: endpoint { remote-endpoint = <&mcodec13_ep>; }; };
			/* [Multi-Codec-2] */
			port@11 { reg = <17>; codec17_ep: endpoint { remote-endpoint = <&mcodec21_ep>; }; };
			port@12 { reg = <18>; codec18_ep: endpoint { remote-endpoint = <&mcodec22_ep>; }; };
		};
	};
};
+228 −49

File changed.

Preview size limit exceeded, changes collapsed.

+12 −16
Original line number Diff line number Diff line
@@ -570,16 +570,14 @@ int sdw_hw_params(struct snd_pcm_substream *substream,
		  struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct snd_soc_dai_link_ch_map *ch_maps;
	int ch = params_channels(params);
	struct snd_soc_dai *codec_dai;
	struct snd_soc_dai *cpu_dai;
	unsigned int ch_mask;
	int num_codecs;
	int step;
	int i;
	int j;

	if (!rtd->dai_link->codec_ch_maps)
	if (!rtd->dai_link->ch_maps)
		return 0;

	/* Identical data will be sent to all codecs in playback */
@@ -605,13 +603,9 @@ int sdw_hw_params(struct snd_pcm_substream *substream,
	 * link has more than one codec DAIs. Set codec channel mask and
	 * ASoC will set the corresponding channel numbers for each cpu dai.
	 */
	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
		for_each_rtd_codec_dais(rtd, j, codec_dai) {
			if (rtd->dai_link->codec_ch_maps[j].connected_cpu_id != i)
				continue;
			rtd->dai_link->codec_ch_maps[j].ch_mask = ch_mask << (j * step);
		}
	}
	for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
		ch_maps->ch_mask = ch_mask << (i * step);

	return 0;
}

@@ -1350,15 +1344,17 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
	return 0;
}

static void set_dailink_map(struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps,
static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps,
			    int codec_num, int cpu_num)
{
	int step;
	int i;

	step = codec_num / cpu_num;
	for (i = 0; i < codec_num; i++)
		sdw_codec_ch_maps[i].connected_cpu_id = i / step;
	for (i = 0; i < codec_num; i++) {
		sdw_codec_ch_maps[i].cpu	= i / step;
		sdw_codec_ch_maps[i].codec	= i;
	}
}

static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
@@ -1453,7 +1449,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
		*ignore_pch_dmic = true;

	for_each_pcm_streams(stream) {
		struct snd_soc_dai_link_codec_ch_map *sdw_codec_ch_maps;
		struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps;
		char *name, *cpu_name;
		int playback, capture;
		static const char * const sdw_stream_name[] = {
@@ -1530,7 +1526,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
		dai_links[*link_index].nonatomic = true;

		set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num);
		dai_links[*link_index].codec_ch_maps = sdw_codec_ch_maps;
		dai_links[*link_index].ch_maps = sdw_codec_ch_maps;
		ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++,
					  playback, group_id, adr_index, dai_index);
		if (ret < 0) {
+94 −1
Original line number Diff line number Diff line
@@ -1015,6 +1015,94 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card,
	return -EINVAL;
}

#define MAX_DEFAULT_CH_MAP_SIZE 7
static struct snd_soc_dai_link_ch_map default_ch_map_sync[MAX_DEFAULT_CH_MAP_SIZE] = {
	{ .cpu = 0, .codec = 0 },
	{ .cpu = 1, .codec = 1 },
	{ .cpu = 2, .codec = 2 },
	{ .cpu = 3, .codec = 3 },
	{ .cpu = 4, .codec = 4 },
	{ .cpu = 5, .codec = 5 },
	{ .cpu = 6, .codec = 6 },
};
static struct snd_soc_dai_link_ch_map default_ch_map_1cpu[MAX_DEFAULT_CH_MAP_SIZE] = {
	{ .cpu = 0, .codec = 0 },
	{ .cpu = 0, .codec = 1 },
	{ .cpu = 0, .codec = 2 },
	{ .cpu = 0, .codec = 3 },
	{ .cpu = 0, .codec = 4 },
	{ .cpu = 0, .codec = 5 },
	{ .cpu = 0, .codec = 6 },
};
static struct snd_soc_dai_link_ch_map default_ch_map_1codec[MAX_DEFAULT_CH_MAP_SIZE] = {
	{ .cpu = 0, .codec = 0 },
	{ .cpu = 1, .codec = 0 },
	{ .cpu = 2, .codec = 0 },
	{ .cpu = 3, .codec = 0 },
	{ .cpu = 4, .codec = 0 },
	{ .cpu = 5, .codec = 0 },
	{ .cpu = 6, .codec = 0 },
};
static int snd_soc_compensate_channel_connection_map(struct snd_soc_card *card,
						     struct snd_soc_dai_link *dai_link)
{
	struct snd_soc_dai_link_ch_map *ch_maps;
	int i;

	/*
	 * dai_link->ch_maps indicates how CPU/Codec are connected.
	 * It will be a map seen from a larger number of DAI.
	 * see
	 *	soc.h :: [dai_link->ch_maps Image sample]
	 */

	/* it should have ch_maps if connection was N:M */
	if (dai_link->num_cpus > 1 && dai_link->num_codecs > 1 &&
	    dai_link->num_cpus != dai_link->num_codecs && !dai_link->ch_maps) {
		dev_err(card->dev, "need to have ch_maps when N:M connction (%s)",
			dai_link->name);
		return -EINVAL;
	}

	/* do nothing if it has own maps */
	if (dai_link->ch_maps)
		goto sanity_check;

	/* check default map size */
	if (dai_link->num_cpus   > MAX_DEFAULT_CH_MAP_SIZE ||
	    dai_link->num_codecs > MAX_DEFAULT_CH_MAP_SIZE) {
		dev_err(card->dev, "soc-core.c needs update default_connection_maps");
		return -EINVAL;
	}

	/* Compensate missing map for ... */
	if (dai_link->num_cpus == dai_link->num_codecs)
		dai_link->ch_maps = default_ch_map_sync;	/* for 1:1 or N:N */
	else if (dai_link->num_cpus <  dai_link->num_codecs)
		dai_link->ch_maps = default_ch_map_1cpu;	/* for 1:N */
	else
		dai_link->ch_maps = default_ch_map_1codec;	/* for N:1 */

sanity_check:
	dev_dbg(card->dev, "dai_link %s\n", dai_link->stream_name);
	for_each_link_ch_maps(dai_link, i, ch_maps) {
		if ((ch_maps->cpu   >= dai_link->num_cpus) ||
		    (ch_maps->codec >= dai_link->num_codecs)) {
			dev_err(card->dev,
				"unexpected dai_link->ch_maps[%d] index (cpu(%d/%d) codec(%d/%d))",
				i,
				ch_maps->cpu,	dai_link->num_cpus,
				ch_maps->codec,	dai_link->num_codecs);
			return -EINVAL;
		}

		dev_dbg(card->dev, "  [%d] cpu%d <-> codec%d\n",
			i, ch_maps->cpu, ch_maps->codec);
	}

	return 0;
}

/**
 * snd_soc_remove_pcm_runtime - Remove a pcm_runtime from card
 * @card: The ASoC card to which the pcm_runtime has
@@ -1121,8 +1209,13 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card,
			     int num_dai_link)
{
	for (int i = 0; i < num_dai_link; i++) {
		int ret = snd_soc_add_pcm_runtime(card, dai_link + i);
		int ret;

		ret = snd_soc_compensate_channel_connection_map(card, dai_link + i);
		if (ret < 0)
			return ret;

		ret = snd_soc_add_pcm_runtime(card, dai_link + i);
		if (ret < 0)
			return ret;
	}
Loading