1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
11 #include <sound/pcm_params.h>
12 #include <sound/hdaudio_ext.h>
13 #include <sound/intel-nhlt.h>
14 #include <sound/sof/ipc4/header.h>
15 #include <uapi/sound/sof/header.h>
16 #include "../ipc4-priv.h"
17 #include "../ipc4-topology.h"
18 #include "../sof-priv.h"
19 #include "../sof-audio.h"
23 * The default method is to fetch NHLT from BIOS. With this parameter set
24 * it is possible to override that with NHLT in the SOF topology manifest.
26 static bool hda_use_tplg_nhlt;
27 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
28 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
30 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
31 struct snd_sof_dai_config_data *data)
33 struct snd_sof_widget *swidget = w->dobj.private;
34 const struct sof_ipc_tplg_ops *tplg_ops;
35 struct snd_soc_component *component;
36 struct snd_sof_dev *sdev;
42 component = swidget->scomp;
43 sdev = snd_soc_component_get_drvdata(component);
44 tplg_ops = sof_ipc_get_ops(sdev, tplg);
46 if (tplg_ops && tplg_ops->dai_config) {
47 ret = tplg_ops->dai_config(sdev, swidget, flags, data);
49 dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n",
58 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
60 static const struct hda_dai_widget_dma_ops *
61 hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
63 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
64 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component);
65 struct snd_sof_widget *swidget = w->dobj.private;
66 struct snd_sof_dai *sdai;
69 * The swidget parameter of hda_select_dai_widget_ops() is ignored in
70 * case of DSPless mode
72 if (sdev->dspless_mode_selected)
73 return hda_select_dai_widget_ops(sdev, NULL);
75 sdai = swidget->private;
77 /* select and set the DAI widget ops if not set already */
78 if (!sdai->platform_private) {
79 const struct hda_dai_widget_dma_ops *ops =
80 hda_select_dai_widget_ops(sdev, swidget);
84 /* check if mandatory ops are set */
85 if (!ops || !ops->get_hext_stream)
88 sdai->platform_private = ops;
91 return sdai->platform_private;
94 static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
95 struct hdac_ext_stream *hext_stream,
96 struct snd_soc_dai *cpu_dai,
97 struct snd_soc_dai *codec_dai)
99 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component);
100 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
101 struct hdac_stream *hstream = &hext_stream->hstream;
102 struct hdac_bus *bus = hstream->bus;
103 struct sof_intel_hda_stream *hda_stream;
104 struct hdac_ext_link *hlink;
107 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
111 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
112 stream_tag = hdac_stream(hext_stream)->stream_tag;
113 snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag);
116 if (ops->release_hext_stream)
117 ops->release_hext_stream(sdev, cpu_dai, substream);
119 hext_stream->link_prepared = 0;
121 /* free the host DMA channel reserved by hostless streams */
122 hda_stream = hstream_to_sof_hda_stream(hext_stream);
123 hda_stream->host_reserved = 0;
128 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
129 struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai)
131 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
132 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
133 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
134 struct hdac_ext_stream *hext_stream;
135 struct hdac_stream *hstream;
136 struct hdac_ext_link *hlink;
137 struct snd_sof_dev *sdev;
138 struct hdac_bus *bus;
139 unsigned int format_val;
140 unsigned int link_bps;
143 sdev = snd_soc_component_get_drvdata(cpu_dai->component);
144 bus = sof_to_bus(sdev);
146 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
150 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
153 if (ops->assign_hext_stream)
154 hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream);
160 hstream = &hext_stream->hstream;
161 stream_tag = hstream->stream_tag;
163 if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK)
164 snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag);
166 /* set the hdac_stream in the codec dai */
167 snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream);
169 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
170 link_bps = codec_dai->driver->playback.sig_bits;
172 link_bps = codec_dai->driver->capture.sig_bits;
174 if (ops->reset_hext_stream)
175 ops->reset_hext_stream(sdev, hext_stream);
177 format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params),
178 params_format(params), link_bps, 0);
180 dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
181 params_rate(params), params_channels(params), params_format(params));
183 if (ops->setup_hext_stream)
184 ops->setup_hext_stream(sdev, hext_stream, format_val);
186 hext_stream->link_prepared = 1;
191 static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
193 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
194 int stream = substream->stream;
196 return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai);
199 static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
201 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component);
202 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
203 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
204 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
205 struct hdac_ext_stream *hext_stream;
208 dev_err(sdev->dev, "DAI widget ops not set\n");
212 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
216 return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai);
219 static int hda_dai_hw_params(struct snd_pcm_substream *substream,
220 struct snd_pcm_hw_params *params,
221 struct snd_soc_dai *dai)
223 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
224 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
225 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
226 struct hdac_ext_stream *hext_stream;
227 struct snd_sof_dai_config_data data = { 0 };
228 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
232 dev_err(sdev->dev, "DAI widget ops not set\n");
236 hext_stream = ops->get_hext_stream(sdev, dai, substream);
237 if (hext_stream && hext_stream->link_prepared)
240 ret = hda_link_dma_hw_params(substream, params, dai);
244 hext_stream = ops->get_hext_stream(sdev, dai, substream);
246 flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
247 data.dai_data = hdac_stream(hext_stream)->stream_tag - 1;
249 return hda_dai_config(w, flags, &data);
252 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
254 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
255 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
256 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
257 struct hdac_ext_stream *hext_stream;
258 struct snd_sof_dai_config_data data = { 0 };
259 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
262 hext_stream = ops->get_hext_stream(sdev, dai, substream);
263 if (hext_stream && hext_stream->link_prepared)
266 dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream);
268 ret = hda_link_dma_prepare(substream, dai);
272 hext_stream = ops->get_hext_stream(sdev, dai, substream);
274 flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
275 data.dai_data = hdac_stream(hext_stream)->stream_tag - 1;
277 return hda_dai_config(w, flags, &data);
281 * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes
282 * (over IPC channel) and DMA state change (direct host register changes).
284 static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
286 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
287 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
288 struct hdac_ext_stream *hext_stream;
289 struct snd_soc_pcm_runtime *rtd;
290 struct snd_soc_dai *codec_dai;
293 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
294 dai->name, substream->stream);
296 hext_stream = ops->get_hext_stream(sdev, dai, substream);
300 rtd = asoc_substream_to_rtd(substream);
301 codec_dai = asoc_rtd_to_codec(rtd, 0);
303 if (ops->pre_trigger) {
304 ret = ops->pre_trigger(sdev, dai, substream, cmd);
310 ret = ops->trigger(sdev, dai, substream, cmd);
315 if (ops->post_trigger) {
316 ret = ops->post_trigger(sdev, dai, substream, cmd);
322 case SNDRV_PCM_TRIGGER_SUSPEND:
323 ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai);
325 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
336 static const struct snd_soc_dai_ops hda_dai_ops = {
337 .hw_params = hda_dai_hw_params,
338 .hw_free = hda_dai_hw_free,
339 .trigger = hda_dai_trigger,
340 .prepare = hda_dai_prepare,
343 static int hda_dai_suspend(struct hdac_bus *bus)
345 struct snd_soc_pcm_runtime *rtd;
346 struct hdac_ext_stream *hext_stream;
347 struct hdac_stream *s;
350 /* set internal flag for BE */
351 list_for_each_entry(s, &bus->stream_list, list) {
353 hext_stream = stream_to_hdac_ext_stream(s);
356 * clear stream. This should already be taken care for running
357 * streams when the SUSPEND trigger is called. But paused
358 * streams do not get suspended, so this needs to be done
359 * explicitly during suspend.
361 if (hext_stream->link_substream) {
362 const struct hda_dai_widget_dma_ops *ops;
363 struct snd_sof_widget *swidget;
364 struct snd_soc_dapm_widget *w;
365 struct snd_soc_dai *codec_dai;
366 struct snd_soc_dai *cpu_dai;
367 struct snd_sof_dev *sdev;
368 struct snd_sof_dai *sdai;
370 rtd = asoc_substream_to_rtd(hext_stream->link_substream);
371 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
372 codec_dai = asoc_rtd_to_codec(rtd, 0);
373 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction);
374 swidget = w->dobj.private;
375 sdev = snd_soc_component_get_drvdata(swidget->scomp);
376 sdai = swidget->private;
377 ops = sdai->platform_private;
379 ret = hda_link_dma_cleanup(hext_stream->link_substream,
385 /* for consistency with TRIGGER_SUSPEND */
386 if (ops->post_trigger) {
387 ret = ops->post_trigger(sdev, cpu_dai,
388 hext_stream->link_substream,
389 SNDRV_PCM_TRIGGER_SUSPEND);
401 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
405 for (i = 0; i < ops->num_drv; i++) {
406 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
407 if (strstr(ops->drv[i].name, "iDisp") ||
408 strstr(ops->drv[i].name, "Analog") ||
409 strstr(ops->drv[i].name, "Digital"))
410 ops->drv[i].ops = &hda_dai_ops;
414 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) {
415 struct sof_ipc4_fw_data *ipc4_data = sdev->private;
417 ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
421 void hda_ops_free(struct snd_sof_dev *sdev)
423 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
424 struct sof_ipc4_fw_data *ipc4_data = sdev->private;
426 if (!hda_use_tplg_nhlt)
427 intel_nhlt_free(ipc4_data->nhlt);
430 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON);
433 * common dai driver for skl+ platforms.
434 * some products who use this DAI array only physically have a subset of
435 * the DAIs, but no harm is done here by adding the whole set.
437 struct snd_soc_dai_driver skl_dai[] = {
505 .name = "DMIC01 Pin",
512 .name = "DMIC16k Pin",
518 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
520 .name = "iDisp1 Pin",
527 .name = "iDisp2 Pin",
534 .name = "iDisp3 Pin",
541 .name = "iDisp4 Pin",
548 .name = "Analog CPU DAI",
559 .name = "Digital CPU DAI",
570 .name = "Alt Analog CPU DAI",
583 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
586 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
587 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
588 * Since the component suspend is called last, we can trap this corner case
589 * and force the DAIs to release their resources.
591 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
594 ret = hda_dai_suspend(sof_to_bus(sdev));