0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <sound/pcm_params.h>
0012 #include <sound/hdaudio_ext.h>
0013 #include <sound/intel-nhlt.h>
0014 #include <sound/sof/ipc4/header.h>
0015 #include <uapi/sound/sof/header.h>
0016 #include "../ipc4-priv.h"
0017 #include "../ipc4-topology.h"
0018 #include "../sof-priv.h"
0019 #include "../sof-audio.h"
0020 #include "hda.h"
0021
0022
0023
0024
0025
0026 static bool hda_use_tplg_nhlt;
0027 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
0028 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
0029
0030 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0031
0032 struct hda_pipe_params {
0033 u32 ch;
0034 u32 s_freq;
0035 u32 s_fmt;
0036 u8 linktype;
0037 snd_pcm_format_t format;
0038 int link_index;
0039 int stream;
0040 unsigned int link_bps;
0041 };
0042
0043
0044
0045
0046
0047
0048 static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd,
0049 int dir, int stream_tag)
0050 {
0051 struct snd_pcm_substream *fe_substream;
0052 struct hdac_stream *fe_hstream;
0053 struct snd_soc_dpcm *dpcm;
0054
0055 for_each_dpcm_fe(rtd, dir, dpcm) {
0056 fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir);
0057 fe_hstream = fe_substream->runtime->private_data;
0058 if (fe_hstream->stream_tag == stream_tag)
0059 return true;
0060 }
0061
0062 return false;
0063 }
0064
0065 static struct hdac_ext_stream *
0066 hda_link_stream_assign(struct hdac_bus *bus,
0067 struct snd_pcm_substream *substream)
0068 {
0069 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0070 struct sof_intel_hda_stream *hda_stream;
0071 const struct sof_intel_dsp_desc *chip;
0072 struct snd_sof_dev *sdev;
0073 struct hdac_ext_stream *res = NULL;
0074 struct hdac_stream *hstream = NULL;
0075
0076 int stream_dir = substream->stream;
0077
0078 if (!bus->ppcap) {
0079 dev_err(bus->dev, "stream type not supported\n");
0080 return NULL;
0081 }
0082
0083 spin_lock_irq(&bus->reg_lock);
0084 list_for_each_entry(hstream, &bus->stream_list, list) {
0085 struct hdac_ext_stream *hext_stream =
0086 stream_to_hdac_ext_stream(hstream);
0087 if (hstream->direction != substream->stream)
0088 continue;
0089
0090 hda_stream = hstream_to_sof_hda_stream(hext_stream);
0091 sdev = hda_stream->sdev;
0092 chip = get_chip_info(sdev->pdata);
0093
0094
0095 if (!hext_stream->link_locked) {
0096
0097
0098
0099
0100 if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) {
0101 res = hext_stream;
0102 break;
0103 }
0104
0105 if (hstream->opened) {
0106
0107
0108
0109
0110 if (hda_check_fes(rtd, stream_dir,
0111 hstream->stream_tag)) {
0112 res = hext_stream;
0113 break;
0114 }
0115 } else {
0116 res = hext_stream;
0117
0118
0119
0120
0121
0122 hda_stream->host_reserved = 1;
0123 break;
0124 }
0125 }
0126 }
0127
0128 if (res) {
0129
0130 snd_hdac_ext_stream_decouple_locked(bus, res, true);
0131
0132 res->link_locked = 1;
0133 res->link_substream = substream;
0134 }
0135 spin_unlock_irq(&bus->reg_lock);
0136
0137 return res;
0138 }
0139
0140 static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
0141 struct hdac_stream *hstream,
0142 struct snd_soc_dai *cpu_dai,
0143 struct snd_soc_dai *codec_dai,
0144 bool trigger_suspend_stop)
0145 {
0146 struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
0147 struct hdac_bus *bus = hstream->bus;
0148 struct sof_intel_hda_stream *hda_stream;
0149 struct hdac_ext_link *link;
0150 int stream_tag;
0151
0152 link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
0153 if (!link)
0154 return -EINVAL;
0155
0156 if (trigger_suspend_stop)
0157 snd_hdac_ext_link_stream_clear(hext_stream);
0158
0159 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0160 stream_tag = hdac_stream(hext_stream)->stream_tag;
0161 snd_hdac_ext_link_clear_stream_id(link, stream_tag);
0162 }
0163 snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
0164 snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
0165 hext_stream->link_prepared = 0;
0166
0167
0168 hda_stream = hstream_to_sof_hda_stream(hext_stream);
0169 hda_stream->host_reserved = 0;
0170
0171 return 0;
0172 }
0173
0174 static int hda_link_dma_params(struct hdac_ext_stream *hext_stream,
0175 struct hda_pipe_params *params)
0176 {
0177 struct hdac_stream *hstream = &hext_stream->hstream;
0178 unsigned char stream_tag = hstream->stream_tag;
0179 struct hdac_bus *bus = hstream->bus;
0180 struct hdac_ext_link *link;
0181 unsigned int format_val;
0182
0183 snd_hdac_ext_link_stream_reset(hext_stream);
0184
0185 format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
0186 params->format,
0187 params->link_bps, 0);
0188
0189 dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
0190 format_val, params->s_freq, params->ch, params->format);
0191
0192 snd_hdac_ext_link_stream_setup(hext_stream, format_val);
0193
0194 if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
0195 list_for_each_entry(link, &bus->hlink_list, list) {
0196 if (link->index == params->link_index)
0197 snd_hdac_ext_link_set_stream_id(link,
0198 stream_tag);
0199 }
0200 }
0201
0202 hext_stream->link_prepared = 1;
0203
0204 return 0;
0205 }
0206
0207 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
0208 struct snd_pcm_hw_params *params)
0209 {
0210 struct hdac_stream *hstream = substream->runtime->private_data;
0211 struct hdac_ext_stream *hext_stream;
0212 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0213 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0214 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0215 struct hda_pipe_params p_params = {0};
0216 struct hdac_bus *bus = hstream->bus;
0217 struct hdac_ext_link *link;
0218
0219 hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
0220 if (!hext_stream) {
0221 hext_stream = hda_link_stream_assign(bus, substream);
0222 if (!hext_stream)
0223 return -EBUSY;
0224
0225 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
0226 }
0227
0228 link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
0229 if (!link)
0230 return -EINVAL;
0231
0232
0233 snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream);
0234
0235 p_params.s_fmt = snd_pcm_format_width(params_format(params));
0236 p_params.ch = params_channels(params);
0237 p_params.s_freq = params_rate(params);
0238 p_params.stream = substream->stream;
0239 p_params.link_index = link->index;
0240 p_params.format = params_format(params);
0241
0242 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0243 p_params.link_bps = codec_dai->driver->playback.sig_bits;
0244 else
0245 p_params.link_bps = codec_dai->driver->capture.sig_bits;
0246
0247 return hda_link_dma_params(hext_stream, &p_params);
0248 }
0249
0250 static int hda_link_dma_prepare(struct snd_pcm_substream *substream)
0251 {
0252 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0253 int stream = substream->stream;
0254
0255 return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params);
0256 }
0257
0258 static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd)
0259 {
0260 struct hdac_stream *hstream = substream->runtime->private_data;
0261 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0262 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0263 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0264 struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
0265 int ret;
0266
0267 if (!hext_stream)
0268 return 0;
0269
0270 switch (cmd) {
0271 case SNDRV_PCM_TRIGGER_START:
0272 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0273 snd_hdac_ext_link_stream_start(hext_stream);
0274 break;
0275 case SNDRV_PCM_TRIGGER_SUSPEND:
0276 case SNDRV_PCM_TRIGGER_STOP:
0277 ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, true);
0278 if (ret < 0)
0279 return ret;
0280
0281 break;
0282 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0283 snd_hdac_ext_link_stream_clear(hext_stream);
0284
0285 break;
0286 default:
0287 return -EINVAL;
0288 }
0289 return 0;
0290 }
0291
0292 static int hda_link_dma_hw_free(struct snd_pcm_substream *substream)
0293 {
0294 struct hdac_stream *hstream = substream->runtime->private_data;
0295 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0296 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0297 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0298 struct hdac_ext_stream *hext_stream;
0299
0300 hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
0301 if (!hext_stream)
0302 return 0;
0303
0304 return hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
0305 }
0306
0307 static int hda_dai_widget_update(struct snd_soc_dapm_widget *w,
0308 int channel, bool widget_setup)
0309 {
0310 struct snd_sof_dai_config_data data;
0311
0312 data.dai_data = channel;
0313
0314
0315 if (widget_setup)
0316 return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data);
0317
0318 return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data);
0319 }
0320
0321 static int hda_dai_hw_params_update(struct snd_pcm_substream *substream,
0322 struct snd_pcm_hw_params *params,
0323 struct snd_soc_dai *dai)
0324 {
0325 struct hdac_ext_stream *hext_stream;
0326 struct snd_soc_dapm_widget *w;
0327 int stream_tag;
0328
0329 hext_stream = snd_soc_dai_get_dma_data(dai, substream);
0330 if (!hext_stream)
0331 return -EINVAL;
0332
0333 stream_tag = hdac_stream(hext_stream)->stream_tag;
0334
0335 w = snd_soc_dai_get_widget(dai, substream->stream);
0336
0337
0338 return hda_dai_widget_update(w, stream_tag - 1, true);
0339 }
0340
0341 static int hda_dai_hw_params(struct snd_pcm_substream *substream,
0342 struct snd_pcm_hw_params *params,
0343 struct snd_soc_dai *dai)
0344 {
0345 struct hdac_ext_stream *hext_stream =
0346 snd_soc_dai_get_dma_data(dai, substream);
0347 int ret;
0348
0349 if (hext_stream && hext_stream->link_prepared)
0350 return 0;
0351
0352 ret = hda_link_dma_hw_params(substream, params);
0353 if (ret < 0)
0354 return ret;
0355
0356 return hda_dai_hw_params_update(substream, params, dai);
0357 }
0358
0359
0360 static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
0361 {
0362 struct snd_sof_widget *swidget = w->dobj.private;
0363 struct snd_soc_component *component = swidget->scomp;
0364 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
0365 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
0366 int ret = 0;
0367
0368 if (tplg_ops->dai_config) {
0369 ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
0370 if (ret < 0)
0371 dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__,
0372 w->name);
0373 }
0374
0375 return ret;
0376 }
0377
0378 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0379 {
0380 struct hdac_ext_stream *hext_stream =
0381 snd_soc_dai_get_dma_data(dai, substream);
0382 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
0383 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0384 int stream = substream->stream;
0385 int ret;
0386
0387 if (hext_stream && hext_stream->link_prepared)
0388 return 0;
0389
0390 dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream);
0391
0392 ret = hda_link_dma_prepare(substream);
0393 if (ret < 0)
0394 return ret;
0395
0396 return hda_dai_hw_params_update(substream, &rtd->dpcm[stream].hw_params, dai);
0397 }
0398
0399 static int hda_dai_hw_free_ipc(int stream,
0400 struct snd_soc_dai *dai)
0401 {
0402 struct snd_soc_dapm_widget *w;
0403
0404 w = snd_soc_dai_get_widget(dai, stream);
0405
0406
0407 return hda_dai_widget_update(w, DMA_CHAN_INVALID, false);
0408 }
0409
0410 static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream,
0411 int cmd, struct snd_soc_dai *dai)
0412 {
0413 struct snd_soc_dapm_widget *w;
0414 int ret;
0415
0416 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
0417 dai->name, substream->stream);
0418
0419 ret = hda_link_dma_trigger(substream, cmd);
0420 if (ret < 0)
0421 return ret;
0422
0423 w = snd_soc_dai_get_widget(dai, substream->stream);
0424
0425 switch (cmd) {
0426 case SNDRV_PCM_TRIGGER_SUSPEND:
0427 case SNDRV_PCM_TRIGGER_STOP:
0428
0429
0430
0431 ret = hda_dai_hw_free_ipc(substream->stream, dai);
0432 if (ret < 0)
0433 return ret;
0434
0435 break;
0436 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0437 ret = hda_dai_config_pause_push_ipc(w);
0438 if (ret < 0)
0439 return ret;
0440 break;
0441
0442 default:
0443 break;
0444 }
0445 return 0;
0446 }
0447
0448
0449
0450
0451
0452 static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream,
0453 int cmd, struct snd_soc_dai *dai)
0454 {
0455 struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(dai, substream);
0456 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
0457 struct snd_soc_pcm_runtime *rtd;
0458 struct snd_sof_widget *swidget;
0459 struct snd_soc_dapm_widget *w;
0460 struct snd_soc_dai *codec_dai;
0461 struct hdac_stream *hstream;
0462 struct snd_soc_dai *cpu_dai;
0463 int ret;
0464
0465 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
0466 dai->name, substream->stream);
0467
0468 hstream = substream->runtime->private_data;
0469 rtd = asoc_substream_to_rtd(substream);
0470 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0471 codec_dai = asoc_rtd_to_codec(rtd, 0);
0472
0473 w = snd_soc_dai_get_widget(dai, substream->stream);
0474 swidget = w->dobj.private;
0475
0476 switch (cmd) {
0477 case SNDRV_PCM_TRIGGER_START:
0478 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0479 snd_hdac_ext_link_stream_start(hext_stream);
0480 break;
0481 case SNDRV_PCM_TRIGGER_SUSPEND:
0482 case SNDRV_PCM_TRIGGER_STOP:
0483 {
0484 struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
0485 struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
0486
0487 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0488 SOF_IPC4_PIPE_PAUSED);
0489 if (ret < 0)
0490 return ret;
0491
0492 pipeline->state = SOF_IPC4_PIPE_PAUSED;
0493
0494 snd_hdac_ext_link_stream_clear(hext_stream);
0495
0496 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0497 SOF_IPC4_PIPE_RESET);
0498 if (ret < 0)
0499 return ret;
0500
0501 pipeline->state = SOF_IPC4_PIPE_RESET;
0502
0503 ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
0504 if (ret < 0) {
0505 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
0506 return ret;
0507 }
0508 break;
0509 }
0510 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0511 {
0512 struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
0513 struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
0514
0515 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0516 SOF_IPC4_PIPE_PAUSED);
0517 if (ret < 0)
0518 return ret;
0519
0520 pipeline->state = SOF_IPC4_PIPE_PAUSED;
0521
0522 snd_hdac_ext_link_stream_clear(hext_stream);
0523 break;
0524 }
0525 default:
0526 dev_err(sdev->dev, "%s: unknown trigger command %d\n", __func__, cmd);
0527 return -EINVAL;
0528 }
0529
0530 return 0;
0531 }
0532
0533 static int hda_dai_hw_free(struct snd_pcm_substream *substream,
0534 struct snd_soc_dai *dai)
0535 {
0536 int ret;
0537
0538 ret = hda_link_dma_hw_free(substream);
0539 if (ret < 0)
0540 return ret;
0541
0542 return hda_dai_hw_free_ipc(substream->stream, dai);
0543 }
0544
0545 static const struct snd_soc_dai_ops ipc3_hda_dai_ops = {
0546 .hw_params = hda_dai_hw_params,
0547 .hw_free = hda_dai_hw_free,
0548 .trigger = ipc3_hda_dai_trigger,
0549 .prepare = hda_dai_prepare,
0550 };
0551
0552 static int hda_dai_suspend(struct hdac_bus *bus)
0553 {
0554 struct snd_soc_pcm_runtime *rtd;
0555 struct hdac_ext_stream *hext_stream;
0556 struct hdac_stream *s;
0557 int ret;
0558
0559
0560 list_for_each_entry(s, &bus->stream_list, list) {
0561
0562 hext_stream = stream_to_hdac_ext_stream(s);
0563
0564
0565
0566
0567
0568
0569
0570 if (hext_stream->link_substream) {
0571 struct snd_soc_dai *cpu_dai;
0572 struct snd_soc_dai *codec_dai;
0573
0574 rtd = asoc_substream_to_rtd(hext_stream->link_substream);
0575 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0576 codec_dai = asoc_rtd_to_codec(rtd, 0);
0577
0578 ret = hda_link_dma_cleanup(hext_stream->link_substream, s,
0579 cpu_dai, codec_dai, false);
0580 if (ret < 0)
0581 return ret;
0582
0583
0584 ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai);
0585 if (ret < 0)
0586 return ret;
0587 }
0588 }
0589
0590 return 0;
0591 }
0592
0593 static const struct snd_soc_dai_ops ipc4_hda_dai_ops = {
0594 .hw_params = hda_dai_hw_params,
0595 .hw_free = hda_dai_hw_free,
0596 .trigger = ipc4_hda_dai_trigger,
0597 .prepare = hda_dai_prepare,
0598 };
0599
0600 #endif
0601
0602
0603 struct ssp_dai_dma_data {
0604 bool setup;
0605 };
0606
0607 static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
0608 bool setup)
0609 {
0610 struct snd_soc_dapm_widget *w;
0611
0612 w = snd_soc_dai_get_widget(dai, substream->stream);
0613
0614 if (setup)
0615 return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
0616
0617 return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
0618 }
0619
0620 static int ssp_dai_startup(struct snd_pcm_substream *substream,
0621 struct snd_soc_dai *dai)
0622 {
0623 struct ssp_dai_dma_data *dma_data;
0624
0625 dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
0626 if (!dma_data)
0627 return -ENOMEM;
0628
0629 snd_soc_dai_set_dma_data(dai, substream, dma_data);
0630
0631 return 0;
0632 }
0633
0634 static int ssp_dai_setup(struct snd_pcm_substream *substream,
0635 struct snd_soc_dai *dai,
0636 bool setup)
0637 {
0638 struct ssp_dai_dma_data *dma_data;
0639 int ret = 0;
0640
0641 dma_data = snd_soc_dai_get_dma_data(dai, substream);
0642 if (!dma_data) {
0643 dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
0644 return -EIO;
0645 }
0646
0647 if (dma_data->setup != setup) {
0648 ret = ssp_dai_setup_or_free(substream, dai, setup);
0649 if (!ret)
0650 dma_data->setup = setup;
0651 }
0652 return ret;
0653 }
0654
0655 static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
0656 struct snd_pcm_hw_params *params,
0657 struct snd_soc_dai *dai)
0658 {
0659
0660 return ssp_dai_setup(substream, dai, true);
0661 }
0662
0663 static int ssp_dai_prepare(struct snd_pcm_substream *substream,
0664 struct snd_soc_dai *dai)
0665 {
0666
0667
0668
0669
0670 return ssp_dai_setup(substream, dai, true);
0671 }
0672
0673 static int ipc3_ssp_dai_trigger(struct snd_pcm_substream *substream,
0674 int cmd, struct snd_soc_dai *dai)
0675 {
0676 if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
0677 return 0;
0678
0679 return ssp_dai_setup(substream, dai, false);
0680 }
0681
0682 static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
0683 struct snd_soc_dai *dai)
0684 {
0685 return ssp_dai_setup(substream, dai, false);
0686 }
0687
0688 static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
0689 struct snd_soc_dai *dai)
0690 {
0691 struct ssp_dai_dma_data *dma_data;
0692
0693 dma_data = snd_soc_dai_get_dma_data(dai, substream);
0694 if (!dma_data) {
0695 dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
0696 return;
0697 }
0698 snd_soc_dai_set_dma_data(dai, substream, NULL);
0699 kfree(dma_data);
0700 }
0701
0702 static const struct snd_soc_dai_ops ipc3_ssp_dai_ops = {
0703 .startup = ssp_dai_startup,
0704 .hw_params = ssp_dai_hw_params,
0705 .prepare = ssp_dai_prepare,
0706 .trigger = ipc3_ssp_dai_trigger,
0707 .hw_free = ssp_dai_hw_free,
0708 .shutdown = ssp_dai_shutdown,
0709 };
0710
0711 static int ipc4_be_dai_common_trigger(struct snd_soc_dai *dai, int cmd, int stream)
0712 {
0713 struct snd_sof_widget *pipe_widget;
0714 struct sof_ipc4_pipeline *pipeline;
0715 struct snd_sof_widget *swidget;
0716 struct snd_soc_dapm_widget *w;
0717 struct snd_sof_dev *sdev;
0718 int ret;
0719
0720 w = snd_soc_dai_get_widget(dai, stream);
0721 swidget = w->dobj.private;
0722 pipe_widget = swidget->pipe_widget;
0723 pipeline = pipe_widget->private;
0724 sdev = snd_soc_component_get_drvdata(swidget->scomp);
0725
0726 switch (cmd) {
0727 case SNDRV_PCM_TRIGGER_SUSPEND:
0728 case SNDRV_PCM_TRIGGER_STOP:
0729 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0730 SOF_IPC4_PIPE_PAUSED);
0731 if (ret < 0)
0732 return ret;
0733 pipeline->state = SOF_IPC4_PIPE_PAUSED;
0734
0735 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0736 SOF_IPC4_PIPE_RESET);
0737 if (ret < 0)
0738 return ret;
0739 pipeline->state = SOF_IPC4_PIPE_RESET;
0740 break;
0741 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0742 ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
0743 SOF_IPC4_PIPE_PAUSED);
0744 if (ret < 0)
0745 return ret;
0746 pipeline->state = SOF_IPC4_PIPE_PAUSED;
0747 break;
0748 default:
0749 break;
0750 }
0751
0752 return 0;
0753 }
0754
0755 static int ipc4_be_dai_trigger(struct snd_pcm_substream *substream,
0756 int cmd, struct snd_soc_dai *dai)
0757 {
0758 return ipc4_be_dai_common_trigger(dai, cmd, substream->stream);
0759 }
0760
0761 static const struct snd_soc_dai_ops ipc4_dmic_dai_ops = {
0762 .trigger = ipc4_be_dai_trigger,
0763 };
0764
0765 static const struct snd_soc_dai_ops ipc4_ssp_dai_ops = {
0766 .trigger = ipc4_be_dai_trigger,
0767 };
0768
0769 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
0770 {
0771 int i;
0772
0773 switch (sdev->pdata->ipc_type) {
0774 case SOF_IPC:
0775 for (i = 0; i < ops->num_drv; i++) {
0776 if (strstr(ops->drv[i].name, "SSP")) {
0777 ops->drv[i].ops = &ipc3_ssp_dai_ops;
0778 continue;
0779 }
0780 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0781 if (strstr(ops->drv[i].name, "iDisp") ||
0782 strstr(ops->drv[i].name, "Analog") ||
0783 strstr(ops->drv[i].name, "Digital"))
0784 ops->drv[i].ops = &ipc3_hda_dai_ops;
0785 #endif
0786 }
0787 break;
0788 case SOF_INTEL_IPC4:
0789 {
0790 struct sof_ipc4_fw_data *ipc4_data = sdev->private;
0791
0792 for (i = 0; i < ops->num_drv; i++) {
0793 if (strstr(ops->drv[i].name, "DMIC")) {
0794 ops->drv[i].ops = &ipc4_dmic_dai_ops;
0795 continue;
0796 }
0797 if (strstr(ops->drv[i].name, "SSP")) {
0798 ops->drv[i].ops = &ipc4_ssp_dai_ops;
0799 continue;
0800 }
0801 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0802 if (strstr(ops->drv[i].name, "iDisp") ||
0803 strstr(ops->drv[i].name, "Analog") ||
0804 strstr(ops->drv[i].name, "Digital"))
0805 ops->drv[i].ops = &ipc4_hda_dai_ops;
0806 #endif
0807 }
0808
0809 if (!hda_use_tplg_nhlt)
0810 ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
0811
0812 if (IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE))
0813 sdw_callback.trigger = ipc4_be_dai_common_trigger;
0814
0815 break;
0816 }
0817 default:
0818 break;
0819 }
0820 }
0821
0822 void hda_ops_free(struct snd_sof_dev *sdev)
0823 {
0824 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
0825 struct sof_ipc4_fw_data *ipc4_data = sdev->private;
0826
0827 if (!hda_use_tplg_nhlt)
0828 intel_nhlt_free(ipc4_data->nhlt);
0829 }
0830 }
0831 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON);
0832
0833
0834
0835
0836
0837
0838 struct snd_soc_dai_driver skl_dai[] = {
0839 {
0840 .name = "SSP0 Pin",
0841 .playback = {
0842 .channels_min = 1,
0843 .channels_max = 8,
0844 },
0845 .capture = {
0846 .channels_min = 1,
0847 .channels_max = 8,
0848 },
0849 },
0850 {
0851 .name = "SSP1 Pin",
0852 .playback = {
0853 .channels_min = 1,
0854 .channels_max = 8,
0855 },
0856 .capture = {
0857 .channels_min = 1,
0858 .channels_max = 8,
0859 },
0860 },
0861 {
0862 .name = "SSP2 Pin",
0863 .playback = {
0864 .channels_min = 1,
0865 .channels_max = 8,
0866 },
0867 .capture = {
0868 .channels_min = 1,
0869 .channels_max = 8,
0870 },
0871 },
0872 {
0873 .name = "SSP3 Pin",
0874 .playback = {
0875 .channels_min = 1,
0876 .channels_max = 8,
0877 },
0878 .capture = {
0879 .channels_min = 1,
0880 .channels_max = 8,
0881 },
0882 },
0883 {
0884 .name = "SSP4 Pin",
0885 .playback = {
0886 .channels_min = 1,
0887 .channels_max = 8,
0888 },
0889 .capture = {
0890 .channels_min = 1,
0891 .channels_max = 8,
0892 },
0893 },
0894 {
0895 .name = "SSP5 Pin",
0896 .playback = {
0897 .channels_min = 1,
0898 .channels_max = 8,
0899 },
0900 .capture = {
0901 .channels_min = 1,
0902 .channels_max = 8,
0903 },
0904 },
0905 {
0906 .name = "DMIC01 Pin",
0907 .capture = {
0908 .channels_min = 1,
0909 .channels_max = 4,
0910 },
0911 },
0912 {
0913 .name = "DMIC16k Pin",
0914 .capture = {
0915 .channels_min = 1,
0916 .channels_max = 4,
0917 },
0918 },
0919 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0920 {
0921 .name = "iDisp1 Pin",
0922 .playback = {
0923 .channels_min = 1,
0924 .channels_max = 8,
0925 },
0926 },
0927 {
0928 .name = "iDisp2 Pin",
0929 .playback = {
0930 .channels_min = 1,
0931 .channels_max = 8,
0932 },
0933 },
0934 {
0935 .name = "iDisp3 Pin",
0936 .playback = {
0937 .channels_min = 1,
0938 .channels_max = 8,
0939 },
0940 },
0941 {
0942 .name = "iDisp4 Pin",
0943 .playback = {
0944 .channels_min = 1,
0945 .channels_max = 8,
0946 },
0947 },
0948 {
0949 .name = "Analog CPU DAI",
0950 .playback = {
0951 .channels_min = 1,
0952 .channels_max = 16,
0953 },
0954 .capture = {
0955 .channels_min = 1,
0956 .channels_max = 16,
0957 },
0958 },
0959 {
0960 .name = "Digital CPU DAI",
0961 .playback = {
0962 .channels_min = 1,
0963 .channels_max = 16,
0964 },
0965 .capture = {
0966 .channels_min = 1,
0967 .channels_max = 16,
0968 },
0969 },
0970 {
0971 .name = "Alt Analog CPU DAI",
0972 .playback = {
0973 .channels_min = 1,
0974 .channels_max = 16,
0975 },
0976 .capture = {
0977 .channels_min = 1,
0978 .channels_max = 16,
0979 },
0980 },
0981 #endif
0982 };
0983
0984 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
0985 {
0986
0987
0988
0989
0990
0991
0992 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0993 int ret;
0994
0995 ret = hda_dai_suspend(sof_to_bus(sdev));
0996 if (ret < 0)
0997 return ret;
0998 #endif
0999
1000 return 0;
1001 }