arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / sof / ipc3-control.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
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.
5 //
6 // Copyright(c) 2021 Intel Corporation. All rights reserved.
7 //
8 //
9
10 #include "sof-priv.h"
11 #include "sof-audio.h"
12 #include "ipc3-priv.h"
13
14 /* IPC set()/get() for kcontrols. */
15 static int sof_ipc3_set_get_kcontrol_data(struct snd_sof_control *scontrol,
16                                           bool set, bool lock)
17 {
18         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp);
19         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
20         const struct sof_ipc_ops *iops = sdev->ipc->ops;
21         enum sof_ipc_ctrl_type ctrl_type;
22         struct snd_sof_widget *swidget;
23         bool widget_found = false;
24         u32 ipc_cmd, msg_bytes;
25         int ret = 0;
26
27         list_for_each_entry(swidget, &sdev->widget_list, list) {
28                 if (swidget->comp_id == scontrol->comp_id) {
29                         widget_found = true;
30                         break;
31                 }
32         }
33
34         if (!widget_found) {
35                 dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
36                         scontrol->comp_id);
37                 return -EINVAL;
38         }
39
40         if (lock)
41                 mutex_lock(&swidget->setup_mutex);
42         else
43                 lockdep_assert_held(&swidget->setup_mutex);
44
45         /*
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.
49          */
50         if (!swidget->use_count)
51                 goto unlock;
52
53         /*
54          * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
55          * direction
56          * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
57          *       for ctrl_type
58          */
59         if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
60                 ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
61                 ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
62         } else {
63                 ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
64                 ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
65         }
66
67         cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
68         cdata->type = ctrl_type;
69         cdata->comp_id = scontrol->comp_id;
70         cdata->msg_index = 0;
71
72         /* calculate header and data size */
73         switch (cdata->type) {
74         case SOF_CTRL_TYPE_VALUE_CHAN_GET:
75         case SOF_CTRL_TYPE_VALUE_CHAN_SET:
76                 cdata->num_elems = scontrol->num_channels;
77
78                 msg_bytes = scontrol->num_channels *
79                             sizeof(struct sof_ipc_ctrl_value_chan);
80                 msg_bytes += sizeof(struct sof_ipc_ctrl_data);
81                 break;
82         case SOF_CTRL_TYPE_DATA_GET:
83         case SOF_CTRL_TYPE_DATA_SET:
84                 cdata->num_elems = cdata->data->size;
85
86                 msg_bytes = cdata->data->size;
87                 msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
88                              sizeof(struct sof_abi_hdr);
89                 break;
90         default:
91                 ret = -EINVAL;
92                 goto unlock;
93         }
94
95         cdata->rhdr.hdr.size = msg_bytes;
96         cdata->elems_remaining = 0;
97
98         ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
99         if (!set)
100                 goto unlock;
101
102         /* It is a set-data operation, and we have a backup that we can restore */
103         if (ret < 0) {
104                 if (!scontrol->old_ipc_control_data)
105                         goto unlock;
106                 /*
107                  * Current ipc_control_data is not valid, we use the last known good
108                  * configuration
109                  */
110                 memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data,
111                        scontrol->max_size);
112                 kfree(scontrol->old_ipc_control_data);
113                 scontrol->old_ipc_control_data = NULL;
114                 /* Send the last known good configuration to firmware */
115                 ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
116                 if (ret < 0)
117                         goto unlock;
118         }
119
120 unlock:
121         if (lock)
122                 mutex_unlock(&swidget->setup_mutex);
123
124         return ret;
125 }
126
127 static void sof_ipc3_refresh_control(struct snd_sof_control *scontrol)
128 {
129         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
130         struct snd_soc_component *scomp = scontrol->scomp;
131         int ret;
132
133         if (!scontrol->comp_data_dirty)
134                 return;
135
136         if (!pm_runtime_active(scomp->dev))
137                 return;
138
139         /* set the ABI header values */
140         cdata->data->magic = SOF_ABI_MAGIC;
141         cdata->data->abi = SOF_ABI_VERSION;
142
143         /* refresh the component data from DSP */
144         scontrol->comp_data_dirty = false;
145         ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true);
146         if (ret < 0) {
147                 dev_err(scomp->dev, "Failed to get control data: %d\n", ret);
148
149                 /* Set the flag to re-try next time to get the data */
150                 scontrol->comp_data_dirty = true;
151         }
152 }
153
154 static int sof_ipc3_volume_get(struct snd_sof_control *scontrol,
155                                struct snd_ctl_elem_value *ucontrol)
156 {
157         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
158         unsigned int channels = scontrol->num_channels;
159         unsigned int i;
160
161         sof_ipc3_refresh_control(scontrol);
162
163         /* read back each channel */
164         for (i = 0; i < channels; i++)
165                 ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value,
166                                                                 scontrol->volume_table,
167                                                                 scontrol->max + 1);
168
169         return 0;
170 }
171
172 static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol,
173                                 struct snd_ctl_elem_value *ucontrol)
174 {
175         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
176         struct snd_soc_component *scomp = scontrol->scomp;
177         unsigned int channels = scontrol->num_channels;
178         unsigned int i;
179         bool change = false;
180
181         /* update each channel */
182         for (i = 0; i < channels; i++) {
183                 u32 value = mixer_to_ipc(ucontrol->value.integer.value[i],
184                                          scontrol->volume_table, scontrol->max + 1);
185
186                 change = change || (value != cdata->chanv[i].value);
187                 cdata->chanv[i].channel = i;
188                 cdata->chanv[i].value = value;
189         }
190
191         /* notify DSP of mixer updates */
192         if (pm_runtime_active(scomp->dev)) {
193                 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
194
195                 if (ret < 0) {
196                         dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
197                                 scontrol->name);
198                         return false;
199                 }
200         }
201
202         return change;
203 }
204
205 static int sof_ipc3_switch_get(struct snd_sof_control *scontrol,
206                                struct snd_ctl_elem_value *ucontrol)
207 {
208         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
209         unsigned int channels = scontrol->num_channels;
210         unsigned int i;
211
212         sof_ipc3_refresh_control(scontrol);
213
214         /* read back each channel */
215         for (i = 0; i < channels; i++)
216                 ucontrol->value.integer.value[i] = cdata->chanv[i].value;
217
218         return 0;
219 }
220
221 static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol,
222                                 struct snd_ctl_elem_value *ucontrol)
223 {
224         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
225         struct snd_soc_component *scomp = scontrol->scomp;
226         unsigned int channels = scontrol->num_channels;
227         unsigned int i;
228         bool change = false;
229         u32 value;
230
231         /* update each channel */
232         for (i = 0; i < channels; i++) {
233                 value = ucontrol->value.integer.value[i];
234                 change = change || (value != cdata->chanv[i].value);
235                 cdata->chanv[i].channel = i;
236                 cdata->chanv[i].value = value;
237         }
238
239         /* notify DSP of mixer updates */
240         if (pm_runtime_active(scomp->dev)) {
241                 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
242
243                 if (ret < 0) {
244                         dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
245                                 scontrol->name);
246                         return false;
247                 }
248         }
249
250         return change;
251 }
252
253 static int sof_ipc3_enum_get(struct snd_sof_control *scontrol,
254                              struct snd_ctl_elem_value *ucontrol)
255 {
256         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
257         unsigned int channels = scontrol->num_channels;
258         unsigned int i;
259
260         sof_ipc3_refresh_control(scontrol);
261
262         /* read back each channel */
263         for (i = 0; i < channels; i++)
264                 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
265
266         return 0;
267 }
268
269 static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol,
270                               struct snd_ctl_elem_value *ucontrol)
271 {
272         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
273         struct snd_soc_component *scomp = scontrol->scomp;
274         unsigned int channels = scontrol->num_channels;
275         unsigned int i;
276         bool change = false;
277         u32 value;
278
279         /* update each channel */
280         for (i = 0; i < channels; i++) {
281                 value = ucontrol->value.enumerated.item[i];
282                 change = change || (value != cdata->chanv[i].value);
283                 cdata->chanv[i].channel = i;
284                 cdata->chanv[i].value = value;
285         }
286
287         /* notify DSP of enum updates */
288         if (pm_runtime_active(scomp->dev)) {
289                 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
290
291                 if (ret < 0) {
292                         dev_err(scomp->dev, "Failed to set enum updates for %s\n",
293                                 scontrol->name);
294                         return false;
295                 }
296         }
297
298         return change;
299 }
300
301 static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol,
302                               struct snd_ctl_elem_value *ucontrol)
303 {
304         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
305         struct snd_soc_component *scomp = scontrol->scomp;
306         struct sof_abi_hdr *data = cdata->data;
307         size_t size;
308
309         sof_ipc3_refresh_control(scontrol);
310
311         if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
312                 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
313                                     scontrol->max_size);
314                 return -EINVAL;
315         }
316
317         /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
318         if (data->size > scontrol->max_size - sizeof(*data)) {
319                 dev_err_ratelimited(scomp->dev,
320                                     "%u bytes of control data is invalid, max is %zu\n",
321                                     data->size, scontrol->max_size - sizeof(*data));
322                 return -EINVAL;
323         }
324
325         size = data->size + sizeof(*data);
326
327         /* copy back to kcontrol */
328         memcpy(ucontrol->value.bytes.data, data, size);
329
330         return 0;
331 }
332
333 static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
334                               struct snd_ctl_elem_value *ucontrol)
335 {
336         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
337         struct snd_soc_component *scomp = scontrol->scomp;
338         struct sof_abi_hdr *data = cdata->data;
339         size_t size;
340
341         if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
342                 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
343                                     scontrol->max_size);
344                 return -EINVAL;
345         }
346
347         /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */
348         if (data->size > scontrol->max_size - sizeof(*data)) {
349                 dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n",
350                                     data->size, scontrol->max_size - sizeof(*data));
351                 return -EINVAL;
352         }
353
354         size = data->size + sizeof(*data);
355
356         /* copy from kcontrol */
357         memcpy(data, ucontrol->value.bytes.data, size);
358
359         /* notify DSP of byte control updates */
360         if (pm_runtime_active(scomp->dev))
361                 return sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
362
363         return 0;
364 }
365
366 static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
367                                   const unsigned int __user *binary_data,
368                                   unsigned int size)
369 {
370         const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data;
371         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
372         struct snd_soc_component *scomp = scontrol->scomp;
373         struct snd_ctl_tlv header;
374         int ret = -EINVAL;
375
376         /*
377          * The beginning of bytes data contains a header from where
378          * the length (as bytes) is needed to know the correct copy
379          * length of data from tlvd->tlv.
380          */
381         if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv)))
382                 return -EFAULT;
383
384         /* make sure TLV info is consistent */
385         if (header.length + sizeof(struct snd_ctl_tlv) > size) {
386                 dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n",
387                                     header.length, sizeof(struct snd_ctl_tlv), size);
388                 return -EINVAL;
389         }
390
391         /* be->max is coming from topology */
392         if (header.length > scontrol->max_size) {
393                 dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n",
394                                     header.length, scontrol->max_size);
395                 return -EINVAL;
396         }
397
398         /* Check that header id matches the command */
399         if (header.numid != cdata->cmd) {
400                 dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n",
401                                     header.numid);
402                 return -EINVAL;
403         }
404
405         if (!scontrol->old_ipc_control_data) {
406                 /* Create a backup of the current, valid bytes control */
407                 scontrol->old_ipc_control_data = kmemdup(scontrol->ipc_control_data,
408                                                          scontrol->max_size, GFP_KERNEL);
409                 if (!scontrol->old_ipc_control_data)
410                         return -ENOMEM;
411         }
412
413         if (copy_from_user(cdata->data, tlvd->tlv, header.length)) {
414                 ret = -EFAULT;
415                 goto err_restore;
416         }
417
418         if (cdata->data->magic != SOF_ABI_MAGIC) {
419                 dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic);
420                 goto err_restore;
421         }
422
423         if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
424                 dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n",
425                                     cdata->data->abi);
426                 goto err_restore;
427         }
428
429         /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
430         if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
431                 dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n");
432                 goto err_restore;
433         }
434
435         /* notify DSP of byte control updates */
436         if (pm_runtime_active(scomp->dev)) {
437                 /* Actually send the data to the DSP; this is an opportunity to validate the data */
438                 return sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
439         }
440
441         return 0;
442
443 err_restore:
444         /* If we have an issue, we restore the old, valid bytes control data */
445         if (scontrol->old_ipc_control_data) {
446                 memcpy(cdata->data, scontrol->old_ipc_control_data, scontrol->max_size);
447                 kfree(scontrol->old_ipc_control_data);
448                 scontrol->old_ipc_control_data = NULL;
449         }
450         return ret;
451 }
452
453 static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
454                                    const unsigned int __user *binary_data,
455                                    unsigned int size, bool from_dsp)
456 {
457         struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
458         struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
459         struct snd_soc_component *scomp = scontrol->scomp;
460         struct snd_ctl_tlv header;
461         size_t data_size;
462
463         /*
464          * Decrement the limit by ext bytes header size to
465          * ensure the user space buffer is not exceeded.
466          */
467         if (size < sizeof(struct snd_ctl_tlv))
468                 return -ENOSPC;
469
470         size -= sizeof(struct snd_ctl_tlv);
471
472         /* set the ABI header values */
473         cdata->data->magic = SOF_ABI_MAGIC;
474         cdata->data->abi = SOF_ABI_VERSION;
475
476         /* get all the component data from DSP */
477         if (from_dsp) {
478                 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true);
479
480                 if (ret < 0)
481                         return ret;
482         }
483
484         /* check data size doesn't exceed max coming from topology */
485         if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
486                 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n",
487                                     cdata->data->size,
488                                     scontrol->max_size - sizeof(struct sof_abi_hdr));
489                 return -EINVAL;
490         }
491
492         data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
493
494         /* make sure we don't exceed size provided by user space for data */
495         if (data_size > size)
496                 return -ENOSPC;
497
498         header.numid = cdata->cmd;
499         header.length = data_size;
500         if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
501                 return -EFAULT;
502
503         if (copy_to_user(tlvd->tlv, cdata->data, data_size))
504                 return -EFAULT;
505
506         return 0;
507 }
508
509 static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
510                                   const unsigned int __user *binary_data, unsigned int size)
511 {
512         return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, false);
513 }
514
515 static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol,
516                                            const unsigned int __user *binary_data,
517                                            unsigned int size)
518 {
519         return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, true);
520 }
521
522 static void snd_sof_update_control(struct snd_sof_control *scontrol,
523                                    struct sof_ipc_ctrl_data *cdata)
524 {
525         struct snd_soc_component *scomp = scontrol->scomp;
526         struct sof_ipc_ctrl_data *local_cdata;
527         int i;
528
529         local_cdata = scontrol->ipc_control_data;
530
531         if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
532                 if (cdata->num_elems != local_cdata->data->size) {
533                         dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n",
534                                 cdata->num_elems, local_cdata->data->size);
535                         return;
536                 }
537
538                 /* copy the new binary data */
539                 memcpy(local_cdata->data, cdata->data, cdata->num_elems);
540         } else if (cdata->num_elems != scontrol->num_channels) {
541                 dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n",
542                         cdata->num_elems, scontrol->num_channels);
543         } else {
544                 /* copy the new values */
545                 for (i = 0; i < cdata->num_elems; i++)
546                         local_cdata->chanv[i].value = cdata->chanv[i].value;
547         }
548 }
549
550 static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_message)
551 {
552         struct sof_ipc_ctrl_data *cdata = ipc_control_message;
553         struct snd_soc_dapm_widget *widget;
554         struct snd_sof_control *scontrol;
555         struct snd_sof_widget *swidget;
556         struct snd_kcontrol *kc = NULL;
557         struct soc_mixer_control *sm;
558         struct soc_bytes_ext *be;
559         size_t expected_size;
560         struct soc_enum *se;
561         bool found = false;
562         int i, type;
563
564         if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET ||
565             cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) {
566                 dev_err(sdev->dev, "Component data is not supported in control notification\n");
567                 return;
568         }
569
570         /* Find the swidget first */
571         list_for_each_entry(swidget, &sdev->widget_list, list) {
572                 if (swidget->comp_id == cdata->comp_id) {
573                         found = true;
574                         break;
575                 }
576         }
577
578         if (!found)
579                 return;
580
581         /* Translate SOF cmd to TPLG type */
582         switch (cdata->cmd) {
583         case SOF_CTRL_CMD_VOLUME:
584         case SOF_CTRL_CMD_SWITCH:
585                 type = SND_SOC_TPLG_TYPE_MIXER;
586                 break;
587         case SOF_CTRL_CMD_BINARY:
588                 type = SND_SOC_TPLG_TYPE_BYTES;
589                 break;
590         case SOF_CTRL_CMD_ENUM:
591                 type = SND_SOC_TPLG_TYPE_ENUM;
592                 break;
593         default:
594                 dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__);
595                 return;
596         }
597
598         widget = swidget->widget;
599         for (i = 0; i < widget->num_kcontrols; i++) {
600                 /* skip non matching types or non matching indexes within type */
601                 if (widget->dobj.widget.kcontrol_type[i] == type &&
602                     widget->kcontrol_news[i].index == cdata->index) {
603                         kc = widget->kcontrols[i];
604                         break;
605                 }
606         }
607
608         if (!kc)
609                 return;
610
611         switch (cdata->cmd) {
612         case SOF_CTRL_CMD_VOLUME:
613         case SOF_CTRL_CMD_SWITCH:
614                 sm = (struct soc_mixer_control *)kc->private_value;
615                 scontrol = sm->dobj.private;
616                 break;
617         case SOF_CTRL_CMD_BINARY:
618                 be = (struct soc_bytes_ext *)kc->private_value;
619                 scontrol = be->dobj.private;
620                 break;
621         case SOF_CTRL_CMD_ENUM:
622                 se = (struct soc_enum *)kc->private_value;
623                 scontrol = se->dobj.private;
624                 break;
625         default:
626                 return;
627         }
628
629         expected_size = sizeof(struct sof_ipc_ctrl_data);
630         switch (cdata->type) {
631         case SOF_CTRL_TYPE_VALUE_CHAN_GET:
632         case SOF_CTRL_TYPE_VALUE_CHAN_SET:
633                 expected_size += cdata->num_elems *
634                                  sizeof(struct sof_ipc_ctrl_value_chan);
635                 break;
636         case SOF_CTRL_TYPE_DATA_GET:
637         case SOF_CTRL_TYPE_DATA_SET:
638                 expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr);
639                 break;
640         default:
641                 return;
642         }
643
644         if (cdata->rhdr.hdr.size != expected_size) {
645                 dev_err(sdev->dev, "Component notification size mismatch\n");
646                 return;
647         }
648
649         if (cdata->num_elems)
650                 /*
651                  * The message includes the updated value/data, update the
652                  * control's local cache using the received notification
653                  */
654                 snd_sof_update_control(scontrol, cdata);
655         else
656                 /* Mark the scontrol that the value/data is changed in SOF */
657                 scontrol->comp_data_dirty = true;
658
659         snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0);
660 }
661
662 static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
663                                           struct snd_sof_widget *swidget)
664 {
665         struct snd_sof_control *scontrol;
666         int ret;
667
668         /* set up all controls for the widget */
669         list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
670                 if (scontrol->comp_id == swidget->comp_id) {
671                         /* set kcontrol data in DSP */
672                         ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, false);
673                         if (ret < 0) {
674                                 dev_err(sdev->dev,
675                                         "kcontrol %d set up failed for widget %s\n",
676                                         scontrol->comp_id, swidget->widget->name);
677                                 return ret;
678                         }
679
680                         /*
681                          * Read back the data from the DSP for static widgets.
682                          * This is particularly useful for binary kcontrols
683                          * associated with static pipeline widgets to initialize
684                          * the data size to match that in the DSP.
685                          */
686                         if (swidget->dynamic_pipeline_widget)
687                                 continue;
688
689                         ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, false);
690                         if (ret < 0)
691                                 dev_warn(sdev->dev,
692                                          "kcontrol %d read failed for widget %s\n",
693                                          scontrol->comp_id, swidget->widget->name);
694                 }
695
696         return 0;
697 }
698
699 static int
700 sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size)
701 {
702         int i;
703
704         /* init the volume table */
705         scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
706         if (!scontrol->volume_table)
707                 return -ENOMEM;
708
709         /* populate the volume table */
710         for (i = 0; i < size ; i++)
711                 scontrol->volume_table[i] = vol_compute_gain(i, tlv);
712
713         return 0;
714 }
715
716 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
717         .volume_put = sof_ipc3_volume_put,
718         .volume_get = sof_ipc3_volume_get,
719         .switch_put = sof_ipc3_switch_put,
720         .switch_get = sof_ipc3_switch_get,
721         .enum_put = sof_ipc3_enum_put,
722         .enum_get = sof_ipc3_enum_get,
723         .bytes_put = sof_ipc3_bytes_put,
724         .bytes_get = sof_ipc3_bytes_get,
725         .bytes_ext_put = sof_ipc3_bytes_ext_put,
726         .bytes_ext_get = sof_ipc3_bytes_ext_get,
727         .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
728         .update = sof_ipc3_control_update,
729         .widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
730         .set_up_volume_table = sof_ipc3_set_up_volume_table,
731 };