@@ -155,49 +155,68 @@ static int hda_link_dma_params(struct hdac_ext_stream *stream,
155155 return 0 ;
156156}
157157
158- /* Send DAI_CONFIG IPC to the DAI that matches the dai_name and direction */
159- static int hda_link_config_ipc (struct sof_intel_hda_stream * hda_stream ,
160- const char * dai_name , int channel , int dir )
158+ /* Update config for the DAI widget */
159+ static struct sof_ipc_dai_config * hda_dai_update_config (struct snd_soc_dapm_widget * w ,
160+ int channel )
161161{
162+ struct snd_sof_widget * swidget = w -> dobj .private ;
162163 struct sof_ipc_dai_config * config ;
163164 struct snd_sof_dai * sof_dai ;
164- struct sof_ipc_reply reply ;
165- int ret = 0 ;
166165
167- list_for_each_entry (sof_dai , & hda_stream -> sdev -> dai_list , list ) {
168- if (!sof_dai -> cpu_dai_name )
169- continue ;
166+ if (!swidget )
167+ return NULL ;
170168
171- if (!strcmp (dai_name , sof_dai -> cpu_dai_name ) &&
172- dir == sof_dai -> comp_dai .direction ) {
173- config = sof_dai -> dai_config ;
169+ sof_dai = swidget -> private ;
174170
175- if (!config ) {
176- dev_err (hda_stream -> sdev -> dev ,
177- "error: no config for DAI %s\n" ,
178- sof_dai -> name );
179- return - EINVAL ;
180- }
171+ if (!sof_dai || !sof_dai -> dai_config ) {
172+ dev_err (swidget -> scomp -> dev , "error: No config for DAI %s\n" , w -> name );
173+ return NULL ;
174+ }
181175
182- /* update config with stream tag */
183- config -> hda .link_dma_ch = channel ;
176+ config = & sof_dai -> dai_config [sof_dai -> current_config ];
184177
185- /* send IPC */
186- ret = sof_ipc_tx_message (hda_stream -> sdev -> ipc ,
187- config -> hdr .cmd ,
188- config ,
189- config -> hdr .size ,
190- & reply , sizeof (reply ));
178+ /* update config with stream tag */
179+ config -> hda .link_dma_ch = channel ;
191180
192- if (ret < 0 )
193- dev_err (hda_stream -> sdev -> dev ,
194- "error: failed to set dai config for %s\n" ,
195- sof_dai -> name );
196- return ret ;
197- }
181+ return config ;
182+ }
183+
184+ static int hda_link_config_ipc (struct sof_intel_hda_stream * hda_stream ,
185+ struct snd_soc_dapm_widget * w , int channel )
186+ {
187+ struct snd_sof_dev * sdev = hda_stream -> sdev ;
188+ struct sof_ipc_dai_config * config ;
189+ struct sof_ipc_reply reply ;
190+
191+ config = hda_dai_update_config (w , channel );
192+ if (!config ) {
193+ dev_err (sdev -> dev , "error: no config for DAI %s\n" , w -> name );
194+ return - ENOENT ;
195+ }
196+
197+ /* send DAI_CONFIG IPC */
198+ return sof_ipc_tx_message (sdev -> ipc , config -> hdr .cmd , config , config -> hdr .size ,
199+ & reply , sizeof (reply ));
200+ }
201+
202+ static int hda_link_dai_widget_update (struct sof_intel_hda_stream * hda_stream ,
203+ struct snd_soc_dapm_widget * w ,
204+ int channel , bool widget_setup )
205+ {
206+ struct snd_sof_dev * sdev = hda_stream -> sdev ;
207+ struct sof_ipc_dai_config * config ;
208+
209+ config = hda_dai_update_config (w , channel );
210+ if (!config ) {
211+ dev_err (sdev -> dev , "error: no config for DAI %s\n" , w -> name );
212+ return - ENOENT ;
198213 }
199214
200- return - EINVAL ;
215+ /* set up/free DAI widget and send DAI_CONFIG IPC */
216+ if (widget_setup )
217+ return hda_ctrl_dai_widget_setup (w );
218+
219+ return hda_ctrl_dai_widget_free (w );
201220}
202221
203222static int hda_link_hw_params (struct snd_pcm_substream * substream ,
@@ -211,6 +230,7 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
211230 struct snd_soc_dai * codec_dai = asoc_rtd_to_codec (rtd , 0 );
212231 struct sof_intel_hda_stream * hda_stream ;
213232 struct hda_pipe_params p_params = {0 };
233+ struct snd_soc_dapm_widget * w ;
214234 struct hdac_ext_link * link ;
215235 int stream_tag ;
216236 int ret ;
@@ -229,9 +249,13 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
229249
230250 hda_stream = hstream_to_sof_hda_stream (link_dev );
231251
232- /* update the DSP with the new tag */
233- ret = hda_link_config_ipc (hda_stream , dai -> name , stream_tag - 1 ,
234- substream -> stream );
252+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
253+ w = dai -> playback_widget ;
254+ else
255+ w = dai -> capture_widget ;
256+
257+ /* set up the DAI widget and send the DAI_CONFIG with the new tag */
258+ ret = hda_link_dai_widget_update (hda_stream , w , stream_tag - 1 , true);
235259 if (ret < 0 )
236260 return ret ;
237261
@@ -287,6 +311,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
287311 snd_soc_dai_get_dma_data (dai , substream );
288312 struct sof_intel_hda_stream * hda_stream ;
289313 struct snd_soc_pcm_runtime * rtd ;
314+ struct snd_soc_dapm_widget * w ;
290315 struct hdac_ext_link * link ;
291316 struct hdac_stream * hstream ;
292317 struct hdac_bus * bus ;
@@ -321,12 +346,16 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
321346 break ;
322347 case SNDRV_PCM_TRIGGER_SUSPEND :
323348 case SNDRV_PCM_TRIGGER_STOP :
349+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
350+ w = dai -> playback_widget ;
351+ else
352+ w = dai -> capture_widget ;
353+
324354 /*
325355 * clear link DMA channel. It will be assigned when
326356 * hw_params is set up again after resume.
327357 */
328- ret = hda_link_config_ipc (hda_stream , dai -> name ,
329- DMA_CHAN_INVALID , substream -> stream );
358+ ret = hda_link_config_ipc (hda_stream , w , DMA_CHAN_INVALID );
330359 if (ret < 0 )
331360 return ret ;
332361
@@ -357,6 +386,7 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
357386 struct hdac_stream * hstream ;
358387 struct snd_soc_pcm_runtime * rtd ;
359388 struct hdac_ext_stream * link_dev ;
389+ struct snd_soc_dapm_widget * w ;
360390 int ret ;
361391
362392 hstream = substream -> runtime -> private_data ;
@@ -372,9 +402,13 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
372402
373403 hda_stream = hstream_to_sof_hda_stream (link_dev );
374404
375- /* free the link DMA channel in the FW */
376- ret = hda_link_config_ipc (hda_stream , dai -> name , DMA_CHAN_INVALID ,
377- substream -> stream );
405+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
406+ w = dai -> playback_widget ;
407+ else
408+ w = dai -> capture_widget ;
409+
410+ /* free the link DMA channel in the FW and the DAI widget */
411+ ret = hda_link_dai_widget_update (hda_stream , w , DMA_CHAN_INVALID , false);
378412 if (ret < 0 )
379413 return ret ;
380414
@@ -406,47 +440,51 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = {
406440
407441#endif
408442
409- static int ssp_dai_hw_params (struct snd_pcm_substream * substream ,
410- struct snd_pcm_hw_params * params ,
411- struct snd_soc_dai * dai )
443+ static int ssp_dai_setup_or_free (struct snd_pcm_substream * substream , struct snd_soc_dai * dai ,
444+ bool setup )
412445{
413- struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd (substream );
414- struct snd_soc_component * component = snd_soc_rtdcom_lookup (rtd , SOF_AUDIO_PCM_DRV_NAME );
415- struct snd_sof_dev * sdev = snd_soc_component_get_drvdata (component );
416- struct sof_ipc_fw_version * v = & sdev -> fw_ready .version ;
417- struct sof_ipc_dai_config * config ;
418- struct snd_sof_dai * sof_dai ;
419- struct sof_ipc_reply reply ;
420- int ret ;
446+ struct snd_soc_component * component ;
447+ struct snd_sof_widget * swidget ;
448+ struct snd_soc_dapm_widget * w ;
449+ struct sof_ipc_fw_version * v ;
450+ struct snd_sof_dev * sdev ;
451+
452+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
453+ w = dai -> playback_widget ;
454+ else
455+ w = dai -> capture_widget ;
456+
457+ swidget = w -> dobj .private ;
458+ component = swidget -> scomp ;
459+ sdev = snd_soc_component_get_drvdata (component );
460+ v = & sdev -> fw_ready .version ;
421461
422462 /* DAI_CONFIG IPC during hw_params is not supported in older firmware */
423463 if (v -> abi_version < SOF_ABI_VER (3 , 18 , 0 ))
424464 return 0 ;
425465
426- list_for_each_entry (sof_dai , & sdev -> dai_list , list ) {
427- if (!sof_dai -> cpu_dai_name || !sof_dai -> dai_config )
428- continue ;
429-
430- if (!strcmp (dai -> name , sof_dai -> cpu_dai_name ) &&
431- substream -> stream == sof_dai -> comp_dai .direction ) {
432- config = & sof_dai -> dai_config [sof_dai -> current_config ];
466+ if (setup )
467+ return hda_ctrl_dai_widget_setup (w );
433468
434- /* send IPC */
435- ret = sof_ipc_tx_message (sdev -> ipc , config -> hdr .cmd , config ,
436- config -> hdr .size , & reply , sizeof (reply ));
469+ return hda_ctrl_dai_widget_free (w );
470+ }
437471
438- if ( ret < 0 )
439- dev_err ( sdev -> dev , "error: failed to set DAI config for %s\n" ,
440- sof_dai -> name );
441- return ret ;
442- }
443- }
472+ static int ssp_dai_hw_params ( struct snd_pcm_substream * substream ,
473+ struct snd_pcm_hw_params * params ,
474+ struct snd_soc_dai * dai )
475+ {
476+ return ssp_dai_setup_or_free ( substream , dai , true);
477+ }
444478
445- return 0 ;
479+ static int ssp_dai_hw_free (struct snd_pcm_substream * substream ,
480+ struct snd_soc_dai * dai )
481+ {
482+ return ssp_dai_setup_or_free (substream , dai , false);
446483}
447484
448485static const struct snd_soc_dai_ops ssp_dai_ops = {
449486 .hw_params = ssp_dai_hw_params ,
487+ .hw_free = ssp_dai_hw_free ,
450488};
451489
452490/*
0 commit comments