@@ -116,10 +116,171 @@ static int intel_link_power_down(struct sdw_intel *sdw)
116116 return ret ;
117117}
118118
119+ /*
120+ * DAI operations
121+ */
122+ static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
123+ };
124+
125+ static const struct snd_soc_component_driver dai_component = {
126+ .name = "soundwire" ,
127+ };
128+
129+ /*
130+ * PDI routines
131+ */
132+ static void intel_pdi_init (struct sdw_intel * sdw ,
133+ struct sdw_cdns_stream_config * config )
134+ {
135+ void __iomem * shim = sdw -> link_res -> shim ;
136+ int pcm_cap ;
137+
138+ /* PCM Stream Capability */
139+ pcm_cap = intel_readw (shim , SDW_SHIM2_PCMSCAP );
140+
141+ config -> pcm_bd = FIELD_GET (SDW_SHIM2_PCMSCAP_BSS , pcm_cap );
142+ config -> pcm_in = FIELD_GET (SDW_SHIM2_PCMSCAP_ISS , pcm_cap );
143+ config -> pcm_out = FIELD_GET (SDW_SHIM2_PCMSCAP_ISS , pcm_cap );
144+
145+ dev_dbg (sdw -> cdns .dev , "PCM cap bd:%d in:%d out:%d\n" ,
146+ config -> pcm_bd , config -> pcm_in , config -> pcm_out );
147+ }
148+
149+ static int
150+ intel_pdi_get_ch_cap (struct sdw_intel * sdw , unsigned int pdi_num )
151+ {
152+ void __iomem * shim = sdw -> link_res -> shim ;
153+
154+ /* zero based values for channel count in register */
155+ return intel_readw (shim , SDW_SHIM2_PCMSYCHC (pdi_num )) + 1 ;
156+ }
157+
158+ static void intel_pdi_get_ch_update (struct sdw_intel * sdw ,
159+ struct sdw_cdns_pdi * pdi ,
160+ unsigned int num_pdi ,
161+ unsigned int * num_ch )
162+ {
163+ int ch_count = 0 ;
164+ int i ;
165+
166+ for (i = 0 ; i < num_pdi ; i ++ ) {
167+ pdi -> ch_count = intel_pdi_get_ch_cap (sdw , pdi -> num );
168+ ch_count += pdi -> ch_count ;
169+ pdi ++ ;
170+ }
171+
172+ * num_ch = ch_count ;
173+ }
174+
175+ static void intel_pdi_stream_ch_update (struct sdw_intel * sdw ,
176+ struct sdw_cdns_streams * stream )
177+ {
178+ intel_pdi_get_ch_update (sdw , stream -> bd , stream -> num_bd ,
179+ & stream -> num_ch_bd );
180+
181+ intel_pdi_get_ch_update (sdw , stream -> in , stream -> num_in ,
182+ & stream -> num_ch_in );
183+
184+ intel_pdi_get_ch_update (sdw , stream -> out , stream -> num_out ,
185+ & stream -> num_ch_out );
186+ }
187+
188+ static int intel_create_dai (struct sdw_cdns * cdns ,
189+ struct snd_soc_dai_driver * dais ,
190+ enum intel_pdi_type type ,
191+ u32 num , u32 off , u32 max_ch )
192+ {
193+ int i ;
194+
195+ if (!num )
196+ return 0 ;
197+
198+ for (i = off ; i < (off + num ); i ++ ) {
199+ dais [i ].name = devm_kasprintf (cdns -> dev , GFP_KERNEL ,
200+ "SDW%d Pin%d" ,
201+ cdns -> instance , i );
202+ if (!dais [i ].name )
203+ return - ENOMEM ;
204+
205+ if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT ) {
206+ dais [i ].playback .channels_min = 1 ;
207+ dais [i ].playback .channels_max = max_ch ;
208+ }
209+
210+ if (type == INTEL_PDI_BD || type == INTEL_PDI_IN ) {
211+ dais [i ].capture .channels_min = 1 ;
212+ dais [i ].capture .channels_max = max_ch ;
213+ }
214+
215+ dais [i ].ops = & intel_pcm_dai_ops ;
216+ }
217+
218+ return 0 ;
219+ }
220+
221+ static int intel_register_dai (struct sdw_intel * sdw )
222+ {
223+ struct sdw_cdns_dai_runtime * * dai_runtime_array ;
224+ struct sdw_cdns_stream_config config ;
225+ struct sdw_cdns * cdns = & sdw -> cdns ;
226+ struct sdw_cdns_streams * stream ;
227+ struct snd_soc_dai_driver * dais ;
228+ int num_dai ;
229+ int ret ;
230+ int off = 0 ;
231+
232+ /* Read the PDI config and initialize cadence PDI */
233+ intel_pdi_init (sdw , & config );
234+ ret = sdw_cdns_pdi_init (cdns , config );
235+ if (ret )
236+ return ret ;
237+
238+ intel_pdi_stream_ch_update (sdw , & sdw -> cdns .pcm );
239+
240+ /* DAIs are created based on total number of PDIs supported */
241+ num_dai = cdns -> pcm .num_pdi ;
242+
243+ dai_runtime_array = devm_kcalloc (cdns -> dev , num_dai ,
244+ sizeof (struct sdw_cdns_dai_runtime * ),
245+ GFP_KERNEL );
246+ if (!dai_runtime_array )
247+ return - ENOMEM ;
248+ cdns -> dai_runtime_array = dai_runtime_array ;
249+
250+ dais = devm_kcalloc (cdns -> dev , num_dai , sizeof (* dais ), GFP_KERNEL );
251+ if (!dais )
252+ return - ENOMEM ;
253+
254+ /* Create PCM DAIs */
255+ stream = & cdns -> pcm ;
256+
257+ ret = intel_create_dai (cdns , dais , INTEL_PDI_IN , cdns -> pcm .num_in ,
258+ off , stream -> num_ch_in );
259+ if (ret )
260+ return ret ;
261+
262+ off += cdns -> pcm .num_in ;
263+ ret = intel_create_dai (cdns , dais , INTEL_PDI_OUT , cdns -> pcm .num_out ,
264+ off , stream -> num_ch_out );
265+ if (ret )
266+ return ret ;
267+
268+ off += cdns -> pcm .num_out ;
269+ ret = intel_create_dai (cdns , dais , INTEL_PDI_BD , cdns -> pcm .num_bd ,
270+ off , stream -> num_ch_bd );
271+ if (ret )
272+ return ret ;
273+
274+ return devm_snd_soc_register_component (cdns -> dev , & dai_component ,
275+ dais , num_dai );
276+ }
277+
119278const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = {
120279 .debugfs_init = intel_ace2x_debugfs_init ,
121280 .debugfs_exit = intel_ace2x_debugfs_exit ,
122281
282+ .register_dai = intel_register_dai ,
283+
123284 .link_power_up = intel_link_power_up ,
124285 .link_power_down = intel_link_power_down ,
125286};
0 commit comments