1 // SPDX-License-Identifier: (GPL-2.0-only 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) 2022 Intel Corporation. All rights reserved.
11 #include "sof-audio.h"
12 #include "ipc4-priv.h"
13 #include "ipc4-topology.h"
15 static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control
*scontrol
,
18 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
19 struct snd_soc_component
*scomp
= scontrol
->scomp
;
20 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
21 const struct sof_ipc_ops
*iops
= sdev
->ipc
->ops
;
22 struct sof_ipc4_msg
*msg
= &cdata
->msg
;
23 struct snd_sof_widget
*swidget
;
24 bool widget_found
= false;
27 /* find widget associated with the control */
28 list_for_each_entry(swidget
, &sdev
->widget_list
, list
) {
29 if (swidget
->comp_id
== scontrol
->comp_id
) {
36 dev_err(scomp
->dev
, "Failed to find widget for kcontrol %s\n", scontrol
->name
);
41 mutex_lock(&swidget
->setup_mutex
);
43 lockdep_assert_held(&swidget
->setup_mutex
);
46 * Volatile controls should always be part of static pipelines and the
47 * widget use_count would always be > 0 in this case. For the others,
48 * just return the cached value if the widget is not set up.
50 if (!swidget
->use_count
)
53 msg
->primary
&= ~SOF_IPC4_MOD_INSTANCE_MASK
;
54 msg
->primary
|= SOF_IPC4_MOD_INSTANCE(swidget
->instance_id
);
56 ret
= iops
->set_get_data(sdev
, msg
, msg
->data_size
, set
);
60 /* It is a set-data operation, and we have a valid backup that we can restore */
62 if (!scontrol
->old_ipc_control_data
)
65 * Current ipc_control_data is not valid, we use the last known good
68 memcpy(scontrol
->ipc_control_data
, scontrol
->old_ipc_control_data
,
70 kfree(scontrol
->old_ipc_control_data
);
71 scontrol
->old_ipc_control_data
= NULL
;
72 /* Send the last known good configuration to firmware */
73 ret
= iops
->set_get_data(sdev
, msg
, msg
->data_size
, set
);
80 mutex_unlock(&swidget
->setup_mutex
);
86 sof_ipc4_set_volume_data(struct snd_sof_dev
*sdev
, struct snd_sof_widget
*swidget
,
87 struct snd_sof_control
*scontrol
, bool lock
)
89 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
90 struct sof_ipc4_gain
*gain
= swidget
->private;
91 struct sof_ipc4_msg
*msg
= &cdata
->msg
;
92 struct sof_ipc4_gain_data data
;
93 bool all_channels_equal
= true;
97 /* check if all channel values are equal */
98 value
= cdata
->chanv
[0].value
;
99 for (i
= 1; i
< scontrol
->num_channels
; i
++) {
100 if (cdata
->chanv
[i
].value
!= value
) {
101 all_channels_equal
= false;
107 * notify DSP with a single IPC message if all channel values are equal. Otherwise send
108 * a separate IPC for each channel.
110 for (i
= 0; i
< scontrol
->num_channels
; i
++) {
111 if (all_channels_equal
) {
112 data
.channels
= SOF_IPC4_GAIN_ALL_CHANNELS_MASK
;
113 data
.init_val
= cdata
->chanv
[0].value
;
115 data
.channels
= cdata
->chanv
[i
].channel
;
116 data
.init_val
= cdata
->chanv
[i
].value
;
119 /* set curve type and duration from topology */
120 data
.curve_duration_l
= gain
->data
.curve_duration_l
;
121 data
.curve_duration_h
= gain
->data
.curve_duration_h
;
122 data
.curve_type
= gain
->data
.curve_type
;
124 msg
->data_ptr
= &data
;
125 msg
->data_size
= sizeof(data
);
127 ret
= sof_ipc4_set_get_kcontrol_data(scontrol
, true, lock
);
128 msg
->data_ptr
= NULL
;
131 dev_err(sdev
->dev
, "Failed to set volume update for %s\n",
136 if (all_channels_equal
)
143 static bool sof_ipc4_volume_put(struct snd_sof_control
*scontrol
,
144 struct snd_ctl_elem_value
*ucontrol
)
146 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
147 struct snd_soc_component
*scomp
= scontrol
->scomp
;
148 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
149 unsigned int channels
= scontrol
->num_channels
;
150 struct snd_sof_widget
*swidget
;
151 bool widget_found
= false;
156 /* update each channel */
157 for (i
= 0; i
< channels
; i
++) {
158 u32 value
= mixer_to_ipc(ucontrol
->value
.integer
.value
[i
],
159 scontrol
->volume_table
, scontrol
->max
+ 1);
161 change
= change
|| (value
!= cdata
->chanv
[i
].value
);
162 cdata
->chanv
[i
].channel
= i
;
163 cdata
->chanv
[i
].value
= value
;
166 if (!pm_runtime_active(scomp
->dev
))
169 /* find widget associated with the control */
170 list_for_each_entry(swidget
, &sdev
->widget_list
, list
) {
171 if (swidget
->comp_id
== scontrol
->comp_id
) {
178 dev_err(scomp
->dev
, "Failed to find widget for kcontrol %s\n", scontrol
->name
);
182 ret
= sof_ipc4_set_volume_data(sdev
, swidget
, scontrol
, true);
189 static int sof_ipc4_volume_get(struct snd_sof_control
*scontrol
,
190 struct snd_ctl_elem_value
*ucontrol
)
192 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
193 unsigned int channels
= scontrol
->num_channels
;
196 for (i
= 0; i
< channels
; i
++)
197 ucontrol
->value
.integer
.value
[i
] = ipc_to_mixer(cdata
->chanv
[i
].value
,
198 scontrol
->volume_table
,
205 sof_ipc4_set_generic_control_data(struct snd_sof_dev
*sdev
,
206 struct snd_sof_widget
*swidget
,
207 struct snd_sof_control
*scontrol
, bool lock
)
209 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
210 struct sof_ipc4_control_msg_payload
*data
;
211 struct sof_ipc4_msg
*msg
= &cdata
->msg
;
216 data_size
= struct_size(data
, chanv
, scontrol
->num_channels
);
217 data
= kzalloc(data_size
, GFP_KERNEL
);
221 data
->id
= cdata
->index
;
222 data
->num_elems
= scontrol
->num_channels
;
223 for (i
= 0; i
< scontrol
->num_channels
; i
++) {
224 data
->chanv
[i
].channel
= cdata
->chanv
[i
].channel
;
225 data
->chanv
[i
].value
= cdata
->chanv
[i
].value
;
228 msg
->data_ptr
= data
;
229 msg
->data_size
= data_size
;
231 ret
= sof_ipc4_set_get_kcontrol_data(scontrol
, true, lock
);
232 msg
->data_ptr
= NULL
;
235 dev_err(sdev
->dev
, "Failed to set control update for %s\n",
243 static bool sof_ipc4_switch_put(struct snd_sof_control
*scontrol
,
244 struct snd_ctl_elem_value
*ucontrol
)
246 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
247 struct snd_soc_component
*scomp
= scontrol
->scomp
;
248 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
249 struct snd_sof_widget
*swidget
;
250 bool widget_found
= false;
256 /* update each channel */
257 for (i
= 0; i
< scontrol
->num_channels
; i
++) {
258 value
= ucontrol
->value
.integer
.value
[i
];
259 change
= change
|| (value
!= cdata
->chanv
[i
].value
);
260 cdata
->chanv
[i
].channel
= i
;
261 cdata
->chanv
[i
].value
= value
;
264 if (!pm_runtime_active(scomp
->dev
))
267 /* find widget associated with the control */
268 list_for_each_entry(swidget
, &sdev
->widget_list
, list
) {
269 if (swidget
->comp_id
== scontrol
->comp_id
) {
276 dev_err(scomp
->dev
, "Failed to find widget for kcontrol %s\n", scontrol
->name
);
280 ret
= sof_ipc4_set_generic_control_data(sdev
, swidget
, scontrol
, true);
287 static int sof_ipc4_switch_get(struct snd_sof_control
*scontrol
,
288 struct snd_ctl_elem_value
*ucontrol
)
290 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
293 /* read back each channel */
294 for (i
= 0; i
< scontrol
->num_channels
; i
++)
295 ucontrol
->value
.integer
.value
[i
] = cdata
->chanv
[i
].value
;
300 static bool sof_ipc4_enum_put(struct snd_sof_control
*scontrol
,
301 struct snd_ctl_elem_value
*ucontrol
)
303 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
304 struct snd_soc_component
*scomp
= scontrol
->scomp
;
305 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
306 struct snd_sof_widget
*swidget
;
307 bool widget_found
= false;
313 /* update each channel */
314 for (i
= 0; i
< scontrol
->num_channels
; i
++) {
315 value
= ucontrol
->value
.enumerated
.item
[i
];
316 change
= change
|| (value
!= cdata
->chanv
[i
].value
);
317 cdata
->chanv
[i
].channel
= i
;
318 cdata
->chanv
[i
].value
= value
;
321 if (!pm_runtime_active(scomp
->dev
))
324 /* find widget associated with the control */
325 list_for_each_entry(swidget
, &sdev
->widget_list
, list
) {
326 if (swidget
->comp_id
== scontrol
->comp_id
) {
333 dev_err(scomp
->dev
, "Failed to find widget for kcontrol %s\n", scontrol
->name
);
337 ret
= sof_ipc4_set_generic_control_data(sdev
, swidget
, scontrol
, true);
344 static int sof_ipc4_enum_get(struct snd_sof_control
*scontrol
,
345 struct snd_ctl_elem_value
*ucontrol
)
347 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
350 /* read back each channel */
351 for (i
= 0; i
< scontrol
->num_channels
; i
++)
352 ucontrol
->value
.enumerated
.item
[i
] = cdata
->chanv
[i
].value
;
357 static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev
*sdev
,
358 struct snd_sof_control
*scontrol
,
361 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
362 struct sof_abi_hdr
*data
= cdata
->data
;
363 struct sof_ipc4_msg
*msg
= &cdata
->msg
;
366 /* Send the new data to the firmware only if it is powered up */
367 if (set
&& !pm_runtime_active(sdev
->dev
))
370 msg
->extension
= SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data
->type
);
372 msg
->data_ptr
= data
->data
;
373 msg
->data_size
= data
->size
;
375 ret
= sof_ipc4_set_get_kcontrol_data(scontrol
, set
, lock
);
377 dev_err(sdev
->dev
, "Failed to %s for %s\n",
378 set
? "set bytes update" : "get bytes",
381 msg
->data_ptr
= NULL
;
387 static int sof_ipc4_bytes_put(struct snd_sof_control
*scontrol
,
388 struct snd_ctl_elem_value
*ucontrol
)
390 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
391 struct snd_soc_component
*scomp
= scontrol
->scomp
;
392 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
393 struct sof_abi_hdr
*data
= cdata
->data
;
396 if (scontrol
->max_size
> sizeof(ucontrol
->value
.bytes
.data
)) {
397 dev_err_ratelimited(scomp
->dev
,
398 "data max %zu exceeds ucontrol data array size\n",
403 /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */
404 if (data
->size
> scontrol
->max_size
- sizeof(*data
)) {
405 dev_err_ratelimited(scomp
->dev
,
406 "data size too big %u bytes max is %zu\n",
407 data
->size
, scontrol
->max_size
- sizeof(*data
));
411 size
= data
->size
+ sizeof(*data
);
413 /* copy from kcontrol */
414 memcpy(data
, ucontrol
->value
.bytes
.data
, size
);
416 sof_ipc4_set_get_bytes_data(sdev
, scontrol
, true, true);
421 static int sof_ipc4_bytes_get(struct snd_sof_control
*scontrol
,
422 struct snd_ctl_elem_value
*ucontrol
)
424 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
425 struct snd_soc_component
*scomp
= scontrol
->scomp
;
426 struct sof_abi_hdr
*data
= cdata
->data
;
429 if (scontrol
->max_size
> sizeof(ucontrol
->value
.bytes
.data
)) {
430 dev_err_ratelimited(scomp
->dev
, "data max %zu exceeds ucontrol data array size\n",
435 if (data
->size
> scontrol
->max_size
- sizeof(*data
)) {
436 dev_err_ratelimited(scomp
->dev
,
437 "%u bytes of control data is invalid, max is %zu\n",
438 data
->size
, scontrol
->max_size
- sizeof(*data
));
442 size
= data
->size
+ sizeof(*data
);
444 /* copy back to kcontrol */
445 memcpy(ucontrol
->value
.bytes
.data
, data
, size
);
450 static int sof_ipc4_bytes_ext_put(struct snd_sof_control
*scontrol
,
451 const unsigned int __user
*binary_data
,
454 struct snd_ctl_tlv __user
*tlvd
= (struct snd_ctl_tlv __user
*)binary_data
;
455 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
456 struct snd_soc_component
*scomp
= scontrol
->scomp
;
457 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
458 struct sof_abi_hdr
*data
= cdata
->data
;
459 struct sof_abi_hdr abi_hdr
;
460 struct snd_ctl_tlv header
;
463 * The beginning of bytes data contains a header from where
464 * the length (as bytes) is needed to know the correct copy
465 * length of data from tlvd->tlv.
467 if (copy_from_user(&header
, tlvd
, sizeof(struct snd_ctl_tlv
)))
470 /* make sure TLV info is consistent */
471 if (header
.length
+ sizeof(struct snd_ctl_tlv
) > size
) {
472 dev_err_ratelimited(scomp
->dev
,
473 "Inconsistent TLV, data %d + header %zu > %d\n",
474 header
.length
, sizeof(struct snd_ctl_tlv
), size
);
478 /* be->max is coming from topology */
479 if (header
.length
> scontrol
->max_size
) {
480 dev_err_ratelimited(scomp
->dev
,
481 "Bytes data size %d exceeds max %zu\n",
482 header
.length
, scontrol
->max_size
);
486 /* Verify the ABI header first */
487 if (copy_from_user(&abi_hdr
, tlvd
->tlv
, sizeof(abi_hdr
)))
490 if (abi_hdr
.magic
!= SOF_IPC4_ABI_MAGIC
) {
491 dev_err_ratelimited(scomp
->dev
, "Wrong ABI magic 0x%08x\n",
496 if (abi_hdr
.size
> scontrol
->max_size
- sizeof(abi_hdr
)) {
497 dev_err_ratelimited(scomp
->dev
,
498 "%u bytes of control data is invalid, max is %zu\n",
499 abi_hdr
.size
, scontrol
->max_size
- sizeof(abi_hdr
));
503 if (!scontrol
->old_ipc_control_data
) {
504 /* Create a backup of the current, valid bytes control */
505 scontrol
->old_ipc_control_data
= kmemdup(scontrol
->ipc_control_data
,
506 scontrol
->max_size
, GFP_KERNEL
);
507 if (!scontrol
->old_ipc_control_data
)
511 /* Copy the whole binary data which includes the ABI header and the payload */
512 if (copy_from_user(data
, tlvd
->tlv
, header
.length
)) {
513 memcpy(scontrol
->ipc_control_data
, scontrol
->old_ipc_control_data
,
515 kfree(scontrol
->old_ipc_control_data
);
516 scontrol
->old_ipc_control_data
= NULL
;
520 return sof_ipc4_set_get_bytes_data(sdev
, scontrol
, true, true);
523 static int _sof_ipc4_bytes_ext_get(struct snd_sof_control
*scontrol
,
524 const unsigned int __user
*binary_data
,
525 unsigned int size
, bool from_dsp
)
527 struct snd_ctl_tlv __user
*tlvd
= (struct snd_ctl_tlv __user
*)binary_data
;
528 struct sof_ipc4_control_data
*cdata
= scontrol
->ipc_control_data
;
529 struct snd_soc_component
*scomp
= scontrol
->scomp
;
530 struct sof_abi_hdr
*data
= cdata
->data
;
531 struct snd_ctl_tlv header
;
535 * Decrement the limit by ext bytes header size to ensure the user space
536 * buffer is not exceeded.
538 if (size
< sizeof(struct snd_ctl_tlv
))
541 size
-= sizeof(struct snd_ctl_tlv
);
543 /* get all the component data from DSP */
545 struct snd_sof_dev
*sdev
= snd_soc_component_get_drvdata(scomp
);
546 int ret
= sof_ipc4_set_get_bytes_data(sdev
, scontrol
, false, true);
551 /* Set the ABI magic (if the control is not initialized) */
552 data
->magic
= SOF_IPC4_ABI_MAGIC
;
555 if (data
->size
> scontrol
->max_size
- sizeof(*data
)) {
556 dev_err_ratelimited(scomp
->dev
,
557 "%u bytes of control data is invalid, max is %zu\n",
558 data
->size
, scontrol
->max_size
- sizeof(*data
));
562 data_size
= data
->size
+ sizeof(struct sof_abi_hdr
);
564 /* make sure we don't exceed size provided by user space for data */
565 if (data_size
> size
)
568 header
.numid
= scontrol
->comp_id
;
569 header
.length
= data_size
;
571 if (copy_to_user(tlvd
, &header
, sizeof(struct snd_ctl_tlv
)))
574 if (copy_to_user(tlvd
->tlv
, data
, data_size
))
580 static int sof_ipc4_bytes_ext_get(struct snd_sof_control
*scontrol
,
581 const unsigned int __user
*binary_data
,
584 return _sof_ipc4_bytes_ext_get(scontrol
, binary_data
, size
, false);
587 static int sof_ipc4_bytes_ext_volatile_get(struct snd_sof_control
*scontrol
,
588 const unsigned int __user
*binary_data
,
591 return _sof_ipc4_bytes_ext_get(scontrol
, binary_data
, size
, true);
595 sof_ipc4_volsw_setup(struct snd_sof_dev
*sdev
, struct snd_sof_widget
*swidget
,
596 struct snd_sof_control
*scontrol
)
598 if (scontrol
->max
== 1)
599 return sof_ipc4_set_generic_control_data(sdev
, swidget
, scontrol
, false);
601 return sof_ipc4_set_volume_data(sdev
, swidget
, scontrol
, false);
604 /* set up all controls for the widget */
605 static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev
*sdev
, struct snd_sof_widget
*swidget
)
607 struct snd_sof_control
*scontrol
;
610 list_for_each_entry(scontrol
, &sdev
->kcontrol_list
, list
) {
611 if (scontrol
->comp_id
== swidget
->comp_id
) {
612 switch (scontrol
->info_type
) {
613 case SND_SOC_TPLG_CTL_VOLSW
:
614 case SND_SOC_TPLG_CTL_VOLSW_SX
:
615 case SND_SOC_TPLG_CTL_VOLSW_XR_SX
:
616 ret
= sof_ipc4_volsw_setup(sdev
, swidget
, scontrol
);
618 case SND_SOC_TPLG_CTL_BYTES
:
619 ret
= sof_ipc4_set_get_bytes_data(sdev
, scontrol
,
622 case SND_SOC_TPLG_CTL_ENUM
:
623 case SND_SOC_TPLG_CTL_ENUM_VALUE
:
624 ret
= sof_ipc4_set_generic_control_data(sdev
, swidget
,
633 "kcontrol %d set up failed for widget %s\n",
634 scontrol
->comp_id
, swidget
->widget
->name
);
644 sof_ipc4_set_up_volume_table(struct snd_sof_control
*scontrol
, int tlv
[SOF_TLV_ITEMS
], int size
)
648 /* init the volume table */
649 scontrol
->volume_table
= kcalloc(size
, sizeof(u32
), GFP_KERNEL
);
650 if (!scontrol
->volume_table
)
653 /* populate the volume table */
654 for (i
= 0; i
< size
; i
++) {
655 u32 val
= vol_compute_gain(i
, tlv
);
656 u64 q31val
= ((u64
)val
) << 15; /* Can be over Q1.31, need to saturate */
658 scontrol
->volume_table
[i
] = q31val
> SOF_IPC4_VOL_ZERO_DB
?
659 SOF_IPC4_VOL_ZERO_DB
: q31val
;
665 const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops
= {
666 .volume_put
= sof_ipc4_volume_put
,
667 .volume_get
= sof_ipc4_volume_get
,
668 .switch_put
= sof_ipc4_switch_put
,
669 .switch_get
= sof_ipc4_switch_get
,
670 .enum_put
= sof_ipc4_enum_put
,
671 .enum_get
= sof_ipc4_enum_get
,
672 .bytes_put
= sof_ipc4_bytes_put
,
673 .bytes_get
= sof_ipc4_bytes_get
,
674 .bytes_ext_put
= sof_ipc4_bytes_ext_put
,
675 .bytes_ext_get
= sof_ipc4_bytes_ext_get
,
676 .bytes_ext_volatile_get
= sof_ipc4_bytes_ext_volatile_get
,
677 .widget_kcontrol_setup
= sof_ipc4_widget_kcontrol_setup
,
678 .set_up_volume_table
= sof_ipc4_set_up_volume_table
,