Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: Intel: hda-dai: prepare LNL support

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

The HDAudio support has not changed much since CometLake/2019: the
code was reshuffled for IPC4 support and we used hdac_hda for external
and Display Audio codec, but the hda-dai code was only used for
HDAudio codecs.

In the LunarLake architecture, all endpoints (HDaudio, SSP, DMIC,
SoundWire) are handled with the HDaudio DMA, which requires us to
revisit the definitions of HDA_LINK, and remove the mutual exclusion
between NOCODEC and HDA_LINK: we do want the ability to test SSP/DMIC
in NOCODEC mode even with an HDA DMA.

This code change exposed a number of issues, with a useless .prepare
callback, a DAI number mismatch and the need to support SoundWire
which is handled by a different component in
drivers/soundwire/intel_ace2.c.

+63 -61
+1 -2
sound/soc/sof/intel/Kconfig
··· 284 284 285 285 config SND_SOC_SOF_HDA_LINK 286 286 bool "SOF support for HDA Links(HDA/HDMI)" 287 - depends on SND_SOC_SOF_NOCODEC_SUPPORT=n 288 - select SND_SOC_SOF_PROBE_WORK_QUEUE 289 287 help 290 288 This adds support for HDA links(HDA/HDMI) with Sound Open Firmware 291 289 for Intel(R) platforms. ··· 293 295 config SND_SOC_SOF_HDA_AUDIO_CODEC 294 296 bool "SOF support for HDAudio codecs" 295 297 depends on SND_SOC_SOF_HDA_LINK 298 + select SND_SOC_SOF_PROBE_WORK_QUEUE 296 299 help 297 300 This adds support for HDAudio codecs with Sound Open Firmware 298 301 for Intel(R) platforms.
+8 -3
sound/soc/sof/intel/hda-bus.c
··· 70 70 { 71 71 struct hdac_bus *bus = sof_to_bus(sdev); 72 72 73 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 73 74 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 74 75 snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops); 75 - #else /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ 76 + #else 77 + snd_hdac_ext_bus_init(bus, dev, NULL, NULL); 78 + #endif 79 + #else 80 + 76 81 memset(bus, 0, sizeof(*bus)); 77 82 bus->dev = dev; 78 83 ··· 92 87 bus->idx = 0; 93 88 94 89 spin_lock_init(&bus->reg_lock); 95 - #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ 90 + #endif /* CONFIG_SND_SOC_SOF_HDA_LINK */ 96 91 } 97 92 98 93 void sof_hda_bus_exit(struct snd_sof_dev *sdev) 99 94 { 100 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 95 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 101 96 struct hdac_bus *bus = sof_to_bus(sdev); 102 97 103 98 snd_hdac_ext_bus_exit(bus);
+2 -2
sound/soc/sof/intel/hda-dai-ops.c
··· 16 16 #include "hda.h" 17 17 18 18 /* These ops are only applicable for the HDA DAI's in their current form */ 19 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 19 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 20 20 /* 21 21 * This function checks if the host dma channel corresponding 22 22 * to the link DMA stream_tag argument is assigned to one ··· 350 350 const struct hda_dai_widget_dma_ops * 351 351 hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 352 352 { 353 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 353 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 354 354 struct snd_sof_dai *sdai; 355 355 356 356 if (sdev->dspless_mode_selected)
+51 -53
sound/soc/sof/intel/hda-dai.c
··· 27 27 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); 28 28 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); 29 29 30 + static struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w) 31 + { 32 + struct snd_sof_widget *swidget = w->dobj.private; 33 + struct snd_soc_component *component = swidget->scomp; 34 + 35 + return snd_soc_component_get_drvdata(component); 36 + } 37 + 30 38 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, 31 39 struct snd_sof_dai_config_data *data) 32 40 { 33 41 struct snd_sof_widget *swidget = w->dobj.private; 34 42 const struct sof_ipc_tplg_ops *tplg_ops; 35 - struct snd_soc_component *component; 36 43 struct snd_sof_dev *sdev; 37 44 int ret; 38 45 39 46 if (!swidget) 40 47 return 0; 41 48 42 - component = swidget->scomp; 43 - sdev = snd_soc_component_get_drvdata(component); 49 + sdev = widget_to_sdev(w); 44 50 tplg_ops = sof_ipc_get_ops(sdev, tplg); 45 51 46 52 if (tplg_ops && tplg_ops->dai_config) { ··· 61 55 return 0; 62 56 } 63 57 64 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 58 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 59 + 60 + static struct snd_sof_dev *dai_to_sdev(struct snd_pcm_substream *substream, 61 + struct snd_soc_dai *cpu_dai) 62 + { 63 + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 64 + 65 + return widget_to_sdev(w); 66 + } 65 67 66 68 static const struct hda_dai_widget_dma_ops * 67 69 hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 68 70 { 69 71 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 70 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); 71 72 struct snd_sof_widget *swidget = w->dobj.private; 73 + struct snd_sof_dev *sdev; 72 74 struct snd_sof_dai *sdai; 75 + 76 + sdev = widget_to_sdev(w); 73 77 74 78 /* 75 79 * The swidget parameter of hda_select_dai_widget_ops() is ignored in ··· 112 96 struct snd_soc_dai *cpu_dai, 113 97 struct snd_soc_dai *codec_dai) 114 98 { 115 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); 116 99 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 117 100 struct hdac_stream *hstream = &hext_stream->hstream; 118 101 struct hdac_bus *bus = hstream->bus; 119 102 struct sof_intel_hda_stream *hda_stream; 120 103 struct hdac_ext_link *hlink; 104 + struct snd_sof_dev *sdev; 121 105 int stream_tag; 106 + 107 + sdev = dai_to_sdev(substream, cpu_dai); 122 108 123 109 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 124 110 if (!hlink) ··· 158 140 unsigned int link_bps; 159 141 int stream_tag; 160 142 161 - sdev = snd_soc_component_get_drvdata(cpu_dai->component); 143 + sdev = dai_to_sdev(substream, cpu_dai); 162 144 bus = sof_to_bus(sdev); 163 145 164 146 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); ··· 206 188 return 0; 207 189 } 208 190 209 - static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 191 + static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, 192 + struct snd_soc_dai *cpu_dai) 210 193 { 211 - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 212 - int stream = substream->stream; 213 - 214 - return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); 215 - } 216 - 217 - static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 218 - { 219 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); 220 194 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 221 195 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 222 196 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 223 197 struct hdac_ext_stream *hext_stream; 198 + struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai); 224 199 225 200 if (!ops) { 226 201 dev_err(sdev->dev, "DAI widget ops not set\n"); ··· 227 216 return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); 228 217 } 229 218 230 - static int hda_dai_hw_params(struct snd_pcm_substream *substream, 231 - struct snd_pcm_hw_params *params, 232 - struct snd_soc_dai *dai) 219 + static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, 220 + struct snd_pcm_hw_params *params, 221 + struct snd_soc_dai *dai) 233 222 { 234 223 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); 235 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); 236 224 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 237 225 struct hdac_ext_stream *hext_stream; 238 226 struct snd_sof_dai_config_data data = { 0 }; 239 227 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 228 + struct snd_sof_dev *sdev = widget_to_sdev(w); 240 229 int ret; 241 230 242 231 if (!ops) { ··· 260 249 return hda_dai_config(w, flags, &data); 261 250 } 262 251 263 - static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 264 - { 265 - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); 266 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); 267 - const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 268 - struct hdac_ext_stream *hext_stream; 269 - struct snd_sof_dai_config_data data = { 0 }; 270 - unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 271 - int ret; 272 - 273 - hext_stream = ops->get_hext_stream(sdev, dai, substream); 274 - if (hext_stream && hext_stream->link_prepared) 275 - return 0; 276 - 277 - dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream); 278 - 279 - ret = hda_link_dma_prepare(substream, dai); 280 - if (ret < 0) 281 - return ret; 282 - 283 - hext_stream = ops->get_hext_stream(sdev, dai, substream); 284 - 285 - flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; 286 - data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; 287 - 288 - return hda_dai_config(w, flags, &data); 289 - } 290 - 291 252 /* 292 253 * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes 293 254 * (over IPC channel) and DMA state change (direct host register changes). 294 255 */ 295 - static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) 256 + static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 257 + struct snd_soc_dai *dai) 296 258 { 297 - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); 298 259 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 299 260 struct hdac_ext_stream *hext_stream; 300 261 struct snd_soc_pcm_runtime *rtd; 301 262 struct snd_soc_dai *codec_dai; 263 + struct snd_sof_dev *sdev; 302 264 int ret; 303 265 304 266 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, 305 267 dai->name, substream->stream); 268 + 269 + sdev = dai_to_sdev(substream, dai); 306 270 307 271 hext_stream = ops->get_hext_stream(sdev, dai, substream); 308 272 if (!hext_stream) ··· 319 333 return 0; 320 334 } 321 335 336 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 337 + 338 + static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 339 + { 340 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 341 + int stream = substream->stream; 342 + 343 + return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); 344 + } 345 + 322 346 static const struct snd_soc_dai_ops hda_dai_ops = { 323 347 .hw_params = hda_dai_hw_params, 324 348 .hw_free = hda_dai_hw_free, 325 349 .trigger = hda_dai_trigger, 326 350 .prepare = hda_dai_prepare, 327 351 }; 352 + 353 + #endif 328 354 329 355 static int hda_dai_suspend(struct hdac_bus *bus) 330 356 { ··· 370 372 codec_dai = asoc_rtd_to_codec(rtd, 0); 371 373 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 372 374 swidget = w->dobj.private; 373 - sdev = snd_soc_component_get_drvdata(swidget->scomp); 375 + sdev = widget_to_sdev(w); 374 376 sdai = swidget->private; 375 377 ops = sdai->platform_private; 376 378 ··· 586 588 * Since the component suspend is called last, we can trap this corner case 587 589 * and force the DAIs to release their resources. 588 590 */ 589 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 591 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 590 592 int ret; 591 593 592 594 ret = hda_dai_suspend(sof_to_bus(sdev));
+1 -1
sound/soc/sof/intel/hda.h
··· 414 414 (HDA_DSP_BDL_SIZE / sizeof(struct sof_intel_dsp_bdl)) 415 415 416 416 /* Number of DAIs */ 417 - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 417 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 418 418 #define SOF_SKL_NUM_DAIS 15 419 419 #else 420 420 #define SOF_SKL_NUM_DAIS 8