1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
11 #include <linux/firmware.h>
12 #include <linux/workqueue.h>
13 #include <sound/tlv.h>
14 #include <sound/pcm_params.h>
15 #include <uapi/sound/sof/tokens.h>
17 #include "sof-audio.h"
20 #define COMP_ID_UNASSIGNED 0xffffffff
22 * Constants used in the computation of linear volume gain
23 * from dB gain 20th root of 10 in Q1.16 fixed-point notation
25 #define VOL_TWENTIETH_ROOT_OF_TEN 73533
26 /* 40th root of 10 in Q1.16 fixed-point notation*/
27 #define VOL_FORTIETH_ROOT_OF_TEN 69419
29 * Volume fractional word length define to 16 sets
30 * the volume linear gain value to use Qx.16 format
33 /* 0.5 dB step value in topology TLV */
34 #define VOL_HALF_DB_STEP 50
35 /* Full volume for default values */
36 #define VOL_ZERO_DB BIT(VOLUME_FWL)
44 /* size of tplg abi in byte */
45 #define SOF_TPLG_ABI_SIZE 3
47 struct sof_widget_data
{
50 struct sof_abi_hdr
*pdata
;
51 struct snd_sof_control
*control
;
54 /* send pcm params ipc */
55 static int ipc_pcm_params(struct snd_sof_widget
*swidget
, int dir
)
57 struct sof_ipc_pcm_params_reply ipc_params_reply
;
58 struct snd_soc_component
*scomp
= swidget
->scomp
;
59 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
60 struct sof_ipc_pcm_params pcm
;
61 struct snd_pcm_hw_params
*params
;
62 struct snd_sof_pcm
*spcm
;
65 memset(&pcm
, 0, sizeof(pcm
));
67 /* get runtime PCM params using widget's stream name */
68 spcm
= snd_sof_find_spcm_name(scomp
, swidget
->widget
->sname
);
70 dev_err(scomp
->dev
, "error: cannot find PCM for %s\n",
71 swidget
->widget
->name
);
75 params
= &spcm
->params
[dir
];
77 /* set IPC PCM params */
78 pcm
.hdr
.size
= sizeof(pcm
);
79 pcm
.hdr
.cmd
= SOF_IPC_GLB_STREAM_MSG
| SOF_IPC_STREAM_PCM_PARAMS
;
80 pcm
.comp_id
= swidget
->comp_id
;
81 pcm
.params
.hdr
.size
= sizeof(pcm
.params
);
82 pcm
.params
.direction
= dir
;
83 pcm
.params
.sample_valid_bytes
= params_width(params
) >> 3;
84 pcm
.params
.buffer_fmt
= SOF_IPC_BUFFER_INTERLEAVED
;
85 pcm
.params
.rate
= params_rate(params
);
86 pcm
.params
.channels
= params_channels(params
);
87 pcm
.params
.host_period_bytes
= params_period_bytes(params
);
90 switch (params_format(params
)) {
91 case SNDRV_PCM_FORMAT_S16
:
92 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S16_LE
;
94 case SNDRV_PCM_FORMAT_S24
:
95 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S24_4LE
;
97 case SNDRV_PCM_FORMAT_S32
:
98 pcm
.params
.frame_fmt
= SOF_IPC_FRAME_S32_LE
;
104 /* send IPC to the DSP */
105 ret
= sof_ipc_tx_message(sdev
->ipc
, pcm
.hdr
.cmd
, &pcm
, sizeof(pcm
),
106 &ipc_params_reply
, sizeof(ipc_params_reply
));
108 dev_err(scomp
->dev
, "error: pcm params failed for %s\n",
109 swidget
->widget
->name
);
114 /* send stream trigger ipc */
115 static int ipc_trigger(struct snd_sof_widget
*swidget
, int cmd
)
117 struct snd_soc_component
*scomp
= swidget
->scomp
;
118 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
119 struct sof_ipc_stream stream
;
120 struct sof_ipc_reply reply
;
123 /* set IPC stream params */
124 stream
.hdr
.size
= sizeof(stream
);
125 stream
.hdr
.cmd
= SOF_IPC_GLB_STREAM_MSG
| cmd
;
126 stream
.comp_id
= swidget
->comp_id
;
128 /* send IPC to the DSP */
129 ret
= sof_ipc_tx_message(sdev
->ipc
, stream
.hdr
.cmd
, &stream
,
130 sizeof(stream
), &reply
, sizeof(reply
));
132 dev_err(scomp
->dev
, "error: failed to trigger %s\n",
133 swidget
->widget
->name
);
138 static int sof_keyword_dapm_event(struct snd_soc_dapm_widget
*w
,
139 struct snd_kcontrol
*k
, int event
)
141 struct snd_sof_widget
*swidget
= w
->dobj
.private;
142 struct snd_soc_component
*scomp
;
143 int stream
= SNDRV_PCM_STREAM_CAPTURE
;
144 struct snd_sof_pcm
*spcm
;
150 scomp
= swidget
->scomp
;
152 dev_dbg(scomp
->dev
, "received event %d for widget %s\n",
155 /* get runtime PCM params using widget's stream name */
156 spcm
= snd_sof_find_spcm_name(scomp
, swidget
->widget
->sname
);
158 dev_err(scomp
->dev
, "error: cannot find PCM for %s\n",
159 swidget
->widget
->name
);
165 case SND_SOC_DAPM_PRE_PMU
:
166 if (spcm
->stream
[stream
].suspend_ignored
) {
167 dev_dbg(scomp
->dev
, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
172 ret
= ipc_pcm_params(swidget
, stream
);
175 "error: failed to set pcm params for widget %s\n",
176 swidget
->widget
->name
);
181 ret
= ipc_trigger(swidget
, SOF_IPC_STREAM_TRIG_START
);
184 "error: failed to trigger widget %s\n",
185 swidget
->widget
->name
);
187 case SND_SOC_DAPM_POST_PMD
:
188 if (spcm
->stream
[stream
].suspend_ignored
) {
189 dev_dbg(scomp
->dev
, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n");
194 ret
= ipc_trigger(swidget
, SOF_IPC_STREAM_TRIG_STOP
);
197 "error: failed to trigger widget %s\n",
198 swidget
->widget
->name
);
201 ret
= ipc_trigger(swidget
, SOF_IPC_STREAM_PCM_FREE
);
204 "error: failed to trigger widget %s\n",
205 swidget
->widget
->name
);
214 /* event handlers for keyword detect component */
215 static const struct snd_soc_tplg_widget_events sof_kwd_events
[] = {
216 {SOF_KEYWORD_DETECT_DAPM_EVENT
, sof_keyword_dapm_event
},
219 static inline int get_tlv_data(const int *p
, int tlv
[TLV_ITEMS
])
221 /* we only support dB scale TLV type at the moment */
222 if ((int)p
[SNDRV_CTL_TLVO_TYPE
] != SNDRV_CTL_TLVT_DB_SCALE
)
225 /* min value in topology tlv data is multiplied by 100 */
226 tlv
[TLV_MIN
] = (int)p
[SNDRV_CTL_TLVO_DB_SCALE_MIN
] / 100;
229 tlv
[TLV_STEP
] = (int)(p
[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP
] &
233 if ((p
[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP
] &
234 TLV_DB_SCALE_MUTE
) == 0)
243 * Function to truncate an unsigned 64-bit number
244 * by x bits and return 32-bit unsigned number. This
245 * function also takes care of rounding while truncating
247 static inline u32
vol_shift_64(u64 i
, u32 x
)
249 /* do not truncate more than 32 bits */
256 return (u32
)(((i
>> (x
- 1)) + 1) >> 1);
260 * Function to compute a ^ exp where,
261 * a is a fractional number represented by a fixed-point
262 * integer with a fractional world length of "fwl"
264 * fwl is the fractional word length
265 * Return value is a fractional number represented by a
266 * fixed-point integer with a fractional word length of "fwl"
268 static u32
vol_pow32(u32 a
, int exp
, u32 fwl
)
271 u32 power
= 1 << fwl
;
274 /* if exponent is 0, return 1 */
278 /* determine the number of iterations based on the exponent */
284 /* mutiply a "iter" times to compute power */
285 for (i
= 0; i
< iter
; i
++) {
287 * Product of 2 Qx.fwl fixed-point numbers yields a Q2*x.2*fwl
288 * Truncate product back to fwl fractional bits with rounding
290 power
= vol_shift_64((u64
)power
* a
, fwl
);
294 /* if exp is positive, return the result */
298 /* if exp is negative, return the multiplicative inverse */
299 numerator
= (u64
)1 << (fwl
<< 1);
300 do_div(numerator
, power
);
302 return (u32
)numerator
;
306 * Function to calculate volume gain from TLV data.
307 * This function can only handle gain steps that are multiples of 0.5 dB
309 static u32
vol_compute_gain(u32 value
, int *tlv
)
316 if (value
== 0 && tlv
[TLV_MUTE
])
320 * compute dB gain from tlv. tlv_step
321 * in topology is multiplied by 100
323 dB_gain
= tlv
[TLV_MIN
] + (value
* tlv
[TLV_STEP
]) / 100;
326 * compute linear gain represented by fixed-point
327 * int with VOLUME_FWL fractional bits
329 linear_gain
= vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN
, dB_gain
, VOLUME_FWL
);
331 /* extract the fractional part of volume step */
332 f_step
= tlv
[TLV_STEP
] - (tlv
[TLV_STEP
] / 100);
334 /* if volume step is an odd multiple of 0.5 dB */
335 if (f_step
== VOL_HALF_DB_STEP
&& (value
& 1))
336 linear_gain
= vol_shift_64((u64
)linear_gain
*
337 VOL_FORTIETH_ROOT_OF_TEN
,
344 * Set up volume table for kcontrols from tlv data
345 * "size" specifies the number of entries in the table
347 static int set_up_volume_table(struct snd_sof_control
*scontrol
,
348 int tlv
[TLV_ITEMS
], int size
)
352 /* init the volume table */
353 scontrol
->volume_table
= kcalloc(size
, sizeof(u32
), GFP_KERNEL
);
354 if (!scontrol
->volume_table
)
357 /* populate the volume table */
358 for (j
= 0; j
< size
; j
++)
359 scontrol
->volume_table
[j
] = vol_compute_gain(j
, tlv
);
364 struct sof_dai_types
{
366 enum sof_ipc_dai_type type
;
369 static const struct sof_dai_types sof_dais
[] = {
370 {"SSP", SOF_DAI_INTEL_SSP
},
371 {"HDA", SOF_DAI_INTEL_HDA
},
372 {"DMIC", SOF_DAI_INTEL_DMIC
},
373 {"ALH", SOF_DAI_INTEL_ALH
},
374 {"SAI", SOF_DAI_IMX_SAI
},
375 {"ESAI", SOF_DAI_IMX_ESAI
},
378 static enum sof_ipc_dai_type
find_dai(const char *name
)
382 for (i
= 0; i
< ARRAY_SIZE(sof_dais
); i
++) {
383 if (strcmp(name
, sof_dais
[i
].name
) == 0)
384 return sof_dais
[i
].type
;
387 return SOF_DAI_INTEL_NONE
;
391 * Supported Frame format types and lookup, add new ones to end of list.
394 struct sof_frame_types
{
396 enum sof_ipc_frame frame
;
399 static const struct sof_frame_types sof_frames
[] = {
400 {"s16le", SOF_IPC_FRAME_S16_LE
},
401 {"s24le", SOF_IPC_FRAME_S24_4LE
},
402 {"s32le", SOF_IPC_FRAME_S32_LE
},
403 {"float", SOF_IPC_FRAME_FLOAT
},
406 static enum sof_ipc_frame
find_format(const char *name
)
410 for (i
= 0; i
< ARRAY_SIZE(sof_frames
); i
++) {
411 if (strcmp(name
, sof_frames
[i
].name
) == 0)
412 return sof_frames
[i
].frame
;
415 /* use s32le if nothing is specified */
416 return SOF_IPC_FRAME_S32_LE
;
419 struct sof_process_types
{
421 enum sof_ipc_process_type type
;
422 enum sof_comp_type comp_type
;
425 static const struct sof_process_types sof_process
[] = {
426 {"EQFIR", SOF_PROCESS_EQFIR
, SOF_COMP_EQ_FIR
},
427 {"EQIIR", SOF_PROCESS_EQIIR
, SOF_COMP_EQ_IIR
},
428 {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT
, SOF_COMP_KEYWORD_DETECT
},
429 {"KPB", SOF_PROCESS_KPB
, SOF_COMP_KPB
},
430 {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR
, SOF_COMP_SELECTOR
},
431 {"MUX", SOF_PROCESS_MUX
, SOF_COMP_MUX
},
432 {"DEMUX", SOF_PROCESS_DEMUX
, SOF_COMP_DEMUX
},
435 static enum sof_ipc_process_type
find_process(const char *name
)
439 for (i
= 0; i
< ARRAY_SIZE(sof_process
); i
++) {
440 if (strcmp(name
, sof_process
[i
].name
) == 0)
441 return sof_process
[i
].type
;
444 return SOF_PROCESS_NONE
;
447 static enum sof_comp_type
find_process_comp_type(enum sof_ipc_process_type type
)
451 for (i
= 0; i
< ARRAY_SIZE(sof_process
); i
++) {
452 if (sof_process
[i
].type
== type
)
453 return sof_process
[i
].comp_type
;
456 return SOF_COMP_NONE
;
460 * Topology Token Parsing.
461 * New tokens should be added to headers and parsing tables below.
464 struct sof_topology_token
{
467 int (*get_token
)(void *elem
, void *object
, u32 offset
, u32 size
);
472 static int get_token_u32(void *elem
, void *object
, u32 offset
, u32 size
)
474 struct snd_soc_tplg_vendor_value_elem
*velem
= elem
;
475 u32
*val
= (u32
*)((u8
*)object
+ offset
);
477 *val
= le32_to_cpu(velem
->value
);
481 static int get_token_u16(void *elem
, void *object
, u32 offset
, u32 size
)
483 struct snd_soc_tplg_vendor_value_elem
*velem
= elem
;
484 u16
*val
= (u16
*)((u8
*)object
+ offset
);
486 *val
= (u16
)le32_to_cpu(velem
->value
);
490 static int get_token_comp_format(void *elem
, void *object
, u32 offset
, u32 size
)
492 struct snd_soc_tplg_vendor_string_elem
*velem
= elem
;
493 u32
*val
= (u32
*)((u8
*)object
+ offset
);
495 *val
= find_format(velem
->string
);
499 static int get_token_dai_type(void *elem
, void *object
, u32 offset
, u32 size
)
501 struct snd_soc_tplg_vendor_string_elem
*velem
= elem
;
502 u32
*val
= (u32
*)((u8
*)object
+ offset
);
504 *val
= find_dai(velem
->string
);
508 static int get_token_process_type(void *elem
, void *object
, u32 offset
,
511 struct snd_soc_tplg_vendor_string_elem
*velem
= elem
;
512 u32
*val
= (u32
*)((u8
*)object
+ offset
);
514 *val
= find_process(velem
->string
);
519 static const struct sof_topology_token buffer_tokens
[] = {
520 {SOF_TKN_BUF_SIZE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
521 offsetof(struct sof_ipc_buffer
, size
), 0},
522 {SOF_TKN_BUF_CAPS
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
523 offsetof(struct sof_ipc_buffer
, caps
), 0},
527 static const struct sof_topology_token dai_tokens
[] = {
528 {SOF_TKN_DAI_TYPE
, SND_SOC_TPLG_TUPLE_TYPE_STRING
, get_token_dai_type
,
529 offsetof(struct sof_ipc_comp_dai
, type
), 0},
530 {SOF_TKN_DAI_INDEX
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
531 offsetof(struct sof_ipc_comp_dai
, dai_index
), 0},
532 {SOF_TKN_DAI_DIRECTION
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
533 offsetof(struct sof_ipc_comp_dai
, direction
), 0},
537 static const struct sof_topology_token dai_link_tokens
[] = {
538 {SOF_TKN_DAI_TYPE
, SND_SOC_TPLG_TUPLE_TYPE_STRING
, get_token_dai_type
,
539 offsetof(struct sof_ipc_dai_config
, type
), 0},
540 {SOF_TKN_DAI_INDEX
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
541 offsetof(struct sof_ipc_dai_config
, dai_index
), 0},
545 static const struct sof_topology_token sched_tokens
[] = {
546 {SOF_TKN_SCHED_PERIOD
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
547 offsetof(struct sof_ipc_pipe_new
, period
), 0},
548 {SOF_TKN_SCHED_PRIORITY
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
549 offsetof(struct sof_ipc_pipe_new
, priority
), 0},
550 {SOF_TKN_SCHED_MIPS
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
551 offsetof(struct sof_ipc_pipe_new
, period_mips
), 0},
552 {SOF_TKN_SCHED_CORE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
553 offsetof(struct sof_ipc_pipe_new
, core
), 0},
554 {SOF_TKN_SCHED_FRAMES
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
555 offsetof(struct sof_ipc_pipe_new
, frames_per_sched
), 0},
556 {SOF_TKN_SCHED_TIME_DOMAIN
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
557 offsetof(struct sof_ipc_pipe_new
, time_domain
), 0},
561 static const struct sof_topology_token volume_tokens
[] = {
562 {SOF_TKN_VOLUME_RAMP_STEP_TYPE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
563 get_token_u32
, offsetof(struct sof_ipc_comp_volume
, ramp
), 0},
564 {SOF_TKN_VOLUME_RAMP_STEP_MS
,
565 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
566 offsetof(struct sof_ipc_comp_volume
, initial_ramp
), 0},
570 static const struct sof_topology_token src_tokens
[] = {
571 {SOF_TKN_SRC_RATE_IN
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
572 offsetof(struct sof_ipc_comp_src
, source_rate
), 0},
573 {SOF_TKN_SRC_RATE_OUT
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
574 offsetof(struct sof_ipc_comp_src
, sink_rate
), 0},
578 static const struct sof_topology_token asrc_tokens
[] = {
579 {SOF_TKN_ASRC_RATE_IN
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
580 offsetof(struct sof_ipc_comp_asrc
, source_rate
), 0},
581 {SOF_TKN_ASRC_RATE_OUT
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
582 offsetof(struct sof_ipc_comp_asrc
, sink_rate
), 0},
583 {SOF_TKN_ASRC_ASYNCHRONOUS_MODE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
585 offsetof(struct sof_ipc_comp_asrc
, asynchronous_mode
), 0},
586 {SOF_TKN_ASRC_OPERATION_MODE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
588 offsetof(struct sof_ipc_comp_asrc
, operation_mode
), 0},
592 static const struct sof_topology_token tone_tokens
[] = {
596 static const struct sof_topology_token process_tokens
[] = {
597 {SOF_TKN_PROCESS_TYPE
, SND_SOC_TPLG_TUPLE_TYPE_STRING
,
598 get_token_process_type
,
599 offsetof(struct sof_ipc_comp_process
, type
), 0},
603 static const struct sof_topology_token pcm_tokens
[] = {
604 {SOF_TKN_PCM_DMAC_CONFIG
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
605 offsetof(struct sof_ipc_comp_host
, dmac_config
), 0},
609 static const struct sof_topology_token stream_tokens
[] = {
610 {SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3
,
611 SND_SOC_TPLG_TUPLE_TYPE_BOOL
, get_token_u16
,
612 offsetof(struct snd_sof_pcm
, stream
[0].d0i3_compatible
), 0},
613 {SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3
,
614 SND_SOC_TPLG_TUPLE_TYPE_BOOL
, get_token_u16
,
615 offsetof(struct snd_sof_pcm
, stream
[1].d0i3_compatible
), 0},
618 /* Generic components */
619 static const struct sof_topology_token comp_tokens
[] = {
620 {SOF_TKN_COMP_PERIOD_SINK_COUNT
,
621 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
622 offsetof(struct sof_ipc_comp_config
, periods_sink
), 0},
623 {SOF_TKN_COMP_PERIOD_SOURCE_COUNT
,
624 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
625 offsetof(struct sof_ipc_comp_config
, periods_source
), 0},
626 {SOF_TKN_COMP_FORMAT
,
627 SND_SOC_TPLG_TUPLE_TYPE_STRING
, get_token_comp_format
,
628 offsetof(struct sof_ipc_comp_config
, frame_fmt
), 0},
632 static const struct sof_topology_token ssp_tokens
[] = {
633 {SOF_TKN_INTEL_SSP_CLKS_CONTROL
,
634 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
635 offsetof(struct sof_ipc_dai_ssp_params
, clks_control
), 0},
636 {SOF_TKN_INTEL_SSP_MCLK_ID
,
637 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
638 offsetof(struct sof_ipc_dai_ssp_params
, mclk_id
), 0},
639 {SOF_TKN_INTEL_SSP_SAMPLE_BITS
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
641 offsetof(struct sof_ipc_dai_ssp_params
, sample_valid_bits
), 0},
642 {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH
, SND_SOC_TPLG_TUPLE_TYPE_SHORT
,
644 offsetof(struct sof_ipc_dai_ssp_params
, frame_pulse_width
), 0},
645 {SOF_TKN_INTEL_SSP_QUIRKS
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
647 offsetof(struct sof_ipc_dai_ssp_params
, quirks
), 0},
648 {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT
, SND_SOC_TPLG_TUPLE_TYPE_BOOL
,
650 offsetof(struct sof_ipc_dai_ssp_params
,
651 tdm_per_slot_padding_flag
), 0},
652 {SOF_TKN_INTEL_SSP_BCLK_DELAY
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
654 offsetof(struct sof_ipc_dai_ssp_params
, bclk_delay
), 0},
659 static const struct sof_topology_token dmic_tokens
[] = {
660 {SOF_TKN_INTEL_DMIC_DRIVER_VERSION
,
661 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
662 offsetof(struct sof_ipc_dai_dmic_params
, driver_ipc_version
),
664 {SOF_TKN_INTEL_DMIC_CLK_MIN
,
665 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
666 offsetof(struct sof_ipc_dai_dmic_params
, pdmclk_min
), 0},
667 {SOF_TKN_INTEL_DMIC_CLK_MAX
,
668 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
669 offsetof(struct sof_ipc_dai_dmic_params
, pdmclk_max
), 0},
670 {SOF_TKN_INTEL_DMIC_SAMPLE_RATE
,
671 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
672 offsetof(struct sof_ipc_dai_dmic_params
, fifo_fs
), 0},
673 {SOF_TKN_INTEL_DMIC_DUTY_MIN
,
674 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
675 offsetof(struct sof_ipc_dai_dmic_params
, duty_min
), 0},
676 {SOF_TKN_INTEL_DMIC_DUTY_MAX
,
677 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
678 offsetof(struct sof_ipc_dai_dmic_params
, duty_max
), 0},
679 {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE
,
680 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
681 offsetof(struct sof_ipc_dai_dmic_params
,
683 {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH
,
684 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
685 offsetof(struct sof_ipc_dai_dmic_params
, fifo_bits
), 0},
686 {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS
,
687 SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
688 offsetof(struct sof_ipc_dai_dmic_params
, unmute_ramp_time
), 0},
693 static const struct sof_topology_token esai_tokens
[] = {
694 {SOF_TKN_IMX_ESAI_MCLK_ID
,
695 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
696 offsetof(struct sof_ipc_dai_esai_params
, mclk_id
), 0},
700 static const struct sof_topology_token sai_tokens
[] = {
701 {SOF_TKN_IMX_SAI_MCLK_ID
,
702 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
703 offsetof(struct sof_ipc_dai_sai_params
, mclk_id
), 0},
708 * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token
709 * as it increments the index while parsing the array of pdm tokens
710 * and determines the correct offset
712 static const struct sof_topology_token dmic_pdm_tokens
[] = {
713 {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID
,
714 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
715 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, id
),
717 {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable
,
718 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
719 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, enable_mic_a
),
721 {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable
,
722 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
723 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, enable_mic_b
),
725 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A
,
726 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
727 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, polarity_mic_a
),
729 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B
,
730 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
731 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, polarity_mic_b
),
733 {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE
,
734 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
735 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, clk_edge
),
737 {SOF_TKN_INTEL_DMIC_PDM_SKEW
,
738 SND_SOC_TPLG_TUPLE_TYPE_SHORT
, get_token_u16
,
739 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl
, skew
),
744 static const struct sof_topology_token hda_tokens
[] = {
748 static const struct sof_topology_token led_tokens
[] = {
749 {SOF_TKN_MUTE_LED_USE
, SND_SOC_TPLG_TUPLE_TYPE_WORD
, get_token_u32
,
750 offsetof(struct snd_sof_led_control
, use_led
), 0},
751 {SOF_TKN_MUTE_LED_DIRECTION
, SND_SOC_TPLG_TUPLE_TYPE_WORD
,
752 get_token_u32
, offsetof(struct snd_sof_led_control
, direction
), 0},
755 static void sof_parse_uuid_tokens(struct snd_soc_component
*scomp
,
757 const struct sof_topology_token
*tokens
,
759 struct snd_soc_tplg_vendor_array
*array
)
761 struct snd_soc_tplg_vendor_uuid_elem
*elem
;
764 /* parse element by element */
765 for (i
= 0; i
< le32_to_cpu(array
->num_elems
); i
++) {
766 elem
= &array
->uuid
[i
];
768 /* search for token */
769 for (j
= 0; j
< count
; j
++) {
770 /* match token type */
771 if (tokens
[j
].type
!= SND_SOC_TPLG_TUPLE_TYPE_UUID
)
775 if (tokens
[j
].token
!= le32_to_cpu(elem
->token
))
778 /* matched - now load token */
779 tokens
[j
].get_token(elem
, object
, tokens
[j
].offset
,
785 static void sof_parse_string_tokens(struct snd_soc_component
*scomp
,
787 const struct sof_topology_token
*tokens
,
789 struct snd_soc_tplg_vendor_array
*array
)
791 struct snd_soc_tplg_vendor_string_elem
*elem
;
794 /* parse element by element */
795 for (i
= 0; i
< le32_to_cpu(array
->num_elems
); i
++) {
796 elem
= &array
->string
[i
];
798 /* search for token */
799 for (j
= 0; j
< count
; j
++) {
800 /* match token type */
801 if (tokens
[j
].type
!= SND_SOC_TPLG_TUPLE_TYPE_STRING
)
805 if (tokens
[j
].token
!= le32_to_cpu(elem
->token
))
808 /* matched - now load token */
809 tokens
[j
].get_token(elem
, object
, tokens
[j
].offset
,
815 static void sof_parse_word_tokens(struct snd_soc_component
*scomp
,
817 const struct sof_topology_token
*tokens
,
819 struct snd_soc_tplg_vendor_array
*array
)
821 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
822 struct snd_soc_tplg_vendor_value_elem
*elem
;
823 size_t size
= sizeof(struct sof_ipc_dai_dmic_pdm_ctrl
);
828 /* parse element by element */
829 for (i
= 0; i
< le32_to_cpu(array
->num_elems
); i
++) {
830 elem
= &array
->value
[i
];
832 /* search for token */
833 for (j
= 0; j
< count
; j
++) {
834 /* match token type */
835 if (!(tokens
[j
].type
== SND_SOC_TPLG_TUPLE_TYPE_WORD
||
836 tokens
[j
].type
== SND_SOC_TPLG_TUPLE_TYPE_SHORT
||
837 tokens
[j
].type
== SND_SOC_TPLG_TUPLE_TYPE_BYTE
||
838 tokens
[j
].type
== SND_SOC_TPLG_TUPLE_TYPE_BOOL
))
842 if (tokens
[j
].token
!= le32_to_cpu(elem
->token
))
845 /* pdm config array index */
847 index
= sdev
->private;
849 /* matched - determine offset */
850 switch (tokens
[j
].token
) {
851 case SOF_TKN_INTEL_DMIC_PDM_CTRL_ID
:
853 /* inc number of pdm array index */
857 case SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable
:
858 case SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable
:
859 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_A
:
860 case SOF_TKN_INTEL_DMIC_PDM_POLARITY_B
:
861 case SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE
:
862 case SOF_TKN_INTEL_DMIC_PDM_SKEW
:
864 /* check if array index is valid */
865 if (!index
|| *index
== 0) {
867 "error: invalid array offset\n");
870 /* offset within the pdm config array */
871 offset
= size
* (*index
- 1);
880 tokens
[j
].get_token(elem
, object
,
881 offset
+ tokens
[j
].offset
,
887 static int sof_parse_tokens(struct snd_soc_component
*scomp
,
889 const struct sof_topology_token
*tokens
,
891 struct snd_soc_tplg_vendor_array
*array
,
896 while (priv_size
> 0) {
897 asize
= le32_to_cpu(array
->size
);
900 if (asize
< 0) { /* FIXME: A zero-size array makes no sense */
901 dev_err(scomp
->dev
, "error: invalid array size 0x%x\n",
906 /* make sure there is enough data before parsing */
909 dev_err(scomp
->dev
, "error: invalid array size 0x%x\n",
914 /* call correct parser depending on type */
915 switch (le32_to_cpu(array
->type
)) {
916 case SND_SOC_TPLG_TUPLE_TYPE_UUID
:
917 sof_parse_uuid_tokens(scomp
, object
, tokens
, count
,
920 case SND_SOC_TPLG_TUPLE_TYPE_STRING
:
921 sof_parse_string_tokens(scomp
, object
, tokens
, count
,
924 case SND_SOC_TPLG_TUPLE_TYPE_BOOL
:
925 case SND_SOC_TPLG_TUPLE_TYPE_BYTE
:
926 case SND_SOC_TPLG_TUPLE_TYPE_WORD
:
927 case SND_SOC_TPLG_TUPLE_TYPE_SHORT
:
928 sof_parse_word_tokens(scomp
, object
, tokens
, count
,
932 dev_err(scomp
->dev
, "error: unknown token type %d\n",
938 array
= (struct snd_soc_tplg_vendor_array
*)((u8
*)array
944 static void sof_dbg_comp_config(struct snd_soc_component
*scomp
,
945 struct sof_ipc_comp_config
*config
)
947 dev_dbg(scomp
->dev
, " config: periods snk %d src %d fmt %d\n",
948 config
->periods_sink
, config
->periods_source
,
953 * Standard Kcontrols.
956 static int sof_control_load_volume(struct snd_soc_component
*scomp
,
957 struct snd_sof_control
*scontrol
,
958 struct snd_kcontrol_new
*kc
,
959 struct snd_soc_tplg_ctl_hdr
*hdr
)
961 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
962 struct snd_soc_tplg_mixer_control
*mc
=
963 container_of(hdr
, struct snd_soc_tplg_mixer_control
, hdr
);
964 struct sof_ipc_ctrl_data
*cdata
;
969 /* validate topology data */
970 if (le32_to_cpu(mc
->num_channels
) > SND_SOC_TPLG_MAX_CHAN
) {
975 /* init the volume get/put data */
976 scontrol
->size
= struct_size(scontrol
->control_data
, chanv
,
977 le32_to_cpu(mc
->num_channels
));
978 scontrol
->control_data
= kzalloc(scontrol
->size
, GFP_KERNEL
);
979 if (!scontrol
->control_data
) {
984 scontrol
->comp_id
= sdev
->next_comp_id
;
985 scontrol
->min_volume_step
= le32_to_cpu(mc
->min
);
986 scontrol
->max_volume_step
= le32_to_cpu(mc
->max
);
987 scontrol
->num_channels
= le32_to_cpu(mc
->num_channels
);
989 /* set cmd for mixer control */
990 if (le32_to_cpu(mc
->max
) == 1) {
991 scontrol
->cmd
= SOF_CTRL_CMD_SWITCH
;
995 scontrol
->cmd
= SOF_CTRL_CMD_VOLUME
;
997 /* extract tlv data */
998 if (get_tlv_data(kc
->tlv
.p
, tlv
) < 0) {
999 dev_err(scomp
->dev
, "error: invalid TLV data\n");
1004 /* set up volume table */
1005 ret
= set_up_volume_table(scontrol
, tlv
, le32_to_cpu(mc
->max
) + 1);
1007 dev_err(scomp
->dev
, "error: setting up volume table\n");
1011 /* set default volume values to 0dB in control */
1012 cdata
= scontrol
->control_data
;
1013 for (i
= 0; i
< scontrol
->num_channels
; i
++) {
1014 cdata
->chanv
[i
].channel
= i
;
1015 cdata
->chanv
[i
].value
= VOL_ZERO_DB
;
1019 /* set up possible led control from mixer private data */
1020 ret
= sof_parse_tokens(scomp
, &scontrol
->led_ctl
, led_tokens
,
1021 ARRAY_SIZE(led_tokens
), mc
->priv
.array
,
1022 le32_to_cpu(mc
->priv
.size
));
1024 dev_err(scomp
->dev
, "error: parse led tokens failed %d\n",
1025 le32_to_cpu(mc
->priv
.size
));
1026 goto out_free_table
;
1029 dev_dbg(scomp
->dev
, "tplg: load kcontrol index %d chans %d\n",
1030 scontrol
->comp_id
, scontrol
->num_channels
);
1035 if (le32_to_cpu(mc
->max
) > 1)
1036 kfree(scontrol
->volume_table
);
1038 kfree(scontrol
->control_data
);
1043 static int sof_control_load_enum(struct snd_soc_component
*scomp
,
1044 struct snd_sof_control
*scontrol
,
1045 struct snd_kcontrol_new
*kc
,
1046 struct snd_soc_tplg_ctl_hdr
*hdr
)
1048 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1049 struct snd_soc_tplg_enum_control
*ec
=
1050 container_of(hdr
, struct snd_soc_tplg_enum_control
, hdr
);
1052 /* validate topology data */
1053 if (le32_to_cpu(ec
->num_channels
) > SND_SOC_TPLG_MAX_CHAN
)
1056 /* init the enum get/put data */
1057 scontrol
->size
= struct_size(scontrol
->control_data
, chanv
,
1058 le32_to_cpu(ec
->num_channels
));
1059 scontrol
->control_data
= kzalloc(scontrol
->size
, GFP_KERNEL
);
1060 if (!scontrol
->control_data
)
1063 scontrol
->comp_id
= sdev
->next_comp_id
;
1064 scontrol
->num_channels
= le32_to_cpu(ec
->num_channels
);
1066 scontrol
->cmd
= SOF_CTRL_CMD_ENUM
;
1068 dev_dbg(scomp
->dev
, "tplg: load kcontrol index %d chans %d comp_id %d\n",
1069 scontrol
->comp_id
, scontrol
->num_channels
, scontrol
->comp_id
);
1074 static int sof_control_load_bytes(struct snd_soc_component
*scomp
,
1075 struct snd_sof_control
*scontrol
,
1076 struct snd_kcontrol_new
*kc
,
1077 struct snd_soc_tplg_ctl_hdr
*hdr
)
1079 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1080 struct sof_ipc_ctrl_data
*cdata
;
1081 struct snd_soc_tplg_bytes_control
*control
=
1082 container_of(hdr
, struct snd_soc_tplg_bytes_control
, hdr
);
1083 struct soc_bytes_ext
*sbe
= (struct soc_bytes_ext
*)kc
->private_value
;
1084 int max_size
= sbe
->max
;
1087 /* init the get/put bytes data */
1088 scontrol
->size
= sizeof(struct sof_ipc_ctrl_data
) +
1089 le32_to_cpu(control
->priv
.size
);
1091 if (scontrol
->size
> max_size
) {
1092 dev_err(scomp
->dev
, "err: bytes data size %d exceeds max %d.\n",
1093 scontrol
->size
, max_size
);
1098 scontrol
->control_data
= kzalloc(max_size
, GFP_KERNEL
);
1099 cdata
= scontrol
->control_data
;
1100 if (!scontrol
->control_data
) {
1105 scontrol
->comp_id
= sdev
->next_comp_id
;
1106 scontrol
->cmd
= SOF_CTRL_CMD_BINARY
;
1108 dev_dbg(scomp
->dev
, "tplg: load kcontrol index %d chans %d\n",
1109 scontrol
->comp_id
, scontrol
->num_channels
);
1111 if (le32_to_cpu(control
->priv
.size
) > 0) {
1112 memcpy(cdata
->data
, control
->priv
.data
,
1113 le32_to_cpu(control
->priv
.size
));
1115 if (cdata
->data
->magic
!= SOF_ABI_MAGIC
) {
1116 dev_err(scomp
->dev
, "error: Wrong ABI magic 0x%08x.\n",
1117 cdata
->data
->magic
);
1121 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION
,
1122 cdata
->data
->abi
)) {
1124 "error: Incompatible ABI version 0x%08x.\n",
1129 if (cdata
->data
->size
+ sizeof(const struct sof_abi_hdr
) !=
1130 le32_to_cpu(control
->priv
.size
)) {
1132 "error: Conflict in bytes vs. priv size.\n");
1141 kfree(scontrol
->control_data
);
1146 /* external kcontrol init - used for any driver specific init */
1147 static int sof_control_load(struct snd_soc_component
*scomp
, int index
,
1148 struct snd_kcontrol_new
*kc
,
1149 struct snd_soc_tplg_ctl_hdr
*hdr
)
1151 struct soc_mixer_control
*sm
;
1152 struct soc_bytes_ext
*sbe
;
1153 struct soc_enum
*se
;
1154 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1155 struct snd_soc_dobj
*dobj
;
1156 struct snd_sof_control
*scontrol
;
1159 dev_dbg(scomp
->dev
, "tplg: load control type %d name : %s\n",
1160 hdr
->type
, hdr
->name
);
1162 scontrol
= kzalloc(sizeof(*scontrol
), GFP_KERNEL
);
1166 scontrol
->scomp
= scomp
;
1168 switch (le32_to_cpu(hdr
->ops
.info
)) {
1169 case SND_SOC_TPLG_CTL_VOLSW
:
1170 case SND_SOC_TPLG_CTL_VOLSW_SX
:
1171 case SND_SOC_TPLG_CTL_VOLSW_XR_SX
:
1172 sm
= (struct soc_mixer_control
*)kc
->private_value
;
1174 ret
= sof_control_load_volume(scomp
, scontrol
, kc
, hdr
);
1176 case SND_SOC_TPLG_CTL_BYTES
:
1177 sbe
= (struct soc_bytes_ext
*)kc
->private_value
;
1179 ret
= sof_control_load_bytes(scomp
, scontrol
, kc
, hdr
);
1181 case SND_SOC_TPLG_CTL_ENUM
:
1182 case SND_SOC_TPLG_CTL_ENUM_VALUE
:
1183 se
= (struct soc_enum
*)kc
->private_value
;
1185 ret
= sof_control_load_enum(scomp
, scontrol
, kc
, hdr
);
1187 case SND_SOC_TPLG_CTL_RANGE
:
1188 case SND_SOC_TPLG_CTL_STROBE
:
1189 case SND_SOC_TPLG_DAPM_CTL_VOLSW
:
1190 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE
:
1191 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT
:
1192 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE
:
1193 case SND_SOC_TPLG_DAPM_CTL_PIN
:
1195 dev_warn(scomp
->dev
, "control type not supported %d:%d:%d\n",
1196 hdr
->ops
.get
, hdr
->ops
.put
, hdr
->ops
.info
);
1206 dobj
->private = scontrol
;
1207 list_add(&scontrol
->list
, &sdev
->kcontrol_list
);
1211 static int sof_control_unload(struct snd_soc_component
*scomp
,
1212 struct snd_soc_dobj
*dobj
)
1214 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1215 struct sof_ipc_free fcomp
;
1216 struct snd_sof_control
*scontrol
= dobj
->private;
1218 dev_dbg(scomp
->dev
, "tplg: unload control name : %s\n", scomp
->name
);
1220 fcomp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_FREE
;
1221 fcomp
.hdr
.size
= sizeof(fcomp
);
1222 fcomp
.id
= scontrol
->comp_id
;
1224 kfree(scontrol
->control_data
);
1225 list_del(&scontrol
->list
);
1227 /* send IPC to the DSP */
1228 return sof_ipc_tx_message(sdev
->ipc
,
1229 fcomp
.hdr
.cmd
, &fcomp
, sizeof(fcomp
),
1237 static int sof_connect_dai_widget(struct snd_soc_component
*scomp
,
1238 struct snd_soc_dapm_widget
*w
,
1239 struct snd_soc_tplg_dapm_widget
*tw
,
1240 struct snd_sof_dai
*dai
)
1242 struct snd_soc_card
*card
= scomp
->card
;
1243 struct snd_soc_pcm_runtime
*rtd
;
1244 struct snd_soc_dai
*cpu_dai
;
1247 list_for_each_entry(rtd
, &card
->rtd_list
, list
) {
1248 dev_vdbg(scomp
->dev
, "tplg: check widget: %s stream: %s dai stream: %s\n",
1249 w
->name
, w
->sname
, rtd
->dai_link
->stream_name
);
1251 if (!w
->sname
|| !rtd
->dai_link
->stream_name
)
1254 /* does stream match DAI link ? */
1255 if (strcmp(w
->sname
, rtd
->dai_link
->stream_name
))
1259 case snd_soc_dapm_dai_out
:
1260 for_each_rtd_cpu_dais(rtd
, i
, cpu_dai
)
1261 cpu_dai
->capture_widget
= w
;
1262 dai
->name
= rtd
->dai_link
->name
;
1263 dev_dbg(scomp
->dev
, "tplg: connected widget %s -> DAI link %s\n",
1264 w
->name
, rtd
->dai_link
->name
);
1266 case snd_soc_dapm_dai_in
:
1267 for_each_rtd_cpu_dais(rtd
, i
, cpu_dai
)
1268 cpu_dai
->playback_widget
= w
;
1269 dai
->name
= rtd
->dai_link
->name
;
1270 dev_dbg(scomp
->dev
, "tplg: connected widget %s -> DAI link %s\n",
1271 w
->name
, rtd
->dai_link
->name
);
1278 /* check we have a connection */
1280 dev_err(scomp
->dev
, "error: can't connect DAI %s stream %s\n",
1288 static int sof_widget_load_dai(struct snd_soc_component
*scomp
, int index
,
1289 struct snd_sof_widget
*swidget
,
1290 struct snd_soc_tplg_dapm_widget
*tw
,
1291 struct sof_ipc_comp_reply
*r
,
1292 struct snd_sof_dai
*dai
)
1294 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1295 struct snd_soc_tplg_private
*private = &tw
->priv
;
1296 struct sof_ipc_comp_dai comp_dai
;
1299 /* configure dai IPC message */
1300 memset(&comp_dai
, 0, sizeof(comp_dai
));
1301 comp_dai
.comp
.hdr
.size
= sizeof(comp_dai
);
1302 comp_dai
.comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1303 comp_dai
.comp
.id
= swidget
->comp_id
;
1304 comp_dai
.comp
.type
= SOF_COMP_DAI
;
1305 comp_dai
.comp
.pipeline_id
= index
;
1306 comp_dai
.config
.hdr
.size
= sizeof(comp_dai
.config
);
1308 ret
= sof_parse_tokens(scomp
, &comp_dai
, dai_tokens
,
1309 ARRAY_SIZE(dai_tokens
), private->array
,
1310 le32_to_cpu(private->size
));
1312 dev_err(scomp
->dev
, "error: parse dai tokens failed %d\n",
1313 le32_to_cpu(private->size
));
1317 ret
= sof_parse_tokens(scomp
, &comp_dai
.config
, comp_tokens
,
1318 ARRAY_SIZE(comp_tokens
), private->array
,
1319 le32_to_cpu(private->size
));
1321 dev_err(scomp
->dev
, "error: parse dai.cfg tokens failed %d\n",
1326 dev_dbg(scomp
->dev
, "dai %s: type %d index %d\n",
1327 swidget
->widget
->name
, comp_dai
.type
, comp_dai
.dai_index
);
1328 sof_dbg_comp_config(scomp
, &comp_dai
.config
);
1330 ret
= sof_ipc_tx_message(sdev
->ipc
, comp_dai
.comp
.hdr
.cmd
,
1331 &comp_dai
, sizeof(comp_dai
), r
, sizeof(*r
));
1333 if (ret
== 0 && dai
) {
1335 memcpy(&dai
->comp_dai
, &comp_dai
, sizeof(comp_dai
));
1345 static int sof_widget_load_buffer(struct snd_soc_component
*scomp
, int index
,
1346 struct snd_sof_widget
*swidget
,
1347 struct snd_soc_tplg_dapm_widget
*tw
,
1348 struct sof_ipc_comp_reply
*r
)
1350 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1351 struct snd_soc_tplg_private
*private = &tw
->priv
;
1352 struct sof_ipc_buffer
*buffer
;
1355 buffer
= kzalloc(sizeof(*buffer
), GFP_KERNEL
);
1359 /* configure dai IPC message */
1360 buffer
->comp
.hdr
.size
= sizeof(*buffer
);
1361 buffer
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_BUFFER_NEW
;
1362 buffer
->comp
.id
= swidget
->comp_id
;
1363 buffer
->comp
.type
= SOF_COMP_BUFFER
;
1364 buffer
->comp
.pipeline_id
= index
;
1366 ret
= sof_parse_tokens(scomp
, buffer
, buffer_tokens
,
1367 ARRAY_SIZE(buffer_tokens
), private->array
,
1368 le32_to_cpu(private->size
));
1370 dev_err(scomp
->dev
, "error: parse buffer tokens failed %d\n",
1376 dev_dbg(scomp
->dev
, "buffer %s: size %d caps 0x%x\n",
1377 swidget
->widget
->name
, buffer
->size
, buffer
->caps
);
1379 swidget
->private = buffer
;
1381 ret
= sof_ipc_tx_message(sdev
->ipc
, buffer
->comp
.hdr
.cmd
, buffer
,
1382 sizeof(*buffer
), r
, sizeof(*r
));
1384 dev_err(scomp
->dev
, "error: buffer %s load failed\n",
1385 swidget
->widget
->name
);
1392 /* bind PCM ID to host component ID */
1393 static int spcm_bind(struct snd_soc_component
*scomp
, struct snd_sof_pcm
*spcm
,
1396 struct snd_sof_widget
*host_widget
;
1398 host_widget
= snd_sof_find_swidget_sname(scomp
,
1399 spcm
->pcm
.caps
[dir
].name
,
1402 dev_err(scomp
->dev
, "can't find host comp to bind pcm\n");
1406 spcm
->stream
[dir
].comp_id
= host_widget
->comp_id
;
1415 static int sof_widget_load_pcm(struct snd_soc_component
*scomp
, int index
,
1416 struct snd_sof_widget
*swidget
,
1417 enum sof_ipc_stream_direction dir
,
1418 struct snd_soc_tplg_dapm_widget
*tw
,
1419 struct sof_ipc_comp_reply
*r
)
1421 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1422 struct snd_soc_tplg_private
*private = &tw
->priv
;
1423 struct sof_ipc_comp_host
*host
;
1426 host
= kzalloc(sizeof(*host
), GFP_KERNEL
);
1430 /* configure host comp IPC message */
1431 host
->comp
.hdr
.size
= sizeof(*host
);
1432 host
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1433 host
->comp
.id
= swidget
->comp_id
;
1434 host
->comp
.type
= SOF_COMP_HOST
;
1435 host
->comp
.pipeline_id
= index
;
1436 host
->direction
= dir
;
1437 host
->config
.hdr
.size
= sizeof(host
->config
);
1439 ret
= sof_parse_tokens(scomp
, host
, pcm_tokens
,
1440 ARRAY_SIZE(pcm_tokens
), private->array
,
1441 le32_to_cpu(private->size
));
1443 dev_err(scomp
->dev
, "error: parse host tokens failed %d\n",
1448 ret
= sof_parse_tokens(scomp
, &host
->config
, comp_tokens
,
1449 ARRAY_SIZE(comp_tokens
), private->array
,
1450 le32_to_cpu(private->size
));
1452 dev_err(scomp
->dev
, "error: parse host.cfg tokens failed %d\n",
1453 le32_to_cpu(private->size
));
1457 dev_dbg(scomp
->dev
, "loaded host %s\n", swidget
->widget
->name
);
1458 sof_dbg_comp_config(scomp
, &host
->config
);
1460 swidget
->private = host
;
1462 ret
= sof_ipc_tx_message(sdev
->ipc
, host
->comp
.hdr
.cmd
, host
,
1463 sizeof(*host
), r
, sizeof(*r
));
1474 int sof_load_pipeline_ipc(struct device
*dev
,
1475 struct sof_ipc_pipe_new
*pipeline
,
1476 struct sof_ipc_comp_reply
*r
)
1478 struct snd_sof_dev
*sdev
= dev_get_drvdata(dev
);
1479 struct sof_ipc_pm_core_config pm_core_config
;
1482 ret
= sof_ipc_tx_message(sdev
->ipc
, pipeline
->hdr
.cmd
, pipeline
,
1483 sizeof(*pipeline
), r
, sizeof(*r
));
1485 dev_err(dev
, "error: load pipeline ipc failure\n");
1489 /* power up the core that this pipeline is scheduled on */
1490 ret
= snd_sof_dsp_core_power_up(sdev
, 1 << pipeline
->core
);
1492 dev_err(dev
, "error: powering up pipeline schedule core %d\n",
1497 /* update enabled cores mask */
1498 sdev
->enabled_cores_mask
|= 1 << pipeline
->core
;
1501 * Now notify DSP that the core that this pipeline is scheduled on
1502 * has been powered up
1504 memset(&pm_core_config
, 0, sizeof(pm_core_config
));
1505 pm_core_config
.enable_mask
= sdev
->enabled_cores_mask
;
1507 /* configure CORE_ENABLE ipc message */
1508 pm_core_config
.hdr
.size
= sizeof(pm_core_config
);
1509 pm_core_config
.hdr
.cmd
= SOF_IPC_GLB_PM_MSG
| SOF_IPC_PM_CORE_ENABLE
;
1512 ret
= sof_ipc_tx_message(sdev
->ipc
, pm_core_config
.hdr
.cmd
,
1513 &pm_core_config
, sizeof(pm_core_config
),
1514 &pm_core_config
, sizeof(pm_core_config
));
1516 dev_err(dev
, "error: core enable ipc failure\n");
1521 static int sof_widget_load_pipeline(struct snd_soc_component
*scomp
,
1522 int index
, struct snd_sof_widget
*swidget
,
1523 struct snd_soc_tplg_dapm_widget
*tw
,
1524 struct sof_ipc_comp_reply
*r
)
1526 struct snd_soc_tplg_private
*private = &tw
->priv
;
1527 struct sof_ipc_pipe_new
*pipeline
;
1528 struct snd_sof_widget
*comp_swidget
;
1531 pipeline
= kzalloc(sizeof(*pipeline
), GFP_KERNEL
);
1535 /* configure dai IPC message */
1536 pipeline
->hdr
.size
= sizeof(*pipeline
);
1537 pipeline
->hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_PIPE_NEW
;
1538 pipeline
->pipeline_id
= index
;
1539 pipeline
->comp_id
= swidget
->comp_id
;
1541 /* component at start of pipeline is our stream id */
1542 comp_swidget
= snd_sof_find_swidget(scomp
, tw
->sname
);
1543 if (!comp_swidget
) {
1544 dev_err(scomp
->dev
, "error: widget %s refers to non existent widget %s\n",
1545 tw
->name
, tw
->sname
);
1550 pipeline
->sched_id
= comp_swidget
->comp_id
;
1552 dev_dbg(scomp
->dev
, "tplg: pipeline id %d comp %d scheduling comp id %d\n",
1553 pipeline
->pipeline_id
, pipeline
->comp_id
, pipeline
->sched_id
);
1555 ret
= sof_parse_tokens(scomp
, pipeline
, sched_tokens
,
1556 ARRAY_SIZE(sched_tokens
), private->array
,
1557 le32_to_cpu(private->size
));
1559 dev_err(scomp
->dev
, "error: parse pipeline tokens failed %d\n",
1564 dev_dbg(scomp
->dev
, "pipeline %s: period %d pri %d mips %d core %d frames %d\n",
1565 swidget
->widget
->name
, pipeline
->period
, pipeline
->priority
,
1566 pipeline
->period_mips
, pipeline
->core
, pipeline
->frames_per_sched
);
1568 swidget
->private = pipeline
;
1570 /* send ipc's to create pipeline comp and power up schedule core */
1571 ret
= sof_load_pipeline_ipc(scomp
->dev
, pipeline
, r
);
1583 static int sof_widget_load_mixer(struct snd_soc_component
*scomp
, int index
,
1584 struct snd_sof_widget
*swidget
,
1585 struct snd_soc_tplg_dapm_widget
*tw
,
1586 struct sof_ipc_comp_reply
*r
)
1588 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1589 struct snd_soc_tplg_private
*private = &tw
->priv
;
1590 struct sof_ipc_comp_mixer
*mixer
;
1593 mixer
= kzalloc(sizeof(*mixer
), GFP_KERNEL
);
1597 /* configure mixer IPC message */
1598 mixer
->comp
.hdr
.size
= sizeof(*mixer
);
1599 mixer
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1600 mixer
->comp
.id
= swidget
->comp_id
;
1601 mixer
->comp
.type
= SOF_COMP_MIXER
;
1602 mixer
->comp
.pipeline_id
= index
;
1603 mixer
->config
.hdr
.size
= sizeof(mixer
->config
);
1605 ret
= sof_parse_tokens(scomp
, &mixer
->config
, comp_tokens
,
1606 ARRAY_SIZE(comp_tokens
), private->array
,
1607 le32_to_cpu(private->size
));
1609 dev_err(scomp
->dev
, "error: parse mixer.cfg tokens failed %d\n",
1615 sof_dbg_comp_config(scomp
, &mixer
->config
);
1617 swidget
->private = mixer
;
1619 ret
= sof_ipc_tx_message(sdev
->ipc
, mixer
->comp
.hdr
.cmd
, mixer
,
1620 sizeof(*mixer
), r
, sizeof(*r
));
1630 static int sof_widget_load_mux(struct snd_soc_component
*scomp
, int index
,
1631 struct snd_sof_widget
*swidget
,
1632 struct snd_soc_tplg_dapm_widget
*tw
,
1633 struct sof_ipc_comp_reply
*r
)
1635 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1636 struct snd_soc_tplg_private
*private = &tw
->priv
;
1637 struct sof_ipc_comp_mux
*mux
;
1640 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
1644 /* configure mux IPC message */
1645 mux
->comp
.hdr
.size
= sizeof(*mux
);
1646 mux
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1647 mux
->comp
.id
= swidget
->comp_id
;
1648 mux
->comp
.type
= SOF_COMP_MUX
;
1649 mux
->comp
.pipeline_id
= index
;
1650 mux
->config
.hdr
.size
= sizeof(mux
->config
);
1652 ret
= sof_parse_tokens(scomp
, &mux
->config
, comp_tokens
,
1653 ARRAY_SIZE(comp_tokens
), private->array
,
1654 le32_to_cpu(private->size
));
1656 dev_err(scomp
->dev
, "error: parse mux.cfg tokens failed %d\n",
1662 sof_dbg_comp_config(scomp
, &mux
->config
);
1664 swidget
->private = mux
;
1666 ret
= sof_ipc_tx_message(sdev
->ipc
, mux
->comp
.hdr
.cmd
, mux
,
1667 sizeof(*mux
), r
, sizeof(*r
));
1678 static int sof_widget_load_pga(struct snd_soc_component
*scomp
, int index
,
1679 struct snd_sof_widget
*swidget
,
1680 struct snd_soc_tplg_dapm_widget
*tw
,
1681 struct sof_ipc_comp_reply
*r
)
1683 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1684 struct snd_soc_tplg_private
*private = &tw
->priv
;
1685 struct sof_ipc_comp_volume
*volume
;
1686 struct snd_sof_control
*scontrol
;
1691 volume
= kzalloc(sizeof(*volume
), GFP_KERNEL
);
1695 if (!le32_to_cpu(tw
->num_kcontrols
)) {
1696 dev_err(scomp
->dev
, "error: invalid kcontrol count %d for volume\n",
1702 /* configure volume IPC message */
1703 volume
->comp
.hdr
.size
= sizeof(*volume
);
1704 volume
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1705 volume
->comp
.id
= swidget
->comp_id
;
1706 volume
->comp
.type
= SOF_COMP_VOLUME
;
1707 volume
->comp
.pipeline_id
= index
;
1708 volume
->config
.hdr
.size
= sizeof(volume
->config
);
1710 ret
= sof_parse_tokens(scomp
, volume
, volume_tokens
,
1711 ARRAY_SIZE(volume_tokens
), private->array
,
1712 le32_to_cpu(private->size
));
1714 dev_err(scomp
->dev
, "error: parse volume tokens failed %d\n",
1718 ret
= sof_parse_tokens(scomp
, &volume
->config
, comp_tokens
,
1719 ARRAY_SIZE(comp_tokens
), private->array
,
1720 le32_to_cpu(private->size
));
1722 dev_err(scomp
->dev
, "error: parse volume.cfg tokens failed %d\n",
1723 le32_to_cpu(private->size
));
1727 sof_dbg_comp_config(scomp
, &volume
->config
);
1729 swidget
->private = volume
;
1731 list_for_each_entry(scontrol
, &sdev
->kcontrol_list
, list
) {
1732 if (scontrol
->comp_id
== swidget
->comp_id
&&
1733 scontrol
->volume_table
) {
1734 min_step
= scontrol
->min_volume_step
;
1735 max_step
= scontrol
->max_volume_step
;
1736 volume
->min_value
= scontrol
->volume_table
[min_step
];
1737 volume
->max_value
= scontrol
->volume_table
[max_step
];
1738 volume
->channels
= scontrol
->num_channels
;
1743 ret
= sof_ipc_tx_message(sdev
->ipc
, volume
->comp
.hdr
.cmd
, volume
,
1744 sizeof(*volume
), r
, sizeof(*r
));
1756 static int sof_widget_load_src(struct snd_soc_component
*scomp
, int index
,
1757 struct snd_sof_widget
*swidget
,
1758 struct snd_soc_tplg_dapm_widget
*tw
,
1759 struct sof_ipc_comp_reply
*r
)
1761 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1762 struct snd_soc_tplg_private
*private = &tw
->priv
;
1763 struct sof_ipc_comp_src
*src
;
1766 src
= kzalloc(sizeof(*src
), GFP_KERNEL
);
1770 /* configure src IPC message */
1771 src
->comp
.hdr
.size
= sizeof(*src
);
1772 src
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1773 src
->comp
.id
= swidget
->comp_id
;
1774 src
->comp
.type
= SOF_COMP_SRC
;
1775 src
->comp
.pipeline_id
= index
;
1776 src
->config
.hdr
.size
= sizeof(src
->config
);
1778 ret
= sof_parse_tokens(scomp
, src
, src_tokens
,
1779 ARRAY_SIZE(src_tokens
), private->array
,
1780 le32_to_cpu(private->size
));
1782 dev_err(scomp
->dev
, "error: parse src tokens failed %d\n",
1787 ret
= sof_parse_tokens(scomp
, &src
->config
, comp_tokens
,
1788 ARRAY_SIZE(comp_tokens
), private->array
,
1789 le32_to_cpu(private->size
));
1791 dev_err(scomp
->dev
, "error: parse src.cfg tokens failed %d\n",
1792 le32_to_cpu(private->size
));
1796 dev_dbg(scomp
->dev
, "src %s: source rate %d sink rate %d\n",
1797 swidget
->widget
->name
, src
->source_rate
, src
->sink_rate
);
1798 sof_dbg_comp_config(scomp
, &src
->config
);
1800 swidget
->private = src
;
1802 ret
= sof_ipc_tx_message(sdev
->ipc
, src
->comp
.hdr
.cmd
, src
,
1803 sizeof(*src
), r
, sizeof(*r
));
1815 static int sof_widget_load_asrc(struct snd_soc_component
*scomp
, int index
,
1816 struct snd_sof_widget
*swidget
,
1817 struct snd_soc_tplg_dapm_widget
*tw
,
1818 struct sof_ipc_comp_reply
*r
)
1820 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1821 struct snd_soc_tplg_private
*private = &tw
->priv
;
1822 struct sof_ipc_comp_asrc
*asrc
;
1825 asrc
= kzalloc(sizeof(*asrc
), GFP_KERNEL
);
1829 /* configure ASRC IPC message */
1830 asrc
->comp
.hdr
.size
= sizeof(*asrc
);
1831 asrc
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1832 asrc
->comp
.id
= swidget
->comp_id
;
1833 asrc
->comp
.type
= SOF_COMP_ASRC
;
1834 asrc
->comp
.pipeline_id
= index
;
1835 asrc
->config
.hdr
.size
= sizeof(asrc
->config
);
1837 ret
= sof_parse_tokens(scomp
, asrc
, asrc_tokens
,
1838 ARRAY_SIZE(asrc_tokens
), private->array
,
1839 le32_to_cpu(private->size
));
1841 dev_err(scomp
->dev
, "error: parse asrc tokens failed %d\n",
1846 ret
= sof_parse_tokens(scomp
, &asrc
->config
, comp_tokens
,
1847 ARRAY_SIZE(comp_tokens
), private->array
,
1848 le32_to_cpu(private->size
));
1850 dev_err(scomp
->dev
, "error: parse asrc.cfg tokens failed %d\n",
1851 le32_to_cpu(private->size
));
1855 dev_dbg(scomp
->dev
, "asrc %s: source rate %d sink rate %d "
1856 "asynch %d operation %d\n",
1857 swidget
->widget
->name
, asrc
->source_rate
, asrc
->sink_rate
,
1858 asrc
->asynchronous_mode
, asrc
->operation_mode
);
1859 sof_dbg_comp_config(scomp
, &asrc
->config
);
1861 swidget
->private = asrc
;
1863 ret
= sof_ipc_tx_message(sdev
->ipc
, asrc
->comp
.hdr
.cmd
, asrc
,
1864 sizeof(*asrc
), r
, sizeof(*r
));
1873 * Signal Generator Topology
1876 static int sof_widget_load_siggen(struct snd_soc_component
*scomp
, int index
,
1877 struct snd_sof_widget
*swidget
,
1878 struct snd_soc_tplg_dapm_widget
*tw
,
1879 struct sof_ipc_comp_reply
*r
)
1881 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
1882 struct snd_soc_tplg_private
*private = &tw
->priv
;
1883 struct sof_ipc_comp_tone
*tone
;
1886 tone
= kzalloc(sizeof(*tone
), GFP_KERNEL
);
1890 /* configure siggen IPC message */
1891 tone
->comp
.hdr
.size
= sizeof(*tone
);
1892 tone
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
1893 tone
->comp
.id
= swidget
->comp_id
;
1894 tone
->comp
.type
= SOF_COMP_TONE
;
1895 tone
->comp
.pipeline_id
= index
;
1896 tone
->config
.hdr
.size
= sizeof(tone
->config
);
1898 ret
= sof_parse_tokens(scomp
, tone
, tone_tokens
,
1899 ARRAY_SIZE(tone_tokens
), private->array
,
1900 le32_to_cpu(private->size
));
1902 dev_err(scomp
->dev
, "error: parse tone tokens failed %d\n",
1903 le32_to_cpu(private->size
));
1907 ret
= sof_parse_tokens(scomp
, &tone
->config
, comp_tokens
,
1908 ARRAY_SIZE(comp_tokens
), private->array
,
1909 le32_to_cpu(private->size
));
1911 dev_err(scomp
->dev
, "error: parse tone.cfg tokens failed %d\n",
1912 le32_to_cpu(private->size
));
1916 dev_dbg(scomp
->dev
, "tone %s: frequency %d amplitude %d\n",
1917 swidget
->widget
->name
, tone
->frequency
, tone
->amplitude
);
1918 sof_dbg_comp_config(scomp
, &tone
->config
);
1920 swidget
->private = tone
;
1922 ret
= sof_ipc_tx_message(sdev
->ipc
, tone
->comp
.hdr
.cmd
, tone
,
1923 sizeof(*tone
), r
, sizeof(*r
));
1931 static int sof_get_control_data(struct snd_soc_component
*scomp
,
1932 struct snd_soc_dapm_widget
*widget
,
1933 struct sof_widget_data
*wdata
,
1936 const struct snd_kcontrol_new
*kc
;
1937 struct soc_mixer_control
*sm
;
1938 struct soc_bytes_ext
*sbe
;
1939 struct soc_enum
*se
;
1944 for (i
= 0; i
< widget
->num_kcontrols
; i
++) {
1945 kc
= &widget
->kcontrol_news
[i
];
1947 switch (widget
->dobj
.widget
.kcontrol_type
) {
1948 case SND_SOC_TPLG_TYPE_MIXER
:
1949 sm
= (struct soc_mixer_control
*)kc
->private_value
;
1950 wdata
[i
].control
= sm
->dobj
.private;
1952 case SND_SOC_TPLG_TYPE_BYTES
:
1953 sbe
= (struct soc_bytes_ext
*)kc
->private_value
;
1954 wdata
[i
].control
= sbe
->dobj
.private;
1956 case SND_SOC_TPLG_TYPE_ENUM
:
1957 se
= (struct soc_enum
*)kc
->private_value
;
1958 wdata
[i
].control
= se
->dobj
.private;
1961 dev_err(scomp
->dev
, "error: unknown kcontrol type %d in widget %s\n",
1962 widget
->dobj
.widget
.kcontrol_type
,
1967 if (!wdata
[i
].control
) {
1968 dev_err(scomp
->dev
, "error: no scontrol for widget %s\n",
1973 wdata
[i
].pdata
= wdata
[i
].control
->control_data
->data
;
1974 if (!wdata
[i
].pdata
)
1977 /* make sure data is valid - data can be updated at runtime */
1978 if (wdata
[i
].pdata
->magic
!= SOF_ABI_MAGIC
)
1981 *size
+= wdata
[i
].pdata
->size
;
1984 switch (wdata
[i
].control
->cmd
) {
1985 case SOF_CTRL_CMD_VOLUME
:
1986 case SOF_CTRL_CMD_ENUM
:
1987 case SOF_CTRL_CMD_SWITCH
:
1988 wdata
[i
].ipc_cmd
= SOF_IPC_COMP_SET_VALUE
;
1989 wdata
[i
].ctrl_type
= SOF_CTRL_TYPE_VALUE_CHAN_SET
;
1991 case SOF_CTRL_CMD_BINARY
:
1992 wdata
[i
].ipc_cmd
= SOF_IPC_COMP_SET_DATA
;
1993 wdata
[i
].ctrl_type
= SOF_CTRL_TYPE_DATA_SET
;
2003 static int sof_process_load(struct snd_soc_component
*scomp
, int index
,
2004 struct snd_sof_widget
*swidget
,
2005 struct snd_soc_tplg_dapm_widget
*tw
,
2006 struct sof_ipc_comp_reply
*r
,
2009 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2010 struct snd_soc_dapm_widget
*widget
= swidget
->widget
;
2011 struct snd_soc_tplg_private
*private = &tw
->priv
;
2012 struct sof_ipc_comp_process
*process
= NULL
;
2013 struct sof_widget_data
*wdata
= NULL
;
2014 size_t ipc_data_size
= 0;
2020 if (type
== SOF_COMP_NONE
) {
2021 dev_err(scomp
->dev
, "error: invalid process comp type %d\n",
2026 /* allocate struct for widget control data sizes and types */
2027 if (widget
->num_kcontrols
) {
2028 wdata
= kcalloc(widget
->num_kcontrols
,
2035 /* get possible component controls and get size of all pdata */
2036 ret
= sof_get_control_data(scomp
, widget
, wdata
,
2043 ipc_size
= sizeof(struct sof_ipc_comp_process
) +
2044 le32_to_cpu(private->size
) +
2047 /* we are exceeding max ipc size, config needs to be sent separately */
2048 if (ipc_size
> SOF_IPC_MSG_MAX_SIZE
) {
2049 ipc_size
-= ipc_data_size
;
2053 process
= kzalloc(ipc_size
, GFP_KERNEL
);
2059 /* configure iir IPC message */
2060 process
->comp
.hdr
.size
= ipc_size
;
2061 process
->comp
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_NEW
;
2062 process
->comp
.id
= swidget
->comp_id
;
2063 process
->comp
.type
= type
;
2064 process
->comp
.pipeline_id
= index
;
2065 process
->config
.hdr
.size
= sizeof(process
->config
);
2067 ret
= sof_parse_tokens(scomp
, &process
->config
, comp_tokens
,
2068 ARRAY_SIZE(comp_tokens
), private->array
,
2069 le32_to_cpu(private->size
));
2071 dev_err(scomp
->dev
, "error: parse process.cfg tokens failed %d\n",
2072 le32_to_cpu(private->size
));
2076 sof_dbg_comp_config(scomp
, &process
->config
);
2079 * found private data in control, so copy it.
2080 * get possible component controls - get size of all pdata,
2081 * then memcpy with headers
2083 if (ipc_data_size
) {
2084 for (i
= 0; i
< widget
->num_kcontrols
; i
++) {
2085 memcpy(&process
->data
+ offset
,
2086 wdata
[i
].pdata
->data
,
2087 wdata
[i
].pdata
->size
);
2088 offset
+= wdata
[i
].pdata
->size
;
2092 process
->size
= ipc_data_size
;
2093 swidget
->private = process
;
2095 ret
= sof_ipc_tx_message(sdev
->ipc
, process
->comp
.hdr
.cmd
, process
,
2096 ipc_size
, r
, sizeof(*r
));
2099 dev_err(scomp
->dev
, "error: create process failed\n");
2103 /* we sent the data in single message so return */
2107 /* send control data with large message supported method */
2108 for (i
= 0; i
< widget
->num_kcontrols
; i
++) {
2109 wdata
[i
].control
->readback_offset
= 0;
2110 ret
= snd_sof_ipc_set_get_comp_data(wdata
[i
].control
,
2113 wdata
[i
].control
->cmd
,
2116 dev_err(scomp
->dev
, "error: send control failed\n");
2130 * Processing Component Topology - can be "effect", "codec", or general
2134 static int sof_widget_load_process(struct snd_soc_component
*scomp
, int index
,
2135 struct snd_sof_widget
*swidget
,
2136 struct snd_soc_tplg_dapm_widget
*tw
,
2137 struct sof_ipc_comp_reply
*r
)
2139 struct snd_soc_tplg_private
*private = &tw
->priv
;
2140 struct sof_ipc_comp_process config
;
2143 /* check we have some tokens - we need at least process type */
2144 if (le32_to_cpu(private->size
) == 0) {
2145 dev_err(scomp
->dev
, "error: process tokens not found\n");
2149 memset(&config
, 0, sizeof(config
));
2151 /* get the process token */
2152 ret
= sof_parse_tokens(scomp
, &config
, process_tokens
,
2153 ARRAY_SIZE(process_tokens
), private->array
,
2154 le32_to_cpu(private->size
));
2156 dev_err(scomp
->dev
, "error: parse process tokens failed %d\n",
2157 le32_to_cpu(private->size
));
2161 /* now load process specific data and send IPC */
2162 ret
= sof_process_load(scomp
, index
, swidget
, tw
, r
,
2163 find_process_comp_type(config
.type
));
2165 dev_err(scomp
->dev
, "error: process loading failed\n");
2172 static int sof_widget_bind_event(struct snd_soc_component
*scomp
,
2173 struct snd_sof_widget
*swidget
,
2176 struct sof_ipc_comp
*ipc_comp
;
2178 /* validate widget event type */
2179 switch (event_type
) {
2180 case SOF_KEYWORD_DETECT_DAPM_EVENT
:
2181 /* only KEYWORD_DETECT comps should handle this */
2182 if (swidget
->id
!= snd_soc_dapm_effect
)
2185 ipc_comp
= swidget
->private;
2186 if (ipc_comp
&& ipc_comp
->type
!= SOF_COMP_KEYWORD_DETECT
)
2189 /* bind event to keyword detect comp */
2190 return snd_soc_tplg_widget_bind_event(swidget
->widget
,
2192 ARRAY_SIZE(sof_kwd_events
),
2199 "error: invalid event type %d for widget %s\n",
2200 event_type
, swidget
->widget
->name
);
2204 /* external widget init - used for any driver specific init */
2205 static int sof_widget_ready(struct snd_soc_component
*scomp
, int index
,
2206 struct snd_soc_dapm_widget
*w
,
2207 struct snd_soc_tplg_dapm_widget
*tw
)
2209 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2210 struct snd_sof_widget
*swidget
;
2211 struct snd_sof_dai
*dai
;
2212 struct sof_ipc_comp_reply reply
;
2213 struct snd_sof_control
*scontrol
;
2216 swidget
= kzalloc(sizeof(*swidget
), GFP_KERNEL
);
2220 swidget
->scomp
= scomp
;
2221 swidget
->widget
= w
;
2222 swidget
->comp_id
= sdev
->next_comp_id
++;
2223 swidget
->complete
= 0;
2224 swidget
->id
= w
->id
;
2225 swidget
->pipeline_id
= index
;
2226 swidget
->private = NULL
;
2227 memset(&reply
, 0, sizeof(reply
));
2229 dev_dbg(scomp
->dev
, "tplg: ready widget id %d pipe %d type %d name : %s stream %s\n",
2230 swidget
->comp_id
, index
, swidget
->id
, tw
->name
,
2231 strnlen(tw
->sname
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) > 0
2232 ? tw
->sname
: "none");
2234 /* handle any special case widgets */
2236 case snd_soc_dapm_dai_in
:
2237 case snd_soc_dapm_dai_out
:
2238 dai
= kzalloc(sizeof(*dai
), GFP_KERNEL
);
2244 ret
= sof_widget_load_dai(scomp
, index
, swidget
, tw
, &reply
,
2247 sof_connect_dai_widget(scomp
, w
, tw
, dai
);
2248 list_add(&dai
->list
, &sdev
->dai_list
);
2249 swidget
->private = dai
;
2254 case snd_soc_dapm_mixer
:
2255 ret
= sof_widget_load_mixer(scomp
, index
, swidget
, tw
, &reply
);
2257 case snd_soc_dapm_pga
:
2258 ret
= sof_widget_load_pga(scomp
, index
, swidget
, tw
, &reply
);
2259 /* Find scontrol for this pga and set readback offset*/
2260 list_for_each_entry(scontrol
, &sdev
->kcontrol_list
, list
) {
2261 if (scontrol
->comp_id
== swidget
->comp_id
) {
2262 scontrol
->readback_offset
= reply
.offset
;
2267 case snd_soc_dapm_buffer
:
2268 ret
= sof_widget_load_buffer(scomp
, index
, swidget
, tw
, &reply
);
2270 case snd_soc_dapm_scheduler
:
2271 ret
= sof_widget_load_pipeline(scomp
, index
, swidget
, tw
,
2274 case snd_soc_dapm_aif_out
:
2275 ret
= sof_widget_load_pcm(scomp
, index
, swidget
,
2276 SOF_IPC_STREAM_CAPTURE
, tw
, &reply
);
2278 case snd_soc_dapm_aif_in
:
2279 ret
= sof_widget_load_pcm(scomp
, index
, swidget
,
2280 SOF_IPC_STREAM_PLAYBACK
, tw
, &reply
);
2282 case snd_soc_dapm_src
:
2283 ret
= sof_widget_load_src(scomp
, index
, swidget
, tw
, &reply
);
2285 case snd_soc_dapm_asrc
:
2286 ret
= sof_widget_load_asrc(scomp
, index
, swidget
, tw
, &reply
);
2288 case snd_soc_dapm_siggen
:
2289 ret
= sof_widget_load_siggen(scomp
, index
, swidget
, tw
, &reply
);
2291 case snd_soc_dapm_effect
:
2292 ret
= sof_widget_load_process(scomp
, index
, swidget
, tw
,
2295 case snd_soc_dapm_mux
:
2296 case snd_soc_dapm_demux
:
2297 ret
= sof_widget_load_mux(scomp
, index
, swidget
, tw
, &reply
);
2299 case snd_soc_dapm_switch
:
2300 case snd_soc_dapm_dai_link
:
2301 case snd_soc_dapm_kcontrol
:
2303 dev_warn(scomp
->dev
, "warning: widget type %d name %s not handled\n",
2304 swidget
->id
, tw
->name
);
2308 /* check IPC reply */
2309 if (ret
< 0 || reply
.rhdr
.error
< 0) {
2311 "error: DSP failed to add widget id %d type %d name : %s stream %s reply %d\n",
2312 tw
->shift
, swidget
->id
, tw
->name
,
2313 strnlen(tw
->sname
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
) > 0
2314 ? tw
->sname
: "none", reply
.rhdr
.error
);
2319 /* bind widget to external event */
2320 if (tw
->event_type
) {
2321 ret
= sof_widget_bind_event(scomp
, swidget
,
2322 le16_to_cpu(tw
->event_type
));
2324 dev_err(scomp
->dev
, "error: widget event binding failed\n");
2325 kfree(swidget
->private);
2331 w
->dobj
.private = swidget
;
2332 list_add(&swidget
->list
, &sdev
->widget_list
);
2336 static int sof_route_unload(struct snd_soc_component
*scomp
,
2337 struct snd_soc_dobj
*dobj
)
2339 struct snd_sof_route
*sroute
;
2341 sroute
= dobj
->private;
2345 /* free sroute and its private data */
2346 kfree(sroute
->private);
2347 list_del(&sroute
->list
);
2353 static int sof_widget_unload(struct snd_soc_component
*scomp
,
2354 struct snd_soc_dobj
*dobj
)
2356 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2357 const struct snd_kcontrol_new
*kc
;
2358 struct snd_soc_dapm_widget
*widget
;
2359 struct sof_ipc_pipe_new
*pipeline
;
2360 struct snd_sof_control
*scontrol
;
2361 struct snd_sof_widget
*swidget
;
2362 struct soc_mixer_control
*sm
;
2363 struct soc_bytes_ext
*sbe
;
2364 struct snd_sof_dai
*dai
;
2365 struct soc_enum
*se
;
2369 swidget
= dobj
->private;
2373 widget
= swidget
->widget
;
2375 switch (swidget
->id
) {
2376 case snd_soc_dapm_dai_in
:
2377 case snd_soc_dapm_dai_out
:
2378 dai
= swidget
->private;
2381 /* free dai config */
2382 kfree(dai
->dai_config
);
2383 list_del(&dai
->list
);
2386 case snd_soc_dapm_scheduler
:
2388 /* power down the pipeline schedule core */
2389 pipeline
= swidget
->private;
2390 ret
= snd_sof_dsp_core_power_down(sdev
, 1 << pipeline
->core
);
2392 dev_err(scomp
->dev
, "error: powering down pipeline schedule core %d\n",
2395 /* update enabled cores mask */
2396 sdev
->enabled_cores_mask
&= ~(1 << pipeline
->core
);
2402 for (i
= 0; i
< widget
->num_kcontrols
; i
++) {
2403 kc
= &widget
->kcontrol_news
[i
];
2404 switch (dobj
->widget
.kcontrol_type
) {
2405 case SND_SOC_TPLG_TYPE_MIXER
:
2406 sm
= (struct soc_mixer_control
*)kc
->private_value
;
2407 scontrol
= sm
->dobj
.private;
2409 kfree(scontrol
->volume_table
);
2411 case SND_SOC_TPLG_TYPE_ENUM
:
2412 se
= (struct soc_enum
*)kc
->private_value
;
2413 scontrol
= se
->dobj
.private;
2415 case SND_SOC_TPLG_TYPE_BYTES
:
2416 sbe
= (struct soc_bytes_ext
*)kc
->private_value
;
2417 scontrol
= sbe
->dobj
.private;
2420 dev_warn(scomp
->dev
, "unsupported kcontrol_type\n");
2423 kfree(scontrol
->control_data
);
2424 list_del(&scontrol
->list
);
2429 /* free private value */
2430 kfree(swidget
->private);
2432 /* remove and free swidget object */
2433 list_del(&swidget
->list
);
2440 * DAI HW configuration.
2443 /* FE DAI - used for any driver specific init */
2444 static int sof_dai_load(struct snd_soc_component
*scomp
, int index
,
2445 struct snd_soc_dai_driver
*dai_drv
,
2446 struct snd_soc_tplg_pcm
*pcm
, struct snd_soc_dai
*dai
)
2448 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2449 struct snd_soc_tplg_stream_caps
*caps
;
2450 struct snd_soc_tplg_private
*private = &pcm
->priv
;
2451 struct snd_sof_pcm
*spcm
;
2455 /* nothing to do for BEs atm */
2459 spcm
= kzalloc(sizeof(*spcm
), GFP_KERNEL
);
2463 spcm
->scomp
= scomp
;
2465 for_each_pcm_streams(stream
) {
2466 spcm
->stream
[stream
].comp_id
= COMP_ID_UNASSIGNED
;
2467 INIT_WORK(&spcm
->stream
[stream
].period_elapsed_work
,
2468 snd_sof_pcm_period_elapsed_work
);
2472 dev_dbg(scomp
->dev
, "tplg: load pcm %s\n", pcm
->dai_name
);
2474 dai_drv
->dobj
.private = spcm
;
2475 list_add(&spcm
->list
, &sdev
->pcm_list
);
2477 ret
= sof_parse_tokens(scomp
, spcm
, stream_tokens
,
2478 ARRAY_SIZE(stream_tokens
), private->array
,
2479 le32_to_cpu(private->size
));
2481 dev_err(scomp
->dev
, "error: parse stream tokens failed %d\n",
2482 le32_to_cpu(private->size
));
2486 /* do we need to allocate playback PCM DMA pages */
2487 if (!spcm
->pcm
.playback
)
2490 stream
= SNDRV_PCM_STREAM_PLAYBACK
;
2492 dev_vdbg(scomp
->dev
, "tplg: pcm %s stream tokens: playback d0i3:%d\n",
2493 spcm
->pcm
.pcm_name
, spcm
->stream
[stream
].d0i3_compatible
);
2495 caps
= &spcm
->pcm
.caps
[stream
];
2497 /* allocate playback page table buffer */
2498 ret
= snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, sdev
->dev
,
2499 PAGE_SIZE
, &spcm
->stream
[stream
].page_table
);
2501 dev_err(scomp
->dev
, "error: can't alloc page table for %s %d\n",
2507 /* bind pcm to host comp */
2508 ret
= spcm_bind(scomp
, spcm
, stream
);
2511 "error: can't bind pcm to host\n");
2512 goto free_playback_tables
;
2516 stream
= SNDRV_PCM_STREAM_CAPTURE
;
2518 /* do we need to allocate capture PCM DMA pages */
2519 if (!spcm
->pcm
.capture
)
2522 dev_vdbg(scomp
->dev
, "tplg: pcm %s stream tokens: capture d0i3:%d\n",
2523 spcm
->pcm
.pcm_name
, spcm
->stream
[stream
].d0i3_compatible
);
2525 caps
= &spcm
->pcm
.caps
[stream
];
2527 /* allocate capture page table buffer */
2528 ret
= snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, sdev
->dev
,
2529 PAGE_SIZE
, &spcm
->stream
[stream
].page_table
);
2531 dev_err(scomp
->dev
, "error: can't alloc page table for %s %d\n",
2533 goto free_playback_tables
;
2536 /* bind pcm to host comp */
2537 ret
= spcm_bind(scomp
, spcm
, stream
);
2540 "error: can't bind pcm to host\n");
2541 snd_dma_free_pages(&spcm
->stream
[stream
].page_table
);
2542 goto free_playback_tables
;
2547 free_playback_tables
:
2548 if (spcm
->pcm
.playback
)
2549 snd_dma_free_pages(&spcm
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].page_table
);
2554 static int sof_dai_unload(struct snd_soc_component
*scomp
,
2555 struct snd_soc_dobj
*dobj
)
2557 struct snd_sof_pcm
*spcm
= dobj
->private;
2559 /* free PCM DMA pages */
2560 if (spcm
->pcm
.playback
)
2561 snd_dma_free_pages(&spcm
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].page_table
);
2563 if (spcm
->pcm
.capture
)
2564 snd_dma_free_pages(&spcm
->stream
[SNDRV_PCM_STREAM_CAPTURE
].page_table
);
2566 /* remove from list and free spcm */
2567 list_del(&spcm
->list
);
2573 static void sof_dai_set_format(struct snd_soc_tplg_hw_config
*hw_config
,
2574 struct sof_ipc_dai_config
*config
)
2576 /* clock directions wrt codec */
2577 if (hw_config
->bclk_master
== SND_SOC_TPLG_BCLK_CM
) {
2578 /* codec is bclk master */
2579 if (hw_config
->fsync_master
== SND_SOC_TPLG_FSYNC_CM
)
2580 config
->format
|= SOF_DAI_FMT_CBM_CFM
;
2582 config
->format
|= SOF_DAI_FMT_CBM_CFS
;
2584 /* codec is bclk slave */
2585 if (hw_config
->fsync_master
== SND_SOC_TPLG_FSYNC_CM
)
2586 config
->format
|= SOF_DAI_FMT_CBS_CFM
;
2588 config
->format
|= SOF_DAI_FMT_CBS_CFS
;
2591 /* inverted clocks ? */
2592 if (hw_config
->invert_bclk
) {
2593 if (hw_config
->invert_fsync
)
2594 config
->format
|= SOF_DAI_FMT_IB_IF
;
2596 config
->format
|= SOF_DAI_FMT_IB_NF
;
2598 if (hw_config
->invert_fsync
)
2599 config
->format
|= SOF_DAI_FMT_NB_IF
;
2601 config
->format
|= SOF_DAI_FMT_NB_NF
;
2605 /* set config for all DAI's with name matching the link name */
2606 static int sof_set_dai_config(struct snd_sof_dev
*sdev
, u32 size
,
2607 struct snd_soc_dai_link
*link
,
2608 struct sof_ipc_dai_config
*config
)
2610 struct snd_sof_dai
*dai
;
2613 list_for_each_entry(dai
, &sdev
->dai_list
, list
) {
2617 if (strcmp(link
->name
, dai
->name
) == 0) {
2618 dai
->dai_config
= kmemdup(config
, size
, GFP_KERNEL
);
2619 if (!dai
->dai_config
)
2622 /* set cpu_dai_name */
2623 dai
->cpu_dai_name
= link
->cpus
->dai_name
;
2630 * machine driver may define a dai link with playback and capture
2631 * dai enabled, but the dai link in topology would support both, one
2632 * or none of them. Here print a warning message to notify user
2635 dev_warn(sdev
->dev
, "warning: failed to find dai for dai link %s",
2642 static int sof_link_ssp_load(struct snd_soc_component
*scomp
, int index
,
2643 struct snd_soc_dai_link
*link
,
2644 struct snd_soc_tplg_link_config
*cfg
,
2645 struct snd_soc_tplg_hw_config
*hw_config
,
2646 struct sof_ipc_dai_config
*config
)
2648 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2649 struct snd_soc_tplg_private
*private = &cfg
->priv
;
2650 struct sof_ipc_reply reply
;
2651 u32 size
= sizeof(*config
);
2654 /* handle master/slave and inverted clocks */
2655 sof_dai_set_format(hw_config
, config
);
2658 memset(&config
->ssp
, 0, sizeof(struct sof_ipc_dai_ssp_params
));
2659 config
->hdr
.size
= size
;
2661 ret
= sof_parse_tokens(scomp
, &config
->ssp
, ssp_tokens
,
2662 ARRAY_SIZE(ssp_tokens
), private->array
,
2663 le32_to_cpu(private->size
));
2665 dev_err(scomp
->dev
, "error: parse ssp tokens failed %d\n",
2666 le32_to_cpu(private->size
));
2670 config
->ssp
.mclk_rate
= le32_to_cpu(hw_config
->mclk_rate
);
2671 config
->ssp
.bclk_rate
= le32_to_cpu(hw_config
->bclk_rate
);
2672 config
->ssp
.fsync_rate
= le32_to_cpu(hw_config
->fsync_rate
);
2673 config
->ssp
.tdm_slots
= le32_to_cpu(hw_config
->tdm_slots
);
2674 config
->ssp
.tdm_slot_width
= le32_to_cpu(hw_config
->tdm_slot_width
);
2675 config
->ssp
.mclk_direction
= hw_config
->mclk_direction
;
2676 config
->ssp
.rx_slots
= le32_to_cpu(hw_config
->rx_slots
);
2677 config
->ssp
.tx_slots
= le32_to_cpu(hw_config
->tx_slots
);
2679 dev_dbg(scomp
->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",
2680 config
->dai_index
, config
->format
,
2681 config
->ssp
.mclk_rate
, config
->ssp
.bclk_rate
,
2682 config
->ssp
.fsync_rate
, config
->ssp
.sample_valid_bits
,
2683 config
->ssp
.tdm_slot_width
, config
->ssp
.tdm_slots
,
2684 config
->ssp
.mclk_id
, config
->ssp
.quirks
);
2686 /* validate SSP fsync rate and channel count */
2687 if (config
->ssp
.fsync_rate
< 8000 || config
->ssp
.fsync_rate
> 192000) {
2688 dev_err(scomp
->dev
, "error: invalid fsync rate for SSP%d\n",
2693 if (config
->ssp
.tdm_slots
< 1 || config
->ssp
.tdm_slots
> 8) {
2694 dev_err(scomp
->dev
, "error: invalid channel count for SSP%d\n",
2699 /* send message to DSP */
2700 ret
= sof_ipc_tx_message(sdev
->ipc
,
2701 config
->hdr
.cmd
, config
, size
, &reply
,
2705 dev_err(scomp
->dev
, "error: failed to set DAI config for SSP%d\n",
2710 /* set config for all DAI's with name matching the link name */
2711 ret
= sof_set_dai_config(sdev
, size
, link
, config
);
2713 dev_err(scomp
->dev
, "error: failed to save DAI config for SSP%d\n",
2719 static int sof_link_sai_load(struct snd_soc_component
*scomp
, int index
,
2720 struct snd_soc_dai_link
*link
,
2721 struct snd_soc_tplg_link_config
*cfg
,
2722 struct snd_soc_tplg_hw_config
*hw_config
,
2723 struct sof_ipc_dai_config
*config
)
2725 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2726 struct snd_soc_tplg_private
*private = &cfg
->priv
;
2727 struct sof_ipc_reply reply
;
2728 u32 size
= sizeof(*config
);
2731 /* handle master/slave and inverted clocks */
2732 sof_dai_set_format(hw_config
, config
);
2735 memset(&config
->sai
, 0, sizeof(struct sof_ipc_dai_sai_params
));
2736 config
->hdr
.size
= size
;
2738 ret
= sof_parse_tokens(scomp
, &config
->sai
, sai_tokens
,
2739 ARRAY_SIZE(sai_tokens
), private->array
,
2740 le32_to_cpu(private->size
));
2742 dev_err(scomp
->dev
, "error: parse sai tokens failed %d\n",
2743 le32_to_cpu(private->size
));
2747 config
->sai
.mclk_rate
= le32_to_cpu(hw_config
->mclk_rate
);
2748 config
->sai
.mclk_direction
= hw_config
->mclk_direction
;
2750 config
->sai
.tdm_slots
= le32_to_cpu(hw_config
->tdm_slots
);
2751 config
->sai
.tdm_slot_width
= le32_to_cpu(hw_config
->tdm_slot_width
);
2752 config
->sai
.rx_slots
= le32_to_cpu(hw_config
->rx_slots
);
2753 config
->sai
.tx_slots
= le32_to_cpu(hw_config
->tx_slots
);
2755 dev_info(scomp
->dev
,
2756 "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n",
2757 config
->dai_index
, config
->format
,
2758 config
->sai
.mclk_rate
, config
->sai
.tdm_slot_width
,
2759 config
->sai
.tdm_slots
, config
->sai
.mclk_id
);
2761 if (config
->sai
.tdm_slots
< 1 || config
->sai
.tdm_slots
> 8) {
2762 dev_err(scomp
->dev
, "error: invalid channel count for SAI%d\n",
2767 /* send message to DSP */
2768 ret
= sof_ipc_tx_message(sdev
->ipc
,
2769 config
->hdr
.cmd
, config
, size
, &reply
,
2773 dev_err(scomp
->dev
, "error: failed to set DAI config for SAI%d\n",
2778 /* set config for all DAI's with name matching the link name */
2779 ret
= sof_set_dai_config(sdev
, size
, link
, config
);
2781 dev_err(scomp
->dev
, "error: failed to save DAI config for SAI%d\n",
2787 static int sof_link_esai_load(struct snd_soc_component
*scomp
, int index
,
2788 struct snd_soc_dai_link
*link
,
2789 struct snd_soc_tplg_link_config
*cfg
,
2790 struct snd_soc_tplg_hw_config
*hw_config
,
2791 struct sof_ipc_dai_config
*config
)
2793 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2794 struct snd_soc_tplg_private
*private = &cfg
->priv
;
2795 struct sof_ipc_reply reply
;
2796 u32 size
= sizeof(*config
);
2799 /* handle master/slave and inverted clocks */
2800 sof_dai_set_format(hw_config
, config
);
2803 memset(&config
->esai
, 0, sizeof(struct sof_ipc_dai_esai_params
));
2804 config
->hdr
.size
= size
;
2806 ret
= sof_parse_tokens(scomp
, &config
->esai
, esai_tokens
,
2807 ARRAY_SIZE(esai_tokens
), private->array
,
2808 le32_to_cpu(private->size
));
2810 dev_err(scomp
->dev
, "error: parse esai tokens failed %d\n",
2811 le32_to_cpu(private->size
));
2815 config
->esai
.mclk_rate
= le32_to_cpu(hw_config
->mclk_rate
);
2816 config
->esai
.bclk_rate
= le32_to_cpu(hw_config
->bclk_rate
);
2817 config
->esai
.fsync_rate
= le32_to_cpu(hw_config
->fsync_rate
);
2818 config
->esai
.mclk_direction
= hw_config
->mclk_direction
;
2819 config
->esai
.tdm_slots
= le32_to_cpu(hw_config
->tdm_slots
);
2820 config
->esai
.tdm_slot_width
= le32_to_cpu(hw_config
->tdm_slot_width
);
2821 config
->esai
.rx_slots
= le32_to_cpu(hw_config
->rx_slots
);
2822 config
->esai
.tx_slots
= le32_to_cpu(hw_config
->tx_slots
);
2824 dev_info(scomp
->dev
,
2825 "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n",
2826 config
->dai_index
, config
->format
,
2827 config
->esai
.mclk_rate
, config
->esai
.tdm_slot_width
,
2828 config
->esai
.tdm_slots
, config
->esai
.mclk_id
);
2830 if (config
->esai
.tdm_slots
< 1 || config
->esai
.tdm_slots
> 8) {
2831 dev_err(scomp
->dev
, "error: invalid channel count for ESAI%d\n",
2836 /* send message to DSP */
2837 ret
= sof_ipc_tx_message(sdev
->ipc
,
2838 config
->hdr
.cmd
, config
, size
, &reply
,
2841 dev_err(scomp
->dev
, "error: failed to set DAI config for ESAI%d\n",
2846 /* set config for all DAI's with name matching the link name */
2847 ret
= sof_set_dai_config(sdev
, size
, link
, config
);
2849 dev_err(scomp
->dev
, "error: failed to save DAI config for ESAI%d\n",
2855 static int sof_link_dmic_load(struct snd_soc_component
*scomp
, int index
,
2856 struct snd_soc_dai_link
*link
,
2857 struct snd_soc_tplg_link_config
*cfg
,
2858 struct snd_soc_tplg_hw_config
*hw_config
,
2859 struct sof_ipc_dai_config
*config
)
2861 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
2862 struct snd_soc_tplg_private
*private = &cfg
->priv
;
2863 struct sof_ipc_dai_config
*ipc_config
;
2864 struct sof_ipc_reply reply
;
2865 struct sof_ipc_fw_ready
*ready
= &sdev
->fw_ready
;
2866 struct sof_ipc_fw_version
*v
= &ready
->version
;
2871 * config is only used for the common params in dmic_params structure
2872 * that does not include the PDM controller config array
2873 * Set the common params to 0.
2875 memset(&config
->dmic
, 0, sizeof(struct sof_ipc_dai_dmic_params
));
2877 /* get DMIC tokens */
2878 ret
= sof_parse_tokens(scomp
, &config
->dmic
, dmic_tokens
,
2879 ARRAY_SIZE(dmic_tokens
), private->array
,
2880 le32_to_cpu(private->size
));
2882 dev_err(scomp
->dev
, "error: parse dmic tokens failed %d\n",
2883 le32_to_cpu(private->size
));
2888 * allocate memory for dmic dai config accounting for the
2889 * variable number of active pdm controllers
2890 * This will be the ipc payload for setting dai config
2892 size
= sizeof(*config
) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl
) *
2893 config
->dmic
.num_pdm_active
;
2895 ipc_config
= kzalloc(size
, GFP_KERNEL
);
2899 /* copy the common dai config and dmic params */
2900 memcpy(ipc_config
, config
, sizeof(*config
));
2903 * alloc memory for private member
2904 * Used to track the pdm config array index currently being parsed
2906 sdev
->private = kzalloc(sizeof(u32
), GFP_KERNEL
);
2907 if (!sdev
->private) {
2912 /* get DMIC PDM tokens */
2913 ret
= sof_parse_tokens(scomp
, &ipc_config
->dmic
.pdm
[0], dmic_pdm_tokens
,
2914 ARRAY_SIZE(dmic_pdm_tokens
), private->array
,
2915 le32_to_cpu(private->size
));
2917 dev_err(scomp
->dev
, "error: parse dmic pdm tokens failed %d\n",
2918 le32_to_cpu(private->size
));
2922 /* set IPC header size */
2923 ipc_config
->hdr
.size
= size
;
2925 /* debug messages */
2926 dev_dbg(scomp
->dev
, "tplg: config DMIC%d driver version %d\n",
2927 ipc_config
->dai_index
, ipc_config
->dmic
.driver_ipc_version
);
2928 dev_dbg(scomp
->dev
, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n",
2929 ipc_config
->dmic
.pdmclk_min
, ipc_config
->dmic
.pdmclk_max
,
2930 ipc_config
->dmic
.duty_min
);
2931 dev_dbg(scomp
->dev
, "duty_max %hd fifo_fs %d num_pdms active %d\n",
2932 ipc_config
->dmic
.duty_max
, ipc_config
->dmic
.fifo_fs
,
2933 ipc_config
->dmic
.num_pdm_active
);
2934 dev_dbg(scomp
->dev
, "fifo word length %hd\n",
2935 ipc_config
->dmic
.fifo_bits
);
2937 for (j
= 0; j
< ipc_config
->dmic
.num_pdm_active
; j
++) {
2938 dev_dbg(scomp
->dev
, "pdm %hd mic a %hd mic b %hd\n",
2939 ipc_config
->dmic
.pdm
[j
].id
,
2940 ipc_config
->dmic
.pdm
[j
].enable_mic_a
,
2941 ipc_config
->dmic
.pdm
[j
].enable_mic_b
);
2942 dev_dbg(scomp
->dev
, "pdm %hd polarity a %hd polarity b %hd\n",
2943 ipc_config
->dmic
.pdm
[j
].id
,
2944 ipc_config
->dmic
.pdm
[j
].polarity_mic_a
,
2945 ipc_config
->dmic
.pdm
[j
].polarity_mic_b
);
2946 dev_dbg(scomp
->dev
, "pdm %hd clk_edge %hd skew %hd\n",
2947 ipc_config
->dmic
.pdm
[j
].id
,
2948 ipc_config
->dmic
.pdm
[j
].clk_edge
,
2949 ipc_config
->dmic
.pdm
[j
].skew
);
2952 if (SOF_ABI_VER(v
->major
, v
->minor
, v
->micro
) < SOF_ABI_VER(3, 0, 1)) {
2953 /* this takes care of backwards compatible handling of fifo_bits_b */
2954 ipc_config
->dmic
.reserved_2
= ipc_config
->dmic
.fifo_bits
;
2957 /* send message to DSP */
2958 ret
= sof_ipc_tx_message(sdev
->ipc
,
2959 ipc_config
->hdr
.cmd
, ipc_config
, size
, &reply
,
2964 "error: failed to set DAI config for DMIC%d\n",
2969 /* set config for all DAI's with name matching the link name */
2970 ret
= sof_set_dai_config(sdev
, size
, link
, ipc_config
);
2972 dev_err(scomp
->dev
, "error: failed to save DAI config for DMIC%d\n",
2976 kfree(sdev
->private);
2983 * for hda link, playback and capture are supported by different dai
2984 * in FW. Here get the dai_index, set dma channel of each dai
2985 * and send config to FW. In FW, each dai sets config by dai_index
2987 static int sof_link_hda_process(struct snd_sof_dev
*sdev
,
2988 struct snd_soc_dai_link
*link
,
2989 struct sof_ipc_dai_config
*config
)
2991 struct sof_ipc_reply reply
;
2992 u32 size
= sizeof(*config
);
2993 struct snd_sof_dai
*sof_dai
;
2997 list_for_each_entry(sof_dai
, &sdev
->dai_list
, list
) {
3001 if (strcmp(link
->name
, sof_dai
->name
) == 0) {
3002 config
->dai_index
= sof_dai
->comp_dai
.dai_index
;
3005 config
->hda
.link_dma_ch
= DMA_CHAN_INVALID
;
3007 /* save config in dai component */
3008 sof_dai
->dai_config
= kmemdup(config
, size
, GFP_KERNEL
);
3009 if (!sof_dai
->dai_config
)
3012 sof_dai
->cpu_dai_name
= link
->cpus
->dai_name
;
3014 /* send message to DSP */
3015 ret
= sof_ipc_tx_message(sdev
->ipc
,
3016 config
->hdr
.cmd
, config
, size
,
3017 &reply
, sizeof(reply
));
3020 dev_err(sdev
->dev
, "error: failed to set DAI config for direction:%d of HDA dai %d\n",
3021 sof_dai
->comp_dai
.direction
,
3030 * machine driver may define a dai link with playback and capture
3031 * dai enabled, but the dai link in topology would support both, one
3032 * or none of them. Here print a warning message to notify user
3035 dev_warn(sdev
->dev
, "warning: failed to find dai for dai link %s",
3042 static int sof_link_hda_load(struct snd_soc_component
*scomp
, int index
,
3043 struct snd_soc_dai_link
*link
,
3044 struct snd_soc_tplg_link_config
*cfg
,
3045 struct snd_soc_tplg_hw_config
*hw_config
,
3046 struct sof_ipc_dai_config
*config
)
3048 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3049 struct snd_soc_tplg_private
*private = &cfg
->priv
;
3050 struct snd_soc_dai
*dai
;
3051 u32 size
= sizeof(*config
);
3055 memset(&config
->hda
, 0, sizeof(struct sof_ipc_dai_hda_params
));
3056 config
->hdr
.size
= size
;
3058 /* get any bespoke DAI tokens */
3059 ret
= sof_parse_tokens(scomp
, config
, hda_tokens
,
3060 ARRAY_SIZE(hda_tokens
), private->array
,
3061 le32_to_cpu(private->size
));
3063 dev_err(scomp
->dev
, "error: parse hda tokens failed %d\n",
3064 le32_to_cpu(private->size
));
3068 dai
= snd_soc_find_dai(link
->cpus
);
3070 dev_err(scomp
->dev
, "error: failed to find dai %s in %s",
3071 link
->cpus
->dai_name
, __func__
);
3075 ret
= sof_link_hda_process(sdev
, link
, config
);
3077 dev_err(scomp
->dev
, "error: failed to process hda dai link %s",
3083 static int sof_link_alh_load(struct snd_soc_component
*scomp
, int index
,
3084 struct snd_soc_dai_link
*link
,
3085 struct snd_soc_tplg_link_config
*cfg
,
3086 struct snd_soc_tplg_hw_config
*hw_config
,
3087 struct sof_ipc_dai_config
*config
)
3089 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3090 struct sof_ipc_reply reply
;
3091 u32 size
= sizeof(*config
);
3095 config
->hdr
.size
= size
;
3097 /* send message to DSP */
3098 ret
= sof_ipc_tx_message(sdev
->ipc
,
3099 config
->hdr
.cmd
, config
, size
, &reply
,
3103 dev_err(scomp
->dev
, "error: failed to set DAI config for ALH %d\n",
3108 /* set config for all DAI's with name matching the link name */
3109 ret
= sof_set_dai_config(sdev
, size
, link
, config
);
3111 dev_err(scomp
->dev
, "error: failed to save DAI config for ALH %d\n",
3117 /* DAI link - used for any driver specific init */
3118 static int sof_link_load(struct snd_soc_component
*scomp
, int index
,
3119 struct snd_soc_dai_link
*link
,
3120 struct snd_soc_tplg_link_config
*cfg
)
3122 struct snd_soc_tplg_private
*private = &cfg
->priv
;
3123 struct sof_ipc_dai_config config
;
3124 struct snd_soc_tplg_hw_config
*hw_config
;
3129 if (!link
->platforms
) {
3130 dev_err(scomp
->dev
, "error: no platforms\n");
3133 link
->platforms
->name
= dev_name(scomp
->dev
);
3136 * Set nonatomic property for FE dai links as their trigger action
3139 if (!link
->no_pcm
) {
3140 link
->nonatomic
= true;
3142 /* set trigger order */
3143 link
->trigger
[0] = SND_SOC_DPCM_TRIGGER_POST
;
3144 link
->trigger
[1] = SND_SOC_DPCM_TRIGGER_POST
;
3146 /* nothing more to do for FE dai links */
3150 /* check we have some tokens - we need at least DAI type */
3151 if (le32_to_cpu(private->size
) == 0) {
3152 dev_err(scomp
->dev
, "error: expected tokens for DAI, none found\n");
3156 /* Send BE DAI link configurations to DSP */
3157 memset(&config
, 0, sizeof(config
));
3159 /* get any common DAI tokens */
3160 ret
= sof_parse_tokens(scomp
, &config
, dai_link_tokens
,
3161 ARRAY_SIZE(dai_link_tokens
), private->array
,
3162 le32_to_cpu(private->size
));
3164 dev_err(scomp
->dev
, "error: parse link tokens failed %d\n",
3165 le32_to_cpu(private->size
));
3170 * DAI links are expected to have at least 1 hw_config.
3171 * But some older topologies might have no hw_config for HDA dai links.
3173 num_hw_configs
= le32_to_cpu(cfg
->num_hw_configs
);
3174 if (!num_hw_configs
) {
3175 if (config
.type
!= SOF_DAI_INTEL_HDA
) {
3176 dev_err(scomp
->dev
, "error: unexpected DAI config count %d!\n",
3177 le32_to_cpu(cfg
->num_hw_configs
));
3181 dev_dbg(scomp
->dev
, "tplg: %d hw_configs found, default id: %d!\n",
3182 cfg
->num_hw_configs
, le32_to_cpu(cfg
->default_hw_config_id
));
3184 for (i
= 0; i
< num_hw_configs
; i
++) {
3185 if (cfg
->hw_config
[i
].id
== cfg
->default_hw_config_id
)
3189 if (i
== num_hw_configs
) {
3190 dev_err(scomp
->dev
, "error: default hw_config id: %d not found!\n",
3191 le32_to_cpu(cfg
->default_hw_config_id
));
3196 /* configure dai IPC message */
3197 hw_config
= &cfg
->hw_config
[i
];
3199 config
.hdr
.cmd
= SOF_IPC_GLB_DAI_MSG
| SOF_IPC_DAI_CONFIG
;
3200 config
.format
= le32_to_cpu(hw_config
->fmt
);
3202 /* now load DAI specific data and send IPC - type comes from token */
3203 switch (config
.type
) {
3204 case SOF_DAI_INTEL_SSP
:
3205 ret
= sof_link_ssp_load(scomp
, index
, link
, cfg
, hw_config
,
3208 case SOF_DAI_INTEL_DMIC
:
3209 ret
= sof_link_dmic_load(scomp
, index
, link
, cfg
, hw_config
,
3212 case SOF_DAI_INTEL_HDA
:
3213 ret
= sof_link_hda_load(scomp
, index
, link
, cfg
, hw_config
,
3216 case SOF_DAI_INTEL_ALH
:
3217 ret
= sof_link_alh_load(scomp
, index
, link
, cfg
, hw_config
,
3220 case SOF_DAI_IMX_SAI
:
3221 ret
= sof_link_sai_load(scomp
, index
, link
, cfg
, hw_config
,
3224 case SOF_DAI_IMX_ESAI
:
3225 ret
= sof_link_esai_load(scomp
, index
, link
, cfg
, hw_config
,
3229 dev_err(scomp
->dev
, "error: invalid DAI type %d\n",
3240 static int sof_link_hda_unload(struct snd_sof_dev
*sdev
,
3241 struct snd_soc_dai_link
*link
)
3243 struct snd_soc_dai
*dai
;
3246 dai
= snd_soc_find_dai(link
->cpus
);
3248 dev_err(sdev
->dev
, "error: failed to find dai %s in %s",
3249 link
->cpus
->dai_name
, __func__
);
3256 static int sof_link_unload(struct snd_soc_component
*scomp
,
3257 struct snd_soc_dobj
*dobj
)
3259 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3260 struct snd_soc_dai_link
*link
=
3261 container_of(dobj
, struct snd_soc_dai_link
, dobj
);
3263 struct snd_sof_dai
*sof_dai
;
3266 /* only BE link is loaded by sof */
3270 list_for_each_entry(sof_dai
, &sdev
->dai_list
, list
) {
3274 if (strcmp(link
->name
, sof_dai
->name
) == 0)
3278 dev_err(scomp
->dev
, "error: failed to find dai %s in %s",
3279 link
->name
, __func__
);
3283 switch (sof_dai
->dai_config
->type
) {
3284 case SOF_DAI_INTEL_SSP
:
3285 case SOF_DAI_INTEL_DMIC
:
3286 case SOF_DAI_INTEL_ALH
:
3287 case SOF_DAI_IMX_SAI
:
3288 case SOF_DAI_IMX_ESAI
:
3289 /* no resource needs to be released for all cases above */
3291 case SOF_DAI_INTEL_HDA
:
3292 ret
= sof_link_hda_unload(sdev
, link
);
3295 dev_err(scomp
->dev
, "error: invalid DAI type %d\n",
3296 sof_dai
->dai_config
->type
);
3304 /* DAI link - used for any driver specific init */
3305 static int sof_route_load(struct snd_soc_component
*scomp
, int index
,
3306 struct snd_soc_dapm_route
*route
)
3308 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3309 struct sof_ipc_pipe_comp_connect
*connect
;
3310 struct snd_sof_widget
*source_swidget
, *sink_swidget
;
3311 struct snd_soc_dobj
*dobj
= &route
->dobj
;
3312 struct snd_sof_route
*sroute
;
3313 struct sof_ipc_reply reply
;
3316 /* allocate memory for sroute and connect */
3317 sroute
= kzalloc(sizeof(*sroute
), GFP_KERNEL
);
3321 sroute
->scomp
= scomp
;
3323 connect
= kzalloc(sizeof(*connect
), GFP_KERNEL
);
3329 connect
->hdr
.size
= sizeof(*connect
);
3330 connect
->hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_COMP_CONNECT
;
3332 dev_dbg(scomp
->dev
, "sink %s control %s source %s\n",
3333 route
->sink
, route
->control
? route
->control
: "none",
3336 /* source component */
3337 source_swidget
= snd_sof_find_swidget(scomp
, (char *)route
->source
);
3338 if (!source_swidget
) {
3339 dev_err(scomp
->dev
, "error: source %s not found\n",
3346 * Virtual widgets of type output/out_drv may be added in topology
3347 * for compatibility. These are not handled by the FW.
3348 * So, don't send routes whose source/sink widget is of such types
3351 if (source_swidget
->id
== snd_soc_dapm_out_drv
||
3352 source_swidget
->id
== snd_soc_dapm_output
)
3355 connect
->source_id
= source_swidget
->comp_id
;
3357 /* sink component */
3358 sink_swidget
= snd_sof_find_swidget(scomp
, (char *)route
->sink
);
3359 if (!sink_swidget
) {
3360 dev_err(scomp
->dev
, "error: sink %s not found\n",
3367 * Don't send routes whose sink widget is of type
3368 * output or out_drv to the DSP
3370 if (sink_swidget
->id
== snd_soc_dapm_out_drv
||
3371 sink_swidget
->id
== snd_soc_dapm_output
)
3374 connect
->sink_id
= sink_swidget
->comp_id
;
3377 * For virtual routes, both sink and source are not
3378 * buffer. Since only buffer linked to component is supported by
3379 * FW, others are reported as error, add check in route function,
3380 * do not send it to FW when both source and sink are not buffer
3382 if (source_swidget
->id
!= snd_soc_dapm_buffer
&&
3383 sink_swidget
->id
!= snd_soc_dapm_buffer
) {
3384 dev_dbg(scomp
->dev
, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n",
3385 route
->source
, route
->sink
);
3389 ret
= sof_ipc_tx_message(sdev
->ipc
,
3391 connect
, sizeof(*connect
),
3392 &reply
, sizeof(reply
));
3394 /* check IPC return value */
3396 dev_err(scomp
->dev
, "error: failed to add route sink %s control %s source %s\n",
3398 route
->control
? route
->control
: "none",
3403 /* check IPC reply */
3404 if (reply
.error
< 0) {
3405 dev_err(scomp
->dev
, "error: DSP failed to add route sink %s control %s source %s result %d\n",
3407 route
->control
? route
->control
: "none",
3408 route
->source
, reply
.error
);
3413 sroute
->route
= route
;
3414 dobj
->private = sroute
;
3415 sroute
->private = connect
;
3417 /* add route to route list */
3418 list_add(&sroute
->list
, &sdev
->route_list
);
3429 /* Function to set the initial value of SOF kcontrols.
3430 * The value will be stored in scontrol->control_data
3432 static int snd_sof_cache_kcontrol_val(struct snd_soc_component
*scomp
)
3434 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3435 struct snd_sof_control
*scontrol
= NULL
;
3436 int ipc_cmd
, ctrl_type
;
3439 list_for_each_entry(scontrol
, &sdev
->kcontrol_list
, list
) {
3441 /* notify DSP of kcontrol values */
3442 switch (scontrol
->cmd
) {
3443 case SOF_CTRL_CMD_VOLUME
:
3444 case SOF_CTRL_CMD_ENUM
:
3445 case SOF_CTRL_CMD_SWITCH
:
3446 ipc_cmd
= SOF_IPC_COMP_GET_VALUE
;
3447 ctrl_type
= SOF_CTRL_TYPE_VALUE_CHAN_GET
;
3449 case SOF_CTRL_CMD_BINARY
:
3450 ipc_cmd
= SOF_IPC_COMP_GET_DATA
;
3451 ctrl_type
= SOF_CTRL_TYPE_DATA_GET
;
3455 "error: Invalid scontrol->cmd: %d\n",
3459 ret
= snd_sof_ipc_set_get_comp_data(scontrol
,
3464 dev_warn(scomp
->dev
,
3465 "error: kcontrol value get for widget: %d\n",
3473 int snd_sof_complete_pipeline(struct device
*dev
,
3474 struct snd_sof_widget
*swidget
)
3476 struct snd_sof_dev
*sdev
= dev_get_drvdata(dev
);
3477 struct sof_ipc_pipe_ready ready
;
3478 struct sof_ipc_reply reply
;
3481 dev_dbg(dev
, "tplg: complete pipeline %s id %d\n",
3482 swidget
->widget
->name
, swidget
->comp_id
);
3484 memset(&ready
, 0, sizeof(ready
));
3485 ready
.hdr
.size
= sizeof(ready
);
3486 ready
.hdr
.cmd
= SOF_IPC_GLB_TPLG_MSG
| SOF_IPC_TPLG_PIPE_COMPLETE
;
3487 ready
.comp_id
= swidget
->comp_id
;
3489 ret
= sof_ipc_tx_message(sdev
->ipc
,
3490 ready
.hdr
.cmd
, &ready
, sizeof(ready
), &reply
,
3497 /* completion - called at completion of firmware loading */
3498 static void sof_complete(struct snd_soc_component
*scomp
)
3500 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
3501 struct snd_sof_widget
*swidget
;
3503 /* some widget types require completion notificattion */
3504 list_for_each_entry(swidget
, &sdev
->widget_list
, list
) {
3505 if (swidget
->complete
)
3508 switch (swidget
->id
) {
3509 case snd_soc_dapm_scheduler
:
3511 snd_sof_complete_pipeline(scomp
->dev
, swidget
);
3518 * cache initial values of SOF kcontrols by reading DSP value over
3519 * IPC. It may be overwritten by alsa-mixer after booting up
3521 snd_sof_cache_kcontrol_val(scomp
);
3524 /* manifest - optional to inform component of manifest */
3525 static int sof_manifest(struct snd_soc_component
*scomp
, int index
,
3526 struct snd_soc_tplg_manifest
*man
)
3531 size
= le32_to_cpu(man
->priv
.size
);
3533 /* backward compatible with tplg without ABI info */
3535 dev_dbg(scomp
->dev
, "No topology ABI info\n");
3539 if (size
!= SOF_TPLG_ABI_SIZE
) {
3540 dev_err(scomp
->dev
, "error: invalid topology ABI size\n");
3544 dev_info(scomp
->dev
,
3545 "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
3546 man
->priv
.data
[0], man
->priv
.data
[1],
3547 man
->priv
.data
[2], SOF_ABI_MAJOR
, SOF_ABI_MINOR
,
3550 abi_version
= SOF_ABI_VER(man
->priv
.data
[0],
3554 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION
, abi_version
)) {
3555 dev_err(scomp
->dev
, "error: incompatible topology ABI version\n");
3559 if (abi_version
> SOF_ABI_VERSION
) {
3560 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS
)) {
3561 dev_warn(scomp
->dev
, "warn: topology ABI is more recent than kernel\n");
3563 dev_err(scomp
->dev
, "error: topology ABI is more recent than kernel\n");
3571 /* vendor specific kcontrol handlers available for binding */
3572 static const struct snd_soc_tplg_kcontrol_ops sof_io_ops
[] = {
3573 {SOF_TPLG_KCTL_VOL_ID
, snd_sof_volume_get
, snd_sof_volume_put
},
3574 {SOF_TPLG_KCTL_BYTES_ID
, snd_sof_bytes_get
, snd_sof_bytes_put
},
3575 {SOF_TPLG_KCTL_ENUM_ID
, snd_sof_enum_get
, snd_sof_enum_put
},
3576 {SOF_TPLG_KCTL_SWITCH_ID
, snd_sof_switch_get
, snd_sof_switch_put
},
3579 /* vendor specific bytes ext handlers available for binding */
3580 static const struct snd_soc_tplg_bytes_ext_ops sof_bytes_ext_ops
[] = {
3581 {SOF_TPLG_KCTL_BYTES_ID
, snd_sof_bytes_ext_get
, snd_sof_bytes_ext_put
},
3584 static struct snd_soc_tplg_ops sof_tplg_ops
= {
3585 /* external kcontrol init - used for any driver specific init */
3586 .control_load
= sof_control_load
,
3587 .control_unload
= sof_control_unload
,
3589 /* external kcontrol init - used for any driver specific init */
3590 .dapm_route_load
= sof_route_load
,
3591 .dapm_route_unload
= sof_route_unload
,
3593 /* external widget init - used for any driver specific init */
3594 /* .widget_load is not currently used */
3595 .widget_ready
= sof_widget_ready
,
3596 .widget_unload
= sof_widget_unload
,
3598 /* FE DAI - used for any driver specific init */
3599 .dai_load
= sof_dai_load
,
3600 .dai_unload
= sof_dai_unload
,
3602 /* DAI link - used for any driver specific init */
3603 .link_load
= sof_link_load
,
3604 .link_unload
= sof_link_unload
,
3606 /* completion - called at completion of firmware loading */
3607 .complete
= sof_complete
,
3609 /* manifest - optional to inform component of manifest */
3610 .manifest
= sof_manifest
,
3612 /* vendor specific kcontrol handlers available for binding */
3613 .io_ops
= sof_io_ops
,
3614 .io_ops_count
= ARRAY_SIZE(sof_io_ops
),
3616 /* vendor specific bytes ext handlers available for binding */
3617 .bytes_ext_ops
= sof_bytes_ext_ops
,
3618 .bytes_ext_ops_count
= ARRAY_SIZE(sof_bytes_ext_ops
),
3621 int snd_sof_load_topology(struct snd_soc_component
*scomp
, const char *file
)
3623 const struct firmware
*fw
;
3626 dev_dbg(scomp
->dev
, "loading topology:%s\n", file
);
3628 ret
= request_firmware(&fw
, file
, scomp
->dev
);
3630 dev_err(scomp
->dev
, "error: tplg request firmware %s failed err: %d\n",
3635 ret
= snd_soc_tplg_component_load(scomp
,
3637 SND_SOC_TPLG_INDEX_ALL
);
3639 dev_err(scomp
->dev
, "error: tplg component load failed %d\n",
3644 release_firmware(fw
);
3647 EXPORT_SYMBOL(snd_sof_load_topology
);