Merge tag 'asoc-fix-v6.9-merge-window' of https://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / sound / virtio / virtio_kctl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * virtio-snd: Virtio sound device
4  * Copyright (C) 2022 OpenSynergy GmbH
5  */
6 #include <sound/control.h>
7 #include <linux/virtio_config.h>
8
9 #include "virtio_card.h"
10
11 /* Map for converting VirtIO types to ALSA types. */
12 static const snd_ctl_elem_type_t g_v2a_type_map[] = {
13         [VIRTIO_SND_CTL_TYPE_BOOLEAN] = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
14         [VIRTIO_SND_CTL_TYPE_INTEGER] = SNDRV_CTL_ELEM_TYPE_INTEGER,
15         [VIRTIO_SND_CTL_TYPE_INTEGER64] = SNDRV_CTL_ELEM_TYPE_INTEGER64,
16         [VIRTIO_SND_CTL_TYPE_ENUMERATED] = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
17         [VIRTIO_SND_CTL_TYPE_BYTES] = SNDRV_CTL_ELEM_TYPE_BYTES,
18         [VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
19 };
20
21 /* Map for converting VirtIO access rights to ALSA access rights. */
22 static const unsigned int g_v2a_access_map[] = {
23         [VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
24         [VIRTIO_SND_CTL_ACCESS_WRITE] = SNDRV_CTL_ELEM_ACCESS_WRITE,
25         [VIRTIO_SND_CTL_ACCESS_VOLATILE] = SNDRV_CTL_ELEM_ACCESS_VOLATILE,
26         [VIRTIO_SND_CTL_ACCESS_INACTIVE] = SNDRV_CTL_ELEM_ACCESS_INACTIVE,
27         [VIRTIO_SND_CTL_ACCESS_TLV_READ] = SNDRV_CTL_ELEM_ACCESS_TLV_READ,
28         [VIRTIO_SND_CTL_ACCESS_TLV_WRITE] = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE,
29         [VIRTIO_SND_CTL_ACCESS_TLV_COMMAND] = SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND
30 };
31
32 /* Map for converting VirtIO event masks to ALSA event masks. */
33 static const unsigned int g_v2a_mask_map[] = {
34         [VIRTIO_SND_CTL_EVT_MASK_VALUE] = SNDRV_CTL_EVENT_MASK_VALUE,
35         [VIRTIO_SND_CTL_EVT_MASK_INFO] = SNDRV_CTL_EVENT_MASK_INFO,
36         [VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
37 };
38
39 /**
40  * virtsnd_kctl_info() - Returns information about the control.
41  * @kcontrol: ALSA control element.
42  * @uinfo: Element information.
43  *
44  * Context: Process context.
45  * Return: 0 on success, -errno on failure.
46  */
47 static int virtsnd_kctl_info(struct snd_kcontrol *kcontrol,
48                              struct snd_ctl_elem_info *uinfo)
49 {
50         struct virtio_snd *snd = kcontrol->private_data;
51         struct virtio_kctl *kctl = &snd->kctls[kcontrol->private_value];
52         struct virtio_snd_ctl_info *kinfo =
53                 &snd->kctl_infos[kcontrol->private_value];
54         unsigned int i;
55
56         uinfo->type = g_v2a_type_map[le32_to_cpu(kinfo->type)];
57         uinfo->count = le32_to_cpu(kinfo->count);
58
59         switch (uinfo->type) {
60         case SNDRV_CTL_ELEM_TYPE_INTEGER:
61                 uinfo->value.integer.min =
62                         le32_to_cpu(kinfo->value.integer.min);
63                 uinfo->value.integer.max =
64                         le32_to_cpu(kinfo->value.integer.max);
65                 uinfo->value.integer.step =
66                         le32_to_cpu(kinfo->value.integer.step);
67
68                 break;
69         case SNDRV_CTL_ELEM_TYPE_INTEGER64:
70                 uinfo->value.integer64.min =
71                         le64_to_cpu(kinfo->value.integer64.min);
72                 uinfo->value.integer64.max =
73                         le64_to_cpu(kinfo->value.integer64.max);
74                 uinfo->value.integer64.step =
75                         le64_to_cpu(kinfo->value.integer64.step);
76
77                 break;
78         case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
79                 uinfo->value.enumerated.items =
80                         le32_to_cpu(kinfo->value.enumerated.items);
81                 i = uinfo->value.enumerated.item;
82                 if (i >= uinfo->value.enumerated.items)
83                         return -EINVAL;
84
85                 strscpy(uinfo->value.enumerated.name, kctl->items[i].item,
86                         sizeof(uinfo->value.enumerated.name));
87
88                 break;
89         }
90
91         return 0;
92 }
93
94 /**
95  * virtsnd_kctl_get() - Read the value from the control.
96  * @kcontrol: ALSA control element.
97  * @uvalue: Element value.
98  *
99  * Context: Process context.
100  * Return: 0 on success, -errno on failure.
101  */
102 static int virtsnd_kctl_get(struct snd_kcontrol *kcontrol,
103                             struct snd_ctl_elem_value *uvalue)
104 {
105         struct virtio_snd *snd = kcontrol->private_data;
106         struct virtio_snd_ctl_info *kinfo =
107                 &snd->kctl_infos[kcontrol->private_value];
108         unsigned int type = le32_to_cpu(kinfo->type);
109         unsigned int count = le32_to_cpu(kinfo->count);
110         struct virtio_snd_msg *msg;
111         struct virtio_snd_ctl_hdr *hdr;
112         struct virtio_snd_ctl_value *kvalue;
113         size_t request_size = sizeof(*hdr);
114         size_t response_size = sizeof(struct virtio_snd_hdr) + sizeof(*kvalue);
115         unsigned int i;
116         int rc;
117
118         msg = virtsnd_ctl_msg_alloc(request_size, response_size, GFP_KERNEL);
119         if (!msg)
120                 return -ENOMEM;
121
122         virtsnd_ctl_msg_ref(msg);
123
124         hdr = virtsnd_ctl_msg_request(msg);
125         hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_READ);
126         hdr->control_id = cpu_to_le32(kcontrol->private_value);
127
128         rc = virtsnd_ctl_msg_send_sync(snd, msg);
129         if (rc)
130                 goto on_failure;
131
132         kvalue = (void *)((u8 *)virtsnd_ctl_msg_response(msg) +
133                           sizeof(struct virtio_snd_hdr));
134
135         switch (type) {
136         case VIRTIO_SND_CTL_TYPE_BOOLEAN:
137         case VIRTIO_SND_CTL_TYPE_INTEGER:
138                 for (i = 0; i < count; ++i)
139                         uvalue->value.integer.value[i] =
140                                 le32_to_cpu(kvalue->value.integer[i]);
141                 break;
142         case VIRTIO_SND_CTL_TYPE_INTEGER64:
143                 for (i = 0; i < count; ++i)
144                         uvalue->value.integer64.value[i] =
145                                 le64_to_cpu(kvalue->value.integer64[i]);
146                 break;
147         case VIRTIO_SND_CTL_TYPE_ENUMERATED:
148                 for (i = 0; i < count; ++i)
149                         uvalue->value.enumerated.item[i] =
150                                 le32_to_cpu(kvalue->value.enumerated[i]);
151                 break;
152         case VIRTIO_SND_CTL_TYPE_BYTES:
153                 memcpy(uvalue->value.bytes.data, kvalue->value.bytes, count);
154                 break;
155         case VIRTIO_SND_CTL_TYPE_IEC958:
156                 memcpy(&uvalue->value.iec958, &kvalue->value.iec958,
157                        sizeof(uvalue->value.iec958));
158                 break;
159         }
160
161 on_failure:
162         virtsnd_ctl_msg_unref(msg);
163
164         return rc;
165 }
166
167 /**
168  * virtsnd_kctl_put() - Write the value to the control.
169  * @kcontrol: ALSA control element.
170  * @uvalue: Element value.
171  *
172  * Context: Process context.
173  * Return: 0 on success, -errno on failure.
174  */
175 static int virtsnd_kctl_put(struct snd_kcontrol *kcontrol,
176                             struct snd_ctl_elem_value *uvalue)
177 {
178         struct virtio_snd *snd = kcontrol->private_data;
179         struct virtio_snd_ctl_info *kinfo =
180                 &snd->kctl_infos[kcontrol->private_value];
181         unsigned int type = le32_to_cpu(kinfo->type);
182         unsigned int count = le32_to_cpu(kinfo->count);
183         struct virtio_snd_msg *msg;
184         struct virtio_snd_ctl_hdr *hdr;
185         struct virtio_snd_ctl_value *kvalue;
186         size_t request_size = sizeof(*hdr) + sizeof(*kvalue);
187         size_t response_size = sizeof(struct virtio_snd_hdr);
188         unsigned int i;
189
190         msg = virtsnd_ctl_msg_alloc(request_size, response_size, GFP_KERNEL);
191         if (!msg)
192                 return -ENOMEM;
193
194         hdr = virtsnd_ctl_msg_request(msg);
195         hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_WRITE);
196         hdr->control_id = cpu_to_le32(kcontrol->private_value);
197
198         kvalue = (void *)((u8 *)hdr + sizeof(*hdr));
199
200         switch (type) {
201         case VIRTIO_SND_CTL_TYPE_BOOLEAN:
202         case VIRTIO_SND_CTL_TYPE_INTEGER:
203                 for (i = 0; i < count; ++i)
204                         kvalue->value.integer[i] =
205                                 cpu_to_le32(uvalue->value.integer.value[i]);
206                 break;
207         case VIRTIO_SND_CTL_TYPE_INTEGER64:
208                 for (i = 0; i < count; ++i)
209                         kvalue->value.integer64[i] =
210                                 cpu_to_le64(uvalue->value.integer64.value[i]);
211                 break;
212         case VIRTIO_SND_CTL_TYPE_ENUMERATED:
213                 for (i = 0; i < count; ++i)
214                         kvalue->value.enumerated[i] =
215                                 cpu_to_le32(uvalue->value.enumerated.item[i]);
216                 break;
217         case VIRTIO_SND_CTL_TYPE_BYTES:
218                 memcpy(kvalue->value.bytes, uvalue->value.bytes.data, count);
219                 break;
220         case VIRTIO_SND_CTL_TYPE_IEC958:
221                 memcpy(&kvalue->value.iec958, &uvalue->value.iec958,
222                        sizeof(kvalue->value.iec958));
223                 break;
224         }
225
226         return virtsnd_ctl_msg_send_sync(snd, msg);
227 }
228
229 /**
230  * virtsnd_kctl_tlv_op() - Perform an operation on the control's metadata.
231  * @kcontrol: ALSA control element.
232  * @op_flag: Operation code (SNDRV_CTL_TLV_OP_XXX).
233  * @size: Size of the TLV data in bytes.
234  * @utlv: TLV data.
235  *
236  * Context: Process context.
237  * Return: 0 on success, -errno on failure.
238  */
239 static int virtsnd_kctl_tlv_op(struct snd_kcontrol *kcontrol, int op_flag,
240                                unsigned int size, unsigned int __user *utlv)
241 {
242         struct virtio_snd *snd = kcontrol->private_data;
243         struct virtio_snd_msg *msg;
244         struct virtio_snd_ctl_hdr *hdr;
245         unsigned int *tlv;
246         struct scatterlist sg;
247         int rc;
248
249         msg = virtsnd_ctl_msg_alloc(sizeof(*hdr), sizeof(struct virtio_snd_hdr),
250                                     GFP_KERNEL);
251         if (!msg)
252                 return -ENOMEM;
253
254         tlv = kzalloc(size, GFP_KERNEL);
255         if (!tlv) {
256                 rc = -ENOMEM;
257                 goto on_msg_unref;
258         }
259
260         sg_init_one(&sg, tlv, size);
261
262         hdr = virtsnd_ctl_msg_request(msg);
263         hdr->control_id = cpu_to_le32(kcontrol->private_value);
264
265         switch (op_flag) {
266         case SNDRV_CTL_TLV_OP_READ:
267                 hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_TLV_READ);
268
269                 rc = virtsnd_ctl_msg_send(snd, msg, NULL, &sg, false);
270                 if (!rc) {
271                         if (copy_to_user(utlv, tlv, size))
272                                 rc = -EFAULT;
273                 }
274
275                 break;
276         case SNDRV_CTL_TLV_OP_WRITE:
277         case SNDRV_CTL_TLV_OP_CMD:
278                 if (op_flag == SNDRV_CTL_TLV_OP_WRITE)
279                         hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_TLV_WRITE);
280                 else
281                         hdr->hdr.code =
282                                 cpu_to_le32(VIRTIO_SND_R_CTL_TLV_COMMAND);
283
284                 if (copy_from_user(tlv, utlv, size)) {
285                         rc = -EFAULT;
286                         goto on_msg_unref;
287                 } else {
288                         rc = virtsnd_ctl_msg_send(snd, msg, &sg, NULL, false);
289                 }
290
291                 break;
292         default:
293                 rc = -EINVAL;
294                 /* We never get here - we listed all values for op_flag */
295                 WARN_ON(1);
296                 goto on_msg_unref;
297         }
298         kfree(tlv);
299         return rc;
300
301 on_msg_unref:
302         virtsnd_ctl_msg_unref(msg);
303         kfree(tlv);
304
305         return rc;
306 }
307
308 /**
309  * virtsnd_kctl_get_enum_items() - Query items for the ENUMERATED element type.
310  * @snd: VirtIO sound device.
311  * @cid: Control element ID.
312  *
313  * This function is called during initial device initialization.
314  *
315  * Context: Any context that permits to sleep.
316  * Return: 0 on success, -errno on failure.
317  */
318 static int virtsnd_kctl_get_enum_items(struct virtio_snd *snd, unsigned int cid)
319 {
320         struct virtio_device *vdev = snd->vdev;
321         struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[cid];
322         struct virtio_kctl *kctl = &snd->kctls[cid];
323         struct virtio_snd_msg *msg;
324         struct virtio_snd_ctl_hdr *hdr;
325         unsigned int n = le32_to_cpu(kinfo->value.enumerated.items);
326         struct scatterlist sg;
327
328         msg = virtsnd_ctl_msg_alloc(sizeof(*hdr),
329                                     sizeof(struct virtio_snd_hdr), GFP_KERNEL);
330         if (!msg)
331                 return -ENOMEM;
332
333         kctl->items = devm_kcalloc(&vdev->dev, n, sizeof(*kctl->items),
334                                    GFP_KERNEL);
335         if (!kctl->items) {
336                 virtsnd_ctl_msg_unref(msg);
337                 return -ENOMEM;
338         }
339
340         sg_init_one(&sg, kctl->items, n * sizeof(*kctl->items));
341
342         hdr = virtsnd_ctl_msg_request(msg);
343         hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_ENUM_ITEMS);
344         hdr->control_id = cpu_to_le32(cid);
345
346         return virtsnd_ctl_msg_send(snd, msg, NULL, &sg, false);
347 }
348
349 /**
350  * virtsnd_kctl_parse_cfg() - Parse the control element configuration.
351  * @snd: VirtIO sound device.
352  *
353  * This function is called during initial device initialization.
354  *
355  * Context: Any context that permits to sleep.
356  * Return: 0 on success, -errno on failure.
357  */
358 int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
359 {
360         struct virtio_device *vdev = snd->vdev;
361         u32 i;
362         int rc;
363
364         virtio_cread_le(vdev, struct virtio_snd_config, controls,
365                         &snd->nkctls);
366         if (!snd->nkctls)
367                 return 0;
368
369         snd->kctl_infos = devm_kcalloc(&vdev->dev, snd->nkctls,
370                                        sizeof(*snd->kctl_infos), GFP_KERNEL);
371         if (!snd->kctl_infos)
372                 return -ENOMEM;
373
374         snd->kctls = devm_kcalloc(&vdev->dev, snd->nkctls, sizeof(*snd->kctls),
375                                   GFP_KERNEL);
376         if (!snd->kctls)
377                 return -ENOMEM;
378
379         rc = virtsnd_ctl_query_info(snd, VIRTIO_SND_R_CTL_INFO, 0, snd->nkctls,
380                                     sizeof(*snd->kctl_infos), snd->kctl_infos);
381         if (rc)
382                 return rc;
383
384         for (i = 0; i < snd->nkctls; ++i) {
385                 struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
386                 unsigned int type = le32_to_cpu(kinfo->type);
387
388                 if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
389                         rc = virtsnd_kctl_get_enum_items(snd, i);
390                         if (rc)
391                                 return rc;
392                 }
393         }
394
395         return 0;
396 }
397
398 /**
399  * virtsnd_kctl_build_devs() - Build ALSA control elements.
400  * @snd: VirtIO sound device.
401  *
402  * Context: Any context that permits to sleep.
403  * Return: 0 on success, -errno on failure.
404  */
405 int virtsnd_kctl_build_devs(struct virtio_snd *snd)
406 {
407         unsigned int cid;
408
409         for (cid = 0; cid < snd->nkctls; ++cid) {
410                 struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[cid];
411                 struct virtio_kctl *kctl = &snd->kctls[cid];
412                 struct snd_kcontrol_new kctl_new;
413                 unsigned int i;
414                 int rc;
415
416                 memset(&kctl_new, 0, sizeof(kctl_new));
417
418                 kctl_new.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
419                 kctl_new.name = kinfo->name;
420                 kctl_new.index = le32_to_cpu(kinfo->index);
421
422                 for (i = 0; i < ARRAY_SIZE(g_v2a_access_map); ++i)
423                         if (le32_to_cpu(kinfo->access) & (1 << i))
424                                 kctl_new.access |= g_v2a_access_map[i];
425
426                 if (kctl_new.access & (SNDRV_CTL_ELEM_ACCESS_TLV_READ |
427                                        SNDRV_CTL_ELEM_ACCESS_TLV_WRITE |
428                                        SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND)) {
429                         kctl_new.access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
430                         kctl_new.tlv.c = virtsnd_kctl_tlv_op;
431                 }
432
433                 kctl_new.info = virtsnd_kctl_info;
434                 kctl_new.get = virtsnd_kctl_get;
435                 kctl_new.put = virtsnd_kctl_put;
436                 kctl_new.private_value = cid;
437
438                 kctl->kctl = snd_ctl_new1(&kctl_new, snd);
439                 if (!kctl->kctl)
440                         return -ENOMEM;
441
442                 rc = snd_ctl_add(snd->card, kctl->kctl);
443                 if (rc)
444                         return rc;
445         }
446
447         return 0;
448 }
449
450 /**
451  * virtsnd_kctl_event() - Handle the control element event notification.
452  * @snd: VirtIO sound device.
453  * @event: VirtIO sound event.
454  *
455  * Context: Interrupt context.
456  */
457 void virtsnd_kctl_event(struct virtio_snd *snd, struct virtio_snd_event *event)
458 {
459         struct virtio_snd_ctl_event *kevent =
460                 (struct virtio_snd_ctl_event *)event;
461         struct virtio_kctl *kctl;
462         unsigned int cid = le16_to_cpu(kevent->control_id);
463         unsigned int mask = 0;
464         unsigned int i;
465
466         if (cid >= snd->nkctls)
467                 return;
468
469         for (i = 0; i < ARRAY_SIZE(g_v2a_mask_map); ++i)
470                 if (le16_to_cpu(kevent->mask) & (1 << i))
471                         mask |= g_v2a_mask_map[i];
472
473
474         kctl = &snd->kctls[cid];
475
476         snd_ctl_notify(snd->card, mask, &kctl->kctl->id);
477 }