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 disable_work_sync(&data->period_elapsed_work);
655 snd_hdac_ext_stream_release(data->host_stream, HDAC_EXT_STREAM_TYPE_HOST);
656 avs_dai_shutdown(substream, dai);
657 }
658
avs_dai_fe_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params,struct snd_soc_dai * dai)659 static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream,
660 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
661 {
662 struct snd_pcm_hw_params *be_hw_params = NULL;
663 struct snd_soc_pcm_runtime *fe, *be;
664 struct snd_soc_dpcm *dpcm;
665 struct avs_dma_data *data;
666 struct hdac_ext_stream *host_stream;
667 int ret;
668
669 data = snd_soc_dai_get_dma_data(dai, substream);
670 if (data->path)
671 return 0;
672
673 host_stream = data->host_stream;
674
675 hdac_stream(host_stream)->bufsize = 0;
676 hdac_stream(host_stream)->period_bytes = 0;
677 hdac_stream(host_stream)->format_val = 0;
678
679 fe = snd_soc_substream_to_rtd(substream);
680 /* dpcm_fe_dai_open() guarantees the list is not empty at this point. */
681 for_each_dpcm_be(fe, substream->stream, dpcm) {
682 be = dpcm->be;
683 be_hw_params = &be->dpcm[substream->stream].hw_params;
684 }
685
686 ret = avs_dai_hw_params(substream, hw_params, be_hw_params, dai,
687 hdac_stream(host_stream)->stream_tag - 1);
688 if (ret)
689 goto create_err;
690
691 ret = avs_path_bind(data->path);
692 if (ret < 0) {
693 dev_err(dai->dev, "bind FE <-> BE failed: %d\n", ret);
694 goto bind_err;
695 }
696
697 return 0;
698
699 bind_err:
700 avs_path_free(data->path);
701 data->path = NULL;
702 create_err:
703 snd_pcm_lib_free_pages(substream);
704 return ret;
705 }
706
__avs_dai_fe_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)707 static int __avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
708 {
709 struct avs_dma_data *data;
710 struct hdac_ext_stream *host_stream;
711 int ret;
712
713 dev_dbg(dai->dev, "%s fe HW_FREE str %p rtd %p",
714 __func__, substream, substream->runtime);
715
716 data = snd_soc_dai_get_dma_data(dai, substream);
717 if (!data->path)
718 return 0;
719
720 host_stream = data->host_stream;
721
722 ret = avs_path_unbind(data->path);
723 if (ret < 0)
724 dev_err(dai->dev, "unbind FE <-> BE failed: %d\n", ret);
725
726 avs_path_free(data->path);
727 data->path = NULL;
728 snd_hdac_stream_cleanup(hdac_stream(host_stream));
729 hdac_stream(host_stream)->prepared = false;
730
731 return ret;
732 }
733
avs_dai_fe_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)734 static int avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
735 {
736 int ret;
737
738 ret = __avs_dai_fe_hw_free(substream, dai);
739 snd_pcm_lib_free_pages(substream);
740
741 return ret;
742 }
743
avs_dai_fe_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)744 static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
745 {
746 struct snd_pcm_runtime *runtime = substream->runtime;
747 const struct snd_soc_pcm_stream *stream_info;
748 struct avs_dma_data *data;
749 struct hdac_ext_stream *host_stream;
750 unsigned int format_val;
751 struct hdac_bus *bus;
752 unsigned int bits;
753 int ret;
754
755 data = snd_soc_dai_get_dma_data(dai, substream);
756 host_stream = data->host_stream;
757
758 if (runtime->state == SNDRV_PCM_STATE_XRUN)
759 hdac_stream(host_stream)->prepared = false;
760 if (hdac_stream(host_stream)->prepared)
761 return 0;
762
763 bus = hdac_stream(host_stream)->bus;
764 snd_hdac_ext_stream_decouple(bus, data->host_stream, true);
765 snd_hdac_stream_reset(hdac_stream(host_stream));
766
767 stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
768 bits = snd_hdac_stream_format_bits(runtime->format, runtime->subformat,
769 stream_info->sig_bits);
770 format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate);
771
772 ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val);
773 if (ret < 0)
774 return ret;
775
776 ret = snd_hdac_ext_host_stream_setup(host_stream, false);
777 if (ret < 0)
778 return ret;
779
780 ret = avs_dai_prepare(substream, dai);
781 if (ret)
782 return ret;
783
784 hdac_stream(host_stream)->prepared = true;
785 return 0;
786 }
787
avs_hda_stream_start(struct hdac_bus * bus,struct hdac_ext_stream * host_stream)788 static void avs_hda_stream_start(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
789 {
790 struct hdac_stream *first_running = NULL;
791 struct hdac_stream *pos;
792 struct avs_dev *adev = hdac_to_avs(bus);
793
794 list_for_each_entry(pos, &bus->stream_list, list) {
795 if (pos->running) {
796 if (first_running)
797 break; /* more than one running */
798 first_running = pos;
799 }
800 }
801
802 /*
803 * If host_stream is a CAPTURE stream and will be the only one running,
804 * disable L1SEN to avoid sound clipping.
805 */
806 if (!first_running) {
807 if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
808 avs_hda_l1sen_enable(adev, false);
809 snd_hdac_stream_start(hdac_stream(host_stream));
810 return;
811 }
812
813 snd_hdac_stream_start(hdac_stream(host_stream));
814 /*
815 * If host_stream is the first stream to break the rule above,
816 * re-enable L1SEN.
817 */
818 if (list_entry_is_head(pos, &bus->stream_list, list) &&
819 first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
820 avs_hda_l1sen_enable(adev, true);
821 }
822
avs_hda_stream_stop(struct hdac_bus * bus,struct hdac_ext_stream * host_stream)823 static void avs_hda_stream_stop(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
824 {
825 struct hdac_stream *first_running = NULL;
826 struct hdac_stream *pos;
827 struct avs_dev *adev = hdac_to_avs(bus);
828
829 list_for_each_entry(pos, &bus->stream_list, list) {
830 if (pos == hdac_stream(host_stream))
831 continue; /* ignore stream that is about to be stopped */
832 if (pos->running) {
833 if (first_running)
834 break; /* more than one running */
835 first_running = pos;
836 }
837 }
838
839 /*
840 * If host_stream is a CAPTURE stream and is the only one running,
841 * re-enable L1SEN.
842 */
843 if (!first_running) {
844 snd_hdac_stream_stop(hdac_stream(host_stream));
845 if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
846 avs_hda_l1sen_enable(adev, true);
847 return;
848 }
849
850 /*
851 * If by stopping host_stream there is only a single, CAPTURE stream running
852 * left, disable L1SEN to avoid sound clipping.
853 */
854 if (list_entry_is_head(pos, &bus->stream_list, list) &&
855 first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
856 avs_hda_l1sen_enable(adev, false);
857
858 snd_hdac_stream_stop(hdac_stream(host_stream));
859 }
860
avs_dai_fe_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)861 static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
862 {
863 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
864 struct avs_dma_data *data;
865 struct hdac_ext_stream *host_stream;
866 struct hdac_bus *bus;
867 unsigned long flags;
868 int ret = 0;
869
870 data = snd_soc_dai_get_dma_data(dai, substream);
871 host_stream = data->host_stream;
872 bus = hdac_stream(host_stream)->bus;
873
874 switch (cmd) {
875 case SNDRV_PCM_TRIGGER_RESUME:
876 if (rtd->dai_link->ignore_suspend)
877 break;
878 fallthrough;
879 case SNDRV_PCM_TRIGGER_START:
880 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
881 spin_lock_irqsave(&bus->reg_lock, flags);
882 avs_hda_stream_start(bus, host_stream);
883 spin_unlock_irqrestore(&bus->reg_lock, flags);
884
885 /* Timeout on DRSM poll shall not stop the resume so ignore the result. */
886 if (cmd == SNDRV_PCM_TRIGGER_RESUME)
887 snd_hdac_stream_wait_drsm(hdac_stream(host_stream));
888
889 ret = avs_path_pause(data->path);
890 if (ret < 0) {
891 dev_err(dai->dev, "pause FE path failed: %d\n", ret);
892 break;
893 }
894
895 ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
896 if (ret < 0)
897 dev_err(dai->dev, "run FE path failed: %d\n", ret);
898
899 break;
900
901 case SNDRV_PCM_TRIGGER_SUSPEND:
902 if (rtd->dai_link->ignore_suspend)
903 break;
904 fallthrough;
905 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
906 case SNDRV_PCM_TRIGGER_STOP:
907 ret = avs_path_pause(data->path);
908 if (ret < 0)
909 dev_err(dai->dev, "pause FE path failed: %d\n", ret);
910
911 spin_lock_irqsave(&bus->reg_lock, flags);
912 avs_hda_stream_stop(bus, host_stream);
913 spin_unlock_irqrestore(&bus->reg_lock, flags);
914
915 ret = avs_path_reset(data->path);
916 if (ret < 0)
917 dev_err(dai->dev, "reset FE path failed: %d\n", ret);
918 break;
919
920 default:
921 ret = -EINVAL;
922 break;
923 }
924
925 return ret;
926 }
927
928 const struct snd_soc_dai_ops avs_dai_fe_ops = {
929 .startup = avs_dai_fe_startup,
930 .shutdown = avs_dai_fe_shutdown,
931 .hw_params = avs_dai_fe_hw_params,
932 .hw_free = avs_dai_fe_hw_free,
933 .prepare = avs_dai_fe_prepare,
934 .trigger = avs_dai_fe_trigger,
935 };
936
topology_name_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)937 static ssize_t topology_name_read(struct file *file, char __user *user_buf, size_t count,
938 loff_t *ppos)
939 {
940 struct snd_soc_component *component = file->private_data;
941 struct snd_soc_card *card = component->card;
942 struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
943 char buf[64];
944 size_t len;
945
946 len = scnprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix,
947 mach->tplg_filename);
948
949 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
950 }
951
952 static const struct file_operations topology_name_fops = {
953 .open = simple_open,
954 .read = topology_name_read,
955 .llseek = default_llseek,
956 };
957
avs_component_load_libraries(struct avs_soc_component * acomp)958 static int avs_component_load_libraries(struct avs_soc_component *acomp)
959 {
960 struct avs_tplg *tplg = acomp->tplg;
961 struct avs_dev *adev = to_avs_dev(acomp->base.dev);
962 int ret;
963
964 if (!tplg->num_libs)
965 return 0;
966
967 /* Parent device may be asleep and library loading involves IPCs. */
968 ret = pm_runtime_resume_and_get(adev->dev);
969 if (ret < 0)
970 return ret;
971
972 avs_hda_power_gating_enable(adev, false);
973 avs_hda_clock_gating_enable(adev, false);
974 avs_hda_l1sen_enable(adev, false);
975
976 ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
977
978 avs_hda_l1sen_enable(adev, true);
979 avs_hda_clock_gating_enable(adev, true);
980 avs_hda_power_gating_enable(adev, true);
981
982 if (!ret)
983 ret = avs_module_info_init(adev, false);
984
985 pm_runtime_put_autosuspend(adev->dev);
986
987 return ret;
988 }
989
avs_component_probe(struct snd_soc_component * component)990 static int avs_component_probe(struct snd_soc_component *component)
991 {
992 struct snd_soc_card *card = component->card;
993 struct snd_soc_acpi_mach *mach;
994 struct avs_soc_component *acomp;
995 struct avs_dev *adev;
996 char *filename;
997 int ret;
998
999 dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
1000 mach = dev_get_platdata(card->dev);
1001 acomp = to_avs_soc_component(component);
1002 adev = to_avs_dev(component->dev);
1003
1004 acomp->tplg = avs_tplg_new(component);
1005 if (!acomp->tplg)
1006 return -ENOMEM;
1007
1008 if (!mach->tplg_filename)
1009 goto finalize;
1010
1011 /* Load specified topology and create debugfs for it. */
1012 filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1013 mach->tplg_filename);
1014 if (!filename)
1015 return -ENOMEM;
1016
1017 ret = avs_load_topology(component, filename);
1018 kfree(filename);
1019 if (ret == -ENOENT && !strncmp(mach->tplg_filename, "hda-", 4)) {
1020 unsigned int vendor_id;
1021
1022 if (sscanf(mach->tplg_filename, "hda-%08x-tplg.bin", &vendor_id) != 1)
1023 return ret;
1024
1025 if (((vendor_id >> 16) & 0xFFFF) == 0x8086)
1026 mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1027 "hda-8086-generic-tplg.bin");
1028 else
1029 mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1030 "hda-generic-tplg.bin");
1031 if (!mach->tplg_filename)
1032 return -ENOMEM;
1033 filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1034 mach->tplg_filename);
1035 if (!filename)
1036 return -ENOMEM;
1037
1038 dev_info(card->dev, "trying to load fallback topology %s\n", mach->tplg_filename);
1039 ret = avs_load_topology(component, filename);
1040 kfree(filename);
1041 }
1042 if (ret < 0)
1043 return ret;
1044
1045 ret = avs_component_load_libraries(acomp);
1046 if (ret < 0) {
1047 dev_err(card->dev, "libraries loading failed: %d\n", ret);
1048 goto err_load_libs;
1049 }
1050
1051 finalize:
1052 debugfs_create_file("topology_name", 0444, component->debugfs_root, component,
1053 &topology_name_fops);
1054
1055 mutex_lock(&adev->comp_list_mutex);
1056 list_add_tail(&acomp->node, &adev->comp_list);
1057 mutex_unlock(&adev->comp_list_mutex);
1058
1059 return 0;
1060
1061 err_load_libs:
1062 avs_remove_topology(component);
1063 return ret;
1064 }
1065
avs_component_remove(struct snd_soc_component * component)1066 static void avs_component_remove(struct snd_soc_component *component)
1067 {
1068 struct avs_soc_component *acomp = to_avs_soc_component(component);
1069 struct snd_soc_acpi_mach *mach;
1070 struct avs_dev *adev = to_avs_dev(component->dev);
1071 int ret;
1072
1073 mach = dev_get_platdata(component->card->dev);
1074
1075 mutex_lock(&adev->comp_list_mutex);
1076 list_del(&acomp->node);
1077 mutex_unlock(&adev->comp_list_mutex);
1078
1079 if (mach->tplg_filename) {
1080 ret = avs_remove_topology(component);
1081 if (ret < 0)
1082 dev_err(component->dev, "unload topology failed: %d\n", ret);
1083 }
1084 }
1085
avs_dai_resume_hw_params(struct snd_soc_dai * dai,struct avs_dma_data * data)1086 static int avs_dai_resume_hw_params(struct snd_soc_dai *dai, struct avs_dma_data *data)
1087 {
1088 struct snd_pcm_substream *substream;
1089 struct snd_soc_pcm_runtime *rtd;
1090 int ret;
1091
1092 substream = data->substream;
1093 rtd = snd_soc_substream_to_rtd(substream);
1094
1095 ret = dai->driver->ops->hw_params(substream, &rtd->dpcm[substream->stream].hw_params, dai);
1096 if (ret)
1097 dev_err(dai->dev, "hw_params on resume failed: %d\n", ret);
1098
1099 return ret;
1100 }
1101
avs_dai_resume_fe_prepare(struct snd_soc_dai * dai,struct avs_dma_data * data)1102 static int avs_dai_resume_fe_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1103 {
1104 struct hdac_ext_stream *host_stream;
1105 struct hdac_stream *hstream;
1106 struct hdac_bus *bus;
1107 int ret;
1108
1109 host_stream = data->host_stream;
1110 hstream = hdac_stream(host_stream);
1111 bus = hdac_stream(host_stream)->bus;
1112
1113 /* Set DRSM before programming stream and position registers. */
1114 snd_hdac_stream_drsm_enable(bus, true, hstream->index);
1115
1116 ret = dai->driver->ops->prepare(data->substream, dai);
1117 if (ret) {
1118 dev_err(dai->dev, "prepare FE on resume failed: %d\n", ret);
1119 return ret;
1120 }
1121
1122 writel(host_stream->pphcllpl, host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1123 writel(host_stream->pphcllpu, host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1124 writel(host_stream->pphcldpl, host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1125 writel(host_stream->pphcldpu, host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1126
1127 /* As per HW spec recommendation, program LPIB and DPIB to the same value. */
1128 snd_hdac_stream_set_lpib(hstream, hstream->lpib);
1129 snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
1130
1131 return 0;
1132 }
1133
avs_dai_resume_be_prepare(struct snd_soc_dai * dai,struct avs_dma_data * data)1134 static int avs_dai_resume_be_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1135 {
1136 int ret;
1137
1138 ret = dai->driver->ops->prepare(data->substream, dai);
1139 if (ret)
1140 dev_err(dai->dev, "prepare BE on resume failed: %d\n", ret);
1141
1142 return ret;
1143 }
1144
avs_dai_suspend_fe_hw_free(struct snd_soc_dai * dai,struct avs_dma_data * data)1145 static int avs_dai_suspend_fe_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1146 {
1147 struct hdac_ext_stream *host_stream;
1148 int ret;
1149
1150 host_stream = data->host_stream;
1151
1152 /* Store position addresses so we can resume from them later on. */
1153 hdac_stream(host_stream)->lpib = snd_hdac_stream_get_pos_lpib(hdac_stream(host_stream));
1154 host_stream->pphcllpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1155 host_stream->pphcllpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1156 host_stream->pphcldpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1157 host_stream->pphcldpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1158
1159 ret = __avs_dai_fe_hw_free(data->substream, dai);
1160 if (ret < 0)
1161 dev_err(dai->dev, "hw_free FE on suspend failed: %d\n", ret);
1162
1163 return ret;
1164 }
1165
avs_dai_suspend_be_hw_free(struct snd_soc_dai * dai,struct avs_dma_data * data)1166 static int avs_dai_suspend_be_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1167 {
1168 int ret;
1169
1170 ret = dai->driver->ops->hw_free(data->substream, dai);
1171 if (ret < 0)
1172 dev_err(dai->dev, "hw_free BE on suspend failed: %d\n", ret);
1173
1174 return ret;
1175 }
1176
avs_component_pm_op(struct snd_soc_component * component,bool be,int (* op)(struct snd_soc_dai *,struct avs_dma_data *))1177 static int avs_component_pm_op(struct snd_soc_component *component, bool be,
1178 int (*op)(struct snd_soc_dai *, struct avs_dma_data *))
1179 {
1180 struct snd_soc_pcm_runtime *rtd;
1181 struct avs_dma_data *data;
1182 struct snd_soc_dai *dai;
1183 int ret;
1184
1185 for_each_component_dais(component, dai) {
1186 data = snd_soc_dai_dma_data_get_playback(dai);
1187 if (data) {
1188 rtd = snd_soc_substream_to_rtd(data->substream);
1189 if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1190 ret = op(dai, data);
1191 if (ret < 0) {
1192 __snd_pcm_set_state(data->substream->runtime,
1193 SNDRV_PCM_STATE_DISCONNECTED);
1194 return ret;
1195 }
1196 }
1197 }
1198
1199 data = snd_soc_dai_dma_data_get_capture(dai);
1200 if (data) {
1201 rtd = snd_soc_substream_to_rtd(data->substream);
1202 if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1203 ret = op(dai, data);
1204 if (ret < 0) {
1205 __snd_pcm_set_state(data->substream->runtime,
1206 SNDRV_PCM_STATE_DISCONNECTED);
1207 return ret;
1208 }
1209 }
1210 }
1211 }
1212
1213 return 0;
1214 }
1215
avs_component_resume_hw_params(struct snd_soc_component * component,bool be)1216 static int avs_component_resume_hw_params(struct snd_soc_component *component, bool be)
1217 {
1218 return avs_component_pm_op(component, be, &avs_dai_resume_hw_params);
1219 }
1220
avs_component_resume_prepare(struct snd_soc_component * component,bool be)1221 static int avs_component_resume_prepare(struct snd_soc_component *component, bool be)
1222 {
1223 int (*prepare_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1224
1225 if (be)
1226 prepare_cb = &avs_dai_resume_be_prepare;
1227 else
1228 prepare_cb = &avs_dai_resume_fe_prepare;
1229
1230 return avs_component_pm_op(component, be, prepare_cb);
1231 }
1232
avs_component_suspend_hw_free(struct snd_soc_component * component,bool be)1233 static int avs_component_suspend_hw_free(struct snd_soc_component *component, bool be)
1234 {
1235 int (*hw_free_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1236
1237 if (be)
1238 hw_free_cb = &avs_dai_suspend_be_hw_free;
1239 else
1240 hw_free_cb = &avs_dai_suspend_fe_hw_free;
1241
1242 return avs_component_pm_op(component, be, hw_free_cb);
1243 }
1244
avs_component_suspend(struct snd_soc_component * component)1245 static int avs_component_suspend(struct snd_soc_component *component)
1246 {
1247 int ret;
1248
1249 /*
1250 * When freeing paths, FEs need to be first as they perform
1251 * path unbinding.
1252 */
1253 ret = avs_component_suspend_hw_free(component, false);
1254 if (ret)
1255 return ret;
1256
1257 return avs_component_suspend_hw_free(component, true);
1258 }
1259
avs_component_resume(struct snd_soc_component * component)1260 static int avs_component_resume(struct snd_soc_component *component)
1261 {
1262 int ret;
1263
1264 /*
1265 * When creating paths, FEs need to be last as they perform
1266 * path binding.
1267 */
1268 ret = avs_component_resume_hw_params(component, true);
1269 if (ret)
1270 return ret;
1271
1272 ret = avs_component_resume_hw_params(component, false);
1273 if (ret)
1274 return ret;
1275
1276 /* It is expected that the LINK stream is prepared first. */
1277 ret = avs_component_resume_prepare(component, true);
1278 if (ret)
1279 return ret;
1280
1281 return avs_component_resume_prepare(component, false);
1282 }
1283
1284 static const struct snd_pcm_hardware avs_pcm_hardware = {
1285 .info = SNDRV_PCM_INFO_MMAP |
1286 SNDRV_PCM_INFO_MMAP_VALID |
1287 SNDRV_PCM_INFO_INTERLEAVED |
1288 SNDRV_PCM_INFO_PAUSE |
1289 SNDRV_PCM_INFO_RESUME |
1290 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
1291 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1292 SNDRV_PCM_FMTBIT_S32_LE,
1293 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1294 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1295 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1296 .buffer_bytes_max = AZX_MAX_BUF_SIZE,
1297 .period_bytes_min = 128,
1298 .period_bytes_max = AZX_MAX_BUF_SIZE / 2,
1299 .periods_min = 2,
1300 .periods_max = AZX_MAX_FRAG,
1301 .fifo_size = 0,
1302 };
1303
avs_component_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)1304 static int avs_component_open(struct snd_soc_component *component,
1305 struct snd_pcm_substream *substream)
1306 {
1307 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1308
1309 /* only FE DAI links are handled here */
1310 if (rtd->dai_link->no_pcm)
1311 return 0;
1312
1313 return snd_soc_set_runtime_hwparams(substream, &avs_pcm_hardware);
1314 }
1315
avs_hda_stream_dpib_read(struct hdac_ext_stream * stream)1316 static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream)
1317 {
1318 return readl(hdac_stream(stream)->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1319 (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index));
1320 }
1321
1322 static snd_pcm_uframes_t
avs_component_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)1323 avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream)
1324 {
1325 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1326 struct avs_dma_data *data;
1327 struct hdac_ext_stream *host_stream;
1328 unsigned int pos;
1329
1330 data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
1331 if (!data->host_stream)
1332 return 0;
1333
1334 host_stream = data->host_stream;
1335 pos = avs_hda_stream_dpib_read(host_stream);
1336
1337 if (pos >= hdac_stream(host_stream)->bufsize)
1338 pos = 0;
1339
1340 return bytes_to_frames(substream->runtime, pos);
1341 }
1342
avs_component_mmap(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct vm_area_struct * vma)1343 static int avs_component_mmap(struct snd_soc_component *component,
1344 struct snd_pcm_substream *substream,
1345 struct vm_area_struct *vma)
1346 {
1347 return snd_pcm_lib_default_mmap(substream, vma);
1348 }
1349
1350 #define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
1351
avs_component_construct(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)1352 static int avs_component_construct(struct snd_soc_component *component,
1353 struct snd_soc_pcm_runtime *rtd)
1354 {
1355 struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
1356 struct snd_pcm *pcm = rtd->pcm;
1357
1358 if (dai->driver->playback.channels_min)
1359 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
1360 SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1361 MAX_PREALLOC_SIZE);
1362
1363 if (dai->driver->capture.channels_min)
1364 snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
1365 SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1366 MAX_PREALLOC_SIZE);
1367
1368 return 0;
1369 }
1370
1371 static struct snd_soc_component_driver avs_component_driver = {
1372 .name = "avs-pcm",
1373 .probe = avs_component_probe,
1374 .remove = avs_component_remove,
1375 .suspend = avs_component_suspend,
1376 .resume = avs_component_resume,
1377 .open = avs_component_open,
1378 .pointer = avs_component_pointer,
1379 .mmap = avs_component_mmap,
1380 .pcm_construct = avs_component_construct,
1381 .module_get_upon_open = 1, /* increment refcount when a pcm is opened */
1382 .topology_name_prefix = "intel/avs",
1383 };
1384
avs_register_component(struct device * dev,const char * name,struct snd_soc_component_driver * drv,struct snd_soc_dai_driver * cpu_dais,int num_cpu_dais)1385 int avs_register_component(struct device *dev, const char *name,
1386 struct snd_soc_component_driver *drv,
1387 struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais)
1388 {
1389 struct avs_soc_component *acomp;
1390 int ret;
1391
1392 acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
1393 if (!acomp)
1394 return -ENOMEM;
1395
1396 acomp->base.name = devm_kstrdup(dev, name, GFP_KERNEL);
1397 if (!acomp->base.name)
1398 return -ENOMEM;
1399
1400 INIT_LIST_HEAD(&acomp->node);
1401
1402 drv->use_dai_pcm_id = !obsolete_card_names;
1403
1404 ret = snd_soc_component_initialize(&acomp->base, drv, dev);
1405 if (ret < 0)
1406 return ret;
1407
1408 return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
1409 }
1410
1411 static struct snd_soc_dai_driver dmic_cpu_dais[] = {
1412 {
1413 .name = "DMIC Pin",
1414 .capture = {
1415 .stream_name = "DMIC Rx",
1416 .channels_min = 1,
1417 .channels_max = 4,
1418 .rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000,
1419 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
1420 },
1421 },
1422 {
1423 .name = "DMIC WoV Pin",
1424 .capture = {
1425 .stream_name = "DMIC WoV Rx",
1426 .channels_min = 1,
1427 .channels_max = 4,
1428 .rates = SNDRV_PCM_RATE_16000,
1429 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1430 },
1431 },
1432 };
1433
avs_register_dmic_component(struct avs_dev * adev,const char * name)1434 int avs_register_dmic_component(struct avs_dev *adev, const char *name)
1435 {
1436 const struct snd_soc_dai_ops *ops;
1437
1438 if (avs_platattr_test(adev, ALTHDA))
1439 ops = &avs_dai_dmichda_be_ops;
1440 else
1441 ops = &avs_dai_nonhda_be_ops;
1442
1443 dmic_cpu_dais[0].ops = ops;
1444 dmic_cpu_dais[1].ops = ops;
1445 return avs_register_component(adev->dev, name, &avs_component_driver, dmic_cpu_dais,
1446 ARRAY_SIZE(dmic_cpu_dais));
1447 }
1448
1449 static const struct snd_soc_dai_driver i2s_dai_template = {
1450 .playback = {
1451 .channels_min = 1,
1452 .channels_max = AVS_CHANNELS_MAX,
1453 .rates = SNDRV_PCM_RATE_8000_192000 |
1454 SNDRV_PCM_RATE_12000 |
1455 SNDRV_PCM_RATE_24000 |
1456 SNDRV_PCM_RATE_128000,
1457 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1458 SNDRV_PCM_FMTBIT_S32_LE,
1459 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1460 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1461 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1462 },
1463 .capture = {
1464 .channels_min = 1,
1465 .channels_max = AVS_CHANNELS_MAX,
1466 .rates = SNDRV_PCM_RATE_8000_192000 |
1467 SNDRV_PCM_RATE_12000 |
1468 SNDRV_PCM_RATE_24000 |
1469 SNDRV_PCM_RATE_128000,
1470 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1471 SNDRV_PCM_FMTBIT_S32_LE,
1472 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1473 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1474 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1475 },
1476 };
1477
avs_register_i2s_component(struct avs_dev * adev,const char * name,unsigned long port_mask,unsigned long * tdms)1478 int avs_register_i2s_component(struct avs_dev *adev, const char *name, unsigned long port_mask,
1479 unsigned long *tdms)
1480 {
1481 struct snd_soc_dai_driver *cpus, *dai;
1482 const struct snd_soc_dai_ops *ops;
1483 size_t ssp_count, cpu_count;
1484 int i, j;
1485
1486 ssp_count = adev->hw_cfg.i2s_caps.ctrl_count;
1487 if (avs_platattr_test(adev, ALTHDA))
1488 ops = &avs_dai_i2shda_be_ops;
1489 else
1490 ops = &avs_dai_nonhda_be_ops;
1491
1492 cpu_count = 0;
1493 for_each_set_bit(i, &port_mask, ssp_count)
1494 if (!tdms || test_bit(0, &tdms[i]))
1495 cpu_count++;
1496 if (tdms)
1497 for_each_set_bit(i, &port_mask, ssp_count)
1498 cpu_count += hweight_long(tdms[i]);
1499
1500 cpus = devm_kcalloc(adev->dev, cpu_count, sizeof(*cpus), GFP_KERNEL);
1501 if (!cpus)
1502 return -ENOMEM;
1503
1504 dai = cpus;
1505 for_each_set_bit(i, &port_mask, ssp_count) {
1506 if (!tdms || test_bit(0, &tdms[i])) {
1507 memcpy(dai, &i2s_dai_template, sizeof(*dai));
1508
1509 dai->name =
1510 devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i);
1511 dai->playback.stream_name =
1512 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i);
1513 dai->capture.stream_name =
1514 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i);
1515
1516 if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1517 return -ENOMEM;
1518 dai->ops = ops;
1519 dai++;
1520 }
1521 }
1522
1523 if (!tdms)
1524 goto plat_register;
1525
1526 for_each_set_bit(i, &port_mask, ssp_count) {
1527 for_each_set_bit(j, &tdms[i], AVS_CHANNELS_MAX) {
1528 memcpy(dai, &i2s_dai_template, sizeof(*dai));
1529
1530 dai->name =
1531 devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d:%d Pin", i, j);
1532 dai->playback.stream_name =
1533 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Tx", i, j);
1534 dai->capture.stream_name =
1535 devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Rx", i, j);
1536
1537 if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1538 return -ENOMEM;
1539 dai->ops = ops;
1540 dai++;
1541 }
1542 }
1543
1544 plat_register:
1545 return avs_register_component(adev->dev, name, &avs_component_driver, cpus, cpu_count);
1546 }
1547
1548 /* HD-Audio CPU DAI template */
1549 static const struct snd_soc_dai_driver hda_cpu_dai = {
1550 .ops = &avs_dai_hda_be_ops,
1551 .playback = {
1552 .channels_min = 1,
1553 .channels_max = AVS_CHANNELS_MAX,
1554 .rates = SNDRV_PCM_RATE_8000_192000,
1555 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1556 SNDRV_PCM_FMTBIT_S32_LE,
1557 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1558 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1559 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1560 },
1561 .capture = {
1562 .channels_min = 1,
1563 .channels_max = AVS_CHANNELS_MAX,
1564 .rates = SNDRV_PCM_RATE_8000_192000,
1565 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1566 SNDRV_PCM_FMTBIT_S32_LE,
1567 .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1568 SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1569 SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1570 },
1571 };
1572
avs_component_hda_unregister_dais(struct snd_soc_component * component)1573 static void avs_component_hda_unregister_dais(struct snd_soc_component *component)
1574 {
1575 struct snd_soc_acpi_mach *mach;
1576 struct snd_soc_dai *dai, *save;
1577 struct avs_mach_pdata *pdata;
1578 struct hda_codec *codec;
1579 char name[32];
1580
1581 mach = dev_get_platdata(component->card->dev);
1582 pdata = mach->pdata;
1583 codec = pdata->codec;
1584 snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev));
1585
1586 for_each_component_dais_safe(component, dai, save) {
1587 int stream;
1588
1589 if (!strstr(dai->driver->name, name))
1590 continue;
1591
1592 for_each_pcm_streams(stream)
1593 snd_soc_dapm_free_widget(snd_soc_dai_get_widget(dai, stream));
1594
1595 snd_soc_unregister_dai(dai);
1596 }
1597 }
1598
avs_component_hda_probe(struct snd_soc_component * component)1599 static int avs_component_hda_probe(struct snd_soc_component *component)
1600 {
1601 struct snd_soc_dapm_context *dapm;
1602 struct snd_soc_dai_driver *dais;
1603 struct snd_soc_acpi_mach *mach;
1604 struct avs_mach_pdata *pdata;
1605 struct hda_codec *codec;
1606 struct hda_pcm *pcm;
1607 const char *cname;
1608 int pcm_count = 0, ret, i;
1609
1610 mach = dev_get_platdata(component->card->dev);
1611 if (!mach)
1612 return -EINVAL;
1613
1614 pdata = mach->pdata;
1615 codec = pdata->codec;
1616 if (list_empty(&codec->pcm_list_head))
1617 return -EINVAL;
1618 list_for_each_entry(pcm, &codec->pcm_list_head, list)
1619 pcm_count++;
1620
1621 dais = devm_kcalloc(component->dev, pcm_count, sizeof(*dais),
1622 GFP_KERNEL);
1623 if (!dais)
1624 return -ENOMEM;
1625
1626 cname = dev_name(&codec->core.dev);
1627 dapm = snd_soc_component_get_dapm(component);
1628 pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list);
1629
1630 for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) {
1631 struct snd_soc_dai *dai;
1632
1633 memcpy(&dais[i], &hda_cpu_dai, sizeof(*dais));
1634 dais[i].id = i;
1635 dais[i].name = devm_kasprintf(component->dev, GFP_KERNEL,
1636 "%s-cpu%d", cname, i);
1637 if (!dais[i].name) {
1638 ret = -ENOMEM;
1639 goto exit;
1640 }
1641
1642 if (pcm->stream[0].substreams) {
1643 dais[i].playback.stream_name =
1644 devm_kasprintf(component->dev, GFP_KERNEL,
1645 "%s-cpu%d Tx", cname, i);
1646 if (!dais[i].playback.stream_name) {
1647 ret = -ENOMEM;
1648 goto exit;
1649 }
1650
1651 if (!hda_codec_is_display(codec)) {
1652 dais[i].playback.formats = pcm->stream[0].formats;
1653 dais[i].playback.subformats = pcm->stream[0].subformats;
1654 dais[i].playback.rates = pcm->stream[0].rates;
1655 dais[i].playback.channels_min = pcm->stream[0].channels_min;
1656 dais[i].playback.channels_max = pcm->stream[0].channels_max;
1657 dais[i].playback.sig_bits = pcm->stream[0].maxbps;
1658 }
1659 }
1660
1661 if (pcm->stream[1].substreams) {
1662 dais[i].capture.stream_name =
1663 devm_kasprintf(component->dev, GFP_KERNEL,
1664 "%s-cpu%d Rx", cname, i);
1665 if (!dais[i].capture.stream_name) {
1666 ret = -ENOMEM;
1667 goto exit;
1668 }
1669
1670 if (!hda_codec_is_display(codec)) {
1671 dais[i].capture.formats = pcm->stream[1].formats;
1672 dais[i].capture.subformats = pcm->stream[1].subformats;
1673 dais[i].capture.rates = pcm->stream[1].rates;
1674 dais[i].capture.channels_min = pcm->stream[1].channels_min;
1675 dais[i].capture.channels_max = pcm->stream[1].channels_max;
1676 dais[i].capture.sig_bits = pcm->stream[1].maxbps;
1677 }
1678 }
1679
1680 dai = snd_soc_register_dai(component, &dais[i], false);
1681 if (!dai) {
1682 dev_err(component->dev, "register dai for %s failed\n",
1683 pcm->name);
1684 ret = -EINVAL;
1685 goto exit;
1686 }
1687
1688 ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
1689 if (ret < 0) {
1690 dev_err(component->dev, "create widgets failed: %d\n",
1691 ret);
1692 snd_soc_unregister_dai(dai);
1693 goto exit;
1694 }
1695 }
1696
1697 ret = avs_component_probe(component);
1698 exit:
1699 if (ret)
1700 avs_component_hda_unregister_dais(component);
1701
1702 return ret;
1703 }
1704
avs_component_hda_remove(struct snd_soc_component * component)1705 static void avs_component_hda_remove(struct snd_soc_component *component)
1706 {
1707 avs_component_remove(component);
1708 avs_component_hda_unregister_dais(component);
1709 }
1710
avs_component_hda_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)1711 static int avs_component_hda_open(struct snd_soc_component *component,
1712 struct snd_pcm_substream *substream)
1713 {
1714 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1715
1716 if (!rtd->dai_link->no_pcm) {
1717 struct snd_pcm_hardware hwparams = avs_pcm_hardware;
1718 struct snd_soc_pcm_runtime *be;
1719 struct snd_soc_dpcm *dpcm;
1720 int dir = substream->stream;
1721
1722 /*
1723 * Support the DPCM reparenting while still fulfilling expectations of HDAudio
1724 * common code - a valid stream pointer at substream->runtime->private_data -
1725 * by having all FEs point to the same private data.
1726 */
1727 for_each_dpcm_be(rtd, dir, dpcm) {
1728 struct snd_pcm_substream *be_substream;
1729
1730 be = dpcm->be;
1731 if (be->dpcm[dir].users == 1)
1732 break;
1733
1734 be_substream = snd_soc_dpcm_get_substream(be, dir);
1735 substream->runtime->private_data = be_substream->runtime->private_data;
1736 break;
1737 }
1738
1739 /* RESUME unsupported for de-coupled HD-Audio capture. */
1740 if (dir == SNDRV_PCM_STREAM_CAPTURE)
1741 hwparams.info &= ~SNDRV_PCM_INFO_RESUME;
1742
1743 return snd_soc_set_runtime_hwparams(substream, &hwparams);
1744 }
1745
1746 return 0;
1747 }
1748
1749 static struct snd_soc_component_driver avs_hda_component_driver = {
1750 .name = "avs-hda-pcm",
1751 .probe = avs_component_hda_probe,
1752 .remove = avs_component_hda_remove,
1753 .suspend = avs_component_suspend,
1754 .resume = avs_component_resume,
1755 .open = avs_component_hda_open,
1756 .pointer = avs_component_pointer,
1757 .mmap = avs_component_mmap,
1758 .pcm_construct = avs_component_construct,
1759 /*
1760 * hda platform component's probe() is dependent on
1761 * codec->pcm_list_head, it needs to be initialized after codec
1762 * component. remove_order is here for completeness sake
1763 */
1764 .probe_order = SND_SOC_COMP_ORDER_LATE,
1765 .remove_order = SND_SOC_COMP_ORDER_EARLY,
1766 .module_get_upon_open = 1,
1767 .topology_name_prefix = "intel/avs",
1768 };
1769
avs_register_hda_component(struct avs_dev * adev,const char * name)1770 int avs_register_hda_component(struct avs_dev *adev, const char *name)
1771 {
1772 return avs_register_component(adev->dev, name, &avs_hda_component_driver, NULL, 0);
1773 }
1774