1
2
3
4
5
6
7
8
9
10
11#include <linux/firmware.h>
12#include <sound/tlv.h>
13#include <sound/pcm_params.h>
14#include <uapi/sound/sof/tokens.h>
15#include "sof-priv.h"
16#include "ops.h"
17
18#define COMP_ID_UNASSIGNED 0xffffffff
19
20
21
22
23#define VOL_TWENTIETH_ROOT_OF_TEN 73533
24
25#define VOL_FORTIETH_ROOT_OF_TEN 69419
26
27
28
29
30#define VOLUME_FWL 16
31
32#define VOL_HALF_DB_STEP 50
33
34#define VOL_ZERO_DB BIT(VOLUME_FWL)
35
36
37#define TLV_ITEMS 3
38#define TLV_MIN 0
39#define TLV_STEP 1
40#define TLV_MUTE 2
41
42
43#define SOF_TPLG_ABI_SIZE 3
44
45struct sof_widget_data {
46 int ctrl_type;
47 int ipc_cmd;
48 struct sof_abi_hdr *pdata;
49 struct snd_sof_control *control;
50};
51
52
53static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir)
54{
55 struct sof_ipc_pcm_params_reply ipc_params_reply;
56 struct snd_sof_dev *sdev = swidget->sdev;
57 struct sof_ipc_pcm_params pcm;
58 struct snd_pcm_hw_params *params;
59 struct snd_sof_pcm *spcm;
60 int ret = 0;
61
62 memset(&pcm, 0, sizeof(pcm));
63
64
65 spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname);
66 if (!spcm) {
67 dev_err(sdev->dev, "error: cannot find PCM for %s\n",
68 swidget->widget->name);
69 return -EINVAL;
70 }
71
72 params = &spcm->params[dir];
73
74
75 pcm.hdr.size = sizeof(pcm);
76 pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
77 pcm.comp_id = swidget->comp_id;
78 pcm.params.hdr.size = sizeof(pcm.params);
79 pcm.params.direction = dir;
80 pcm.params.sample_valid_bytes = params_width(params) >> 3;
81 pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
82 pcm.params.rate = params_rate(params);
83 pcm.params.channels = params_channels(params);
84 pcm.params.host_period_bytes = params_period_bytes(params);
85
86
87 switch (params_format(params)) {
88 case SNDRV_PCM_FORMAT_S16:
89 pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
90 break;
91 case SNDRV_PCM_FORMAT_S24:
92 pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
93 break;
94 case SNDRV_PCM_FORMAT_S32:
95 pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
96 break;
97 default:
98 return -EINVAL;
99 }
100
101
102 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
103 &ipc_params_reply, sizeof(ipc_params_reply));
104 if (ret < 0)
105 dev_err(sdev->dev, "error: pcm params failed for %s\n",
106 swidget->widget->name);
107
108 return ret;
109}
110
111
112static int ipc_trigger(struct snd_sof_widget *swidget, int cmd)
113{
114 struct snd_sof_dev *sdev = swidget->sdev;
115 struct sof_ipc_stream stream;
116 struct sof_ipc_reply reply;
117 int ret = 0;
118
119
120 stream.hdr.size = sizeof(stream);
121 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd;
122 stream.comp_id = swidget->comp_id;
123
124
125 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
126 sizeof(stream), &reply, sizeof(reply));
127 if (ret < 0)
128 dev_err(sdev->dev, "error: failed to trigger %s\n",
129 swidget->widget->name);
130
131 return ret;
132}
133
134static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
135 struct snd_kcontrol *k, int event)
136{
137 struct snd_sof_widget *swidget = w->dobj.private;
138 int stream = SNDRV_PCM_STREAM_CAPTURE;
139 struct snd_sof_dev *sdev;
140 struct snd_sof_pcm *spcm;
141 int ret = 0;
142
143 if (!swidget)
144 return 0;
145
146 sdev = swidget->sdev;
147
148 dev_dbg(sdev->dev, "received event %d for widget %s\n",
149 event, w->name);
150
151
152 spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname);
153 if (!spcm) {
154 dev_err(sdev->dev, "error: cannot find PCM for %s\n",
155 swidget->widget->name);
156 return -EINVAL;
157 }
158
159
160 switch (event) {
161 case SND_SOC_DAPM_PRE_PMU:
162 if (spcm->stream[stream].suspend_ignored) {
163 dev_dbg(sdev->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
164 return 0;
165 }
166
167
168 ret = ipc_pcm_params(swidget, stream);
169 if (ret < 0) {
170 dev_err(sdev->dev,
171 "error: failed to set pcm params for widget %s\n",
172 swidget->widget->name);
173 break;
174 }
175
176
177 ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_START);
178 if (ret < 0)
179 dev_err(sdev->dev,
180 "error: failed to trigger widget %s\n",
181 swidget->widget->name);
182 break;
183 case SND_SOC_DAPM_POST_PMD:
184 if (spcm->stream[stream].suspend_ignored) {
185 dev_dbg(sdev->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n");
186 return 0;
187 }
188
189
190 ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP);
191 if (ret < 0)
192 dev_err(sdev->dev,
193 "error: failed to trigger widget %s\n",
194 swidget->widget->name);
195
196
197 ret = ipc_trigger(swidget, SOF_IPC_STREAM_PCM_FREE);
198 if (ret < 0)
199 dev_err(sdev->dev,
200 "error: failed to trigger widget %s\n",
201 swidget->widget->name);
202 break;
203 default:
204 break;
205 }
206
207 return ret;
208}
209
210
211static const struct snd_soc_tplg_widget_events sof_kwd_events[] = {
212 {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_keyword_dapm_event},
213};
214
215static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS])
216{
217
218 if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
219 return -EINVAL;
220
221
222 tlv[TLV_MIN] = (int)p[SNDRV_CTL_TLVO_DB_SCALE_MIN] / 100;
223
224
225 tlv[TLV_STEP] = (int)(p[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] &
226 TLV_DB_SCALE_MASK);
227
228
229 if ((p[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] &
230 TLV_DB_SCALE_MUTE) == 0)
231 tlv[TLV_MUTE] = 0;
232 else
233 tlv[TLV_MUTE] = 1;
234
235 return 0;
236}
237
238
239
240
241
242
243static inline u32 vol_shift_64(u64 i, u32 x)
244{
245
246 if (x > 32)
247 x = 32;
248
249 if (x == 0)
250 return (u32)i;
251
252 return (u32)(((i >> (x - 1)) + 1) >> 1);
253}
254
255
256
257
258
259
260
261
262
263
264static u32 vol_pow32(u32 a, int exp, u32 fwl)
265{
266 int i, iter;
267 u32 power = 1 << fwl;
268 u64 numerator;
269
270
271 if (exp == 0)
272 return power;
273
274
275 if (exp < 0)
276 iter = exp * -1;
277 else
278 iter = exp;
279
280
281 for (i = 0; i < iter; i++) {
282
283
284
285
286 power = vol_shift_64((u64)power * a, fwl);
287 }
288
289 if (exp > 0) {
290
291 return power;
292 }
293
294
295 numerator = (u64)1 << (fwl << 1);
296 do_div(numerator, power);
297
298 return (u32)numerator;
299}
300
301
302
303
304
305static u32 vol_compute_gain(u32 value, int *tlv)
306{
307 int dB_gain;
308 u32 linear_gain;
309 int f_step;
310
311
312 if (value == 0 && tlv[TLV_MUTE])
313 return 0;
314
315
316
317
318
319 dB_gain = tlv[TLV_MIN] + (value * tlv[TLV_STEP]) / 100;
320
321
322
323
324
325 linear_gain = vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN, dB_gain, VOLUME_FWL);
326
327
328 f_step = tlv[TLV_STEP] - (tlv[TLV_STEP] / 100);
329
330
331 if (f_step == VOL_HALF_DB_STEP && (value & 1))
332 linear_gain = vol_shift_64((u64)linear_gain *
333 VOL_FORTIETH_ROOT_OF_TEN,
334 VOLUME_FWL);
335
336 return linear_gain;
337}
338
339
340
341
342
343static int set_up_volume_table(struct snd_sof_control *scontrol,
344 int tlv[TLV_ITEMS], int size)
345{
346 int j;
347
348
349 scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
350 if (!scontrol->volume_table)
351 return -ENOMEM;
352
353
354 for (j = 0; j < size ; j++)
355 scontrol->volume_table[j] = vol_compute_gain(j, tlv);
356
357 return 0;
358}
359
360struct sof_dai_types {
361 const char *name;
362 enum sof_ipc_dai_type type;
363};
364
365static const struct sof_dai_types sof_dais[] = {
366 {"SSP", SOF_DAI_INTEL_SSP},
367 {"HDA", SOF_DAI_INTEL_HDA},
368 {"DMIC", SOF_DAI_INTEL_DMIC},
369 {"ALH", SOF_DAI_INTEL_ALH},
370 {"SAI", SOF_DAI_IMX_SAI},
371 {"ESAI", SOF_DAI_IMX_ESAI},
372};
373
374static enum sof_ipc_dai_type find_dai(const char *name)
375{
376 int i;
377
378 for (i = 0; i < ARRAY_SIZE(sof_dais); i++) {
379 if (strcmp(name, sof_dais[i].name) == 0)
380 return sof_dais[i].type;
381 }
382
383 return SOF_DAI_INTEL_NONE;
384}
385
386
387
388
389
390struct sof_frame_types {
391 const char *name;
392 enum sof_ipc_frame frame;
393};
394
395static const struct sof_frame_types sof_frames[] = {
396 {"s16le", SOF_IPC_FRAME_S16_LE},
397 {"s24le", SOF_IPC_FRAME_S24_4LE},
398 {"s32le", SOF_IPC_FRAME_S32_LE},
399 {"float", SOF_IPC_FRAME_FLOAT},
400};
401
402static enum sof_ipc_frame find_format(const char *name)
403{
404 int i;
405
406 for (i = 0; i < ARRAY_SIZE(sof_frames); i++) {
407 if (strcmp(name, sof_frames[i].name) == 0)
408 return sof_frames[i].frame;
409 }
410
411
412 return SOF_IPC_FRAME_S32_LE;
413}
414
415struct sof_process_types {
416 const char *name;
417 enum sof_ipc_process_type type;
418 enum sof_comp_type comp_type;
419};
420
421static const struct sof_process_types sof_process[] = {
422 {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR},
423 {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR},
424 {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT},
425 {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB},
426 {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR},
427 {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX},
428 {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX},
429};
430
431static enum sof_ipc_process_type find_process(const char *name)
432{
433 int i;
434
435 for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
436 if (strcmp(name, sof_process[i].name) == 0)
437 return sof_process[i].type;
438 }
439
440 return SOF_PROCESS_NONE;
441}
442
443static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type)
444{
445 int i;
446
447 for (i = 0; i < ARRAY_SIZE(sof_process); i++) {
448 if (sof_process[i].type == type)
449 return sof_process[i].comp_type;
450 }
451
452 return SOF_COMP_NONE;
453}
454
455
456
457
458
459
460struct sof_topology_token {
461 u32 token;
462 u32 type;
463 int (*get_token)(void *elem, void *object, u32 offset, u32 size);
464 u32 offset;
465 u32 size;
466};
467
468static int get_token_u32(void *elem, void *object, u32 offset, u32 size)
469{
470 struct snd_soc_tplg_vendor_value_elem *velem = elem;
471 u32 *val = (u32 *)((u8 *)object + offset);
472
473 *val = le32_to_cpu(velem->value);
474 return 0;
475}
476
477static int get_token_u16(void *elem, void *object, u32 offset, u32 size)
478{
479 struct snd_soc_tplg_vendor_value_elem *velem = elem;
480 u16 *val = (u16 *)((u8 *)object + offset);
481
482 *val = (u16)le32_to_cpu(velem->value);
483 return 0;
484}
485
486static int get_token_comp_format(void *elem, void *object, u32 offset, u32 size)
487{
488 struct snd_soc_tplg_vendor_string_elem *velem = elem;
489 u32 *val = (u32 *)((u8 *)object + offset);
490
491 *val = find_format(velem->string);
492 return 0;
493}
494
495static int get_token_dai_type(void *elem, void *object, u32 offset, u32 size)
496{
497 struct snd_soc_tplg_vendor_string_elem *velem = elem;
498 u32 *val = (u32 *)((u8 *)object + offset);
499
500 *val = find_dai(velem->string);
501 return 0;
502}
503
504static int get_token_process_type(void *elem, void *object, u32 offset,
505 u32 size)
506{
507 struct snd_soc_tplg_vendor_string_elem *velem = elem;
508 u32 *val = (u32 *)((u8 *)object + offset);
509
510 *val = find_process(velem->string);
511 return 0;
512}
513
514
515static const struct sof_topology_token buffer_tokens[] = {
516 {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
517 offsetof(struct sof_ipc_buffer, size), 0},
518 {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
519 offsetof(struct sof_ipc_buffer, caps), 0},
520};
521
522
523static const struct sof_topology_token dai_tokens[] = {
524 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type,
525 offsetof(struct sof_ipc_comp_dai, type), 0},
526 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
527 offsetof(struct sof_ipc_comp_dai, dai_index), 0},
528 {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
529 offsetof(struct sof_ipc_comp_dai, direction), 0},
530};
531
532
533static const struct sof_topology_token dai_link_tokens[] = {
534 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type,
535 offsetof(struct sof_ipc_dai_config, type), 0},
536 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
537 offsetof(struct sof_ipc_dai_config, dai_index), 0},
538};
539
540
541static const struct sof_topology_token sched_tokens[] = {
542 {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
543 offsetof(struct sof_ipc_pipe_new, period), 0},
544 {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
545 offsetof(struct sof_ipc_pipe_new, priority), 0},
546 {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
547 offsetof(struct sof_ipc_pipe_new, period_mips), 0},
548 {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
549 offsetof(struct sof_ipc_pipe_new, core), 0},
550 {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
551 offsetof(struct sof_ipc_pipe_new, frames_per_sched), 0},
552 {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
553 offsetof(struct sof_ipc_pipe_new, time_domain), 0},
554};
555
556
557static const struct sof_topology_token volume_tokens[] = {
558 {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
559 get_token_u32, offsetof(struct sof_ipc_comp_volume, ramp), 0},
560 {SOF_TKN_VOLUME_RAMP_STEP_MS,
561 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
562 offsetof(struct sof_ipc_comp_volume, initial_ramp), 0},
563};
564
565
566static const struct sof_topology_token src_tokens[] = {
567 {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
568 offsetof(struct sof_ipc_comp_src, source_rate), 0},
569 {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
570 offsetof(struct sof_ipc_comp_src, sink_rate), 0},
571};
572
573
574static const struct sof_topology_token tone_tokens[] = {
575};
576
577
578static const struct sof_topology_token process_tokens[] = {
579 {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING,
580 get_token_process_type,
581 offsetof(struct sof_ipc_comp_process, type), 0},
582};
583
584
585static const struct sof_topology_token pcm_tokens[] = {
586 {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
587 offsetof(struct sof_ipc_comp_host, dmac_config), 0},
588};
589
590
591static const struct sof_topology_token stream_tokens[] = {
592 {SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3,
593 SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
594 offsetof(struct snd_sof_pcm, stream[0].d0i3_compatible), 0},
595 {SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3,
596 SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
597 offsetof(struct snd_sof_pcm, stream[1].d0i3_compatible), 0},
598};
599
600
601static const struct sof_topology_token comp_tokens[] = {
602 {SOF_TKN_COMP_PERIOD_SINK_COUNT,
603 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
604 offsetof(struct sof_ipc_comp_config, periods_sink), 0},
605 {SOF_TKN_COMP_PERIOD_SOURCE_COUNT,
606 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
607 offsetof(struct sof_ipc_comp_config, periods_source), 0},
608 {SOF_TKN_COMP_FORMAT,
609 SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format,
610 offsetof(struct sof_ipc_comp_config, frame_fmt), 0},
611};
612
613
614static const struct sof_topology_token ssp_tokens[] = {
615 {SOF_TKN_INTEL_SSP_CLKS_CONTROL,
616 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
617 offsetof(struct sof_ipc_dai_ssp_params, clks_control), 0},
618 {SOF_TKN_INTEL_SSP_MCLK_ID,
619 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
620 offsetof(struct sof_ipc_dai_ssp_params, mclk_id), 0},
621 {SOF_TKN_INTEL_SSP_SAMPLE_BITS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
622 get_token_u32,
623 offsetof(struct sof_ipc_dai_ssp_params, sample_valid_bits), 0},
624 {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT,
625 get_token_u16,
626 offsetof(struct sof_ipc_dai_ssp_params, frame_pulse_width), 0},
627 {SOF_TKN_INTEL_SSP_QUIRKS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
628 get_token_u32,
629 offsetof(struct sof_ipc_dai_ssp_params, quirks), 0},
630 {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT, SND_SOC_TPLG_TUPLE_TYPE_BOOL,
631 get_token_u16,
632 offsetof(struct sof_ipc_dai_ssp_params,
633 tdm_per_slot_padding_flag), 0},
634 {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD,
635 get_token_u32,
636 offsetof(struct sof_ipc_dai_ssp_params, bclk_delay), 0},
637
638};
639
640
641static const struct sof_topology_token dmic_tokens[] = {
642 {SOF_TKN_INTEL_DMIC_DRIVER_VERSION,
643 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
644 offsetof(struct sof_ipc_dai_dmic_params, driver_ipc_version),
645 0},
646 {SOF_TKN_INTEL_DMIC_CLK_MIN,
647 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
648 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_min), 0},
649 {SOF_TKN_INTEL_DMIC_CLK_MAX,
650 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
651 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_max), 0},
652 {SOF_TKN_INTEL_DMIC_SAMPLE_RATE,
653 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
654 offsetof(struct sof_ipc_dai_dmic_params, fifo_fs), 0},
655 {SOF_TKN_INTEL_DMIC_DUTY_MIN,
656 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
657 offsetof(struct sof_ipc_dai_dmic_params, duty_min), 0},
658 {SOF_TKN_INTEL_DMIC_DUTY_MAX,
659 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
660 offsetof(struct sof_ipc_dai_dmic_params, duty_max), 0},
661 {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE,
662 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
663 offsetof(struct sof_ipc_dai_dmic_params,
664 num_pdm_active), 0},
665 {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH,
666 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
667 offsetof(struct sof_ipc_dai_dmic_params, fifo_bits), 0},
668 {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS,
669 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
670 offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time), 0},
671
672};
673
674
675static const struct sof_topology_token esai_tokens[] = {
676 {SOF_TKN_IMX_ESAI_MCLK_ID,
677 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
678 offsetof(struct sof_ipc_dai_esai_params, mclk_id), 0},
679};
680
681
682
683
684
685
686
687static const struct sof_topology_token dmic_pdm_tokens[] = {
688 {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID,
689 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
690 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, id),
691 0},
692 {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable,
693 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
694 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_a),
695 0},
696 {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable,
697 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
698 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_b),
699 0},
700 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A,
701 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
702 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_a),
703 0},
704 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B,
705 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
706 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_b),
707 0},
708 {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE,
709 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
710 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, clk_edge),
711 0},
712 {SOF_TKN_INTEL_DMIC_PDM_SKEW,
713 SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16,
714 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, skew),
715 0},
716};
717
718
719static const struct sof_topology_token hda_tokens[] = {
720};
721
722
723static const struct sof_topology_token led_tokens[] = {
724 {SOF_TKN_MUTE_LED_USE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
725 offsetof(struct snd_sof_led_control, use_led), 0},
726 {SOF_TKN_MUTE_LED_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD,
727 get_token_u32, offsetof(struct snd_sof_led_control, direction), 0},
728};
729
730static void sof_parse_uuid_tokens(struct snd_soc_component *scomp,
731 void *object,
732 const struct sof_topology_token *tokens,
733 int count,
734 struct snd_soc_tplg_vendor_array *array)
735{
736 struct snd_soc_tplg_vendor_uuid_elem *elem;
737 int i, j;
738
739
740 for (i = 0; i < le32_to_cpu(array->num_elems); i++) {
741 elem = &array->uuid[i];
742
743
744 for (j = 0; j < count; j++) {
745
746 if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID)
747 continue;
748
749
750 if (tokens[j].token != le32_to_cpu(elem->token))
751 continue;
752
753
754 tokens[j].get_token(elem, object, tokens[j].offset,
755 tokens[j].size);
756 }
757 }
758}
759
760static void sof_parse_string_tokens(struct snd_soc_component *scomp,
761 void *object,
762 const struct sof_topology_token *tokens,
763 int count,
764 struct snd_soc_tplg_vendor_array *array)
765{
766 struct snd_soc_tplg_vendor_string_elem *elem;
767 int i, j;
768
769
770 for (i = 0; i < le32_to_cpu(array->num_elems); i++) {
771 elem = &array->string[i];
772
773
774 for (j = 0; j < count; j++) {
775
776 if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING)
777 continue;
778
779
780 if (tokens[j].token != le32_to_cpu(elem->token))
781 continue;
782
783
784 tokens[j].get_token(elem, object, tokens[j].offset,
785 tokens[j].size);
786 }
787 }
788}
789
790static void sof_parse_word_tokens(struct snd_soc_component *scomp,
791 void *object,
792 const struct sof_topology_token *tokens,
793 int count,
794 struct snd_soc_tplg_vendor_array *array)
795{
796 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
797 struct snd_soc_tplg_vendor_value_elem *elem;
798 size_t size = sizeof(struct sof_ipc_dai_dmic_pdm_ctrl);
799 int i, j;
800 u32 offset;
801 u32 *index = NULL;
802
803
804 for (i = 0; i < le32_to_cpu(array->num_elems); i++) {
805 elem = &array->value[i];
806
807
808 for (j = 0; j < count; j++) {
809
810 if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
811 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
812 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
813 tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
814 continue;
815
816
817 if (tokens[j].token != le32_to_cpu(elem->token))
818 continue;
819
820
821 if (sdev->private)
822 index = sdev->private;
823
824
825 switch (tokens[j].token) {
826 case SOF_TKN_INTEL_DMIC_PDM_CTRL_ID:
827
828
829 if (index)
830 (*index)++;
831
832 case SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable:
833 case SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable:
834 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_A:
835 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_B:
836 case SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE:
837 case SOF_TKN_INTEL_DMIC_PDM_SKEW:
838
839
840 if (!index || *index == 0) {
841 dev_err(sdev->dev,
842 "error: invalid array offset\n");
843 continue;
844 } else {
845
846 offset = size * (*index - 1);
847 }
848 break;
849 default:
850 offset = 0;
851 break;
852 }
853
854
855 tokens[j].get_token(elem, object,
856 offset + tokens[j].offset,
857 tokens[j].size);
858 }
859 }
860}
861
862static int sof_parse_tokens(struct snd_soc_component *scomp,
863 void *object,
864 const struct sof_topology_token *tokens,
865 int count,
866 struct snd_soc_tplg_vendor_array *array,
867 int priv_size)
868{
869 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
870 int asize;
871
872 while (priv_size > 0) {
873 asize = le32_to_cpu(array->size);
874
875
876 if (asize < 0) {
877 dev_err(sdev->dev, "error: invalid array size 0x%x\n",
878 asize);
879 return -EINVAL;
880 }
881
882
883 priv_size -= asize;
884 if (priv_size < 0) {
885 dev_err(sdev->dev, "error: invalid array size 0x%x\n",
886 asize);
887 return -EINVAL;
888 }
889
890
891 switch (le32_to_cpu(array->type)) {
892 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
893 sof_parse_uuid_tokens(scomp, object, tokens, count,
894 array);
895 break;
896 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
897 sof_parse_string_tokens(scomp, object, tokens, count,
898 array);
899 break;
900 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
901 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
902 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
903 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
904 sof_parse_word_tokens(scomp, object, tokens, count,
905 array);
906 break;
907 default:
908 dev_err(sdev->dev, "error: unknown token type %d\n",
909 array->type);
910 return -EINVAL;
911 }
912
913
914 array = (struct snd_soc_tplg_vendor_array *)((u8 *)array
915 + asize);
916 }
917 return 0;
918}
919
920static void sof_dbg_comp_config(struct snd_soc_component *scomp,
921 struct sof_ipc_comp_config *config)
922{
923 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
924
925 dev_dbg(sdev->dev, " config: periods snk %d src %d fmt %d\n",
926 config->periods_sink, config->periods_source,
927 config->frame_fmt);
928}
929
930
931
932
933
934static int sof_control_load_volume(struct snd_soc_component *scomp,
935 struct snd_sof_control *scontrol,
936 struct snd_kcontrol_new *kc,
937 struct snd_soc_tplg_ctl_hdr *hdr)
938{
939 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
940 struct snd_soc_tplg_mixer_control *mc =
941 container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
942 struct sof_ipc_ctrl_data *cdata;
943 int tlv[TLV_ITEMS];
944 unsigned int i;
945 int ret = 0;
946
947
948 if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN) {
949 ret = -EINVAL;
950 goto out;
951 }
952
953
954 scontrol->size = struct_size(scontrol->control_data, chanv,
955 le32_to_cpu(mc->num_channels));
956 scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
957 if (!scontrol->control_data) {
958 ret = -ENOMEM;
959 goto out;
960 }
961
962 scontrol->comp_id = sdev->next_comp_id;
963 scontrol->min_volume_step = le32_to_cpu(mc->min);
964 scontrol->max_volume_step = le32_to_cpu(mc->max);
965 scontrol->num_channels = le32_to_cpu(mc->num_channels);
966
967
968 if (le32_to_cpu(mc->max) == 1) {
969 scontrol->cmd = SOF_CTRL_CMD_SWITCH;
970 goto skip;
971 }
972
973 scontrol->cmd = SOF_CTRL_CMD_VOLUME;
974
975
976 if (get_tlv_data(kc->tlv.p, tlv) < 0) {
977 dev_err(sdev->dev, "error: invalid TLV data\n");
978 ret = -EINVAL;
979 goto out_free;
980 }
981
982
983 ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1);
984 if (ret < 0) {
985 dev_err(sdev->dev, "error: setting up volume table\n");
986 goto out_free;
987 }
988
989
990 cdata = scontrol->control_data;
991 for (i = 0; i < scontrol->num_channels; i++) {
992 cdata->chanv[i].channel = i;
993 cdata->chanv[i].value = VOL_ZERO_DB;
994 }
995
996skip:
997
998 ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens,
999 ARRAY_SIZE(led_tokens), mc->priv.array,
1000 le32_to_cpu(mc->priv.size));
1001 if (ret != 0) {
1002 dev_err(sdev->dev, "error: parse led tokens failed %d\n",
1003 le32_to_cpu(mc->priv.size));
1004 goto out_free_table;
1005 }
1006
1007 dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
1008 scontrol->comp_id, scontrol->num_channels);
1009
1010 return ret;
1011
1012out_free_table:
1013 if (le32_to_cpu(mc->max) > 1)
1014 kfree(scontrol->volume_table);
1015out_free:
1016 kfree(scontrol->control_data);
1017out:
1018 return ret;
1019}
1020
1021static int sof_control_load_enum(struct snd_soc_component *scomp,
1022 struct snd_sof_control *scontrol,
1023 struct snd_kcontrol_new *kc,
1024 struct snd_soc_tplg_ctl_hdr *hdr)
1025{
1026 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1027 struct snd_soc_tplg_enum_control *ec =
1028 container_of(hdr, struct snd_soc_tplg_enum_control, hdr);
1029
1030
1031 if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN)
1032 return -EINVAL;
1033
1034
1035 scontrol->size = struct_size(scontrol->control_data, chanv,
1036 le32_to_cpu(ec->num_channels));
1037 scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
1038 if (!scontrol->control_data)
1039 return -ENOMEM;
1040
1041 scontrol->comp_id = sdev->next_comp_id;
1042 scontrol->num_channels = le32_to_cpu(ec->num_channels);
1043
1044 scontrol->cmd = SOF_CTRL_CMD_ENUM;
1045
1046 dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n",
1047 scontrol->comp_id, scontrol->num_channels, scontrol->comp_id);
1048
1049 return 0;
1050}
1051
1052static int sof_control_load_bytes(struct snd_soc_component *scomp,
1053 struct snd_sof_control *scontrol,
1054 struct snd_kcontrol_new *kc,
1055 struct snd_soc_tplg_ctl_hdr *hdr)
1056{
1057 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1058 struct sof_ipc_ctrl_data *cdata;
1059 struct snd_soc_tplg_bytes_control *control =
1060 container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
1061 struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value;
1062 int max_size = sbe->max;
1063 int ret = 0;
1064
1065
1066 scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
1067 le32_to_cpu(control->priv.size);
1068
1069 if (scontrol->size > max_size) {
1070 dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n",
1071 scontrol->size, max_size);
1072 ret = -EINVAL;
1073 goto out;
1074 }
1075
1076 scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
1077 cdata = scontrol->control_data;
1078 if (!scontrol->control_data) {
1079 ret = -ENOMEM;
1080 goto out;
1081 }
1082
1083 scontrol->comp_id = sdev->next_comp_id;
1084 scontrol->cmd = SOF_CTRL_CMD_BINARY;
1085
1086 dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
1087 scontrol->comp_id, scontrol->num_channels);
1088
1089 if (le32_to_cpu(control->priv.size) > 0) {
1090 memcpy(cdata->data, control->priv.data,
1091 le32_to_cpu(control->priv.size));
1092
1093 if (cdata->data->magic != SOF_ABI_MAGIC) {
1094 dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n",
1095 cdata->data->magic);
1096 ret = -EINVAL;
1097 goto out_free;
1098 }
1099 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION,
1100 cdata->data->abi)) {
1101 dev_err(sdev->dev,
1102 "error: Incompatible ABI version 0x%08x.\n",
1103 cdata->data->abi);
1104 ret = -EINVAL;
1105 goto out_free;
1106 }
1107 if (cdata->data->size + sizeof(const struct sof_abi_hdr) !=
1108 le32_to_cpu(control->priv.size)) {
1109 dev_err(sdev->dev,
1110 "error: Conflict in bytes vs. priv size.\n");
1111 ret = -EINVAL;
1112 goto out_free;
1113 }
1114 }
1115
1116 return ret;
1117
1118out_free:
1119 kfree(scontrol->control_data);
1120out:
1121 return ret;
1122}
1123
1124
1125static int sof_control_load(struct snd_soc_component *scomp, int index,
1126 struct snd_kcontrol_new *kc,
1127 struct snd_soc_tplg_ctl_hdr *hdr)
1128{
1129 struct soc_mixer_control *sm;
1130 struct soc_bytes_ext *sbe;
1131 struct soc_enum *se;
1132 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1133 struct snd_soc_dobj *dobj;
1134 struct snd_sof_control *scontrol;
1135 int ret = -EINVAL;
1136
1137 dev_dbg(sdev->dev, "tplg: load control type %d name : %s\n",
1138 hdr->type, hdr->name);
1139
1140 scontrol = kzalloc(sizeof(*scontrol), GFP_KERNEL);
1141 if (!scontrol)
1142 return -ENOMEM;
1143
1144 scontrol->sdev = sdev;
1145
1146 switch (le32_to_cpu(hdr->ops.info)) {
1147 case SND_SOC_TPLG_CTL_VOLSW:
1148 case SND_SOC_TPLG_CTL_VOLSW_SX:
1149 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
1150 sm = (struct soc_mixer_control *)kc->private_value;
1151 dobj = &sm->dobj;
1152 ret = sof_control_load_volume(scomp, scontrol, kc, hdr);
1153 break;
1154 case SND_SOC_TPLG_CTL_BYTES:
1155 sbe = (struct soc_bytes_ext *)kc->private_value;
1156 dobj = &sbe->dobj;
1157 ret = sof_control_load_bytes(scomp, scontrol, kc, hdr);
1158 break;
1159 case SND_SOC_TPLG_CTL_ENUM:
1160 case SND_SOC_TPLG_CTL_ENUM_VALUE:
1161 se = (struct soc_enum *)kc->private_value;
1162 dobj = &se->dobj;
1163 ret = sof_control_load_enum(scomp, scontrol, kc, hdr);
1164 break;
1165 case SND_SOC_TPLG_CTL_RANGE:
1166 case SND_SOC_TPLG_CTL_STROBE:
1167 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
1168 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
1169 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
1170 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1171 case SND_SOC_TPLG_DAPM_CTL_PIN:
1172 default:
1173 dev_warn(sdev->dev, "control type not supported %d:%d:%d\n",
1174 hdr->ops.get, hdr->ops.put, hdr->ops.info);
1175 kfree(scontrol);
1176 return 0;
1177 }
1178
1179 if (ret < 0) {
1180 kfree(scontrol);
1181 return ret;
1182 }
1183
1184 dobj->private = scontrol;
1185 list_add(&scontrol->list, &sdev->kcontrol_list);
1186 return ret;
1187}
1188
1189static int sof_control_unload(struct snd_soc_component *scomp,
1190 struct snd_soc_dobj *dobj)
1191{
1192 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1193 struct sof_ipc_free fcomp;
1194 struct snd_sof_control *scontrol = dobj->private;
1195
1196 dev_dbg(sdev->dev, "tplg: unload control name : %s\n", scomp->name);
1197
1198 fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE;
1199 fcomp.hdr.size = sizeof(fcomp);
1200 fcomp.id = scontrol->comp_id;
1201
1202 kfree(scontrol->control_data);
1203 list_del(&scontrol->list);
1204 kfree(scontrol);
1205
1206 return sof_ipc_tx_message(sdev->ipc,
1207 fcomp.hdr.cmd, &fcomp, sizeof(fcomp),
1208 NULL, 0);
1209}
1210
1211
1212
1213
1214
1215static int sof_connect_dai_widget(struct snd_soc_component *scomp,
1216 struct snd_soc_dapm_widget *w,
1217 struct snd_soc_tplg_dapm_widget *tw,
1218 struct snd_sof_dai *dai)
1219{
1220 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1221 struct snd_soc_card *card = scomp->card;
1222 struct snd_soc_pcm_runtime *rtd;
1223
1224 list_for_each_entry(rtd, &card->rtd_list, list) {
1225 dev_vdbg(sdev->dev, "tplg: check widget: %s stream: %s dai stream: %s\n",
1226 w->name, w->sname, rtd->dai_link->stream_name);
1227
1228 if (!w->sname || !rtd->dai_link->stream_name)
1229 continue;
1230
1231
1232 if (strcmp(w->sname, rtd->dai_link->stream_name))
1233 continue;
1234
1235 switch (w->id) {
1236 case snd_soc_dapm_dai_out:
1237 rtd->cpu_dai->capture_widget = w;
1238 dai->name = rtd->dai_link->name;
1239 dev_dbg(sdev->dev, "tplg: connected widget %s -> DAI link %s\n",
1240 w->name, rtd->dai_link->name);
1241 break;
1242 case snd_soc_dapm_dai_in:
1243 rtd->cpu_dai->playback_widget = w;
1244 dai->name = rtd->dai_link->name;
1245 dev_dbg(sdev->dev, "tplg: connected widget %s -> DAI link %s\n",
1246 w->name, rtd->dai_link->name);
1247 break;
1248 default:
1249 break;
1250 }
1251 }
1252
1253
1254 if (!dai->name) {
1255 dev_err(sdev->dev, "error: can't connect DAI %s stream %s\n",
1256 w->name, w->sname);
1257 return -EINVAL;
1258 }
1259
1260 return 0;
1261}
1262
1263static int sof_widget_load_dai(struct snd_soc_component *scomp, int index,
1264 struct snd_sof_widget *swidget,
1265 struct snd_soc_tplg_dapm_widget *tw,
1266 struct sof_ipc_comp_reply *r,
1267 struct snd_sof_dai *dai)
1268{
1269 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1270 struct snd_soc_tplg_private *private = &tw->priv;
1271 struct sof_ipc_comp_dai comp_dai;
1272 int ret;
1273
1274
1275 memset(&comp_dai, 0, sizeof(comp_dai));
1276 comp_dai.comp.hdr.size = sizeof(comp_dai);
1277 comp_dai.comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1278 comp_dai.comp.id = swidget->comp_id;
1279 comp_dai.comp.type = SOF_COMP_DAI;
1280 comp_dai.comp.pipeline_id = index;
1281 comp_dai.config.hdr.size = sizeof(comp_dai.config);
1282
1283 ret = sof_parse_tokens(scomp, &comp_dai, dai_tokens,
1284 ARRAY_SIZE(dai_tokens), private->array,
1285 le32_to_cpu(private->size));
1286 if (ret != 0) {
1287 dev_err(sdev->dev, "error: parse dai tokens failed %d\n",
1288 le32_to_cpu(private->size));
1289 return ret;
1290 }
1291
1292 ret = sof_parse_tokens(scomp, &comp_dai.config, comp_tokens,
1293 ARRAY_SIZE(comp_tokens), private->array,
1294 le32_to_cpu(private->size));
1295 if (ret != 0) {
1296 dev_err(sdev->dev, "error: parse dai.cfg tokens failed %d\n",
1297 private->size);
1298 return ret;
1299 }
1300
1301 dev_dbg(sdev->dev, "dai %s: type %d index %d\n",
1302 swidget->widget->name, comp_dai.type, comp_dai.dai_index);
1303 sof_dbg_comp_config(scomp, &comp_dai.config);
1304
1305 ret = sof_ipc_tx_message(sdev->ipc, comp_dai.comp.hdr.cmd,
1306 &comp_dai, sizeof(comp_dai), r, sizeof(*r));
1307
1308 if (ret == 0 && dai) {
1309 dai->sdev = sdev;
1310 memcpy(&dai->comp_dai, &comp_dai, sizeof(comp_dai));
1311 }
1312
1313 return ret;
1314}
1315
1316
1317
1318
1319
1320static int sof_widget_load_buffer(struct snd_soc_component *scomp, int index,
1321 struct snd_sof_widget *swidget,
1322 struct snd_soc_tplg_dapm_widget *tw,
1323 struct sof_ipc_comp_reply *r)
1324{
1325 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1326 struct snd_soc_tplg_private *private = &tw->priv;
1327 struct sof_ipc_buffer *buffer;
1328 int ret;
1329
1330 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
1331 if (!buffer)
1332 return -ENOMEM;
1333
1334
1335 buffer->comp.hdr.size = sizeof(*buffer);
1336 buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW;
1337 buffer->comp.id = swidget->comp_id;
1338 buffer->comp.type = SOF_COMP_BUFFER;
1339 buffer->comp.pipeline_id = index;
1340
1341 ret = sof_parse_tokens(scomp, buffer, buffer_tokens,
1342 ARRAY_SIZE(buffer_tokens), private->array,
1343 le32_to_cpu(private->size));
1344 if (ret != 0) {
1345 dev_err(sdev->dev, "error: parse buffer tokens failed %d\n",
1346 private->size);
1347 kfree(buffer);
1348 return ret;
1349 }
1350
1351 dev_dbg(sdev->dev, "buffer %s: size %d caps 0x%x\n",
1352 swidget->widget->name, buffer->size, buffer->caps);
1353
1354 swidget->private = buffer;
1355
1356 ret = sof_ipc_tx_message(sdev->ipc, buffer->comp.hdr.cmd, buffer,
1357 sizeof(*buffer), r, sizeof(*r));
1358 if (ret < 0) {
1359 dev_err(sdev->dev, "error: buffer %s load failed\n",
1360 swidget->widget->name);
1361 kfree(buffer);
1362 }
1363
1364 return ret;
1365}
1366
1367
1368static int spcm_bind(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
1369 int dir)
1370{
1371 struct snd_sof_widget *host_widget;
1372
1373 host_widget = snd_sof_find_swidget_sname(sdev,
1374 spcm->pcm.caps[dir].name,
1375 dir);
1376 if (!host_widget) {
1377 dev_err(sdev->dev, "can't find host comp to bind pcm\n");
1378 return -EINVAL;
1379 }
1380
1381 spcm->stream[dir].comp_id = host_widget->comp_id;
1382
1383 return 0;
1384}
1385
1386
1387
1388
1389
1390static int sof_widget_load_pcm(struct snd_soc_component *scomp, int index,
1391 struct snd_sof_widget *swidget,
1392 enum sof_ipc_stream_direction dir,
1393 struct snd_soc_tplg_dapm_widget *tw,
1394 struct sof_ipc_comp_reply *r)
1395{
1396 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1397 struct snd_soc_tplg_private *private = &tw->priv;
1398 struct sof_ipc_comp_host *host;
1399 int ret;
1400
1401 host = kzalloc(sizeof(*host), GFP_KERNEL);
1402 if (!host)
1403 return -ENOMEM;
1404
1405
1406 host->comp.hdr.size = sizeof(*host);
1407 host->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1408 host->comp.id = swidget->comp_id;
1409 host->comp.type = SOF_COMP_HOST;
1410 host->comp.pipeline_id = index;
1411 host->direction = dir;
1412 host->config.hdr.size = sizeof(host->config);
1413
1414 ret = sof_parse_tokens(scomp, host, pcm_tokens,
1415 ARRAY_SIZE(pcm_tokens), private->array,
1416 le32_to_cpu(private->size));
1417 if (ret != 0) {
1418 dev_err(sdev->dev, "error: parse host tokens failed %d\n",
1419 private->size);
1420 goto err;
1421 }
1422
1423 ret = sof_parse_tokens(scomp, &host->config, comp_tokens,
1424 ARRAY_SIZE(comp_tokens), private->array,
1425 le32_to_cpu(private->size));
1426 if (ret != 0) {
1427 dev_err(sdev->dev, "error: parse host.cfg tokens failed %d\n",
1428 le32_to_cpu(private->size));
1429 goto err;
1430 }
1431
1432 dev_dbg(sdev->dev, "loaded host %s\n", swidget->widget->name);
1433 sof_dbg_comp_config(scomp, &host->config);
1434
1435 swidget->private = host;
1436
1437 ret = sof_ipc_tx_message(sdev->ipc, host->comp.hdr.cmd, host,
1438 sizeof(*host), r, sizeof(*r));
1439 if (ret >= 0)
1440 return ret;
1441err:
1442 kfree(host);
1443 return ret;
1444}
1445
1446
1447
1448
1449int sof_load_pipeline_ipc(struct snd_sof_dev *sdev,
1450 struct sof_ipc_pipe_new *pipeline,
1451 struct sof_ipc_comp_reply *r)
1452{
1453 struct sof_ipc_pm_core_config pm_core_config;
1454 int ret;
1455
1456 ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline,
1457 sizeof(*pipeline), r, sizeof(*r));
1458 if (ret < 0) {
1459 dev_err(sdev->dev, "error: load pipeline ipc failure\n");
1460 return ret;
1461 }
1462
1463
1464 ret = snd_sof_dsp_core_power_up(sdev, 1 << pipeline->core);
1465 if (ret < 0) {
1466 dev_err(sdev->dev, "error: powering up pipeline schedule core %d\n",
1467 pipeline->core);
1468 return ret;
1469 }
1470
1471
1472 sdev->enabled_cores_mask |= 1 << pipeline->core;
1473
1474
1475
1476
1477
1478 memset(&pm_core_config, 0, sizeof(pm_core_config));
1479 pm_core_config.enable_mask = sdev->enabled_cores_mask;
1480
1481
1482 pm_core_config.hdr.size = sizeof(pm_core_config);
1483 pm_core_config.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CORE_ENABLE;
1484
1485
1486 ret = sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd,
1487 &pm_core_config, sizeof(pm_core_config),
1488 &pm_core_config, sizeof(pm_core_config));
1489 if (ret < 0)
1490 dev_err(sdev->dev, "error: core enable ipc failure\n");
1491
1492 return ret;
1493}
1494
1495static int sof_widget_load_pipeline(struct snd_soc_component *scomp,
1496 int index, struct snd_sof_widget *swidget,
1497 struct snd_soc_tplg_dapm_widget *tw,
1498 struct sof_ipc_comp_reply *r)
1499{
1500 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1501 struct snd_soc_tplg_private *private = &tw->priv;
1502 struct sof_ipc_pipe_new *pipeline;
1503 struct snd_sof_widget *comp_swidget;
1504 int ret;
1505
1506 pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
1507 if (!pipeline)
1508 return -ENOMEM;
1509
1510
1511 pipeline->hdr.size = sizeof(*pipeline);
1512 pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW;
1513 pipeline->pipeline_id = index;
1514 pipeline->comp_id = swidget->comp_id;
1515
1516
1517 comp_swidget = snd_sof_find_swidget(sdev, tw->sname);
1518 if (!comp_swidget) {
1519 dev_err(sdev->dev, "error: widget %s refers to non existent widget %s\n",
1520 tw->name, tw->sname);
1521 ret = -EINVAL;
1522 goto err;
1523 }
1524
1525 pipeline->sched_id = comp_swidget->comp_id;
1526
1527 dev_dbg(sdev->dev, "tplg: pipeline id %d comp %d scheduling comp id %d\n",
1528 pipeline->pipeline_id, pipeline->comp_id, pipeline->sched_id);
1529
1530 ret = sof_parse_tokens(scomp, pipeline, sched_tokens,
1531 ARRAY_SIZE(sched_tokens), private->array,
1532 le32_to_cpu(private->size));
1533 if (ret != 0) {
1534 dev_err(sdev->dev, "error: parse pipeline tokens failed %d\n",
1535 private->size);
1536 goto err;
1537 }
1538
1539 dev_dbg(sdev->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d\n",
1540 swidget->widget->name, pipeline->period, pipeline->priority,
1541 pipeline->period_mips, pipeline->core, pipeline->frames_per_sched);
1542
1543 swidget->private = pipeline;
1544
1545
1546 ret = sof_load_pipeline_ipc(sdev, pipeline, r);
1547 if (ret >= 0)
1548 return ret;
1549err:
1550 kfree(pipeline);
1551 return ret;
1552}
1553
1554
1555
1556
1557
1558static int sof_widget_load_mixer(struct snd_soc_component *scomp, int index,
1559 struct snd_sof_widget *swidget,
1560 struct snd_soc_tplg_dapm_widget *tw,
1561 struct sof_ipc_comp_reply *r)
1562{
1563 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1564 struct snd_soc_tplg_private *private = &tw->priv;
1565 struct sof_ipc_comp_mixer *mixer;
1566 int ret;
1567
1568 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
1569 if (!mixer)
1570 return -ENOMEM;
1571
1572
1573 mixer->comp.hdr.size = sizeof(*mixer);
1574 mixer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1575 mixer->comp.id = swidget->comp_id;
1576 mixer->comp.type = SOF_COMP_MIXER;
1577 mixer->comp.pipeline_id = index;
1578 mixer->config.hdr.size = sizeof(mixer->config);
1579
1580 ret = sof_parse_tokens(scomp, &mixer->config, comp_tokens,
1581 ARRAY_SIZE(comp_tokens), private->array,
1582 le32_to_cpu(private->size));
1583 if (ret != 0) {
1584 dev_err(sdev->dev, "error: parse mixer.cfg tokens failed %d\n",
1585 private->size);
1586 kfree(mixer);
1587 return ret;
1588 }
1589
1590 sof_dbg_comp_config(scomp, &mixer->config);
1591
1592 swidget->private = mixer;
1593
1594 ret = sof_ipc_tx_message(sdev->ipc, mixer->comp.hdr.cmd, mixer,
1595 sizeof(*mixer), r, sizeof(*r));
1596 if (ret < 0)
1597 kfree(mixer);
1598
1599 return ret;
1600}
1601
1602
1603
1604
1605static int sof_widget_load_mux(struct snd_soc_component *scomp, int index,
1606 struct snd_sof_widget *swidget,
1607 struct snd_soc_tplg_dapm_widget *tw,
1608 struct sof_ipc_comp_reply *r)
1609{
1610 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1611 struct snd_soc_tplg_private *private = &tw->priv;
1612 struct sof_ipc_comp_mux *mux;
1613 int ret;
1614
1615 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
1616 if (!mux)
1617 return -ENOMEM;
1618
1619
1620 mux->comp.hdr.size = sizeof(*mux);
1621 mux->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1622 mux->comp.id = swidget->comp_id;
1623 mux->comp.type = SOF_COMP_MUX;
1624 mux->comp.pipeline_id = index;
1625 mux->config.hdr.size = sizeof(mux->config);
1626
1627 ret = sof_parse_tokens(scomp, &mux->config, comp_tokens,
1628 ARRAY_SIZE(comp_tokens), private->array,
1629 le32_to_cpu(private->size));
1630 if (ret != 0) {
1631 dev_err(sdev->dev, "error: parse mux.cfg tokens failed %d\n",
1632 private->size);
1633 kfree(mux);
1634 return ret;
1635 }
1636
1637 sof_dbg_comp_config(scomp, &mux->config);
1638
1639 swidget->private = mux;
1640
1641 ret = sof_ipc_tx_message(sdev->ipc, mux->comp.hdr.cmd, mux,
1642 sizeof(*mux), r, sizeof(*r));
1643 if (ret < 0)
1644 kfree(mux);
1645
1646 return ret;
1647}
1648
1649
1650
1651
1652
1653static int sof_widget_load_pga(struct snd_soc_component *scomp, int index,
1654 struct snd_sof_widget *swidget,
1655 struct snd_soc_tplg_dapm_widget *tw,
1656 struct sof_ipc_comp_reply *r)
1657{
1658 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1659 struct snd_soc_tplg_private *private = &tw->priv;
1660 struct sof_ipc_comp_volume *volume;
1661 struct snd_sof_control *scontrol;
1662 int min_step;
1663 int max_step;
1664 int ret;
1665
1666 volume = kzalloc(sizeof(*volume), GFP_KERNEL);
1667 if (!volume)
1668 return -ENOMEM;
1669
1670 if (!le32_to_cpu(tw->num_kcontrols)) {
1671 dev_err(sdev->dev, "error: invalid kcontrol count %d for volume\n",
1672 tw->num_kcontrols);
1673 ret = -EINVAL;
1674 goto err;
1675 }
1676
1677
1678 volume->comp.hdr.size = sizeof(*volume);
1679 volume->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1680 volume->comp.id = swidget->comp_id;
1681 volume->comp.type = SOF_COMP_VOLUME;
1682 volume->comp.pipeline_id = index;
1683 volume->config.hdr.size = sizeof(volume->config);
1684
1685 ret = sof_parse_tokens(scomp, volume, volume_tokens,
1686 ARRAY_SIZE(volume_tokens), private->array,
1687 le32_to_cpu(private->size));
1688 if (ret != 0) {
1689 dev_err(sdev->dev, "error: parse volume tokens failed %d\n",
1690 private->size);
1691 goto err;
1692 }
1693 ret = sof_parse_tokens(scomp, &volume->config, comp_tokens,
1694 ARRAY_SIZE(comp_tokens), private->array,
1695 le32_to_cpu(private->size));
1696 if (ret != 0) {
1697 dev_err(sdev->dev, "error: parse volume.cfg tokens failed %d\n",
1698 le32_to_cpu(private->size));
1699 goto err;
1700 }
1701
1702 sof_dbg_comp_config(scomp, &volume->config);
1703
1704 swidget->private = volume;
1705
1706 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
1707 if (scontrol->comp_id == swidget->comp_id &&
1708 scontrol->volume_table) {
1709 min_step = scontrol->min_volume_step;
1710 max_step = scontrol->max_volume_step;
1711 volume->min_value = scontrol->volume_table[min_step];
1712 volume->max_value = scontrol->volume_table[max_step];
1713 volume->channels = scontrol->num_channels;
1714 break;
1715 }
1716 }
1717
1718 ret = sof_ipc_tx_message(sdev->ipc, volume->comp.hdr.cmd, volume,
1719 sizeof(*volume), r, sizeof(*r));
1720 if (ret >= 0)
1721 return ret;
1722err:
1723 kfree(volume);
1724 return ret;
1725}
1726
1727
1728
1729
1730
1731static int sof_widget_load_src(struct snd_soc_component *scomp, int index,
1732 struct snd_sof_widget *swidget,
1733 struct snd_soc_tplg_dapm_widget *tw,
1734 struct sof_ipc_comp_reply *r)
1735{
1736 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1737 struct snd_soc_tplg_private *private = &tw->priv;
1738 struct sof_ipc_comp_src *src;
1739 int ret;
1740
1741 src = kzalloc(sizeof(*src), GFP_KERNEL);
1742 if (!src)
1743 return -ENOMEM;
1744
1745
1746 src->comp.hdr.size = sizeof(*src);
1747 src->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1748 src->comp.id = swidget->comp_id;
1749 src->comp.type = SOF_COMP_SRC;
1750 src->comp.pipeline_id = index;
1751 src->config.hdr.size = sizeof(src->config);
1752
1753 ret = sof_parse_tokens(scomp, src, src_tokens,
1754 ARRAY_SIZE(src_tokens), private->array,
1755 le32_to_cpu(private->size));
1756 if (ret != 0) {
1757 dev_err(sdev->dev, "error: parse src tokens failed %d\n",
1758 private->size);
1759 goto err;
1760 }
1761
1762 ret = sof_parse_tokens(scomp, &src->config, comp_tokens,
1763 ARRAY_SIZE(comp_tokens), private->array,
1764 le32_to_cpu(private->size));
1765 if (ret != 0) {
1766 dev_err(sdev->dev, "error: parse src.cfg tokens failed %d\n",
1767 le32_to_cpu(private->size));
1768 goto err;
1769 }
1770
1771 dev_dbg(sdev->dev, "src %s: source rate %d sink rate %d\n",
1772 swidget->widget->name, src->source_rate, src->sink_rate);
1773 sof_dbg_comp_config(scomp, &src->config);
1774
1775 swidget->private = src;
1776
1777 ret = sof_ipc_tx_message(sdev->ipc, src->comp.hdr.cmd, src,
1778 sizeof(*src), r, sizeof(*r));
1779 if (ret >= 0)
1780 return ret;
1781err:
1782 kfree(src);
1783 return ret;
1784}
1785
1786
1787
1788
1789
1790static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index,
1791 struct snd_sof_widget *swidget,
1792 struct snd_soc_tplg_dapm_widget *tw,
1793 struct sof_ipc_comp_reply *r)
1794{
1795 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1796 struct snd_soc_tplg_private *private = &tw->priv;
1797 struct sof_ipc_comp_tone *tone;
1798 int ret;
1799
1800 tone = kzalloc(sizeof(*tone), GFP_KERNEL);
1801 if (!tone)
1802 return -ENOMEM;
1803
1804
1805 tone->comp.hdr.size = sizeof(*tone);
1806 tone->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1807 tone->comp.id = swidget->comp_id;
1808 tone->comp.type = SOF_COMP_TONE;
1809 tone->comp.pipeline_id = index;
1810 tone->config.hdr.size = sizeof(tone->config);
1811
1812 ret = sof_parse_tokens(scomp, tone, tone_tokens,
1813 ARRAY_SIZE(tone_tokens), private->array,
1814 le32_to_cpu(private->size));
1815 if (ret != 0) {
1816 dev_err(sdev->dev, "error: parse tone tokens failed %d\n",
1817 le32_to_cpu(private->size));
1818 goto err;
1819 }
1820
1821 ret = sof_parse_tokens(scomp, &tone->config, comp_tokens,
1822 ARRAY_SIZE(comp_tokens), private->array,
1823 le32_to_cpu(private->size));
1824 if (ret != 0) {
1825 dev_err(sdev->dev, "error: parse tone.cfg tokens failed %d\n",
1826 le32_to_cpu(private->size));
1827 goto err;
1828 }
1829
1830 dev_dbg(sdev->dev, "tone %s: frequency %d amplitude %d\n",
1831 swidget->widget->name, tone->frequency, tone->amplitude);
1832 sof_dbg_comp_config(scomp, &tone->config);
1833
1834 swidget->private = tone;
1835
1836 ret = sof_ipc_tx_message(sdev->ipc, tone->comp.hdr.cmd, tone,
1837 sizeof(*tone), r, sizeof(*r));
1838 if (ret >= 0)
1839 return ret;
1840err:
1841 kfree(tone);
1842 return ret;
1843}
1844
1845static int sof_get_control_data(struct snd_sof_dev *sdev,
1846 struct snd_soc_dapm_widget *widget,
1847 struct sof_widget_data *wdata,
1848 size_t *size)
1849{
1850 const struct snd_kcontrol_new *kc;
1851 struct soc_mixer_control *sm;
1852 struct soc_bytes_ext *sbe;
1853 struct soc_enum *se;
1854 int i;
1855
1856 *size = 0;
1857
1858 for (i = 0; i < widget->num_kcontrols; i++) {
1859 kc = &widget->kcontrol_news[i];
1860
1861 switch (widget->dobj.widget.kcontrol_type) {
1862 case SND_SOC_TPLG_TYPE_MIXER:
1863 sm = (struct soc_mixer_control *)kc->private_value;
1864 wdata[i].control = sm->dobj.private;
1865 break;
1866 case SND_SOC_TPLG_TYPE_BYTES:
1867 sbe = (struct soc_bytes_ext *)kc->private_value;
1868 wdata[i].control = sbe->dobj.private;
1869 break;
1870 case SND_SOC_TPLG_TYPE_ENUM:
1871 se = (struct soc_enum *)kc->private_value;
1872 wdata[i].control = se->dobj.private;
1873 break;
1874 default:
1875 dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n",
1876 widget->dobj.widget.kcontrol_type,
1877 widget->name);
1878 return -EINVAL;
1879 }
1880
1881 if (!wdata[i].control) {
1882 dev_err(sdev->dev, "error: no scontrol for widget %s\n",
1883 widget->name);
1884 return -EINVAL;
1885 }
1886
1887 wdata[i].pdata = wdata[i].control->control_data->data;
1888 if (!wdata[i].pdata)
1889 return -EINVAL;
1890
1891
1892 if (wdata[i].pdata->magic != SOF_ABI_MAGIC)
1893 return -EINVAL;
1894
1895 *size += wdata[i].pdata->size;
1896
1897
1898 switch (wdata[i].control->cmd) {
1899 case SOF_CTRL_CMD_VOLUME:
1900 case SOF_CTRL_CMD_ENUM:
1901 case SOF_CTRL_CMD_SWITCH:
1902 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE;
1903 wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET;
1904 break;
1905 case SOF_CTRL_CMD_BINARY:
1906 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA;
1907 wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET;
1908 break;
1909 default:
1910 break;
1911 }
1912 }
1913
1914 return 0;
1915}
1916
1917static int sof_process_load(struct snd_soc_component *scomp, int index,
1918 struct snd_sof_widget *swidget,
1919 struct snd_soc_tplg_dapm_widget *tw,
1920 struct sof_ipc_comp_reply *r,
1921 int type)
1922{
1923 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1924 struct snd_soc_dapm_widget *widget = swidget->widget;
1925 struct snd_soc_tplg_private *private = &tw->priv;
1926 struct sof_ipc_comp_process *process = NULL;
1927 struct sof_widget_data *wdata = NULL;
1928 size_t ipc_data_size = 0;
1929 size_t ipc_size;
1930 int offset = 0;
1931 int ret = 0;
1932 int i;
1933
1934 if (type == SOF_COMP_NONE) {
1935 dev_err(sdev->dev, "error: invalid process comp type %d\n",
1936 type);
1937 return -EINVAL;
1938 }
1939
1940
1941 if (widget->num_kcontrols) {
1942 wdata = kcalloc(widget->num_kcontrols,
1943 sizeof(*wdata),
1944 GFP_KERNEL);
1945
1946 if (!wdata)
1947 return -ENOMEM;
1948
1949
1950 ret = sof_get_control_data(sdev, widget, wdata,
1951 &ipc_data_size);
1952
1953 if (ret < 0)
1954 goto out;
1955 }
1956
1957 ipc_size = sizeof(struct sof_ipc_comp_process) +
1958 le32_to_cpu(private->size) +
1959 ipc_data_size;
1960
1961
1962 if (ipc_size > SOF_IPC_MSG_MAX_SIZE) {
1963 ipc_size -= ipc_data_size;
1964 ipc_data_size = 0;
1965 }
1966
1967 process = kzalloc(ipc_size, GFP_KERNEL);
1968 if (!process) {
1969 ret = -ENOMEM;
1970 goto out;
1971 }
1972
1973
1974 process->comp.hdr.size = ipc_size;
1975 process->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1976 process->comp.id = swidget->comp_id;
1977 process->comp.type = type;
1978 process->comp.pipeline_id = index;
1979 process->config.hdr.size = sizeof(process->config);
1980
1981 ret = sof_parse_tokens(scomp, &process->config, comp_tokens,
1982 ARRAY_SIZE(comp_tokens), private->array,
1983 le32_to_cpu(private->size));
1984 if (ret != 0) {
1985 dev_err(sdev->dev, "error: parse process.cfg tokens failed %d\n",
1986 le32_to_cpu(private->size));
1987 goto err;
1988 }
1989
1990 sof_dbg_comp_config(scomp, &process->config);
1991
1992
1993
1994
1995
1996
1997 if (ipc_data_size) {
1998 for (i = 0; i < widget->num_kcontrols; i++) {
1999 memcpy(&process->data + offset,
2000 wdata[i].pdata->data,
2001 wdata[i].pdata->size);
2002 offset += wdata[i].pdata->size;
2003 }
2004 }
2005
2006 process->size = ipc_data_size;
2007 swidget->private = process;
2008
2009 ret = sof_ipc_tx_message(sdev->ipc, process->comp.hdr.cmd, process,
2010 ipc_size, r, sizeof(*r));
2011
2012 if (ret < 0) {
2013 dev_err(sdev->dev, "error: create process failed\n");
2014 goto err;
2015 }
2016
2017
2018 if (ipc_data_size)
2019 goto out;
2020
2021
2022 for (i = 0; i < widget->num_kcontrols; i++) {
2023 wdata[i].control->readback_offset = 0;
2024 ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, wdata[i].control,
2025 wdata[i].ipc_cmd,
2026 wdata[i].ctrl_type,
2027 wdata[i].control->cmd,
2028 true);
2029 if (ret != 0) {
2030 dev_err(sdev->dev, "error: send control failed\n");
2031 break;
2032 }
2033 }
2034
2035err:
2036 if (ret < 0)
2037 kfree(process);
2038out:
2039 kfree(wdata);
2040 return ret;
2041}
2042
2043
2044
2045
2046
2047
2048static int sof_widget_load_process(struct snd_soc_component *scomp, int index,
2049 struct snd_sof_widget *swidget,
2050 struct snd_soc_tplg_dapm_widget *tw,
2051 struct sof_ipc_comp_reply *r)
2052{
2053 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2054 struct snd_soc_tplg_private *private = &tw->priv;
2055 struct sof_ipc_comp_process config;
2056 int ret;
2057
2058
2059 if (le32_to_cpu(private->size) == 0) {
2060 dev_err(sdev->dev, "error: process tokens not found\n");
2061 return -EINVAL;
2062 }
2063
2064 memset(&config, 0, sizeof(config));
2065
2066
2067 ret = sof_parse_tokens(scomp, &config, process_tokens,
2068 ARRAY_SIZE(process_tokens), private->array,
2069 le32_to_cpu(private->size));
2070 if (ret != 0) {
2071 dev_err(sdev->dev, "error: parse process tokens failed %d\n",
2072 le32_to_cpu(private->size));
2073 return ret;
2074 }
2075
2076
2077 ret = sof_process_load(scomp, index, swidget, tw, r,
2078 find_process_comp_type(config.type));
2079 if (ret < 0) {
2080 dev_err(sdev->dev, "error: process loading failed\n");
2081 return ret;
2082 }
2083
2084 return 0;
2085}
2086
2087static int sof_widget_bind_event(struct snd_sof_dev *sdev,
2088 struct snd_sof_widget *swidget,
2089 u16 event_type)
2090{
2091 struct sof_ipc_comp *ipc_comp;
2092
2093
2094 switch (event_type) {
2095 case SOF_KEYWORD_DETECT_DAPM_EVENT:
2096
2097 if (swidget->id != snd_soc_dapm_effect)
2098 break;
2099
2100 ipc_comp = swidget->private;
2101 if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT)
2102 break;
2103
2104
2105 return snd_soc_tplg_widget_bind_event(swidget->widget,
2106 sof_kwd_events,
2107 ARRAY_SIZE(sof_kwd_events),
2108 event_type);
2109 default:
2110 break;
2111 }
2112
2113 dev_err(sdev->dev,
2114 "error: invalid event type %d for widget %s\n",
2115 event_type, swidget->widget->name);
2116 return -EINVAL;
2117}
2118
2119
2120static int sof_widget_ready(struct snd_soc_component *scomp, int index,
2121 struct snd_soc_dapm_widget *w,
2122 struct snd_soc_tplg_dapm_widget *tw)
2123{
2124 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2125 struct snd_sof_widget *swidget;
2126 struct snd_sof_dai *dai;
2127 struct sof_ipc_comp_reply reply;
2128 struct snd_sof_control *scontrol;
2129 int ret = 0;
2130
2131 swidget = kzalloc(sizeof(*swidget), GFP_KERNEL);
2132 if (!swidget)
2133 return -ENOMEM;
2134
2135 swidget->sdev = sdev;
2136 swidget->widget = w;
2137 swidget->comp_id = sdev->next_comp_id++;
2138 swidget->complete = 0;
2139 swidget->id = w->id;
2140 swidget->pipeline_id = index;
2141 swidget->private = NULL;
2142 memset(&reply, 0, sizeof(reply));
2143
2144 dev_dbg(sdev->dev, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n",
2145 swidget->comp_id, index, swidget->id, tw->name,
2146 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0
2147 ? tw->sname : "none");
2148
2149
2150 switch (w->id) {
2151 case snd_soc_dapm_dai_in:
2152 case snd_soc_dapm_dai_out:
2153 dai = kzalloc(sizeof(*dai), GFP_KERNEL);
2154 if (!dai) {
2155 kfree(swidget);
2156 return -ENOMEM;
2157 }
2158
2159 ret = sof_widget_load_dai(scomp, index, swidget, tw, &reply,
2160 dai);
2161 if (ret == 0) {
2162 sof_connect_dai_widget(scomp, w, tw, dai);
2163 list_add(&dai->list, &sdev->dai_list);
2164 swidget->private = dai;
2165 } else {
2166 kfree(dai);
2167 }
2168 break;
2169 case snd_soc_dapm_mixer:
2170 ret = sof_widget_load_mixer(scomp, index, swidget, tw, &reply);
2171 break;
2172 case snd_soc_dapm_pga:
2173 ret = sof_widget_load_pga(scomp, index, swidget, tw, &reply);
2174
2175 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
2176 if (scontrol->comp_id == swidget->comp_id) {
2177 scontrol->readback_offset = reply.offset;
2178 break;
2179 }
2180 }
2181 break;
2182 case snd_soc_dapm_buffer:
2183 ret = sof_widget_load_buffer(scomp, index, swidget, tw, &reply);
2184 break;
2185 case snd_soc_dapm_scheduler:
2186 ret = sof_widget_load_pipeline(scomp, index, swidget, tw,
2187 &reply);
2188 break;
2189 case snd_soc_dapm_aif_out:
2190 ret = sof_widget_load_pcm(scomp, index, swidget,
2191 SOF_IPC_STREAM_CAPTURE, tw, &reply);
2192 break;
2193 case snd_soc_dapm_aif_in:
2194 ret = sof_widget_load_pcm(scomp, index, swidget,
2195 SOF_IPC_STREAM_PLAYBACK, tw, &reply);
2196 break;
2197 case snd_soc_dapm_src:
2198 ret = sof_widget_load_src(scomp, index, swidget, tw, &reply);
2199 break;
2200 case snd_soc_dapm_siggen:
2201 ret = sof_widget_load_siggen(scomp, index, swidget, tw, &reply);
2202 break;
2203 case snd_soc_dapm_effect:
2204 ret = sof_widget_load_process(scomp, index, swidget, tw,
2205 &reply);
2206 break;
2207 case snd_soc_dapm_mux:
2208 case snd_soc_dapm_demux:
2209 ret = sof_widget_load_mux(scomp, index, swidget, tw, &reply);
2210 break;
2211 case snd_soc_dapm_switch:
2212 case snd_soc_dapm_dai_link:
2213 case snd_soc_dapm_kcontrol:
2214 default:
2215 dev_warn(sdev->dev, "warning: widget type %d name %s not handled\n",
2216 swidget->id, tw->name);
2217 break;
2218 }
2219
2220
2221 if (ret < 0 || reply.rhdr.error < 0) {
2222 dev_err(sdev->dev,
2223 "error: DSP failed to add widget id %d type %d name : %s stream %s reply %d\n",
2224 tw->shift, swidget->id, tw->name,
2225 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0
2226 ? tw->sname : "none", reply.rhdr.error);
2227 kfree(swidget);
2228 return ret;
2229 }
2230
2231
2232 if (tw->event_type) {
2233 ret = sof_widget_bind_event(sdev, swidget,
2234 le16_to_cpu(tw->event_type));
2235 if (ret) {
2236 dev_err(sdev->dev, "error: widget event binding failed\n");
2237 kfree(swidget->private);
2238 kfree(swidget);
2239 return ret;
2240 }
2241 }
2242
2243 w->dobj.private = swidget;
2244 list_add(&swidget->list, &sdev->widget_list);
2245 return ret;
2246}
2247
2248static int sof_route_unload(struct snd_soc_component *scomp,
2249 struct snd_soc_dobj *dobj)
2250{
2251 struct snd_sof_route *sroute;
2252
2253 sroute = dobj->private;
2254 if (!sroute)
2255 return 0;
2256
2257
2258 kfree(sroute->private);
2259 list_del(&sroute->list);
2260 kfree(sroute);
2261
2262 return 0;
2263}
2264
2265static int sof_widget_unload(struct snd_soc_component *scomp,
2266 struct snd_soc_dobj *dobj)
2267{
2268 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2269 const struct snd_kcontrol_new *kc;
2270 struct snd_soc_dapm_widget *widget;
2271 struct sof_ipc_pipe_new *pipeline;
2272 struct snd_sof_control *scontrol;
2273 struct snd_sof_widget *swidget;
2274 struct soc_mixer_control *sm;
2275 struct soc_bytes_ext *sbe;
2276 struct snd_sof_dai *dai;
2277 struct soc_enum *se;
2278 int ret = 0;
2279 int i;
2280
2281 swidget = dobj->private;
2282 if (!swidget)
2283 return 0;
2284
2285 widget = swidget->widget;
2286
2287 switch (swidget->id) {
2288 case snd_soc_dapm_dai_in:
2289 case snd_soc_dapm_dai_out:
2290 dai = swidget->private;
2291
2292 if (dai) {
2293
2294 kfree(dai->dai_config);
2295 list_del(&dai->list);
2296 }
2297 break;
2298 case snd_soc_dapm_scheduler:
2299
2300
2301 pipeline = swidget->private;
2302 ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core);
2303 if (ret < 0)
2304 dev_err(sdev->dev, "error: powering down pipeline schedule core %d\n",
2305 pipeline->core);
2306
2307
2308 sdev->enabled_cores_mask &= ~(1 << pipeline->core);
2309
2310 break;
2311 default:
2312 break;
2313 }
2314 for (i = 0; i < widget->num_kcontrols; i++) {
2315 kc = &widget->kcontrol_news[i];
2316 switch (dobj->widget.kcontrol_type) {
2317 case SND_SOC_TPLG_TYPE_MIXER:
2318 sm = (struct soc_mixer_control *)kc->private_value;
2319 scontrol = sm->dobj.private;
2320 if (sm->max > 1)
2321 kfree(scontrol->volume_table);
2322 break;
2323 case SND_SOC_TPLG_TYPE_ENUM:
2324 se = (struct soc_enum *)kc->private_value;
2325 scontrol = se->dobj.private;
2326 break;
2327 case SND_SOC_TPLG_TYPE_BYTES:
2328 sbe = (struct soc_bytes_ext *)kc->private_value;
2329 scontrol = sbe->dobj.private;
2330 break;
2331 default:
2332 dev_warn(sdev->dev, "unsupported kcontrol_type\n");
2333 goto out;
2334 }
2335 kfree(scontrol->control_data);
2336 list_del(&scontrol->list);
2337 kfree(scontrol);
2338 }
2339
2340out:
2341
2342 kfree(swidget->private);
2343
2344
2345 list_del(&swidget->list);
2346 kfree(swidget);
2347
2348 return ret;
2349}
2350
2351
2352
2353
2354
2355
2356static int sof_dai_load(struct snd_soc_component *scomp, int index,
2357 struct snd_soc_dai_driver *dai_drv,
2358 struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
2359{
2360 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2361 struct snd_soc_tplg_stream_caps *caps;
2362 struct snd_soc_tplg_private *private = &pcm->priv;
2363 struct snd_sof_pcm *spcm;
2364 int stream = SNDRV_PCM_STREAM_PLAYBACK;
2365 int ret = 0;
2366
2367
2368 if (!pcm)
2369 return 0;
2370
2371 spcm = kzalloc(sizeof(*spcm), GFP_KERNEL);
2372 if (!spcm)
2373 return -ENOMEM;
2374
2375 spcm->sdev = sdev;
2376 spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id = COMP_ID_UNASSIGNED;
2377 spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id = COMP_ID_UNASSIGNED;
2378
2379 spcm->pcm = *pcm;
2380 dev_dbg(sdev->dev, "tplg: load pcm %s\n", pcm->dai_name);
2381
2382 dai_drv->dobj.private = spcm;
2383 list_add(&spcm->list, &sdev->pcm_list);
2384
2385 ret = sof_parse_tokens(scomp, spcm, stream_tokens,
2386 ARRAY_SIZE(stream_tokens), private->array,
2387 le32_to_cpu(private->size));
2388 if (ret) {
2389 dev_err(sdev->dev, "error: parse stream tokens failed %d\n",
2390 le32_to_cpu(private->size));
2391 return ret;
2392 }
2393
2394
2395 if (!spcm->pcm.playback)
2396 goto capture;
2397
2398 dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: playback d0i3:%d\n",
2399 spcm->pcm.pcm_name, spcm->stream[0].d0i3_compatible);
2400
2401 caps = &spcm->pcm.caps[stream];
2402
2403
2404 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
2405 PAGE_SIZE, &spcm->stream[stream].page_table);
2406 if (ret < 0) {
2407 dev_err(sdev->dev, "error: can't alloc page table for %s %d\n",
2408 caps->name, ret);
2409
2410 return ret;
2411 }
2412
2413
2414 ret = spcm_bind(sdev, spcm, stream);
2415 if (ret) {
2416 dev_err(sdev->dev,
2417 "error: can't bind pcm to host\n");
2418 goto free_playback_tables;
2419 }
2420
2421capture:
2422 stream = SNDRV_PCM_STREAM_CAPTURE;
2423
2424
2425 if (!spcm->pcm.capture)
2426 return ret;
2427
2428 dev_vdbg(sdev->dev, "tplg: pcm %s stream tokens: capture d0i3:%d\n",
2429 spcm->pcm.pcm_name, spcm->stream[1].d0i3_compatible);
2430
2431 caps = &spcm->pcm.caps[stream];
2432
2433
2434 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
2435 PAGE_SIZE, &spcm->stream[stream].page_table);
2436 if (ret < 0) {
2437 dev_err(sdev->dev, "error: can't alloc page table for %s %d\n",
2438 caps->name, ret);
2439 goto free_playback_tables;
2440 }
2441
2442
2443 ret = spcm_bind(sdev, spcm, stream);
2444 if (ret) {
2445 dev_err(sdev->dev,
2446 "error: can't bind pcm to host\n");
2447 snd_dma_free_pages(&spcm->stream[stream].page_table);
2448 goto free_playback_tables;
2449 }
2450
2451 return ret;
2452
2453free_playback_tables:
2454 if (spcm->pcm.playback)
2455 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].page_table);
2456
2457 return ret;
2458}
2459
2460static int sof_dai_unload(struct snd_soc_component *scomp,
2461 struct snd_soc_dobj *dobj)
2462{
2463 struct snd_sof_pcm *spcm = dobj->private;
2464
2465
2466 if (spcm->pcm.playback)
2467 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].page_table);
2468
2469 if (spcm->pcm.capture)
2470 snd_dma_free_pages(&spcm->stream[SNDRV_PCM_STREAM_CAPTURE].page_table);
2471
2472
2473 list_del(&spcm->list);
2474 kfree(spcm);
2475
2476 return 0;
2477}
2478
2479static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config,
2480 struct sof_ipc_dai_config *config)
2481{
2482
2483 if (hw_config->bclk_master == SND_SOC_TPLG_BCLK_CM) {
2484
2485 if (hw_config->fsync_master == SND_SOC_TPLG_FSYNC_CM)
2486 config->format |= SOF_DAI_FMT_CBM_CFM;
2487 else
2488 config->format |= SOF_DAI_FMT_CBM_CFS;
2489 } else {
2490
2491 if (hw_config->fsync_master == SND_SOC_TPLG_FSYNC_CM)
2492 config->format |= SOF_DAI_FMT_CBS_CFM;
2493 else
2494 config->format |= SOF_DAI_FMT_CBS_CFS;
2495 }
2496
2497
2498 if (hw_config->invert_bclk) {
2499 if (hw_config->invert_fsync)
2500 config->format |= SOF_DAI_FMT_IB_IF;
2501 else
2502 config->format |= SOF_DAI_FMT_IB_NF;
2503 } else {
2504 if (hw_config->invert_fsync)
2505 config->format |= SOF_DAI_FMT_NB_IF;
2506 else
2507 config->format |= SOF_DAI_FMT_NB_NF;
2508 }
2509}
2510
2511
2512static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size,
2513 struct snd_soc_dai_link *link,
2514 struct sof_ipc_dai_config *config)
2515{
2516 struct snd_sof_dai *dai;
2517 int found = 0;
2518
2519 list_for_each_entry(dai, &sdev->dai_list, list) {
2520 if (!dai->name)
2521 continue;
2522
2523 if (strcmp(link->name, dai->name) == 0) {
2524 dai->dai_config = kmemdup(config, size, GFP_KERNEL);
2525 if (!dai->dai_config)
2526 return -ENOMEM;
2527
2528
2529 dai->cpu_dai_name = link->cpus->dai_name;
2530
2531 found = 1;
2532 }
2533 }
2534
2535
2536
2537
2538
2539
2540 if (!found) {
2541 dev_warn(sdev->dev, "warning: failed to find dai for dai link %s",
2542 link->name);
2543 }
2544
2545 return 0;
2546}
2547
2548static int sof_link_ssp_load(struct snd_soc_component *scomp, int index,
2549 struct snd_soc_dai_link *link,
2550 struct snd_soc_tplg_link_config *cfg,
2551 struct snd_soc_tplg_hw_config *hw_config,
2552 struct sof_ipc_dai_config *config)
2553{
2554 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2555 struct snd_soc_tplg_private *private = &cfg->priv;
2556 struct sof_ipc_reply reply;
2557 u32 size = sizeof(*config);
2558 int ret;
2559
2560
2561 sof_dai_set_format(hw_config, config);
2562
2563
2564 memset(&config->ssp, 0, sizeof(struct sof_ipc_dai_ssp_params));
2565 config->hdr.size = size;
2566
2567 ret = sof_parse_tokens(scomp, &config->ssp, ssp_tokens,
2568 ARRAY_SIZE(ssp_tokens), private->array,
2569 le32_to_cpu(private->size));
2570 if (ret != 0) {
2571 dev_err(sdev->dev, "error: parse ssp tokens failed %d\n",
2572 le32_to_cpu(private->size));
2573 return ret;
2574 }
2575
2576 config->ssp.mclk_rate = le32_to_cpu(hw_config->mclk_rate);
2577 config->ssp.bclk_rate = le32_to_cpu(hw_config->bclk_rate);
2578 config->ssp.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
2579 config->ssp.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
2580 config->ssp.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width);
2581 config->ssp.mclk_direction = hw_config->mclk_direction;
2582 config->ssp.rx_slots = le32_to_cpu(hw_config->rx_slots);
2583 config->ssp.tx_slots = le32_to_cpu(hw_config->tx_slots);
2584
2585 dev_dbg(sdev->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n",
2586 config->dai_index, config->format,
2587 config->ssp.mclk_rate, config->ssp.bclk_rate,
2588 config->ssp.fsync_rate, config->ssp.sample_valid_bits,
2589 config->ssp.tdm_slot_width, config->ssp.tdm_slots,
2590 config->ssp.mclk_id, config->ssp.quirks);
2591
2592
2593 if (config->ssp.fsync_rate < 8000 || config->ssp.fsync_rate > 192000) {
2594 dev_err(sdev->dev, "error: invalid fsync rate for SSP%d\n",
2595 config->dai_index);
2596 return -EINVAL;
2597 }
2598
2599 if (config->ssp.tdm_slots < 1 || config->ssp.tdm_slots > 8) {
2600 dev_err(sdev->dev, "error: invalid channel count for SSP%d\n",
2601 config->dai_index);
2602 return -EINVAL;
2603 }
2604
2605
2606 ret = sof_ipc_tx_message(sdev->ipc,
2607 config->hdr.cmd, config, size, &reply,
2608 sizeof(reply));
2609
2610 if (ret < 0) {
2611 dev_err(sdev->dev, "error: failed to set DAI config for SSP%d\n",
2612 config->dai_index);
2613 return ret;
2614 }
2615
2616
2617 ret = sof_set_dai_config(sdev, size, link, config);
2618 if (ret < 0)
2619 dev_err(sdev->dev, "error: failed to save DAI config for SSP%d\n",
2620 config->dai_index);
2621
2622 return ret;
2623}
2624
2625static int sof_link_sai_load(struct snd_soc_component *scomp, int index,
2626 struct snd_soc_dai_link *link,
2627 struct snd_soc_tplg_link_config *cfg,
2628 struct snd_soc_tplg_hw_config *hw_config,
2629 struct sof_ipc_dai_config *config)
2630{
2631
2632 return 0;
2633}
2634
2635static int sof_link_esai_load(struct snd_soc_component *scomp, int index,
2636 struct snd_soc_dai_link *link,
2637 struct snd_soc_tplg_link_config *cfg,
2638 struct snd_soc_tplg_hw_config *hw_config,
2639 struct sof_ipc_dai_config *config)
2640{
2641 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2642 struct snd_soc_tplg_private *private = &cfg->priv;
2643 struct sof_ipc_reply reply;
2644 u32 size = sizeof(*config);
2645 int ret;
2646
2647
2648 sof_dai_set_format(hw_config, config);
2649
2650
2651 memset(&config->esai, 0, sizeof(struct sof_ipc_dai_esai_params));
2652 config->hdr.size = size;
2653
2654 ret = sof_parse_tokens(scomp, &config->esai, esai_tokens,
2655 ARRAY_SIZE(esai_tokens), private->array,
2656 le32_to_cpu(private->size));
2657 if (ret != 0) {
2658 dev_err(sdev->dev, "error: parse esai tokens failed %d\n",
2659 le32_to_cpu(private->size));
2660 return ret;
2661 }
2662
2663 config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate);
2664 config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate);
2665 config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
2666 config->esai.mclk_direction = hw_config->mclk_direction;
2667 config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
2668 config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width);
2669 config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots);
2670 config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots);
2671
2672 dev_info(sdev->dev,
2673 "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n",
2674 config->dai_index, config->format,
2675 config->esai.mclk_rate, config->esai.tdm_slot_width,
2676 config->esai.tdm_slots, config->esai.mclk_id);
2677
2678 if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) {
2679 dev_err(sdev->dev, "error: invalid channel count for ESAI%d\n",
2680 config->dai_index);
2681 return -EINVAL;
2682 }
2683
2684
2685 ret = sof_ipc_tx_message(sdev->ipc,
2686 config->hdr.cmd, config, size, &reply,
2687 sizeof(reply));
2688 if (ret < 0) {
2689 dev_err(sdev->dev, "error: failed to set DAI config for ESAI%d\n",
2690 config->dai_index);
2691 return ret;
2692 }
2693
2694
2695 ret = sof_set_dai_config(sdev, size, link, config);
2696 if (ret < 0)
2697 dev_err(sdev->dev, "error: failed to save DAI config for ESAI%d\n",
2698 config->dai_index);
2699
2700 return ret;
2701}
2702
2703static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
2704 struct snd_soc_dai_link *link,
2705 struct snd_soc_tplg_link_config *cfg,
2706 struct snd_soc_tplg_hw_config *hw_config,
2707 struct sof_ipc_dai_config *config)
2708{
2709 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2710 struct snd_soc_tplg_private *private = &cfg->priv;
2711 struct sof_ipc_dai_config *ipc_config;
2712 struct sof_ipc_reply reply;
2713 struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
2714 struct sof_ipc_fw_version *v = &ready->version;
2715 u32 size;
2716 int ret, j;
2717
2718
2719
2720
2721
2722
2723 memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params));
2724
2725
2726 ret = sof_parse_tokens(scomp, &config->dmic, dmic_tokens,
2727 ARRAY_SIZE(dmic_tokens), private->array,
2728 le32_to_cpu(private->size));
2729 if (ret != 0) {
2730 dev_err(sdev->dev, "error: parse dmic tokens failed %d\n",
2731 le32_to_cpu(private->size));
2732 return ret;
2733 }
2734
2735
2736
2737
2738
2739
2740 size = sizeof(*config) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl) *
2741 config->dmic.num_pdm_active;
2742
2743 ipc_config = kzalloc(size, GFP_KERNEL);
2744 if (!ipc_config)
2745 return -ENOMEM;
2746
2747
2748 memcpy(ipc_config, config, sizeof(*config));
2749
2750
2751
2752
2753
2754 sdev->private = kzalloc(sizeof(u32), GFP_KERNEL);
2755 if (!sdev->private) {
2756 kfree(ipc_config);
2757 return -ENOMEM;
2758 }
2759
2760
2761 ret = sof_parse_tokens(scomp, &ipc_config->dmic.pdm[0], dmic_pdm_tokens,
2762 ARRAY_SIZE(dmic_pdm_tokens), private->array,
2763 le32_to_cpu(private->size));
2764 if (ret != 0) {
2765 dev_err(sdev->dev, "error: parse dmic pdm tokens failed %d\n",
2766 le32_to_cpu(private->size));
2767 goto err;
2768 }
2769
2770
2771 ipc_config->hdr.size = size;
2772
2773
2774 dev_dbg(sdev->dev, "tplg: config DMIC%d driver version %d\n",
2775 ipc_config->dai_index, ipc_config->dmic.driver_ipc_version);
2776 dev_dbg(sdev->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n",
2777 ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max,
2778 ipc_config->dmic.duty_min);
2779 dev_dbg(sdev->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n",
2780 ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs,
2781 ipc_config->dmic.num_pdm_active);
2782 dev_dbg(sdev->dev, "fifo word length %hd\n",
2783 ipc_config->dmic.fifo_bits);
2784
2785 for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) {
2786 dev_dbg(sdev->dev, "pdm %hd mic a %hd mic b %hd\n",
2787 ipc_config->dmic.pdm[j].id,
2788 ipc_config->dmic.pdm[j].enable_mic_a,
2789 ipc_config->dmic.pdm[j].enable_mic_b);
2790 dev_dbg(sdev->dev, "pdm %hd polarity a %hd polarity b %hd\n",
2791 ipc_config->dmic.pdm[j].id,
2792 ipc_config->dmic.pdm[j].polarity_mic_a,
2793 ipc_config->dmic.pdm[j].polarity_mic_b);
2794 dev_dbg(sdev->dev, "pdm %hd clk_edge %hd skew %hd\n",
2795 ipc_config->dmic.pdm[j].id,
2796 ipc_config->dmic.pdm[j].clk_edge,
2797 ipc_config->dmic.pdm[j].skew);
2798 }
2799
2800 if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) {
2801
2802 ipc_config->dmic.reserved_2 = ipc_config->dmic.fifo_bits;
2803 }
2804
2805
2806 ret = sof_ipc_tx_message(sdev->ipc,
2807 ipc_config->hdr.cmd, ipc_config, size, &reply,
2808 sizeof(reply));
2809
2810 if (ret < 0) {
2811 dev_err(sdev->dev,
2812 "error: failed to set DAI config for DMIC%d\n",
2813 config->dai_index);
2814 goto err;
2815 }
2816
2817
2818 ret = sof_set_dai_config(sdev, size, link, ipc_config);
2819 if (ret < 0)
2820 dev_err(sdev->dev, "error: failed to save DAI config for DMIC%d\n",
2821 config->dai_index);
2822
2823err:
2824 kfree(sdev->private);
2825 kfree(ipc_config);
2826
2827 return ret;
2828}
2829
2830
2831
2832
2833
2834
2835static int sof_link_hda_process(struct snd_sof_dev *sdev,
2836 struct snd_soc_dai_link *link,
2837 struct sof_ipc_dai_config *config)
2838{
2839 struct sof_ipc_reply reply;
2840 u32 size = sizeof(*config);
2841 struct snd_sof_dai *sof_dai;
2842 int found = 0;
2843 int ret;
2844
2845 list_for_each_entry(sof_dai, &sdev->dai_list, list) {
2846 if (!sof_dai->name)
2847 continue;
2848
2849 if (strcmp(link->name, sof_dai->name) == 0) {
2850 config->dai_index = sof_dai->comp_dai.dai_index;
2851 found = 1;
2852
2853 config->hda.link_dma_ch = DMA_CHAN_INVALID;
2854
2855
2856 sof_dai->dai_config = kmemdup(config, size, GFP_KERNEL);
2857 if (!sof_dai->dai_config)
2858 return -ENOMEM;
2859
2860 sof_dai->cpu_dai_name = link->cpus->dai_name;
2861
2862
2863 ret = sof_ipc_tx_message(sdev->ipc,
2864 config->hdr.cmd, config, size,
2865 &reply, sizeof(reply));
2866
2867 if (ret < 0) {
2868 dev_err(sdev->dev, "error: failed to set DAI config for direction:%d of HDA dai %d\n",
2869 sof_dai->comp_dai.direction,
2870 config->dai_index);
2871
2872 return ret;
2873 }
2874 }
2875 }
2876
2877
2878
2879
2880
2881
2882 if (!found) {
2883 dev_warn(sdev->dev, "warning: failed to find dai for dai link %s",
2884 link->name);
2885 }
2886
2887 return 0;
2888}
2889
2890static int sof_link_hda_load(struct snd_soc_component *scomp, int index,
2891 struct snd_soc_dai_link *link,
2892 struct snd_soc_tplg_link_config *cfg,
2893 struct snd_soc_tplg_hw_config *hw_config,
2894 struct sof_ipc_dai_config *config)
2895{
2896 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2897 struct snd_soc_tplg_private *private = &cfg->priv;
2898 struct snd_soc_dai *dai;
2899 u32 size = sizeof(*config);
2900 int ret;
2901
2902
2903 memset(&config->hda, 0, sizeof(struct sof_ipc_dai_hda_params));
2904 config->hdr.size = size;
2905
2906
2907 ret = sof_parse_tokens(scomp, config, hda_tokens,
2908 ARRAY_SIZE(hda_tokens), private->array,
2909 le32_to_cpu(private->size));
2910 if (ret != 0) {
2911 dev_err(sdev->dev, "error: parse hda tokens failed %d\n",
2912 le32_to_cpu(private->size));
2913 return ret;
2914 }
2915
2916 dai = snd_soc_find_dai(link->cpus);
2917 if (!dai) {
2918 dev_err(sdev->dev, "error: failed to find dai %s in %s",
2919 link->cpus->dai_name, __func__);
2920 return -EINVAL;
2921 }
2922
2923 ret = sof_link_hda_process(sdev, link, config);
2924 if (ret < 0)
2925 dev_err(sdev->dev, "error: failed to process hda dai link %s",
2926 link->name);
2927
2928 return ret;
2929}
2930
2931static int sof_link_alh_load(struct snd_soc_component *scomp, int index,
2932 struct snd_soc_dai_link *link,
2933 struct snd_soc_tplg_link_config *cfg,
2934 struct snd_soc_tplg_hw_config *hw_config,
2935 struct sof_ipc_dai_config *config)
2936{
2937 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2938 struct sof_ipc_reply reply;
2939 u32 size = sizeof(*config);
2940 int ret;
2941
2942
2943 config->hdr.size = size;
2944
2945
2946 ret = sof_ipc_tx_message(sdev->ipc,
2947 config->hdr.cmd, config, size, &reply,
2948 sizeof(reply));
2949
2950 if (ret < 0) {
2951 dev_err(sdev->dev, "error: failed to set DAI config for ALH %d\n",
2952 config->dai_index);
2953 return ret;
2954 }
2955
2956
2957 ret = sof_set_dai_config(sdev, size, link, config);
2958 if (ret < 0)
2959 dev_err(sdev->dev, "error: failed to save DAI config for ALH %d\n",
2960 config->dai_index);
2961
2962 return ret;
2963}
2964
2965
2966static int sof_link_load(struct snd_soc_component *scomp, int index,
2967 struct snd_soc_dai_link *link,
2968 struct snd_soc_tplg_link_config *cfg)
2969{
2970 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2971 struct snd_soc_tplg_private *private = &cfg->priv;
2972 struct sof_ipc_dai_config config;
2973 struct snd_soc_tplg_hw_config *hw_config;
2974 int num_hw_configs;
2975 int ret;
2976 int i = 0;
2977
2978 if (!link->platforms) {
2979 dev_err(sdev->dev, "error: no platforms\n");
2980 return -EINVAL;
2981 }
2982 link->platforms->name = dev_name(sdev->dev);
2983
2984
2985
2986
2987
2988 if (!link->no_pcm) {
2989 link->nonatomic = true;
2990
2991
2992 link->trigger[0] = SND_SOC_DPCM_TRIGGER_POST;
2993 link->trigger[1] = SND_SOC_DPCM_TRIGGER_POST;
2994
2995
2996 return 0;
2997 }
2998
2999
3000 if (le32_to_cpu(private->size) == 0) {
3001 dev_err(sdev->dev, "error: expected tokens for DAI, none found\n");
3002 return -EINVAL;
3003 }
3004
3005
3006 memset(&config, 0, sizeof(config));
3007
3008
3009 ret = sof_parse_tokens(scomp, &config, dai_link_tokens,
3010 ARRAY_SIZE(dai_link_tokens), private->array,
3011 le32_to_cpu(private->size));
3012 if (ret != 0) {
3013 dev_err(sdev->dev, "error: parse link tokens failed %d\n",
3014 le32_to_cpu(private->size));
3015 return ret;
3016 }
3017
3018
3019
3020
3021
3022 num_hw_configs = le32_to_cpu(cfg->num_hw_configs);
3023 if (!num_hw_configs) {
3024 if (config.type != SOF_DAI_INTEL_HDA) {
3025 dev_err(sdev->dev, "error: unexpected DAI config count %d!\n",
3026 le32_to_cpu(cfg->num_hw_configs));
3027 return -EINVAL;
3028 }
3029 } else {
3030 dev_dbg(sdev->dev, "tplg: %d hw_configs found, default id: %d!\n",
3031 cfg->num_hw_configs, le32_to_cpu(cfg->default_hw_config_id));
3032
3033 for (i = 0; i < num_hw_configs; i++) {
3034 if (cfg->hw_config[i].id == cfg->default_hw_config_id)
3035 break;
3036 }
3037
3038 if (i == num_hw_configs) {
3039 dev_err(sdev->dev, "error: default hw_config id: %d not found!\n",
3040 le32_to_cpu(cfg->default_hw_config_id));
3041 return -EINVAL;
3042 }
3043 }
3044
3045
3046 hw_config = &cfg->hw_config[i];
3047
3048 config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
3049 config.format = le32_to_cpu(hw_config->fmt);
3050
3051
3052 switch (config.type) {
3053 case SOF_DAI_INTEL_SSP:
3054 ret = sof_link_ssp_load(scomp, index, link, cfg, hw_config,
3055 &config);
3056 break;
3057 case SOF_DAI_INTEL_DMIC:
3058 ret = sof_link_dmic_load(scomp, index, link, cfg, hw_config,
3059 &config);
3060 break;
3061 case SOF_DAI_INTEL_HDA:
3062 ret = sof_link_hda_load(scomp, index, link, cfg, hw_config,
3063 &config);
3064 break;
3065 case SOF_DAI_INTEL_ALH:
3066 ret = sof_link_alh_load(scomp, index, link, cfg, hw_config,
3067 &config);
3068 break;
3069 case SOF_DAI_IMX_SAI:
3070 ret = sof_link_sai_load(scomp, index, link, cfg, hw_config,
3071 &config);
3072 break;
3073 case SOF_DAI_IMX_ESAI:
3074 ret = sof_link_esai_load(scomp, index, link, cfg, hw_config,
3075 &config);
3076 break;
3077 default:
3078 dev_err(sdev->dev, "error: invalid DAI type %d\n", config.type);
3079 ret = -EINVAL;
3080 break;
3081 }
3082 if (ret < 0)
3083 return ret;
3084
3085 return 0;
3086}
3087
3088static int sof_link_hda_unload(struct snd_sof_dev *sdev,
3089 struct snd_soc_dai_link *link)
3090{
3091 struct snd_soc_dai *dai;
3092 int ret = 0;
3093
3094 dai = snd_soc_find_dai(link->cpus);
3095 if (!dai) {
3096 dev_err(sdev->dev, "error: failed to find dai %s in %s",
3097 link->cpus->dai_name, __func__);
3098 return -EINVAL;
3099 }
3100
3101 return ret;
3102}
3103
3104static int sof_link_unload(struct snd_soc_component *scomp,
3105 struct snd_soc_dobj *dobj)
3106{
3107 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
3108 struct snd_soc_dai_link *link =
3109 container_of(dobj, struct snd_soc_dai_link, dobj);
3110
3111 struct snd_sof_dai *sof_dai;
3112 int ret = 0;
3113
3114
3115 if (!link->no_pcm)
3116 return 0;
3117
3118 list_for_each_entry(sof_dai, &sdev->dai_list, list) {
3119 if (!sof_dai->name)
3120 continue;
3121
3122 if (strcmp(link->name, sof_dai->name) == 0)
3123 goto found;
3124 }
3125
3126 dev_err(sdev->dev, "error: failed to find dai %s in %s",
3127 link->name, __func__);
3128 return -EINVAL;
3129found:
3130
3131 switch (sof_dai->dai_config->type) {
3132 case SOF_DAI_INTEL_SSP:
3133 case SOF_DAI_INTEL_DMIC:
3134 case SOF_DAI_INTEL_ALH:
3135 case SOF_DAI_IMX_SAI:
3136 case SOF_DAI_IMX_ESAI:
3137
3138 break;
3139 case SOF_DAI_INTEL_HDA:
3140 ret = sof_link_hda_unload(sdev, link);
3141 break;
3142 default:
3143 dev_err(sdev->dev, "error: invalid DAI type %d\n",
3144 sof_dai->dai_config->type);
3145 ret = -EINVAL;
3146 break;
3147 }
3148
3149 return ret;
3150}
3151
3152
3153static int sof_route_load(struct snd_soc_component *scomp, int index,
3154 struct snd_soc_dapm_route *route)
3155{
3156 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
3157 struct sof_ipc_pipe_comp_connect *connect;
3158 struct snd_sof_widget *source_swidget, *sink_swidget;
3159 struct snd_soc_dobj *dobj = &route->dobj;
3160 struct snd_sof_route *sroute;
3161 struct sof_ipc_reply reply;
3162 int ret = 0;
3163
3164
3165 sroute = kzalloc(sizeof(*sroute), GFP_KERNEL);
3166 if (!sroute)
3167 return -ENOMEM;
3168
3169 sroute->sdev = sdev;
3170
3171 connect = kzalloc(sizeof(*connect), GFP_KERNEL);
3172 if (!connect) {
3173 kfree(sroute);
3174 return -ENOMEM;
3175 }
3176
3177 connect->hdr.size = sizeof(*connect);
3178 connect->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT;
3179
3180 dev_dbg(sdev->dev, "sink %s control %s source %s\n",
3181 route->sink, route->control ? route->control : "none",
3182 route->source);
3183
3184
3185 source_swidget = snd_sof_find_swidget(sdev, (char *)route->source);
3186 if (!source_swidget) {
3187 dev_err(sdev->dev, "error: source %s not found\n",
3188 route->source);
3189 ret = -EINVAL;
3190 goto err;
3191 }
3192
3193
3194
3195
3196
3197
3198
3199 if (source_swidget->id == snd_soc_dapm_out_drv ||
3200 source_swidget->id == snd_soc_dapm_output)
3201 goto err;
3202
3203 connect->source_id = source_swidget->comp_id;
3204
3205
3206 sink_swidget = snd_sof_find_swidget(sdev, (char *)route->sink);
3207 if (!sink_swidget) {
3208 dev_err(sdev->dev, "error: sink %s not found\n",
3209 route->sink);
3210 ret = -EINVAL;
3211 goto err;
3212 }
3213
3214
3215
3216
3217
3218 if (sink_swidget->id == snd_soc_dapm_out_drv ||
3219 sink_swidget->id == snd_soc_dapm_output)
3220 goto err;
3221
3222 connect->sink_id = sink_swidget->comp_id;
3223
3224
3225
3226
3227
3228
3229
3230 if (source_swidget->id != snd_soc_dapm_buffer &&
3231 sink_swidget->id != snd_soc_dapm_buffer) {
3232 dev_dbg(sdev->dev, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n",
3233 route->source, route->sink);
3234 ret = 0;
3235 goto err;
3236 } else {
3237 ret = sof_ipc_tx_message(sdev->ipc,
3238 connect->hdr.cmd,
3239 connect, sizeof(*connect),
3240 &reply, sizeof(reply));
3241
3242
3243 if (ret < 0) {
3244 dev_err(sdev->dev, "error: failed to add route sink %s control %s source %s\n",
3245 route->sink,
3246 route->control ? route->control : "none",
3247 route->source);
3248 goto err;
3249 }
3250
3251
3252 if (reply.error < 0) {
3253 dev_err(sdev->dev, "error: DSP failed to add route sink %s control %s source %s result %d\n",
3254 route->sink,
3255 route->control ? route->control : "none",
3256 route->source, reply.error);
3257 ret = reply.error;
3258 goto err;
3259 }
3260
3261 sroute->route = route;
3262 dobj->private = sroute;
3263 sroute->private = connect;
3264
3265
3266 list_add(&sroute->list, &sdev->route_list);
3267
3268 return ret;
3269 }
3270
3271err:
3272 kfree(connect);
3273 kfree(sroute);
3274 return ret;
3275}
3276
3277
3278
3279
3280static int snd_sof_cache_kcontrol_val(struct snd_sof_dev *sdev)
3281{
3282 struct snd_sof_control *scontrol = NULL;
3283 int ipc_cmd, ctrl_type;
3284 int ret = 0;
3285
3286 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
3287
3288
3289 switch (scontrol->cmd) {
3290 case SOF_CTRL_CMD_VOLUME:
3291 case SOF_CTRL_CMD_ENUM:
3292 case SOF_CTRL_CMD_SWITCH:
3293 ipc_cmd = SOF_IPC_COMP_GET_VALUE;
3294 ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_GET;
3295 break;
3296 case SOF_CTRL_CMD_BINARY:
3297 ipc_cmd = SOF_IPC_COMP_GET_DATA;
3298 ctrl_type = SOF_CTRL_TYPE_DATA_GET;
3299 break;
3300 default:
3301 dev_err(sdev->dev,
3302 "error: Invalid scontrol->cmd: %d\n",
3303 scontrol->cmd);
3304 return -EINVAL;
3305 }
3306 ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
3307 ipc_cmd, ctrl_type,
3308 scontrol->cmd,
3309 false);
3310 if (ret < 0) {
3311 dev_warn(sdev->dev,
3312 "error: kcontrol value get for widget: %d\n",
3313 scontrol->comp_id);
3314 }
3315 }
3316
3317 return ret;
3318}
3319
3320int snd_sof_complete_pipeline(struct snd_sof_dev *sdev,
3321 struct snd_sof_widget *swidget)
3322{
3323 struct sof_ipc_pipe_ready ready;
3324 struct sof_ipc_reply reply;
3325 int ret;
3326
3327 dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n",
3328 swidget->widget->name, swidget->comp_id);
3329
3330 memset(&ready, 0, sizeof(ready));
3331 ready.hdr.size = sizeof(ready);
3332 ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE;
3333 ready.comp_id = swidget->comp_id;
3334
3335 ret = sof_ipc_tx_message(sdev->ipc,
3336 ready.hdr.cmd, &ready, sizeof(ready), &reply,
3337 sizeof(reply));
3338 if (ret < 0)
3339 return ret;
3340 return 1;
3341}
3342
3343
3344static void sof_complete(struct snd_soc_component *scomp)
3345{
3346 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
3347 struct snd_sof_widget *swidget;
3348
3349
3350 list_for_each_entry(swidget, &sdev->widget_list, list) {
3351 if (swidget->complete)
3352 continue;
3353
3354 switch (swidget->id) {
3355 case snd_soc_dapm_scheduler:
3356 swidget->complete =
3357 snd_sof_complete_pipeline(sdev, swidget);
3358 break;
3359 default:
3360 break;
3361 }
3362 }
3363
3364
3365
3366
3367 snd_sof_cache_kcontrol_val(sdev);
3368}
3369
3370
3371static int sof_manifest(struct snd_soc_component *scomp, int index,
3372 struct snd_soc_tplg_manifest *man)
3373{
3374 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
3375 u32 size;
3376 u32 abi_version;
3377
3378 size = le32_to_cpu(man->priv.size);
3379
3380
3381 if (!size) {
3382 dev_dbg(sdev->dev, "No topology ABI info\n");
3383 return 0;
3384 }
3385
3386 if (size != SOF_TPLG_ABI_SIZE) {
3387 dev_err(sdev->dev, "error: invalid topology ABI size\n");
3388 return -EINVAL;
3389 }
3390
3391 dev_info(sdev->dev,
3392 "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
3393 man->priv.data[0], man->priv.data[1],
3394 man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR,
3395 SOF_ABI_PATCH);
3396
3397 abi_version = SOF_ABI_VER(man->priv.data[0],
3398 man->priv.data[1],
3399 man->priv.data[2]);
3400
3401 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) {
3402 dev_err(sdev->dev, "error: incompatible topology ABI version\n");
3403 return -EINVAL;
3404 }
3405
3406 if (abi_version > SOF_ABI_VERSION) {
3407 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
3408 dev_warn(sdev->dev, "warn: topology ABI is more recent than kernel\n");
3409 } else {
3410 dev_err(sdev->dev, "error: topology ABI is more recent than kernel\n");
3411 return -EINVAL;
3412 }
3413 }
3414
3415 return 0;
3416}
3417
3418
3419static const struct snd_soc_tplg_kcontrol_ops sof_io_ops[] = {
3420 {SOF_TPLG_KCTL_VOL_ID, snd_sof_volume_get, snd_sof_volume_put},
3421 {SOF_TPLG_KCTL_BYTES_ID, snd_sof_bytes_get, snd_sof_bytes_put},
3422 {SOF_TPLG_KCTL_ENUM_ID, snd_sof_enum_get, snd_sof_enum_put},
3423 {SOF_TPLG_KCTL_SWITCH_ID, snd_sof_switch_get, snd_sof_switch_put},
3424};
3425
3426
3427static const struct snd_soc_tplg_bytes_ext_ops sof_bytes_ext_ops[] = {
3428 {SOF_TPLG_KCTL_BYTES_ID, snd_sof_bytes_ext_get, snd_sof_bytes_ext_put},
3429};
3430
3431static struct snd_soc_tplg_ops sof_tplg_ops = {
3432
3433 .control_load = sof_control_load,
3434 .control_unload = sof_control_unload,
3435
3436
3437 .dapm_route_load = sof_route_load,
3438 .dapm_route_unload = sof_route_unload,
3439
3440
3441
3442 .widget_ready = sof_widget_ready,
3443 .widget_unload = sof_widget_unload,
3444
3445
3446 .dai_load = sof_dai_load,
3447 .dai_unload = sof_dai_unload,
3448
3449
3450 .link_load = sof_link_load,
3451 .link_unload = sof_link_unload,
3452
3453
3454 .complete = sof_complete,
3455
3456
3457 .manifest = sof_manifest,
3458
3459
3460 .io_ops = sof_io_ops,
3461 .io_ops_count = ARRAY_SIZE(sof_io_ops),
3462
3463
3464 .bytes_ext_ops = sof_bytes_ext_ops,
3465 .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops),
3466};
3467
3468int snd_sof_init_topology(struct snd_sof_dev *sdev,
3469 struct snd_soc_tplg_ops *ops)
3470{
3471
3472 sdev->tplg_ops = ops;
3473 return 0;
3474}
3475EXPORT_SYMBOL(snd_sof_init_topology);
3476
3477int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file)
3478{
3479 const struct firmware *fw;
3480 int ret;
3481
3482 dev_dbg(sdev->dev, "loading topology:%s\n", file);
3483
3484 ret = request_firmware(&fw, file, sdev->dev);
3485 if (ret < 0) {
3486 dev_err(sdev->dev, "error: tplg request firmware %s failed err: %d\n",
3487 file, ret);
3488 return ret;
3489 }
3490
3491 ret = snd_soc_tplg_component_load(sdev->component,
3492 &sof_tplg_ops, fw,
3493 SND_SOC_TPLG_INDEX_ALL);
3494 if (ret < 0) {
3495 dev_err(sdev->dev, "error: tplg component load failed %d\n",
3496 ret);
3497 ret = -EINVAL;
3498 }
3499
3500 release_firmware(fw);
3501 return ret;
3502}
3503EXPORT_SYMBOL(snd_sof_load_topology);
3504