Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/avs/pcm.c
26583 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
//
3
// Copyright(c) 2021-2022 Intel Corporation
4
//
5
// Authors: Cezary Rojewski <[email protected]>
6
// Amadeusz Slawinski <[email protected]>
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 *
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
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
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);
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_put_autosuspend(adev->dev);
983
984
return ret;
985
}
986
987
static int avs_component_probe(struct snd_soc_component *component)
988
{
989
struct snd_soc_card *card = component->card;
990
struct snd_soc_acpi_mach *mach;
991
struct avs_soc_component *acomp;
992
struct avs_dev *adev;
993
char *filename;
994
int ret;
995
996
dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
997
mach = dev_get_platdata(card->dev);
998
acomp = to_avs_soc_component(component);
999
adev = to_avs_dev(component->dev);
1000
1001
acomp->tplg = avs_tplg_new(component);
1002
if (!acomp->tplg)
1003
return -ENOMEM;
1004
1005
if (!mach->tplg_filename)
1006
goto finalize;
1007
1008
/* Load specified topology and create debugfs for it. */
1009
filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1010
mach->tplg_filename);
1011
if (!filename)
1012
return -ENOMEM;
1013
1014
ret = avs_load_topology(component, filename);
1015
kfree(filename);
1016
if (ret == -ENOENT && !strncmp(mach->tplg_filename, "hda-", 4)) {
1017
unsigned int vendor_id;
1018
1019
if (sscanf(mach->tplg_filename, "hda-%08x-tplg.bin", &vendor_id) != 1)
1020
return ret;
1021
1022
if (((vendor_id >> 16) & 0xFFFF) == 0x8086)
1023
mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1024
"hda-8086-generic-tplg.bin");
1025
else
1026
mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
1027
"hda-generic-tplg.bin");
1028
if (!mach->tplg_filename)
1029
return -ENOMEM;
1030
filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
1031
mach->tplg_filename);
1032
if (!filename)
1033
return -ENOMEM;
1034
1035
dev_info(card->dev, "trying to load fallback topology %s\n", mach->tplg_filename);
1036
ret = avs_load_topology(component, filename);
1037
kfree(filename);
1038
}
1039
if (ret < 0)
1040
return ret;
1041
1042
ret = avs_component_load_libraries(acomp);
1043
if (ret < 0) {
1044
dev_err(card->dev, "libraries loading failed: %d\n", ret);
1045
goto err_load_libs;
1046
}
1047
1048
finalize:
1049
debugfs_create_file("topology_name", 0444, component->debugfs_root, component,
1050
&topology_name_fops);
1051
1052
mutex_lock(&adev->comp_list_mutex);
1053
list_add_tail(&acomp->node, &adev->comp_list);
1054
mutex_unlock(&adev->comp_list_mutex);
1055
1056
return 0;
1057
1058
err_load_libs:
1059
avs_remove_topology(component);
1060
return ret;
1061
}
1062
1063
static void avs_component_remove(struct snd_soc_component *component)
1064
{
1065
struct avs_soc_component *acomp = to_avs_soc_component(component);
1066
struct snd_soc_acpi_mach *mach;
1067
struct avs_dev *adev = to_avs_dev(component->dev);
1068
int ret;
1069
1070
mach = dev_get_platdata(component->card->dev);
1071
1072
mutex_lock(&adev->comp_list_mutex);
1073
list_del(&acomp->node);
1074
mutex_unlock(&adev->comp_list_mutex);
1075
1076
if (mach->tplg_filename) {
1077
ret = avs_remove_topology(component);
1078
if (ret < 0)
1079
dev_err(component->dev, "unload topology failed: %d\n", ret);
1080
}
1081
}
1082
1083
static int avs_dai_resume_hw_params(struct snd_soc_dai *dai, struct avs_dma_data *data)
1084
{
1085
struct snd_pcm_substream *substream;
1086
struct snd_soc_pcm_runtime *rtd;
1087
int ret;
1088
1089
substream = data->substream;
1090
rtd = snd_soc_substream_to_rtd(substream);
1091
1092
ret = dai->driver->ops->hw_params(substream, &rtd->dpcm[substream->stream].hw_params, dai);
1093
if (ret)
1094
dev_err(dai->dev, "hw_params on resume failed: %d\n", ret);
1095
1096
return ret;
1097
}
1098
1099
static int avs_dai_resume_fe_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1100
{
1101
struct hdac_ext_stream *host_stream;
1102
struct hdac_stream *hstream;
1103
struct hdac_bus *bus;
1104
int ret;
1105
1106
host_stream = data->host_stream;
1107
hstream = hdac_stream(host_stream);
1108
bus = hdac_stream(host_stream)->bus;
1109
1110
/* Set DRSM before programming stream and position registers. */
1111
snd_hdac_stream_drsm_enable(bus, true, hstream->index);
1112
1113
ret = dai->driver->ops->prepare(data->substream, dai);
1114
if (ret) {
1115
dev_err(dai->dev, "prepare FE on resume failed: %d\n", ret);
1116
return ret;
1117
}
1118
1119
writel(host_stream->pphcllpl, host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1120
writel(host_stream->pphcllpu, host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1121
writel(host_stream->pphcldpl, host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1122
writel(host_stream->pphcldpu, host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1123
1124
/* As per HW spec recommendation, program LPIB and DPIB to the same value. */
1125
snd_hdac_stream_set_lpib(hstream, hstream->lpib);
1126
snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
1127
1128
return 0;
1129
}
1130
1131
static int avs_dai_resume_be_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
1132
{
1133
int ret;
1134
1135
ret = dai->driver->ops->prepare(data->substream, dai);
1136
if (ret)
1137
dev_err(dai->dev, "prepare BE on resume failed: %d\n", ret);
1138
1139
return ret;
1140
}
1141
1142
static int avs_dai_suspend_fe_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1143
{
1144
struct hdac_ext_stream *host_stream;
1145
int ret;
1146
1147
host_stream = data->host_stream;
1148
1149
/* Store position addresses so we can resume from them later on. */
1150
hdac_stream(host_stream)->lpib = snd_hdac_stream_get_pos_lpib(hdac_stream(host_stream));
1151
host_stream->pphcllpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPL);
1152
host_stream->pphcllpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPU);
1153
host_stream->pphcldpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPL);
1154
host_stream->pphcldpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPU);
1155
1156
ret = __avs_dai_fe_hw_free(data->substream, dai);
1157
if (ret < 0)
1158
dev_err(dai->dev, "hw_free FE on suspend failed: %d\n", ret);
1159
1160
return ret;
1161
}
1162
1163
static int avs_dai_suspend_be_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
1164
{
1165
int ret;
1166
1167
ret = dai->driver->ops->hw_free(data->substream, dai);
1168
if (ret < 0)
1169
dev_err(dai->dev, "hw_free BE on suspend failed: %d\n", ret);
1170
1171
return ret;
1172
}
1173
1174
static int avs_component_pm_op(struct snd_soc_component *component, bool be,
1175
int (*op)(struct snd_soc_dai *, struct avs_dma_data *))
1176
{
1177
struct snd_soc_pcm_runtime *rtd;
1178
struct avs_dma_data *data;
1179
struct snd_soc_dai *dai;
1180
int ret;
1181
1182
for_each_component_dais(component, dai) {
1183
data = snd_soc_dai_dma_data_get_playback(dai);
1184
if (data) {
1185
rtd = snd_soc_substream_to_rtd(data->substream);
1186
if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1187
ret = op(dai, data);
1188
if (ret < 0) {
1189
__snd_pcm_set_state(data->substream->runtime,
1190
SNDRV_PCM_STATE_DISCONNECTED);
1191
return ret;
1192
}
1193
}
1194
}
1195
1196
data = snd_soc_dai_dma_data_get_capture(dai);
1197
if (data) {
1198
rtd = snd_soc_substream_to_rtd(data->substream);
1199
if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
1200
ret = op(dai, data);
1201
if (ret < 0) {
1202
__snd_pcm_set_state(data->substream->runtime,
1203
SNDRV_PCM_STATE_DISCONNECTED);
1204
return ret;
1205
}
1206
}
1207
}
1208
}
1209
1210
return 0;
1211
}
1212
1213
static int avs_component_resume_hw_params(struct snd_soc_component *component, bool be)
1214
{
1215
return avs_component_pm_op(component, be, &avs_dai_resume_hw_params);
1216
}
1217
1218
static int avs_component_resume_prepare(struct snd_soc_component *component, bool be)
1219
{
1220
int (*prepare_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1221
1222
if (be)
1223
prepare_cb = &avs_dai_resume_be_prepare;
1224
else
1225
prepare_cb = &avs_dai_resume_fe_prepare;
1226
1227
return avs_component_pm_op(component, be, prepare_cb);
1228
}
1229
1230
static int avs_component_suspend_hw_free(struct snd_soc_component *component, bool be)
1231
{
1232
int (*hw_free_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1233
1234
if (be)
1235
hw_free_cb = &avs_dai_suspend_be_hw_free;
1236
else
1237
hw_free_cb = &avs_dai_suspend_fe_hw_free;
1238
1239
return avs_component_pm_op(component, be, hw_free_cb);
1240
}
1241
1242
static int avs_component_suspend(struct snd_soc_component *component)
1243
{
1244
int ret;
1245
1246
/*
1247
* When freeing paths, FEs need to be first as they perform
1248
* path unbinding.
1249
*/
1250
ret = avs_component_suspend_hw_free(component, false);
1251
if (ret)
1252
return ret;
1253
1254
return avs_component_suspend_hw_free(component, true);
1255
}
1256
1257
static int avs_component_resume(struct snd_soc_component *component)
1258
{
1259
int ret;
1260
1261
/*
1262
* When creating paths, FEs need to be last as they perform
1263
* path binding.
1264
*/
1265
ret = avs_component_resume_hw_params(component, true);
1266
if (ret)
1267
return ret;
1268
1269
ret = avs_component_resume_hw_params(component, false);
1270
if (ret)
1271
return ret;
1272
1273
/* It is expected that the LINK stream is prepared first. */
1274
ret = avs_component_resume_prepare(component, true);
1275
if (ret)
1276
return ret;
1277
1278
return avs_component_resume_prepare(component, false);
1279
}
1280
1281
static const struct snd_pcm_hardware avs_pcm_hardware = {
1282
.info = SNDRV_PCM_INFO_MMAP |
1283
SNDRV_PCM_INFO_MMAP_VALID |
1284
SNDRV_PCM_INFO_INTERLEAVED |
1285
SNDRV_PCM_INFO_PAUSE |
1286
SNDRV_PCM_INFO_RESUME |
1287
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
1288
.formats = SNDRV_PCM_FMTBIT_S16_LE |
1289
SNDRV_PCM_FMTBIT_S32_LE,
1290
.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1291
SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1292
SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1293
.buffer_bytes_max = AZX_MAX_BUF_SIZE,
1294
.period_bytes_min = 128,
1295
.period_bytes_max = AZX_MAX_BUF_SIZE / 2,
1296
.periods_min = 2,
1297
.periods_max = AZX_MAX_FRAG,
1298
.fifo_size = 0,
1299
};
1300
1301
static int avs_component_open(struct snd_soc_component *component,
1302
struct snd_pcm_substream *substream)
1303
{
1304
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1305
1306
/* only FE DAI links are handled here */
1307
if (rtd->dai_link->no_pcm)
1308
return 0;
1309
1310
return snd_soc_set_runtime_hwparams(substream, &avs_pcm_hardware);
1311
}
1312
1313
static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream)
1314
{
1315
return readl(hdac_stream(stream)->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1316
(AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index));
1317
}
1318
1319
static snd_pcm_uframes_t
1320
avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream)
1321
{
1322
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1323
struct avs_dma_data *data;
1324
struct hdac_ext_stream *host_stream;
1325
unsigned int pos;
1326
1327
data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
1328
if (!data->host_stream)
1329
return 0;
1330
1331
host_stream = data->host_stream;
1332
pos = avs_hda_stream_dpib_read(host_stream);
1333
1334
if (pos >= hdac_stream(host_stream)->bufsize)
1335
pos = 0;
1336
1337
return bytes_to_frames(substream->runtime, pos);
1338
}
1339
1340
static int avs_component_mmap(struct snd_soc_component *component,
1341
struct snd_pcm_substream *substream,
1342
struct vm_area_struct *vma)
1343
{
1344
return snd_pcm_lib_default_mmap(substream, vma);
1345
}
1346
1347
#define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
1348
1349
static int avs_component_construct(struct snd_soc_component *component,
1350
struct snd_soc_pcm_runtime *rtd)
1351
{
1352
struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
1353
struct snd_pcm *pcm = rtd->pcm;
1354
1355
if (dai->driver->playback.channels_min)
1356
snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
1357
SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1358
MAX_PREALLOC_SIZE);
1359
1360
if (dai->driver->capture.channels_min)
1361
snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
1362
SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1363
MAX_PREALLOC_SIZE);
1364
1365
return 0;
1366
}
1367
1368
static struct snd_soc_component_driver avs_component_driver = {
1369
.name = "avs-pcm",
1370
.probe = avs_component_probe,
1371
.remove = avs_component_remove,
1372
.suspend = avs_component_suspend,
1373
.resume = avs_component_resume,
1374
.open = avs_component_open,
1375
.pointer = avs_component_pointer,
1376
.mmap = avs_component_mmap,
1377
.pcm_construct = avs_component_construct,
1378
.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
1379
.topology_name_prefix = "intel/avs",
1380
};
1381
1382
int avs_soc_component_register(struct device *dev, const char *name,
1383
struct snd_soc_component_driver *drv,
1384
struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais)
1385
{
1386
struct avs_soc_component *acomp;
1387
int ret;
1388
1389
acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
1390
if (!acomp)
1391
return -ENOMEM;
1392
1393
ret = snd_soc_component_initialize(&acomp->base, drv, dev);
1394
if (ret < 0)
1395
return ret;
1396
1397
/* force name change after ASoC is done with its init */
1398
acomp->base.name = name;
1399
INIT_LIST_HEAD(&acomp->node);
1400
1401
drv->use_dai_pcm_id = !obsolete_card_names;
1402
1403
return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
1404
}
1405
1406
static struct snd_soc_dai_driver dmic_cpu_dais[] = {
1407
{
1408
.name = "DMIC Pin",
1409
.capture = {
1410
.stream_name = "DMIC Rx",
1411
.channels_min = 1,
1412
.channels_max = 4,
1413
.rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000,
1414
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
1415
},
1416
},
1417
{
1418
.name = "DMIC WoV Pin",
1419
.capture = {
1420
.stream_name = "DMIC WoV Rx",
1421
.channels_min = 1,
1422
.channels_max = 4,
1423
.rates = SNDRV_PCM_RATE_16000,
1424
.formats = SNDRV_PCM_FMTBIT_S16_LE,
1425
},
1426
},
1427
};
1428
1429
int avs_dmic_platform_register(struct avs_dev *adev, const char *name)
1430
{
1431
const struct snd_soc_dai_ops *ops;
1432
1433
if (avs_platattr_test(adev, ALTHDA))
1434
ops = &avs_dai_dmichda_be_ops;
1435
else
1436
ops = &avs_dai_nonhda_be_ops;
1437
1438
dmic_cpu_dais[0].ops = ops;
1439
dmic_cpu_dais[1].ops = ops;
1440
return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais,
1441
ARRAY_SIZE(dmic_cpu_dais));
1442
}
1443
1444
static const struct snd_soc_dai_driver i2s_dai_template = {
1445
.playback = {
1446
.channels_min = 1,
1447
.channels_max = AVS_CHANNELS_MAX,
1448
.rates = SNDRV_PCM_RATE_8000_192000 |
1449
SNDRV_PCM_RATE_12000 |
1450
SNDRV_PCM_RATE_24000 |
1451
SNDRV_PCM_RATE_128000,
1452
.formats = SNDRV_PCM_FMTBIT_S16_LE |
1453
SNDRV_PCM_FMTBIT_S32_LE,
1454
.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1455
SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1456
SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1457
},
1458
.capture = {
1459
.channels_min = 1,
1460
.channels_max = AVS_CHANNELS_MAX,
1461
.rates = SNDRV_PCM_RATE_8000_192000 |
1462
SNDRV_PCM_RATE_12000 |
1463
SNDRV_PCM_RATE_24000 |
1464
SNDRV_PCM_RATE_128000,
1465
.formats = SNDRV_PCM_FMTBIT_S16_LE |
1466
SNDRV_PCM_FMTBIT_S32_LE,
1467
.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1468
SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1469
SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1470
},
1471
};
1472
1473
int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask,
1474
unsigned long *tdms)
1475
{
1476
struct snd_soc_dai_driver *cpus, *dai;
1477
const struct snd_soc_dai_ops *ops;
1478
size_t ssp_count, cpu_count;
1479
int i, j;
1480
1481
ssp_count = adev->hw_cfg.i2s_caps.ctrl_count;
1482
if (avs_platattr_test(adev, ALTHDA))
1483
ops = &avs_dai_i2shda_be_ops;
1484
else
1485
ops = &avs_dai_nonhda_be_ops;
1486
1487
cpu_count = 0;
1488
for_each_set_bit(i, &port_mask, ssp_count)
1489
if (!tdms || test_bit(0, &tdms[i]))
1490
cpu_count++;
1491
if (tdms)
1492
for_each_set_bit(i, &port_mask, ssp_count)
1493
cpu_count += hweight_long(tdms[i]);
1494
1495
cpus = devm_kcalloc(adev->dev, cpu_count, sizeof(*cpus), GFP_KERNEL);
1496
if (!cpus)
1497
return -ENOMEM;
1498
1499
dai = cpus;
1500
for_each_set_bit(i, &port_mask, ssp_count) {
1501
if (!tdms || test_bit(0, &tdms[i])) {
1502
memcpy(dai, &i2s_dai_template, sizeof(*dai));
1503
1504
dai->name =
1505
devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i);
1506
dai->playback.stream_name =
1507
devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i);
1508
dai->capture.stream_name =
1509
devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i);
1510
1511
if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1512
return -ENOMEM;
1513
dai->ops = ops;
1514
dai++;
1515
}
1516
}
1517
1518
if (!tdms)
1519
goto plat_register;
1520
1521
for_each_set_bit(i, &port_mask, ssp_count) {
1522
for_each_set_bit(j, &tdms[i], AVS_CHANNELS_MAX) {
1523
memcpy(dai, &i2s_dai_template, sizeof(*dai));
1524
1525
dai->name =
1526
devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d:%d Pin", i, j);
1527
dai->playback.stream_name =
1528
devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Tx", i, j);
1529
dai->capture.stream_name =
1530
devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Rx", i, j);
1531
1532
if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1533
return -ENOMEM;
1534
dai->ops = ops;
1535
dai++;
1536
}
1537
}
1538
1539
plat_register:
1540
return avs_soc_component_register(adev->dev, name, &avs_component_driver, cpus, cpu_count);
1541
}
1542
1543
/* HD-Audio CPU DAI template */
1544
static const struct snd_soc_dai_driver hda_cpu_dai = {
1545
.ops = &avs_dai_hda_be_ops,
1546
.playback = {
1547
.channels_min = 1,
1548
.channels_max = AVS_CHANNELS_MAX,
1549
.rates = SNDRV_PCM_RATE_8000_192000,
1550
.formats = SNDRV_PCM_FMTBIT_S16_LE |
1551
SNDRV_PCM_FMTBIT_S32_LE,
1552
.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1553
SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1554
SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1555
},
1556
.capture = {
1557
.channels_min = 1,
1558
.channels_max = AVS_CHANNELS_MAX,
1559
.rates = SNDRV_PCM_RATE_8000_192000,
1560
.formats = SNDRV_PCM_FMTBIT_S16_LE |
1561
SNDRV_PCM_FMTBIT_S32_LE,
1562
.subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
1563
SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
1564
SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
1565
},
1566
};
1567
1568
static void avs_component_hda_unregister_dais(struct snd_soc_component *component)
1569
{
1570
struct snd_soc_acpi_mach *mach;
1571
struct snd_soc_dai *dai, *save;
1572
struct avs_mach_pdata *pdata;
1573
struct hda_codec *codec;
1574
char name[32];
1575
1576
mach = dev_get_platdata(component->card->dev);
1577
pdata = mach->pdata;
1578
codec = pdata->codec;
1579
snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev));
1580
1581
for_each_component_dais_safe(component, dai, save) {
1582
int stream;
1583
1584
if (!strstr(dai->driver->name, name))
1585
continue;
1586
1587
for_each_pcm_streams(stream)
1588
snd_soc_dapm_free_widget(snd_soc_dai_get_widget(dai, stream));
1589
1590
snd_soc_unregister_dai(dai);
1591
}
1592
}
1593
1594
static int avs_component_hda_probe(struct snd_soc_component *component)
1595
{
1596
struct snd_soc_dapm_context *dapm;
1597
struct snd_soc_dai_driver *dais;
1598
struct snd_soc_acpi_mach *mach;
1599
struct avs_mach_pdata *pdata;
1600
struct hda_codec *codec;
1601
struct hda_pcm *pcm;
1602
const char *cname;
1603
int pcm_count = 0, ret, i;
1604
1605
mach = dev_get_platdata(component->card->dev);
1606
if (!mach)
1607
return -EINVAL;
1608
1609
pdata = mach->pdata;
1610
codec = pdata->codec;
1611
if (list_empty(&codec->pcm_list_head))
1612
return -EINVAL;
1613
list_for_each_entry(pcm, &codec->pcm_list_head, list)
1614
pcm_count++;
1615
1616
dais = devm_kcalloc(component->dev, pcm_count, sizeof(*dais),
1617
GFP_KERNEL);
1618
if (!dais)
1619
return -ENOMEM;
1620
1621
cname = dev_name(&codec->core.dev);
1622
dapm = snd_soc_component_get_dapm(component);
1623
pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list);
1624
1625
for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) {
1626
struct snd_soc_dai *dai;
1627
1628
memcpy(&dais[i], &hda_cpu_dai, sizeof(*dais));
1629
dais[i].id = i;
1630
dais[i].name = devm_kasprintf(component->dev, GFP_KERNEL,
1631
"%s-cpu%d", cname, i);
1632
if (!dais[i].name) {
1633
ret = -ENOMEM;
1634
goto exit;
1635
}
1636
1637
if (pcm->stream[0].substreams) {
1638
dais[i].playback.stream_name =
1639
devm_kasprintf(component->dev, GFP_KERNEL,
1640
"%s-cpu%d Tx", cname, i);
1641
if (!dais[i].playback.stream_name) {
1642
ret = -ENOMEM;
1643
goto exit;
1644
}
1645
1646
if (!hda_codec_is_display(codec)) {
1647
dais[i].playback.formats = pcm->stream[0].formats;
1648
dais[i].playback.subformats = pcm->stream[0].subformats;
1649
dais[i].playback.rates = pcm->stream[0].rates;
1650
dais[i].playback.channels_min = pcm->stream[0].channels_min;
1651
dais[i].playback.channels_max = pcm->stream[0].channels_max;
1652
dais[i].playback.sig_bits = pcm->stream[0].maxbps;
1653
}
1654
}
1655
1656
if (pcm->stream[1].substreams) {
1657
dais[i].capture.stream_name =
1658
devm_kasprintf(component->dev, GFP_KERNEL,
1659
"%s-cpu%d Rx", cname, i);
1660
if (!dais[i].capture.stream_name) {
1661
ret = -ENOMEM;
1662
goto exit;
1663
}
1664
1665
if (!hda_codec_is_display(codec)) {
1666
dais[i].capture.formats = pcm->stream[1].formats;
1667
dais[i].capture.subformats = pcm->stream[1].subformats;
1668
dais[i].capture.rates = pcm->stream[1].rates;
1669
dais[i].capture.channels_min = pcm->stream[1].channels_min;
1670
dais[i].capture.channels_max = pcm->stream[1].channels_max;
1671
dais[i].capture.sig_bits = pcm->stream[1].maxbps;
1672
}
1673
}
1674
1675
dai = snd_soc_register_dai(component, &dais[i], false);
1676
if (!dai) {
1677
dev_err(component->dev, "register dai for %s failed\n",
1678
pcm->name);
1679
ret = -EINVAL;
1680
goto exit;
1681
}
1682
1683
ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
1684
if (ret < 0) {
1685
dev_err(component->dev, "create widgets failed: %d\n",
1686
ret);
1687
snd_soc_unregister_dai(dai);
1688
goto exit;
1689
}
1690
}
1691
1692
ret = avs_component_probe(component);
1693
exit:
1694
if (ret)
1695
avs_component_hda_unregister_dais(component);
1696
1697
return ret;
1698
}
1699
1700
static void avs_component_hda_remove(struct snd_soc_component *component)
1701
{
1702
avs_component_remove(component);
1703
avs_component_hda_unregister_dais(component);
1704
}
1705
1706
static int avs_component_hda_open(struct snd_soc_component *component,
1707
struct snd_pcm_substream *substream)
1708
{
1709
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1710
1711
if (!rtd->dai_link->no_pcm) {
1712
struct snd_pcm_hardware hwparams = avs_pcm_hardware;
1713
struct snd_soc_pcm_runtime *be;
1714
struct snd_soc_dpcm *dpcm;
1715
int dir = substream->stream;
1716
1717
/*
1718
* Support the DPCM reparenting while still fulfilling expectations of HDAudio
1719
* common code - a valid stream pointer at substream->runtime->private_data -
1720
* by having all FEs point to the same private data.
1721
*/
1722
for_each_dpcm_be(rtd, dir, dpcm) {
1723
struct snd_pcm_substream *be_substream;
1724
1725
be = dpcm->be;
1726
if (be->dpcm[dir].users == 1)
1727
break;
1728
1729
be_substream = snd_soc_dpcm_get_substream(be, dir);
1730
substream->runtime->private_data = be_substream->runtime->private_data;
1731
break;
1732
}
1733
1734
/* RESUME unsupported for de-coupled HD-Audio capture. */
1735
if (dir == SNDRV_PCM_STREAM_CAPTURE)
1736
hwparams.info &= ~SNDRV_PCM_INFO_RESUME;
1737
1738
return snd_soc_set_runtime_hwparams(substream, &hwparams);
1739
}
1740
1741
return 0;
1742
}
1743
1744
static struct snd_soc_component_driver avs_hda_component_driver = {
1745
.name = "avs-hda-pcm",
1746
.probe = avs_component_hda_probe,
1747
.remove = avs_component_hda_remove,
1748
.suspend = avs_component_suspend,
1749
.resume = avs_component_resume,
1750
.open = avs_component_hda_open,
1751
.pointer = avs_component_pointer,
1752
.mmap = avs_component_mmap,
1753
.pcm_construct = avs_component_construct,
1754
/*
1755
* hda platform component's probe() is dependent on
1756
* codec->pcm_list_head, it needs to be initialized after codec
1757
* component. remove_order is here for completeness sake
1758
*/
1759
.probe_order = SND_SOC_COMP_ORDER_LATE,
1760
.remove_order = SND_SOC_COMP_ORDER_EARLY,
1761
.module_get_upon_open = 1,
1762
.topology_name_prefix = "intel/avs",
1763
};
1764
1765
int avs_hda_platform_register(struct avs_dev *adev, const char *name)
1766
{
1767
return avs_soc_component_register(adev->dev, name,
1768
&avs_hda_component_driver, NULL, 0);
1769
}
1770
1771