2 * VIRTIO Sound Device conforming to
4 * "Virtual I/O Device (VIRTIO) Version 1.2
5 * Committee Specification Draft 01
8 * <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014>
10 * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
11 * Copyright (C) 2019 OpenSynergy GmbH
13 * This work is licensed under the terms of the GNU GPL, version 2 or
14 * (at your option) any later version. See the COPYING file in the
15 * top-level directory.
18 #include "qemu/osdep.h"
21 #include "qemu/error-report.h"
22 #include "include/qemu/lockable.h"
23 #include "sysemu/runstate.h"
25 #include "qapi/error.h"
26 #include "hw/audio/virtio-snd.h"
27 #include "hw/core/cpu.h"
29 #define VIRTIO_SOUND_VM_VERSION 1
30 #define VIRTIO_SOUND_JACK_DEFAULT 0
31 #define VIRTIO_SOUND_STREAM_DEFAULT 1
32 #define VIRTIO_SOUND_CHMAP_DEFAULT 0
33 #define VIRTIO_SOUND_HDA_FN_NID 0
35 static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
36 | BIT(VIRTIO_SND_PCM_FMT_U8)
37 | BIT(VIRTIO_SND_PCM_FMT_S16)
38 | BIT(VIRTIO_SND_PCM_FMT_U16)
39 | BIT(VIRTIO_SND_PCM_FMT_S32)
40 | BIT(VIRTIO_SND_PCM_FMT_U32)
41 | BIT(VIRTIO_SND_PCM_FMT_FLOAT);
43 static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512)
44 | BIT(VIRTIO_SND_PCM_RATE_8000)
45 | BIT(VIRTIO_SND_PCM_RATE_11025)
46 | BIT(VIRTIO_SND_PCM_RATE_16000)
47 | BIT(VIRTIO_SND_PCM_RATE_22050)
48 | BIT(VIRTIO_SND_PCM_RATE_32000)
49 | BIT(VIRTIO_SND_PCM_RATE_44100)
50 | BIT(VIRTIO_SND_PCM_RATE_48000)
51 | BIT(VIRTIO_SND_PCM_RATE_64000)
52 | BIT(VIRTIO_SND_PCM_RATE_88200)
53 | BIT(VIRTIO_SND_PCM_RATE_96000)
54 | BIT(VIRTIO_SND_PCM_RATE_176400)
55 | BIT(VIRTIO_SND_PCM_RATE_192000)
56 | BIT(VIRTIO_SND_PCM_RATE_384000);
58 static const VMStateDescription vmstate_virtio_snd_device = {
59 .name = TYPE_VIRTIO_SND,
60 .version_id = VIRTIO_SOUND_VM_VERSION,
61 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
64 static const VMStateDescription vmstate_virtio_snd = {
65 .name = TYPE_VIRTIO_SND,
66 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
67 .version_id = VIRTIO_SOUND_VM_VERSION,
68 .fields = (VMStateField[]) {
69 VMSTATE_VIRTIO_DEVICE,
74 static Property virtio_snd_properties[] = {
75 DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
76 DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
77 VIRTIO_SOUND_JACK_DEFAULT),
78 DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
79 VIRTIO_SOUND_STREAM_DEFAULT),
80 DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
81 VIRTIO_SOUND_CHMAP_DEFAULT),
82 DEFINE_PROP_END_OF_LIST(),
86 virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
88 VirtIOSound *s = VIRTIO_SND(vdev);
89 virtio_snd_config *sndconfig =
90 (virtio_snd_config *)config;
91 trace_virtio_snd_get_config(vdev,
96 memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf));
97 cpu_to_le32s(&sndconfig->jacks);
98 cpu_to_le32s(&sndconfig->streams);
99 cpu_to_le32s(&sndconfig->chmaps);
104 virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
106 VirtIOSound *s = VIRTIO_SND(vdev);
107 const virtio_snd_config *sndconfig =
108 (const virtio_snd_config *)config;
111 trace_virtio_snd_set_config(vdev,
119 memcpy(&s->snd_conf, sndconfig, sizeof(virtio_snd_config));
120 le32_to_cpus(&s->snd_conf.jacks);
121 le32_to_cpus(&s->snd_conf.streams);
122 le32_to_cpus(&s->snd_conf.chmaps);
127 virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd)
134 * Get a specific stream from the virtio sound card device.
135 * Returns NULL if @stream_id is invalid or not allocated.
137 * @s: VirtIOSound device
138 * @stream_id: stream id
140 static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
143 return stream_id >= s->snd_conf.streams ? NULL :
144 s->pcm->streams[stream_id];
148 * Get params for a specific stream.
150 * @s: VirtIOSound device
151 * @stream_id: stream id
153 static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s,
156 return stream_id >= s->snd_conf.streams ? NULL
157 : &s->pcm->pcm_params[stream_id];
161 * Set the given stream params.
162 * Called by both virtio_snd_handle_pcm_set_params and during device
164 * Returns the response status code. (VIRTIO_SND_S_*).
166 * @s: VirtIOSound device
167 * @params: The PCM params as defined in the virtio specification
170 uint32_t virtio_snd_set_pcm_params(VirtIOSound *s,
172 virtio_snd_pcm_set_params *params)
174 virtio_snd_pcm_set_params *st_params;
176 if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) {
178 * TODO: do we need to set DEVICE_NEEDS_RESET?
180 virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n");
181 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
184 st_params = virtio_snd_pcm_get_params(s, stream_id);
186 if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) {
187 error_report("Number of channels is not supported.");
188 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
190 if (!(supported_formats & BIT(params->format))) {
191 error_report("Stream format is not supported.");
192 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
194 if (!(supported_rates & BIT(params->rate))) {
195 error_report("Stream rate is not supported.");
196 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
199 st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes);
200 st_params->period_bytes = le32_to_cpu(params->period_bytes);
201 st_params->features = le32_to_cpu(params->features);
202 /* the following are uint8_t, so there's no need to bswap the values. */
203 st_params->channels = params->channels;
204 st_params->format = params->format;
205 st_params->rate = params->rate;
207 return cpu_to_le32(VIRTIO_SND_S_OK);
211 * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
213 static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
216 case VIRTIO_SND_PCM_FMT_##FMT: \
217 return AUDIO_FORMAT_##FMT;
226 case VIRTIO_SND_PCM_FMT_FLOAT:
227 return AUDIO_FORMAT_F32;
229 g_assert_not_reached();
236 * Get a QEMU Audiosystem compatible frequency value from a
237 * VIRTIO_SND_PCM_RATE_*
239 static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
242 case VIRTIO_SND_PCM_RATE_##RATE: \
261 g_assert_not_reached();
268 * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream
271 static void virtio_snd_get_qemu_audsettings(audsettings *as,
272 virtio_snd_pcm_set_params *params)
274 as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
275 as->fmt = virtio_snd_get_qemu_format(params->format);
276 as->freq = virtio_snd_get_qemu_freq(params->rate);
277 as->endianness = target_words_bigendian() ? 1 : 0;
281 * Close a stream and free all its resources.
283 * @stream: VirtIOSoundPCMStream *stream
285 static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
290 * Prepares a VirtIOSound card stream.
291 * Returns the response status code. (VIRTIO_SND_S_*).
293 * @s: VirtIOSound device
294 * @stream_id: stream id
296 static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
299 virtio_snd_pcm_set_params *params;
300 VirtIOSoundPCMStream *stream;
302 if (s->pcm->streams == NULL ||
303 s->pcm->pcm_params == NULL ||
304 stream_id >= s->snd_conf.streams) {
305 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
308 params = virtio_snd_pcm_get_params(s, stream_id);
309 if (params == NULL) {
310 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
313 stream = virtio_snd_pcm_get_stream(s, stream_id);
314 if (stream == NULL) {
315 stream = g_new0(VirtIOSoundPCMStream, 1);
316 stream->active = false;
317 stream->id = stream_id;
318 stream->pcm = s->pcm;
322 * stream_id >= s->snd_conf.streams was checked before so this is
325 s->pcm->streams[stream_id] = stream;
328 virtio_snd_get_qemu_audsettings(&as, params);
329 stream->info.direction = stream_id < s->snd_conf.streams / 2 +
330 (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
331 stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
332 stream->info.features = 0;
333 stream->info.channels_min = 1;
334 stream->info.channels_max = as.nchannels;
335 stream->info.formats = supported_formats;
336 stream->info.rates = supported_rates;
337 stream->params = *params;
339 stream->positions[0] = VIRTIO_SND_CHMAP_FL;
340 stream->positions[1] = VIRTIO_SND_CHMAP_FR;
343 return cpu_to_le32(VIRTIO_SND_S_OK);
346 static const char *print_code(uint32_t code)
349 case VIRTIO_SND_R_##CODE: \
350 return "VIRTIO_SND_R_"#CODE
356 CASE(PCM_SET_PARAMS);
363 return "invalid code";
370 * The actual processing done in virtio_snd_process_cmdq().
372 * @s: VirtIOSound device
373 * @cmd: control command request
376 process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
379 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
383 sizeof(virtio_snd_hdr));
385 if (msg_sz != sizeof(virtio_snd_hdr)) {
387 * TODO: do we need to set DEVICE_NEEDS_RESET?
389 qemu_log_mask(LOG_GUEST_ERROR,
390 "%s: virtio-snd command size incorrect %zu vs \
391 %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr));
395 code = le32_to_cpu(cmd->ctrl.code);
397 trace_virtio_snd_handle_code(code, print_code(code));
400 case VIRTIO_SND_R_JACK_INFO:
401 case VIRTIO_SND_R_JACK_REMAP:
402 qemu_log_mask(LOG_UNIMP,
403 "virtio_snd: jack functionality is unimplemented.\n");
404 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
406 case VIRTIO_SND_R_PCM_INFO:
407 case VIRTIO_SND_R_PCM_SET_PARAMS:
408 case VIRTIO_SND_R_PCM_PREPARE:
409 case VIRTIO_SND_R_PCM_START:
410 case VIRTIO_SND_R_PCM_STOP:
411 case VIRTIO_SND_R_PCM_RELEASE:
412 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
414 case VIRTIO_SND_R_CHMAP_INFO:
415 qemu_log_mask(LOG_UNIMP,
416 "virtio_snd: chmap info functionality is unimplemented.\n");
417 trace_virtio_snd_handle_chmap_info();
418 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
422 error_report("virtio snd header not recognized: %"PRIu32, code);
423 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
426 iov_from_buf(cmd->elem->in_sg,
430 sizeof(virtio_snd_hdr));
431 virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr));
432 virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
436 * Consume all elements in command queue.
438 * @s: VirtIOSound device
440 static void virtio_snd_process_cmdq(VirtIOSound *s)
442 virtio_snd_ctrl_command *cmd;
444 if (unlikely(qatomic_read(&s->processing_cmdq))) {
448 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
449 qatomic_set(&s->processing_cmdq, true);
450 while (!QTAILQ_EMPTY(&s->cmdq)) {
451 cmd = QTAILQ_FIRST(&s->cmdq);
453 /* process command */
456 QTAILQ_REMOVE(&s->cmdq, cmd, next);
458 virtio_snd_ctrl_cmd_free(cmd);
460 qatomic_set(&s->processing_cmdq, false);
465 * The control message handler. Pops an element from the control virtqueue,
466 * and stores them to VirtIOSound's cmdq queue and finally calls
467 * virtio_snd_process_cmdq() for processing.
469 * @vdev: VirtIOSound device
470 * @vq: Control virtqueue
472 static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
474 VirtIOSound *s = VIRTIO_SND(vdev);
475 VirtQueueElement *elem;
476 virtio_snd_ctrl_command *cmd;
478 trace_virtio_snd_handle_ctrl(vdev, vq);
480 if (!virtio_queue_ready(vq)) {
484 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
486 cmd = g_new0(virtio_snd_ctrl_command, 1);
489 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
490 QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
491 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
494 virtio_snd_process_cmdq(s);
498 * The event virtqueue handler.
499 * Not implemented yet.
501 * @vdev: VirtIOSound device
504 static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
506 qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.\n");
507 trace_virtio_snd_handle_event();
511 * Stub buffer virtqueue handler.
513 * @vdev: VirtIOSound device
516 static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {}
518 static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
522 * virtio-v1.2-csd01, 5.14.3,
524 * None currently defined.
526 VirtIOSound *s = VIRTIO_SND(vdev);
527 features |= s->features;
529 trace_virtio_snd_get_features(vdev, features);
535 virtio_snd_vm_state_change(void *opaque, bool running,
539 trace_virtio_snd_vm_state_running();
541 trace_virtio_snd_vm_state_stopped();
545 static void virtio_snd_realize(DeviceState *dev, Error **errp)
548 VirtIOSound *vsnd = VIRTIO_SND(dev);
549 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
550 virtio_snd_pcm_set_params default_params = { 0 };
555 qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
557 trace_virtio_snd_realize(vsnd);
559 vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
560 vsnd->pcm->snd = vsnd;
562 g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
563 vsnd->pcm->pcm_params =
564 g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
566 virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
567 virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
569 /* set number of jacks and streams */
570 if (vsnd->snd_conf.jacks > 8) {
572 "Invalid number of jacks: %"PRIu32,
573 vsnd->snd_conf.jacks);
576 if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
578 "Invalid number of streams: %"PRIu32,
579 vsnd->snd_conf.streams);
583 if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
585 "Invalid number of channel maps: %"PRIu32,
586 vsnd->snd_conf.chmaps);
590 AUD_register_card("virtio-sound", &vsnd->card, errp);
592 /* set default params for all streams */
593 default_params.features = 0;
594 default_params.buffer_bytes = cpu_to_le32(8192);
595 default_params.period_bytes = cpu_to_le32(2048);
596 default_params.channels = 2;
597 default_params.format = VIRTIO_SND_PCM_FMT_S16;
598 default_params.rate = VIRTIO_SND_PCM_RATE_48000;
599 vsnd->queues[VIRTIO_SND_VQ_CONTROL] =
600 virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl);
601 vsnd->queues[VIRTIO_SND_VQ_EVENT] =
602 virtio_add_queue(vdev, 64, virtio_snd_handle_event);
603 vsnd->queues[VIRTIO_SND_VQ_TX] =
604 virtio_add_queue(vdev, 64, virtio_snd_handle_xfer);
605 vsnd->queues[VIRTIO_SND_VQ_RX] =
606 virtio_add_queue(vdev, 64, virtio_snd_handle_xfer);
607 qemu_mutex_init(&vsnd->cmdq_mutex);
608 QTAILQ_INIT(&vsnd->cmdq);
610 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
611 status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
612 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
614 "Can't initalize stream params, device responded with %s.",
618 status = virtio_snd_pcm_prepare(vsnd, i);
619 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
621 "Can't prepare streams, device responded with %s.",
628 static void virtio_snd_unrealize(DeviceState *dev)
630 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
631 VirtIOSound *vsnd = VIRTIO_SND(dev);
632 VirtIOSoundPCMStream *stream;
634 qemu_del_vm_change_state_handler(vsnd->vmstate);
635 trace_virtio_snd_unrealize(vsnd);
638 if (vsnd->pcm->streams) {
639 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
640 stream = vsnd->pcm->streams[i];
642 virtio_snd_process_cmdq(stream->s);
643 virtio_snd_pcm_close(stream);
647 g_free(vsnd->pcm->streams);
649 g_free(vsnd->pcm->pcm_params);
653 AUD_remove_card(&vsnd->card);
654 qemu_mutex_destroy(&vsnd->cmdq_mutex);
655 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
656 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]);
657 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]);
658 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]);
659 virtio_cleanup(vdev);
663 static void virtio_snd_reset(VirtIODevice *vdev)
665 VirtIOSound *s = VIRTIO_SND(vdev);
666 virtio_snd_ctrl_command *cmd;
668 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
669 while (!QTAILQ_EMPTY(&s->cmdq)) {
670 cmd = QTAILQ_FIRST(&s->cmdq);
671 QTAILQ_REMOVE(&s->cmdq, cmd, next);
672 virtio_snd_ctrl_cmd_free(cmd);
677 static void virtio_snd_class_init(ObjectClass *klass, void *data)
679 DeviceClass *dc = DEVICE_CLASS(klass);
680 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
683 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
684 device_class_set_props(dc, virtio_snd_properties);
686 dc->vmsd = &vmstate_virtio_snd;
687 vdc->vmsd = &vmstate_virtio_snd_device;
688 vdc->realize = virtio_snd_realize;
689 vdc->unrealize = virtio_snd_unrealize;
690 vdc->get_config = virtio_snd_get_config;
691 vdc->set_config = virtio_snd_set_config;
692 vdc->get_features = get_features;
693 vdc->reset = virtio_snd_reset;
694 vdc->legacy_features = 0;
697 static const TypeInfo virtio_snd_types[] = {
699 .name = TYPE_VIRTIO_SND,
700 .parent = TYPE_VIRTIO_DEVICE,
701 .instance_size = sizeof(VirtIOSound),
702 .class_init = virtio_snd_class_init,
706 DEFINE_TYPES(virtio_snd_types)