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 } 478