1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2021-2022 Intel Corporation
4 //
5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
6 // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
7 //
8
9 #include <linux/debugfs.h>
10 #include <linux/device.h>
11 #include <sound/hda_register.h>
12 #include <sound/hdaudio_ext.h>
13 #include <sound/pcm_params.h>
14 #include <sound/soc-acpi.h>
15 #include <sound/soc-acpi-intel-match.h>
16 #include <sound/soc-component.h>
17 #include "avs.h"
18 #include "path.h"
19 #include "pcm.h"
20 #include "topology.h"
21 #include "utils.h"
22 #include "../../codecs/hda.h"
23
24 struct avs_dma_data {
25 struct avs_tplg_path_template *template;
26 struct avs_path *path;
27 struct avs_dev *adev;
28
29 /* LINK-stream utilized in BE operations while HOST in FE ones. */
30 union {
31 struct hdac_ext_stream *link_stream;
32 struct hdac_ext_stream *host_stream;
33 };
34
35 struct snd_pcm_hw_constraint_list rate_list;
36 struct snd_pcm_hw_constraint_list channels_list;
37 struct snd_pcm_hw_constraint_list sample_bits_list;
38
39 struct work_struct period_elapsed_work;
40 struct hdac_ext_link *link;
41 struct snd_pcm_substream *substream;
42 };
43
44 static struct avs_tplg_path_template *
avs_dai_find_path_template(struct snd_soc_dai * dai,bool is_fe,int direction)45 avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
46 {
47 struct snd_soc_dapm_widget *dw = snd_soc_dai_get_widget(dai, direction);
48 struct snd_soc_dapm_path *dp;
49 enum snd_soc_dapm_direction dir;
50
51 if (direction == SNDRV_PCM_STREAM_CAPTURE) {
52 dir = is_fe ? SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN;
53 } else {
54 dir = is_fe ? SND_SOC_DAPM_DIR_IN : SND_SOC_DAPM_DIR_OUT;
55 }
56
57 dp = list_first_entry_or_null(&dw->edges[dir], typeof(*dp), list_node[dir]);
58 if (!dp)
59 return NULL;
60
61 /* Get the other widget, with actual path template data */
62 dw = (dp->source == dw) ? dp->sink : dp->source;
63
64 return dw->priv;
65 }
66
avs_period_elapsed_work(struct work_struct * work)67 static void avs_period_elapsed_work(struct work_struct *work)
68 {
69 struct avs_dma_data *data = container_of(work, struct avs_dma_data, period_elapsed_work);
70
71 snd_pcm_period_elapsed(data->substream);
72 }
73
avs_period_elapsed(struct snd_pcm_substream * substream)74 void avs_period_elapsed(struct snd_pcm_substream *substream)
75 {
76 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
77 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
78 struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream);
79
80 schedule_work(&data->period_elapsed_work);
81 }
82
83 static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
avs_hw_constraints_init(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)84 static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
85 {
86 struct snd_pcm_runtime *runtime = substream->runtime;
87 struct snd_pcm_hw_constraint_list *r, *c, *s;
88 struct avs_dma_data *data;
89 int ret;
90
91 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
92 if (ret < 0)
93 return ret;
94
95 data = snd_soc_dai_get_dma_data(dai, substream);
96 r = &(data->rate_list);
97 c = &(data->channels_list);
98 s = &(data->sample_bits_list);
99
100 ret = avs_path_set_constraint(data->adev, data->template, r, c, s);
101 if (ret <= 0)
102 return ret;
103
104 ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, r);
105 if (ret < 0)
106 return ret;
107
108 ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, c);
109 if (ret < 0)
110 return ret;
111
112 ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, s);
113 if (ret < 0)
114 return ret;
115
116 return 0;
117 }
118
avs_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)119 static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
120 {
121 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
122 struct avs_dev *adev = to_avs_dev(dai->component->dev);
123 struct avs_tplg_path_template *template;
124 struct avs_dma_data *data;
125
126 template = avs_dai_find_path_template(dai, !rtd->dai_link->no_pcm, substream->stream);
127 if (!template) {
128 dev_err(dai->dev, "no %s path for dai %s, invalid tplg?\n",
129 snd_pcm_stream_str(substream), dai->name);
130 return -EINVAL;
131 }
132
133 data = kzalloc(sizeof(*data), GFP_KERNEL);
134 if (!data)
135 return -ENOMEM;
136
137 data->substream = substream;
138 data->template = template;
139 data->adev = adev;
140 INIT_WORK(&data->period_elapsed_work, avs_period_elapsed_work);
141 snd_soc_dai_set_dma_data(dai, substream, data);
142
143 if (rtd->dai_link->ignore_suspend)
144 adev->num_lp_paths++;
145
146 return avs_hw_constraints_init(substream, dai);
147 }
148
avs_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)149 static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
150 {
151 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
152 struct avs_dma_data *data;
153
154 data = snd_soc_dai_get_dma_data(dai, substream);
155
156 if (rtd->dai_link->ignore_suspend)
157 data->adev->num_lp_paths--;
158
159 kfree(data->rate_list.list);
160 kfree(data->channels_list.list);
161 kfree(data->sample_bits_list.list);
162
163 snd_soc_dai_set_dma_data(dai, substream, NULL);
164 kfree(data);
165 }
166
avs_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * fe_hw_params,struct snd_pcm_hw_params * be_hw_params,struct snd_soc_dai * dai,int dma_id)167 static int avs_dai_hw_params(struct snd_pcm_substream *substream,
168 struct snd_pcm_hw_params *fe_hw_params,
169 struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
170 int dma_id)
171 {
172 struct avs_dma_data *data;
173 struct avs_path *path;
174 int ret;
175
176 data = snd_soc_dai_get_dma_data(dai, substream);
177
178 dev_dbg(dai->dev, "%s FE hw_params str %p rtd %p",
179 __func__, substream, substream->runtime);
180 dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
181 params_rate(fe_hw_params), params_channels(fe_hw_params),
182 params_width(fe_hw_params), params_physical_width(fe_hw_params));
183
184 dev_dbg(dai->dev, "%s BE hw_params str %p rtd %p",
185 __func__, substream, substream->runtime);
186 dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
187 params_rate(be_hw_params), params_channels(be_hw_params),
188 params_width(be_hw_params), params_physical_width(be_hw_params));
189
190 path = avs_path_create(data->adev, dma_id, data->template, fe_hw_params, be_hw_params);
191 if (IS_ERR(path)) {
192 ret = PTR_ERR(path);
193 dev_err(dai->dev, "create path failed: %d\n", ret);
194 return ret;
195 }
196
197 data->path = path;
198 return 0;
199 }
200
avs_dai_be_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * be_hw_params,struct snd_soc_dai * dai,int dma_id)201 static int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
202 struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
203 int dma_id)
204 {
205 struct snd_pcm_hw_params *fe_hw_params = NULL;
206 struct snd_soc_pcm_runtime *fe, *be;
207 struct snd_soc_dpcm *dpcm;
208
209 be = snd_soc_substream_to_rtd(substream);
210 /* dpcm_fe_dai_open() guarantees the list is not empty at this point. */
211 for_each_dpcm_fe(be, substream->stream, dpcm) {
212 fe = dpcm->fe;
213 fe_hw_params = &fe->dpcm[substream->stream].hw_params;
214 }
215
216 return avs_dai_hw_params(substream, fe_hw_params, be_hw_params, dai, dma_id);
217 }
218
avs_dai_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)219 static int avs_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
220 {
221 struct avs_dma_data *data;
222 int ret;
223
224 data = snd_soc_dai_get_dma_data(dai, substream);
225 if (!data->path)
226 return 0;
227
228 ret = avs_path_reset(data->path);
229 if (ret < 0) {
230 dev_err(dai->dev, "reset path failed: %d\n", ret);
231 return ret;
232 }
233
234 ret = avs_path_pause(data->path);
235 if (ret < 0)
236 dev_err(dai->dev, "pause path failed: %d\n", ret);
237 return ret;
238 }
239
avs_dai_nonhda_be_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params,struct snd_soc_dai * dai)240 static int avs_dai_nonhda_be_hw_params(struct snd_pcm_substream *substream,
241 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
242 {
243 struct avs_dma_data *data;
244
245 data = snd_soc_dai_get_dma_data(dai, substream);
246 if (data->path)
247 return 0;
248
249 /* Actual port-id comes from topology. */
250 return avs_dai_be_hw_params(substream, hw_params, dai, 0);
251 }
252
avs_dai_nonhda_be_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)253 static int avs_dai_nonhda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
254 {
255 struct avs_dma_data *data;
256
257 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
258
259 data = snd_soc_dai_get_dma_data(dai, substream);
260 if (data->path) {
261 avs_path_free(data->path);
262 data->path = NULL;
263 }
264
265 return 0;
266 }
267
avs_dai_nonhda_be_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)268 static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd,
269 struct snd_soc_dai *dai)
270 {
271 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
272 struct avs_dma_data *data;
273 int ret = 0;
274
275 data = snd_soc_dai_get_dma_data(dai, substream);
276
277 switch (cmd) {
278 case SNDRV_PCM_TRIGGER_RESUME:
279 if (rtd->dai_link->ignore_suspend)
280 break;
281 fallthrough;
282 case SNDRV_PCM_TRIGGER_START:
283 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
284 ret = avs_path_pause(data->path);
285 if (ret < 0) {
286 dev_err(dai->dev, "pause BE path failed: %d\n", ret);
287 break;
288 }
289
290 ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
291 if (ret < 0)
292 dev_err(dai->dev, "run BE path failed: %d\n", ret);
293 break;
294
295 case SNDRV_PCM_TRIGGER_SUSPEND:
296 if (rtd->dai_link->ignore_suspend)
297 break;
298 fallthrough;
299 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
300 case SNDRV_PCM_TRIGGER_STOP:
301 ret = avs_path_pause(data->path);
302 if (ret < 0)
303 dev_err(dai->dev, "pause BE path failed: %d\n", ret);
304
305 ret = avs_path_reset(data->path);
306 if (ret < 0)
307 dev_err(dai->dev, "reset BE path failed: %d\n", ret);
308 break;
309
310 default:
311 ret = -EINVAL;
312 break;
313 }
314
315 return ret;
316 }
317
318 static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = {
319 .startup = avs_dai_startup,
320 .shutdown = avs_dai_shutdown,
321 .hw_params = avs_dai_nonhda_be_hw_params,
322 .hw_free = avs_dai_nonhda_be_hw_free,
323 .prepare = avs_dai_prepare,
324 .trigger = avs_dai_nonhda_be_trigger,
325 };
326
__avs_dai_hda_be_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai,struct hdac_ext_link * link)327 static int __avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
328 struct hdac_ext_link *link)
329 {
330 struct hdac_ext_stream *link_stream;
331 struct avs_dma_data *data;
332 int ret;
333
334 ret = avs_dai_startup(substream, dai);
335 if (ret)
336 return ret;
337
338 data = snd_soc_dai_get_dma_data(dai, substream);
339 link_stream = snd_hdac_ext_stream_assign(&data->adev->base.core, substream,
340 HDAC_EXT_STREAM_TYPE_LINK);
341 if (!link_stream) {
342 avs_dai_shutdown(substream, dai);
343 return -EBUSY;
344 }
345
346 data->link_stream = link_stream;
347 data->link = link;
348 return 0;
349 }
350
avs_dai_hda_be_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)351 static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
352 {
353 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
354 struct hdac_ext_link *link;
355 struct avs_dma_data *data;
356 struct hda_codec *codec;
357 int ret;
358
359 codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev);
360
361 link = snd_hdac_ext_bus_get_hlink_by_addr(&codec->bus->core, codec->core.addr);
362 if (!link)
363 return -EINVAL;
364
365 ret = __avs_dai_hda_be_startup(substream, dai, link);
366 if (!ret) {
367 data = snd_soc_dai_get_dma_data(dai, substream);
368 substream->runtime->private_data = data->link_stream;
369 }
370
371 return ret;
372 }
373
avs_dai_i2shda_be_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)374 static int avs_dai_i2shda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
375 {
376 struct avs_dev *adev = to_avs_dev(dai->component->dev);
377 struct hdac_ext_link *link;
378
379 link = snd_hdac_ext_bus_get_hlink_by_id(&adev->base.core, AZX_REG_ML_LEPTR_ID_INTEL_SSP);
380 if (!link)
381 return -EINVAL;
382 return __avs_dai_hda_be_startup(substream, dai, link);
383 }
384
avs_dai_dmichda_be_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)385 static int avs_dai_dmichda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
386 {
387 struct avs_dev *adev = to_avs_dev(dai->component->dev);
388 struct hdac_ext_link *link;
389
390 link = snd_hdac_ext_bus_get_hlink_by_id(&adev->base.core, AZX_REG_ML_LEPTR_ID_INTEL_DMIC);
391 if (!link)
392 return -EINVAL;
393 return __avs_dai_hda_be_startup(substream, dai, link);
394 }
395
avs_dai_hda_be_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)396 static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
397 {
398 struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream);
399
400 snd_hdac_ext_stream_release(data->link_stream, HDAC_EXT_STREAM_TYPE_LINK);
401 substream->runtime->private_data = NULL;
402 avs_dai_shutdown(substream, dai);
403 }
404
avs_dai_althda_be_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)405 static void avs_dai_althda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
406 {
407 struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream);
408
409 snd_hdac_ext_stream_release(data->link_stream, HDAC_EXT_STREAM_TYPE_LINK);
410 avs_dai_shutdown(substream, dai);
411 }
412
avs_dai_hda_be_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params,struct snd_soc_dai * dai)413 static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream,
414 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
415 {
416 struct avs_dma_data *data;
417
418 data = snd_soc_dai_get_dma_data(dai, substream);
419 if (data->path)
420 return 0;
421
422 return avs_dai_be_hw_params(substream, hw_params, dai,
423 hdac_stream(data->link_stream)->stream_tag - 1);
424 }
425
avs_dai_hda_be_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)426 static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
427 {
428 struct hdac_ext_stream *link_stream;
429 struct avs_dma_data *data;
430
431 data = snd_soc_dai_get_dma_data(dai, substream);
432 if (!data->path)
433 return 0;
434
435 link_stream = data->link_stream;
436 link_stream->link_prepared = false;
437 avs_path_free(data->path);
438 data->path = NULL;
439
440 /* clear link <-> stream mapping */
441 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
442 snd_hdac_ext_bus_link_clear_stream_id(data->link,
443 hdac_stream(link_stream)->stream_tag);
444
445 return 0;
446 }
447
avs_dai_hda_be_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)448 static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
449 {
450 struct snd_soc_pcm_runtime *be = snd_soc_substream_to_rtd(substream);
451 const struct snd_soc_pcm_stream *stream_info;
452 struct hdac_ext_stream *link_stream;
453 const struct snd_pcm_hw_params *p;
454 struct avs_dma_data *data;
455 unsigned int format_val;
456 unsigned int bits;
457 int ret;
458
459 data = snd_soc_dai_get_dma_data(dai, substream);
460 link_stream = data->link_stream;
461 p = &be->dpcm[substream->stream].hw_params;
462
463 if (link_stream->link_prepared)
464 return 0;
465
466 stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
467 bits = snd_hdac_stream_format_bits(params_format(p), params_subformat(p),
468 stream_info->sig_bits);
469 format_val = snd_hdac_stream_format(params_channels(p), bits, params_rate(p));
470
471 snd_hdac_ext_stream_decouple(&data->adev->base.core, link_stream, true);
472 snd_hdac_ext_stream_reset(link_stream);
473 snd_hdac_ext_stream_setup(link_stream, format_val);
474
475 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
476 snd_hdac_ext_bus_link_set_stream_id(data->link,
477 hdac_stream(link_stream)->stream_tag);
478
479 ret = avs_dai_prepare(substream, dai);
480 if (ret)
481 return ret;
482
483 link_stream->link_prepared = true;
484 return 0;
485 }
486
avs_dai_hda_be_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)487 static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
488 struct snd_soc_dai *dai)
489 {
490 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
491 struct avs_dma_data *data;
492 int ret = 0;
493
494 dev_dbg(dai->dev, "entry %s cmd=%d\n", __func__, cmd);
495
496 data = snd_soc_dai_get_dma_data(dai, substream);
497
498 switch (cmd) {
499 case SNDRV_PCM_TRIGGER_RESUME:
500 if (rtd->dai_link->ignore_suspend)
501 break;
502 fallthrough;
503 case SNDRV_PCM_TRIGGER_START:
504 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
505 snd_hdac_ext_stream_start(data->link_stream);
506
507 ret = avs_path_pause(data->path);
508 if (ret < 0) {
509 dev_err(dai->dev, "pause BE path failed: %d\n", ret);
510 break;
511 }
512
513 ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
514 if (ret < 0)
515 dev_err(dai->dev, "run BE path failed: %d\n", ret);
516 break;
517
518 case SNDRV_PCM_TRIGGER_SUSPEND:
519 if (rtd->dai_link->ignore_suspend)
520 break;
521 fallthrough;
522 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
523 case SNDRV_PCM_TRIGGER_STOP:
524 ret = avs_path_pause(data->path);
525 if (ret < 0)
526 dev_err(dai->dev, "pause BE path failed: %d\n", ret);
527
528 snd_hdac_ext_stream_clear(data->link_stream);
529
530 ret = avs_path_reset(data->path);
531 if (ret < 0)
532 dev_err(dai->dev, "reset BE path failed: %d\n", ret);
533 break;
534
535 default:
536 ret = -EINVAL;
537 break;
538 }
539
540 return ret;
541 }
542
543 static const struct snd_soc_dai_ops avs_dai_hda_be_ops = {
544 .startup = avs_dai_hda_be_startup,
545 .shutdown = avs_dai_hda_be_shutdown,
546 .hw_params = avs_dai_hda_be_hw_params,
547 .hw_free = avs_dai_hda_be_hw_free,
548 .prepare = avs_dai_hda_be_prepare,
549 .trigger = avs_dai_hda_be_trigger,
550 };
551
552 static const struct snd_soc_dai_ops avs_dai_i2shda_be_ops = {
553 .startup = avs_dai_i2shda_be_startup,
554 .shutdown = avs_dai_althda_be_shutdown,
555 .hw_params = avs_dai_hda_be_hw_params,
556 .hw_free = avs_dai_hda_be_hw_free,
557 .prepare = avs_dai_hda_be_prepare,
558 .trigger = avs_dai_hda_be_trigger,
559 };
560
561 static const struct snd_soc_dai_ops avs_dai_dmichda_be_ops = {
562 .startup = avs_dai_dmichda_be_startup,
563 .shutdown = avs_dai_althda_be_shutdown,
564 .hw_params = avs_dai_hda_be_hw_params,
565 .hw_free = avs_dai_hda_be_hw_free,
566 .prepare = avs_dai_hda_be_prepare,
567 .trigger = avs_dai_hda_be_trigger,
568 };
569
hw_rule_param_size(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)570 static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
571 {
572 struct snd_interval *interval = hw_param_interval(params, rule->var);
573 struct snd_interval to;
574
575 snd_interval_any(&to);
576 to.integer = interval->integer;
577 to.max = interval->max;
578 /*
579 * Commonly 2ms buffer size is used in HDA scenarios whereas 4ms is used
580 * when streaming through GPDMA. Align to the latter to account for both.
581 */
582 to.min = params_rate(params) / 1000 * 4;
583
584 if (rule->var == SNDRV_PCM_HW_PARAM_PERIOD_SIZE)
585 to.min /= params_periods(params);
586
587 return snd_interval_refine(interval, &to);
588 }
589
avs_pcm_hw_constraints_init(struct snd_pcm_substream * substream)590 static int avs_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
591 {
592 struct snd_pcm_runtime *runtime = substream->runtime;
593 int ret;
594
595 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
596 if (ret < 0)
597 return ret;
598
599 /* Avoid wrap-around with wall-clock. */
600 ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
601 if (ret < 0)
602 return ret;
603
604 /* Adjust buffer and period size based on the audio format. */
605 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, hw_rule_param_size, NULL,
606 SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS,
607 SNDRV_PCM_HW_PARAM_RATE, -1);
608 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, hw_rule_param_size, NULL,
609 SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS,
610 SNDRV_PCM_HW_PARAM_RATE, -1);
611
612 return 0;
613 }
614
avs_dai_fe_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)615 static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
616 {
617 struct hdac_ext_stream *host_stream;
618 struct avs_dma_data *data;
619 struct hdac_bus *bus;
620 int ret;
621
622 ret = avs_pcm_hw_constraints_init(substream);
623 if (ret)
624 return ret;
625
626 ret = avs_dai_startup(substream, dai);
627 if (ret)
628 return ret;
629
630 data = snd_soc_dai_get_dma_data(dai, substream);
631 bus = &data->adev->base.core;
632
633 host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
634 if (!host_stream) {
635 avs_dai_shutdown(substream, dai);
636 return -EBUSY;
637 }
638
639 data->host_stream = host_stream;
640 snd_pcm_set_sync(substream);
641
642 dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
643 __func__, hdac_stream(host_stream)->stream_tag, substream);
644
645 return 0;
646 }
647
avs_dai_fe_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)648 static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
649 {
650 struct avs_dma_data *data;
651
652 data = snd_soc_dai_get_dma_data(dai, substream);
653
654 snd_hdac_ext_stream_release(data->host_stream, HDAC_EXT_STREAM_TYPE_HOST);
655 avs_dai_shutdown(substream, dai);
656 }
657
avs_dai_fe_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params,struct snd_soc_dai * dai)658 static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream,
659 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
660 {
661 struct snd_pcm_hw_params *be_hw_params = NULL;
662 struct snd_soc_pcm_runtime *fe, *be;
663 struct snd_soc_dpcm *dpcm;
664 struct avs_dma_data *data;
665 struct hdac_ext_stream *host_stream;
666 int ret;
667
668 data = snd_soc_dai_get_dma_data(dai, substream);
669 if (data->path)
670 return 0;
671
672 host_stream = data->host_stream;
673
674 hdac_stream(host_stream)->bufsize = 0;
675 hdac_stream(host_stream)->period_bytes = 0;
676 hdac_stream(host_stream)->format_val = 0;
677
678 fe = snd_soc_substream_to_rtd(substream);
679 /* dpcm_fe_dai_open() guarantees the list is not empty at this point. */
680 for_each_dpcm_be(fe, substream->stream, dpcm) {
681 be = dpcm->be;
682 be_hw_params = &be->dpcm[substream->stream].hw_params;
683 }
684
685 ret = avs_dai_hw_params(substream, hw_params, be_hw_params, dai,
686 hdac_stream(host_stream)->stream_tag - 1);
687 if (ret)
688 goto create_err;
689
690 ret = avs_path_bind(data->path);
691 if (ret < 0) {
692 dev_err(dai->dev, "bind FE <-> BE failed: %d\n", ret);
693 goto bind_err;
694 }
695
696 return 0;
697
698 bind_err:
699 avs_path_free(data->path);
700 data->path = NULL;
701 create_err:
702 snd_pcm_lib_free_pages(substream);
703 return ret;
704 }
705
__avs_dai_fe_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)706 static int __avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
707 {
708 struct avs_dma_data *data;
709 struct hdac_ext_stream *host_stream;
710 int ret;
711
712 dev_dbg(dai->dev, "%s fe HW_FREE str %p rtd %p",
713 __func__, substream, substream->runtime);
714
715 data = snd_soc_dai_get_dma_data(dai, substream);
716 if (!data->path)
717 return 0;
718
719 host_stream = data->host_stream;
720
721 ret = avs_path_unbind(data->path);
722 if (ret < 0)
723 dev_err(dai->dev, "unbind FE <-> BE failed: %d\n", ret);
724
725 avs_path_free(data->path);
726 data->path = NULL;
727 snd_hdac_stream_cleanup(hdac_stream(host_stream));
728 hdac_stream(host_stream)->prepared = false;
729
730 return ret;
731 }
732
avs_dai_fe_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)733 static int avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
734 {
735 int ret;
736
737 ret = __avs_dai_fe_hw_free(substream, dai);
738 snd_pcm_lib_free_pages(substream);
739
740 return ret;
741 }
742
avs_dai_fe_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)743 static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
744 {
745 struct snd_pcm_runtime *runtime = substream->runtime;
746 const struct snd_soc_pcm_stream *stream_info;
747 struct avs_dma_data *data;
748 struct hdac_ext_stream *host_stream;
749 unsigned int format_val;
750 struct hdac_bus *bus;
751 unsigned int bits;
752 int ret;
753
754 data = snd_soc_dai_get_dma_data(dai, substream);
755 host_stream = data->host_stream;
756
757 if (hdac_stream(host_stream)->prepared)
758 return 0;
759
760 bus = hdac_stream(host_stream)->bus;
761 snd_hdac_ext_stream_decouple(bus, data->host_stream, true);
762 snd_hdac_stream_reset(hdac_stream(host_stream));
763
764 stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
765 bits = snd_hdac_stream_format_bits(runtime->format, runtime->subformat,
766 stream_info->sig_bits);
767 format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate);
768
769 ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val);
770 if (ret < 0)
771 return ret;
772
773 ret = snd_hdac_ext_host_stream_setup(host_stream, false);
774 if (ret < 0)
775 return ret;
776
777 ret = avs_dai_prepare(substream, dai);
778 if (ret)
779 return ret;
780
781 hdac_stream(host_stream)->prepared = true;
782 return 0;
783 }
784
avs_hda_stream_start(struct hdac_bus * bus,struct hdac_ext_stream * host_stream)785 static void avs_hda_stream_start(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
786 {
787 struct hdac_stream *first_running = NULL;
788 struct hdac_stream *pos;
789 struct avs_dev *adev = hdac_to_avs(bus);
790
791 list_for_each_entry(pos, &bus->stream_list, list) {
792 if (pos->running) {
793 if (first_running)
794 break; /* more than one running */
795 first_running = pos;
796 }
797 }
798
799 /*
800 * If host_stream is a CAPTURE stream and will be the only one running,
801 * disable L1SEN to avoid sound clipping.
802 */
803 if (!first_running) {
804 if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
805 avs_hda_l1sen_enable(adev, false);
806 snd_hdac_stream_start(hdac_stream(host_stream));
807 return;
808 }
809
810 snd_hdac_stream_start(hdac_stream(host_stream));
811 /*
812 * If host_stream is the first stream to break the rule above,
813 * re-enable L1SEN.
814 */
815 if (list_entry_is_head(pos, &bus->stream_list, list) &&
816 first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
817 avs_hda_l1sen_enable(adev, true);
818 }
819
avs_hda_stream_stop(struct hdac_bus * bus,struct hdac_ext_stream * host_stream)820 static void avs_hda_stream_stop(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
821 {
822 struct hdac_stream *first_running = NULL;
823 struct hdac_stream *pos;
824 struct avs_dev *adev = hdac_to_avs(bus);
825
826 list_for_each_entry(pos, &bus->stream_list, list) {
827 if (pos == hdac_stream(host_stream))
828 continue; /* ignore stream that is about to be stopped */
829 if (pos->running) {
830 if (first_running)
831 break; /* more than one running */
832 first_running = pos;
833 }
834 }
835
836 /*
837 * If host_stream is a CAPTURE stream and is the only one running,
838 * re-enable L1SEN.
839 */
840 if (!first_running) {
841 snd_hdac_stream_stop(hdac_stream(host_stream));
842 if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
843 avs_hda_l1sen_enable(adev, true);
844 return;
845 }
846
847 /*
848 * If by stopping host_stream there is only a single, CAPTURE stream running
849 * left, disable L1SEN to avoid sound clipping.
850 */
851 if (list_entry_is_head(pos, &bus->stream_list, list) &&
852 first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
853 avs_hda_l1sen_enable(adev, false);
854
855 snd_hdac_stream_stop(hdac_stream(host_stream));
856 }
857
avs_dai_fe_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)858 static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
859 {
860 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
861 struct avs_dma_data *data;
862 struct hdac_ext_stream *host_stream;
863 struct hdac_bus *bus;
864 unsigned long flags;
865 int ret = 0;
866
867 data = snd_soc_dai_get_dma_data(dai, substream);
868 host_stream = data->host_stream;
869 bus = hdac_stream(host_stream)->bus;
870
871 switch (cmd) {
872 case SNDRV_PCM_TRIGGER_RESUME:
873 if (rtd->dai_link->ignore_suspend)
874 break;
875 fallthrough;
876 case SNDRV_PCM_TRIGGER_START:
877 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
878 spin_lock_irqsave(&bus->reg_lock, flags);
879 avs_hda_stream_start(bus, host_stream);
880 spin_unlock_irqrestore(&bus->reg_lock, flags);
881
882 /* Timeout on DRSM poll shall not stop the resume so ignore the result. */
883 if (cmd == SNDRV_PCM_TRIGGER_RESUME)
884 snd_hdac_stream_wait_drsm(hdac_stream(host_stream));
885
886 ret = avs_path_pause(data->path);
887 if (ret < 0) {
888 dev_err(dai->dev, "pause FE path failed: %d\n", ret);
889 break;
890 }
891
892 ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
893 if (ret < 0)
894 dev_err(dai->dev, "run FE path failed: %d\n", ret);
895
896 break;
897
898 case SNDRV_PCM_TRIGGER_SUSPEND:
899 if (rtd->dai_link->ignore_suspend)
900 break;
901 fallthrough;
902 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
903 case SNDRV_PCM_TRIGGER_STOP:
904 ret = avs_path_pause(data->path);
905 if (ret < 0)
906 dev_err(dai->dev, "pause FE path failed: %d\n", ret);
907
908 spin_lock_irqsave(&bus->reg_lock, flags);
909 avs_hda_stream_stop(bus, host_stream);
910 spin_unlock_irqrestore(&bus->reg_lock, flags);
911
912 ret = avs_path_reset(data->path);
913 if (ret < 0)
914 dev_err(dai->dev, "reset FE path failed: %d\n", ret);
915 break;
916
917 default:
918 ret = -EINVAL;
919 break;
920 }
921
922 return ret;
923 }
924
925 const struct snd_soc_dai_ops avs_dai_fe_ops = {
926 .startup = avs_dai_fe_startup,
927 .shutdown = avs_dai_fe_shutdown,
928 .hw_params = avs_dai_fe_hw_params,
929 .hw_free = avs_dai_fe_hw_free,
930 .prepare = avs_dai_fe_prepare,
931 .trigger = avs_dai_fe_trigger,
932 };
933
topology_name_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)934 static ssize_t topology_name_read(struct file *file, char __user *user_buf, size_t count,
935 loff_t *ppos)
936 {
937 struct snd_soc_component *component = file->private_data;
938 struct snd_soc_card *card = component->card;
939 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
940 char buf[64];
941 size_t len;
942
943 len = scnprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix,
944 mach->tplg_filename);
945
946 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
947 }
948
949 static const struct file_operations topology_name_fops = {
950 .open = simple_open,
951 .read = topology_name_read,
952 .llseek = default_llseek,
953 };
954
avs_component_load_libraries(struct avs_soc_component * acomp)955 static int avs_component_load_libraries(struct avs_soc_component *acomp)
956 {
957 struct avs_tplg *tplg = acomp->tplg;
958 struct avs_dev *adev = to_avs_dev(acomp->base.dev);
959 int ret;
960
961 if (!tplg->num_libs)
962 return 0;
963
964 /* Parent device may be asleep and library loading involves IPCs. */
965 ret = pm_runtime_resume_and_get(adev->dev);
966 if (ret < 0)
967 return ret;
968
969 avs_hda_power_gating_enable(adev, false);
970 avs_hda_clock_gating_enable(adev, false);
971 avs_hda_l1sen_enable(adev, false);
972
973 ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
974
975 avs_hda_l1sen_enable(adev, true);
976 avs_hda_clock_gating_enable(adev, true);
977 avs_hda_power_gating_enable(adev, true);
978
979 if (!ret)
980 ret = avs_module_info_init(adev, false);
981
982 pm_runtime_mark_last_busy(adev->dev);
983 pm_runtime_put_autosuspend(adev->dev);
984
985 return ret;
986 }
987
avs_component_probe(struct snd_soc_component * component)988 static int avs_component_probe(struct snd_soc_component *component)
989 {
990 struct snd_soc_card *card = component->card;
991 struct snd_soc_acpi_mach *mach;
992 struct avs_soc_component *acomp;
993 struct avs_dev *adev;
994 char *filename;
995 int ret;
996
997 dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
998 mach = dev_get_platdata(card->dev);
999 acomp = to_avs_soc_component(component);
1000 adev = to_avs_dev(component->dev);
1001
1002 acomp->tplg = avs_tplg_new(component);
1003 if (!acomp->tplg)
1004 return -ENOMEM;
1005
1006 if (!mach->tplg_filename)
1007 goto finalize;
1008
1009 /* Load specified topology and create debugfs for it. */
1010 filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1011 mach->tplg_filename);
1012 if (!filename)
1013 return -ENOMEM;
1014
1015 ret = avs_load_topology(component, filename);
1016 kfree(filename);
1017 if (ret == -ENOENT && !strncmp(mach->tplg_filename, "hda-", 4)) {
1018 unsigned int vendor_id;
1019
1020 if (sscanf(mach->tplg_filename, "hda-%08x-tplg.bin", &vendor_id) != 1)
1021 return ret;
1022
1023 if (((vendor_id >> 16) & 0xFFFF) == 0x8086)
1024 mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1025 "hda-8086-generic-tplg.bin");
1026 else
1027 mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1028 "hda-generic-tplg.bin");
1029 if (!mach->tplg_filename)
1030 return -ENOMEM;
1031 filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1032 mach->tplg_filename);
1033 if (!filename)
1034 return -ENOMEM;
1035
1036 dev_info(card->dev, "trying to load fallback topology %s\n", mach->tplg_filename);
1037 ret = avs_load_topology(component, filename);
1038 kfree(filename);
1039 }
1040 if (ret < 0)
1041 return ret;
1042
1043 ret = avs_component_load_libraries(acomp);
1044 if (ret < 0) {
1045 dev_err(card->dev, "libraries loading failed: %d\n", ret);
1046 goto err_load_libs;
1047 }
1048
1049 finalize:
1050 debugfs_create_file("topology_name", 0444, component->debugfs_root, component,
1051 &topology_name_fops);
1052
1053 mutex_lock(&adev->comp_list_mutex);
1054 list_add_tail(&acomp->node, &adev->comp_list);
1055 mutex_unlock(&adev->comp_list_mutex);
1056
1057 return 0;
1058
1059 err_load_libs:
1060 avs_remove_topology(component);
1061 return ret;
1062 }
1063
avs_component_remove(struct snd_soc_component * component)1064 static void avs_component_remove(struct snd_soc_component *component)
1065 {
1066 struct avs_soc_component *acomp = to_avs_soc_component(component);
1067 struct snd_soc_acpi_mach *mach;
1068 struct avs_dev *adev = to_avs_dev(component->dev);
1069 int ret;
1070
1071 mach = dev_get_platdata(component->card->dev);
1072
1073 mutex_lock(&adev->comp_list_mutex);
1074 list_del(&acomp->node);
1075 mutex_unlock(&adev->comp_list_mutex);
1076
1077 if (mach->tplg_filename) {
1078 ret = avs_remove_topology(component);
1079 if (ret < 0)
1080 dev_err(component->dev, "unload topology failed: %d\n", ret);
1081 }
1082 }
1083
avs_dai_resume_hw_params(struct snd_soc_dai * dai,struct avs_dma_data * data)1084 static int avs_dai_resume_hw_params(struct snd_soc_dai *dai, struct avs_dma_data *data)
1085 {
1086 struct snd_pcm_substream *substream;
1087 struct snd_soc_pcm_runtime *rtd;
1088 int ret;
1089
1090 substream = data->substream;
1091 rtd = snd_soc_substream_to_rtd(substream);
1092
1093 ret = dai->driver->ops->hw_params(substream, &rtd->dpcm[substream->stream].hw_params, dai);
1094 if (ret)
1095 dev_err(dai->dev, "hw_params on resume failed: %d\n", ret);
1096
1097 return ret;
1098 }
1099
avs_dai_resume_fe_prepare(struct snd_soc_dai * dai,struct avs_dma_data * data)1100 static int avs_dai_resume_fe_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1101 {
1102 struct hdac_ext_stream *host_stream;
1103 struct hdac_stream *hstream;
1104 struct hdac_bus *bus;
1105 int ret;
1106
1107 host_stream = data->host_stream;
1108 hstream = hdac_stream(host_stream);
1109 bus = hdac_stream(host_stream)->bus;
1110
1111 /* Set DRSM before programming stream and position registers. */
1112 snd_hdac_stream_drsm_enable(bus, true, hstream->index);
1113
1114 ret = dai->driver->ops->prepare(data->substream, dai);
1115 if (ret) {
1116 dev_err(dai->dev, "prepare FE on resume failed: %d\n", ret);
1117 return ret;
1118 }
1119
1120 writel(host_stream->pphcllpl, host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1121 writel(host_stream->pphcllpu, host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1122 writel(host_stream->pphcldpl, host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1123 writel(host_stream->pphcldpu, host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1124
1125 /* As per HW spec recommendation, program LPIB and DPIB to the same value. */
1126 snd_hdac_stream_set_lpib(hstream, hstream->lpib);
1127 snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
1128
1129 return 0;
1130 }
1131
avs_dai_resume_be_prepare(struct snd_soc_dai * dai,struct avs_dma_data * data)1132 static int avs_dai_resume_be_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1133 {
1134 int ret;
1135
1136 ret = dai->driver->ops->prepare(data->substream, dai);
1137 if (ret)
1138 dev_err(dai->dev, "prepare BE on resume failed: %d\n", ret);
1139
1140 return ret;
1141 }
1142
avs_dai_suspend_fe_hw_free(struct snd_soc_dai * dai,struct avs_dma_data * data)1143 static int avs_dai_suspend_fe_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1144 {
1145 struct hdac_ext_stream *host_stream;
1146 int ret;
1147
1148 host_stream = data->host_stream;
1149
1150 /* Store position addresses so we can resume from them later on. */
1151 hdac_stream(host_stream)->lpib = snd_hdac_stream_get_pos_lpib(hdac_stream(host_stream));
1152 host_stream->pphcllpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1153 host_stream->pphcllpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1154 host_stream->pphcldpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1155 host_stream->pphcldpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1156
1157 ret = __avs_dai_fe_hw_free(data->substream, dai);
1158 if (ret < 0)
1159 dev_err(dai->dev, "hw_free FE on suspend failed: %d\n", ret);
1160
1161 return ret;
1162 }
1163
avs_dai_suspend_be_hw_free(struct snd_soc_dai * dai,struct avs_dma_data * data)1164 static int avs_dai_suspend_be_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1165 {
1166 int ret;
1167
1168 ret = dai->driver->ops->hw_free(data->substream, dai);
1169 if (ret < 0)
1170 dev_err(dai->dev, "hw_free BE on suspend failed: %d\n", ret);
1171
1172 return ret;
1173 }
1174
avs_component_pm_op(struct snd_soc_component * component,bool be,int (* op)(struct snd_soc_dai *,struct avs_dma_data *))1175 static int avs_component_pm_op(struct snd_soc_component *component, bool be,
1176 int (*op)(struct snd_soc_dai *, struct avs_dma_data *))
1177 {
1178 struct snd_soc_pcm_runtime *rtd;
1179 struct avs_dma_data *data;
1180 struct snd_soc_dai *dai;
1181 int ret;
1182
1183 for_each_component_dais(component, dai) {
1184 data = snd_soc_dai_dma_data_get_playback(dai);
1185 if (data) {
1186 rtd = snd_soc_substream_to_rtd(data->substream);
1187 if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1188 ret = op(dai, data);
1189 if (ret < 0) {
1190 __snd_pcm_set_state(data->substream->runtime,
1191 SNDRV_PCM_STATE_DISCONNECTED);
1192 return ret;
1193 }
1194 }
1195 }
1196
1197 data = snd_soc_dai_dma_data_get_capture(dai);
1198 if (data) {
1199 rtd = snd_soc_substream_to_rtd(data->substream);
1200 if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1201 ret = op(dai, data);
1202 if (ret < 0) {
1203 __snd_pcm_set_state(data->substream->runtime,
1204 SNDRV_PCM_STATE_DISCONNECTED);
1205 return ret;
1206 }
1207 }
1208 }
1209 }
1210
1211 return 0;
1212 }
1213
avs_component_resume_hw_params(struct snd_soc_component * component,bool be)1214 static int avs_component_resume_hw_params(struct snd_soc_component *component, bool be)
1215 {
1216 return avs_component_pm_op(component, be, &avs_dai_resume_hw_params);
1217 }
1218
avs_component_resume_prepare(struct snd_soc_component * component,bool be)1219 static int avs_component_resume_prepare(struct snd_soc_component *component, bool be)
1220 {
1221 int (*prepare_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1222
1223 if (be)
1224 prepare_cb = &avs_dai_resume_be_prepare;
1225 else
1226 prepare_cb = &avs_dai_resume_fe_prepare;
1227
1228 return avs_component_pm_op(component, be, prepare_cb);
1229 }
1230
avs_component_suspend_hw_free(struct snd_soc_component * component,bool be)1231 static int avs_component_suspend_hw_free(struct snd_soc_component *component, bool be)
1232 {
1233 int (*hw_free_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1234
1235 if (be)
1236 hw_free_cb = &avs_dai_suspend_be_hw_free;
1237 else
1238 hw_free_cb = &avs_dai_suspend_fe_hw_free;
1239
1240 return avs_component_pm_op(component, be, hw_free_cb);
1241 }
1242
avs_component_suspend(struct snd_soc_component * component)1243 static int avs_component_suspend(struct snd_soc_component *component)
1244 {
1245 int ret;
1246
1247 /*
1248 * When freeing paths, FEs need to be first as they perform
1249 * path unbinding.
1250 */
1251 ret = avs_component_suspend_hw_free(component, false);
1252 if (ret)
1253 return ret;
1254
1255 return avs_component_suspend_hw_free(component, true);
1256 }
1257
avs_component_resume(struct snd_soc_component * component)1258 static int avs_component_resume(struct snd_soc_component *component)
1259 {
1260 int ret;
1261
1262 /*
1263 * When creating paths, FEs need to be last as they perform
1264 * path binding.
1265 */
1266 ret = avs_component_resume_hw_params(component, true);
1267 if (ret)
1268 return ret;
1269
1270 ret = avs_component_resume_hw_params(component, false);
1271 if (ret)
1272 return ret;
1273
1274 /* It is expected that the LINK stream is prepared first. */
1275 ret = avs_component_resume_prepare(component, true);
1276 if (ret)
1277 return ret;
1278
1279 return avs_component_resume_prepare(component, false);
1280 }
1281
1282 static const struct snd_pcm_hardware avs_pcm_hardware = {
1283 .info = SNDRV_PCM_INFO_MMAP |
1284 SNDRV_PCM_INFO_MMAP_VALID |
1285 SNDRV_PCM_INFO_INTERLEAVED |
1286 SNDRV_PCM_INFO_PAUSE |
1287 SNDRV_PCM_INFO_RESUME |
1288 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
1289 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1290 SNDRV_PCM_FMTBIT_S32_LE,
1291 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1292 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1293 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1294 .buffer_bytes_max = AZX_MAX_BUF_SIZE,
1295 .period_bytes_min = 128,
1296 .period_bytes_max = AZX_MAX_BUF_SIZE / 2,
1297 .periods_min = 2,
1298 .periods_max = AZX_MAX_FRAG,
1299 .fifo_size = 0,
1300 };
1301
avs_component_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)1302 static int avs_component_open(struct snd_soc_component *component,
1303 struct snd_pcm_substream *substream)
1304 {
1305 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1306
1307 /* only FE DAI links are handled here */
1308 if (rtd->dai_link->no_pcm)
1309 return 0;
1310
1311 return snd_soc_set_runtime_hwparams(substream, &avs_pcm_hardware);
1312 }
1313
avs_hda_stream_dpib_read(struct hdac_ext_stream * stream)1314 static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream)
1315 {
1316 return readl(hdac_stream(stream)->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1317 (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index));
1318 }
1319
1320 static snd_pcm_uframes_t
avs_component_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)1321 avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream)
1322 {
1323 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1324 struct avs_dma_data *data;
1325 struct hdac_ext_stream *host_stream;
1326 unsigned int pos;
1327
1328 data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
1329 if (!data->host_stream)
1330 return 0;
1331
1332 host_stream = data->host_stream;
1333 pos = avs_hda_stream_dpib_read(host_stream);
1334
1335 if (pos >= hdac_stream(host_stream)->bufsize)
1336 pos = 0;
1337
1338 return bytes_to_frames(substream->runtime, pos);
1339 }
1340
avs_component_mmap(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct vm_area_struct * vma)1341 static int avs_component_mmap(struct snd_soc_component *component,
1342 struct snd_pcm_substream *substream,
1343 struct vm_area_struct *vma)
1344 {
1345 return snd_pcm_lib_default_mmap(substream, vma);
1346 }
1347
1348 #define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
1349
avs_component_construct(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)1350 static int avs_component_construct(struct snd_soc_component *component,
1351 struct snd_soc_pcm_runtime *rtd)
1352 {
1353 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
1354 struct snd_pcm *pcm = rtd->pcm;
1355
1356 if (dai->driver->playback.channels_min)
1357 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
1358 SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1359 MAX_PREALLOC_SIZE);
1360
1361 if (dai->driver->capture.channels_min)
1362 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
1363 SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1364 MAX_PREALLOC_SIZE);
1365
1366 return 0;
1367 }
1368
1369 static struct snd_soc_component_driver avs_component_driver = {
1370 .name = "avs-pcm",
1371 .probe = avs_component_probe,
1372 .remove = avs_component_remove,
1373 .suspend = avs_component_suspend,
1374 .resume = avs_component_resume,
1375 .open = avs_component_open,
1376 .pointer = avs_component_pointer,
1377 .mmap = avs_component_mmap,
1378 .pcm_construct = avs_component_construct,
1379 .module_get_upon_open = 1, /* increment refcount when a pcm is opened */
1380 .topology_name_prefix = "intel/avs",
1381 };
1382
avs_soc_component_register(struct device * dev,const char * name,struct snd_soc_component_driver * drv,struct snd_soc_dai_driver * cpu_dais,int num_cpu_dais)1383 int avs_soc_component_register(struct device *dev, const char *name,
1384 struct snd_soc_component_driver *drv,
1385 struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais)
1386 {
1387 struct avs_soc_component *acomp;
1388 int ret;
1389
1390 acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
1391 if (!acomp)
1392 return -ENOMEM;
1393
1394 ret = snd_soc_component_initialize(&acomp->base, drv, dev);
1395 if (ret < 0)
1396 return ret;
1397
1398 /* force name change after ASoC is done with its init */
1399 acomp->base.name = name;
1400 INIT_LIST_HEAD(&acomp->node);
1401
1402 drv->use_dai_pcm_id = !obsolete_card_names;
1403
1404 return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
1405 }
1406
1407 static struct snd_soc_dai_driver dmic_cpu_dais[] = {
1408 {
1409 .name = "DMIC Pin",
1410 .capture = {
1411 .stream_name = "DMIC Rx",
1412 .channels_min = 1,
1413 .channels_max = 4,
1414 .rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000,
1415 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
1416 },
1417 },
1418 {
1419 .name = "DMIC WoV Pin",
1420 .capture = {
1421 .stream_name = "DMIC WoV Rx",
1422 .channels_min = 1,
1423 .channels_max = 4,
1424 .rates = SNDRV_PCM_RATE_16000,
1425 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1426 },
1427 },
1428 };
1429
avs_dmic_platform_register(struct avs_dev * adev,const char * name)1430 int avs_dmic_platform_register(struct avs_dev *adev, const char *name)
1431 {
1432 const struct snd_soc_dai_ops *ops;
1433
1434 if (avs_platattr_test(adev, ALTHDA))
1435 ops = &avs_dai_dmichda_be_ops;
1436 else
1437 ops = &avs_dai_nonhda_be_ops;
1438
1439 dmic_cpu_dais[0].ops = ops;
1440 dmic_cpu_dais[1].ops = ops;
1441 return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais,
1442 ARRAY_SIZE(dmic_cpu_dais));
1443 }
1444
1445 static const struct snd_soc_dai_driver i2s_dai_template = {
1446 .playback = {
1447 .channels_min = 1,
1448 .channels_max = AVS_CHANNELS_MAX,
1449 .rates = SNDRV_PCM_RATE_8000_192000 |
1450 SNDRV_PCM_RATE_12000 |
1451 SNDRV_PCM_RATE_24000 |
1452 SNDRV_PCM_RATE_128000,
1453 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1454 SNDRV_PCM_FMTBIT_S32_LE,
1455 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1456 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1457 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1458 },
1459 .capture = {
1460 .channels_min = 1,
1461 .channels_max = AVS_CHANNELS_MAX,
1462 .rates = SNDRV_PCM_RATE_8000_192000 |
1463 SNDRV_PCM_RATE_12000 |
1464 SNDRV_PCM_RATE_24000 |
1465 SNDRV_PCM_RATE_128000,
1466 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1467 SNDRV_PCM_FMTBIT_S32_LE,
1468 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1469 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1470 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1471 },
1472 };
1473
avs_i2s_platform_register(struct avs_dev * adev,const char * name,unsigned long port_mask,unsigned long * tdms)1474 int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask,
1475 unsigned long *tdms)
1476 {
1477 struct snd_soc_dai_driver *cpus, *dai;
1478 const struct snd_soc_dai_ops *ops;
1479 size_t ssp_count, cpu_count;
1480 int i, j;
1481
1482 ssp_count = adev->hw_cfg.i2s_caps.ctrl_count;
1483 if (avs_platattr_test(adev, ALTHDA))
1484 ops = &avs_dai_i2shda_be_ops;
1485 else
1486 ops = &avs_dai_nonhda_be_ops;
1487
1488 cpu_count = 0;
1489 for_each_set_bit(i, &port_mask, ssp_count)
1490 if (!tdms || test_bit(0, &tdms[i]))
1491 cpu_count++;
1492 if (tdms)
1493 for_each_set_bit(i, &port_mask, ssp_count)
1494 cpu_count += hweight_long(tdms[i]);
1495
1496 cpus = devm_kcalloc(adev->dev, cpu_count, sizeof(*cpus), GFP_KERNEL);
1497 if (!cpus)
1498 return -ENOMEM;
1499
1500 dai = cpus;
1501 for_each_set_bit(i, &port_mask, ssp_count) {
1502 if (!tdms || test_bit(0, &tdms[i])) {
1503 memcpy(dai, &i2s_dai_template, sizeof(*dai));
1504
1505 dai->name =
1506 devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i);
1507 dai->playback.stream_name =
1508 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i);
1509 dai->capture.stream_name =
1510 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i);
1511
1512 if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1513 return -ENOMEM;
1514 dai->ops = ops;
1515 dai++;
1516 }
1517 }
1518
1519 if (!tdms)
1520 goto plat_register;
1521
1522 for_each_set_bit(i, &port_mask, ssp_count) {
1523 for_each_set_bit(j, &tdms[i], AVS_CHANNELS_MAX) {
1524 memcpy(dai, &i2s_dai_template, sizeof(*dai));
1525
1526 dai->name =
1527 devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d:%d Pin", i, j);
1528 dai->playback.stream_name =
1529 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Tx", i, j);
1530 dai->capture.stream_name =
1531 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Rx", i, j);
1532
1533 if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1534 return -ENOMEM;
1535 dai->ops = ops;
1536 dai++;
1537 }
1538 }
1539
1540 plat_register:
1541 return avs_soc_component_register(adev->dev, name, &avs_component_driver, cpus, cpu_count);
1542 }
1543
1544 /* HD-Audio CPU DAI template */
1545 static const struct snd_soc_dai_driver hda_cpu_dai = {
1546 .ops = &avs_dai_hda_be_ops,
1547 .playback = {
1548 .channels_min = 1,
1549 .channels_max = AVS_CHANNELS_MAX,
1550 .rates = SNDRV_PCM_RATE_8000_192000,
1551 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1552 SNDRV_PCM_FMTBIT_S32_LE,
1553 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1554 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1555 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1556 },
1557 .capture = {
1558 .channels_min = 1,
1559 .channels_max = AVS_CHANNELS_MAX,
1560 .rates = SNDRV_PCM_RATE_8000_192000,
1561 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1562 SNDRV_PCM_FMTBIT_S32_LE,
1563 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1564 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1565 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1566 },
1567 };
1568
avs_component_hda_unregister_dais(struct snd_soc_component * component)1569 static void avs_component_hda_unregister_dais(struct snd_soc_component *component)
1570 {
1571 struct snd_soc_acpi_mach *mach;
1572 struct snd_soc_dai *dai, *save;
1573 struct hda_codec *codec;
1574 char name[32];
1575
1576 mach = dev_get_platdata(component->card->dev);
1577 codec = mach->pdata;
1578 snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev));
1579
1580 for_each_component_dais_safe(component, dai, save) {
1581 int stream;
1582
1583 if (!strstr(dai->driver->name, name))
1584 continue;
1585
1586 for_each_pcm_streams(stream)
1587 snd_soc_dapm_free_widget(snd_soc_dai_get_widget(dai, stream));
1588
1589 snd_soc_unregister_dai(dai);
1590 }
1591 }
1592
avs_component_hda_probe(struct snd_soc_component * component)1593 static int avs_component_hda_probe(struct snd_soc_component *component)
1594 {
1595 struct snd_soc_dapm_context *dapm;
1596 struct snd_soc_dai_driver *dais;
1597 struct snd_soc_acpi_mach *mach;
1598 struct avs_mach_pdata *pdata;
1599 struct hda_codec *codec;
1600 struct hda_pcm *pcm;
1601 const char *cname;
1602 int pcm_count = 0, ret, i;
1603
1604 mach = dev_get_platdata(component->card->dev);
1605 if (!mach)
1606 return -EINVAL;
1607
1608 pdata = mach->pdata;
1609 codec = pdata->codec;
1610 if (list_empty(&codec->pcm_list_head))
1611 return -EINVAL;
1612 list_for_each_entry(pcm, &codec->pcm_list_head, list)
1613 pcm_count++;
1614
1615 dais = devm_kcalloc(component->dev, pcm_count, sizeof(*dais),
1616 GFP_KERNEL);
1617 if (!dais)
1618 return -ENOMEM;
1619
1620 cname = dev_name(&codec->core.dev);
1621 dapm = snd_soc_component_get_dapm(component);
1622 pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list);
1623
1624 for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) {
1625 struct snd_soc_dai *dai;
1626
1627 memcpy(&dais[i], &hda_cpu_dai, sizeof(*dais));
1628 dais[i].id = i;
1629 dais[i].name = devm_kasprintf(component->dev, GFP_KERNEL,
1630 "%s-cpu%d", cname, i);
1631 if (!dais[i].name) {
1632 ret = -ENOMEM;
1633 goto exit;
1634 }
1635
1636 if (pcm->stream[0].substreams) {
1637 dais[i].playback.stream_name =
1638 devm_kasprintf(component->dev, GFP_KERNEL,
1639 "%s-cpu%d Tx", cname, i);
1640 if (!dais[i].playback.stream_name) {
1641 ret = -ENOMEM;
1642 goto exit;
1643 }
1644
1645 if (!hda_codec_is_display(codec)) {
1646 dais[i].playback.formats = pcm->stream[0].formats;
1647 dais[i].playback.subformats = pcm->stream[0].subformats;
1648 dais[i].playback.rates = pcm->stream[0].rates;
1649 dais[i].playback.channels_min = pcm->stream[0].channels_min;
1650 dais[i].playback.channels_max = pcm->stream[0].channels_max;
1651 dais[i].playback.sig_bits = pcm->stream[0].maxbps;
1652 }
1653 }
1654
1655 if (pcm->stream[1].substreams) {
1656 dais[i].capture.stream_name =
1657 devm_kasprintf(component->dev, GFP_KERNEL,
1658 "%s-cpu%d Rx", cname, i);
1659 if (!dais[i].capture.stream_name) {
1660 ret = -ENOMEM;
1661 goto exit;
1662 }
1663
1664 if (!hda_codec_is_display(codec)) {
1665 dais[i].capture.formats = pcm->stream[1].formats;
1666 dais[i].capture.subformats = pcm->stream[1].subformats;
1667 dais[i].capture.rates = pcm->stream[1].rates;
1668 dais[i].capture.channels_min = pcm->stream[1].channels_min;
1669 dais[i].capture.channels_max = pcm->stream[1].channels_max;
1670 dais[i].capture.sig_bits = pcm->stream[1].maxbps;
1671 }
1672 }
1673
1674 dai = snd_soc_register_dai(component, &dais[i], false);
1675 if (!dai) {
1676 dev_err(component->dev, "register dai for %s failed\n",
1677 pcm->name);
1678 ret = -EINVAL;
1679 goto exit;
1680 }
1681
1682 ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
1683 if (ret < 0) {
1684 dev_err(component->dev, "create widgets failed: %d\n",
1685 ret);
1686 snd_soc_unregister_dai(dai);
1687 goto exit;
1688 }
1689 }
1690
1691 ret = avs_component_probe(component);
1692 exit:
1693 if (ret)
1694 avs_component_hda_unregister_dais(component);
1695
1696 return ret;
1697 }
1698
avs_component_hda_remove(struct snd_soc_component * component)1699 static void avs_component_hda_remove(struct snd_soc_component *component)
1700 {
1701 avs_component_remove(component);
1702 avs_component_hda_unregister_dais(component);
1703 }
1704
avs_component_hda_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)1705 static int avs_component_hda_open(struct snd_soc_component *component,
1706 struct snd_pcm_substream *substream)
1707 {
1708 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1709
1710 if (!rtd->dai_link->no_pcm) {
1711 struct snd_pcm_hardware hwparams = avs_pcm_hardware;
1712 struct snd_soc_pcm_runtime *be;
1713 struct snd_soc_dpcm *dpcm;
1714 int dir = substream->stream;
1715
1716 /*
1717 * Support the DPCM reparenting while still fulfilling expectations of HDAudio
1718 * common code - a valid stream pointer at substream->runtime->private_data -
1719 * by having all FEs point to the same private data.
1720 */
1721 for_each_dpcm_be(rtd, dir, dpcm) {
1722 struct snd_pcm_substream *be_substream;
1723
1724 be = dpcm->be;
1725 if (be->dpcm[dir].users == 1)
1726 break;
1727
1728 be_substream = snd_soc_dpcm_get_substream(be, dir);
1729 substream->runtime->private_data = be_substream->runtime->private_data;
1730 break;
1731 }
1732
1733 /* RESUME unsupported for de-coupled HD-Audio capture. */
1734 if (dir == SNDRV_PCM_STREAM_CAPTURE)
1735 hwparams.info &= ~SNDRV_PCM_INFO_RESUME;
1736
1737 return snd_soc_set_runtime_hwparams(substream, &hwparams);
1738 }
1739
1740 return 0;
1741 }
1742
1743 static struct snd_soc_component_driver avs_hda_component_driver = {
1744 .name = "avs-hda-pcm",
1745 .probe = avs_component_hda_probe,
1746 .remove = avs_component_hda_remove,
1747 .suspend = avs_component_suspend,
1748 .resume = avs_component_resume,
1749 .open = avs_component_hda_open,
1750 .pointer = avs_component_pointer,
1751 .mmap = avs_component_mmap,
1752 .pcm_construct = avs_component_construct,
1753 /*
1754 * hda platform component's probe() is dependent on
1755 * codec->pcm_list_head, it needs to be initialized after codec
1756 * component. remove_order is here for completeness sake
1757 */
1758 .probe_order = SND_SOC_COMP_ORDER_LATE,
1759 .remove_order = SND_SOC_COMP_ORDER_EARLY,
1760 .module_get_upon_open = 1,
1761 .topology_name_prefix = "intel/avs",
1762 };
1763
avs_hda_platform_register(struct avs_dev * adev,const char * name)1764 int avs_hda_platform_register(struct avs_dev *adev, const char *name)
1765 {
1766 return avs_soc_component_register(adev->dev, name,
1767 &avs_hda_component_driver, NULL, 0);
1768 }
1769