xref: /qemu/include/hw/audio/virtio-snd.h (revision eb9ad377bb94d2d98d18cfccc431a028361385c6)
12880e676SManos Pitsidianakis /*
22880e676SManos Pitsidianakis  * VIRTIO Sound Device conforming to
32880e676SManos Pitsidianakis  *
42880e676SManos Pitsidianakis  * "Virtual I/O Device (VIRTIO) Version 1.2
52880e676SManos Pitsidianakis  * Committee Specification Draft 01
62880e676SManos Pitsidianakis  * 09 May 2022"
72880e676SManos Pitsidianakis  *
82880e676SManos Pitsidianakis  * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
92880e676SManos Pitsidianakis  * Copyright (C) 2019 OpenSynergy GmbH
102880e676SManos Pitsidianakis  *
112880e676SManos Pitsidianakis  * This work is licensed under the terms of the GNU GPL, version 2 or
122880e676SManos Pitsidianakis  * (at your option) any later version.  See the COPYING file in the
132880e676SManos Pitsidianakis  * top-level directory.
142880e676SManos Pitsidianakis  */
152880e676SManos Pitsidianakis 
162880e676SManos Pitsidianakis #ifndef QEMU_VIRTIO_SOUND_H
172880e676SManos Pitsidianakis #define QEMU_VIRTIO_SOUND_H
182880e676SManos Pitsidianakis 
192880e676SManos Pitsidianakis #include "hw/virtio/virtio.h"
202880e676SManos Pitsidianakis #include "audio/audio.h"
212880e676SManos Pitsidianakis #include "standard-headers/linux/virtio_ids.h"
222880e676SManos Pitsidianakis #include "standard-headers/linux/virtio_snd.h"
232880e676SManos Pitsidianakis 
242880e676SManos Pitsidianakis #define TYPE_VIRTIO_SND "virtio-sound-device"
252880e676SManos Pitsidianakis #define VIRTIO_SND(obj) \
262880e676SManos Pitsidianakis         OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND)
272880e676SManos Pitsidianakis 
282880e676SManos Pitsidianakis /* CONFIGURATION SPACE */
292880e676SManos Pitsidianakis 
302880e676SManos Pitsidianakis typedef struct virtio_snd_config virtio_snd_config;
312880e676SManos Pitsidianakis 
322880e676SManos Pitsidianakis /* COMMON DEFINITIONS */
332880e676SManos Pitsidianakis 
342880e676SManos Pitsidianakis /* common header for request/response*/
352880e676SManos Pitsidianakis typedef struct virtio_snd_hdr virtio_snd_hdr;
362880e676SManos Pitsidianakis 
372880e676SManos Pitsidianakis /* event notification */
382880e676SManos Pitsidianakis typedef struct virtio_snd_event virtio_snd_event;
392880e676SManos Pitsidianakis 
402880e676SManos Pitsidianakis /* common control request to query an item information */
412880e676SManos Pitsidianakis typedef struct virtio_snd_query_info virtio_snd_query_info;
422880e676SManos Pitsidianakis 
432880e676SManos Pitsidianakis /* JACK CONTROL MESSAGES */
442880e676SManos Pitsidianakis 
452880e676SManos Pitsidianakis typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr;
462880e676SManos Pitsidianakis 
472880e676SManos Pitsidianakis /* jack information structure */
482880e676SManos Pitsidianakis typedef struct virtio_snd_jack_info virtio_snd_jack_info;
492880e676SManos Pitsidianakis 
502880e676SManos Pitsidianakis /* jack remapping control request */
512880e676SManos Pitsidianakis typedef struct virtio_snd_jack_remap virtio_snd_jack_remap;
522880e676SManos Pitsidianakis 
532880e676SManos Pitsidianakis /*
542880e676SManos Pitsidianakis  * PCM CONTROL MESSAGES
552880e676SManos Pitsidianakis  */
562880e676SManos Pitsidianakis typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr;
572880e676SManos Pitsidianakis 
582880e676SManos Pitsidianakis /* PCM stream info structure */
592880e676SManos Pitsidianakis typedef struct virtio_snd_pcm_info virtio_snd_pcm_info;
602880e676SManos Pitsidianakis 
612880e676SManos Pitsidianakis /* set PCM stream params */
622880e676SManos Pitsidianakis typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params;
632880e676SManos Pitsidianakis 
642880e676SManos Pitsidianakis /* I/O request header */
652880e676SManos Pitsidianakis typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
662880e676SManos Pitsidianakis 
672880e676SManos Pitsidianakis /* I/O request status */
682880e676SManos Pitsidianakis typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
692880e676SManos Pitsidianakis 
70*eb9ad377SManos Pitsidianakis /* device structs */
71*eb9ad377SManos Pitsidianakis 
72*eb9ad377SManos Pitsidianakis typedef struct VirtIOSound VirtIOSound;
73*eb9ad377SManos Pitsidianakis 
74*eb9ad377SManos Pitsidianakis typedef struct VirtIOSoundPCMStream VirtIOSoundPCMStream;
75*eb9ad377SManos Pitsidianakis 
76*eb9ad377SManos Pitsidianakis typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command;
77*eb9ad377SManos Pitsidianakis 
78*eb9ad377SManos Pitsidianakis typedef struct VirtIOSoundPCM VirtIOSoundPCM;
79*eb9ad377SManos Pitsidianakis 
80*eb9ad377SManos Pitsidianakis struct VirtIOSoundPCM {
81*eb9ad377SManos Pitsidianakis     VirtIOSound *snd;
82*eb9ad377SManos Pitsidianakis     /*
83*eb9ad377SManos Pitsidianakis      * PCM parameters are a separate field instead of a VirtIOSoundPCMStream
84*eb9ad377SManos Pitsidianakis      * field, because the operation of PCM control requests is first
85*eb9ad377SManos Pitsidianakis      * VIRTIO_SND_R_PCM_SET_PARAMS and then VIRTIO_SND_R_PCM_PREPARE; this
86*eb9ad377SManos Pitsidianakis      * means that some times we get parameters without having an allocated
87*eb9ad377SManos Pitsidianakis      * stream yet.
88*eb9ad377SManos Pitsidianakis      */
89*eb9ad377SManos Pitsidianakis     virtio_snd_pcm_set_params *pcm_params;
90*eb9ad377SManos Pitsidianakis     VirtIOSoundPCMStream **streams;
91*eb9ad377SManos Pitsidianakis };
92*eb9ad377SManos Pitsidianakis 
93*eb9ad377SManos Pitsidianakis struct VirtIOSoundPCMStream {
94*eb9ad377SManos Pitsidianakis     VirtIOSoundPCM *pcm;
95*eb9ad377SManos Pitsidianakis     virtio_snd_pcm_info info;
96*eb9ad377SManos Pitsidianakis     virtio_snd_pcm_set_params params;
97*eb9ad377SManos Pitsidianakis     uint32_t id;
98*eb9ad377SManos Pitsidianakis     /* channel position values (VIRTIO_SND_CHMAP_XXX) */
99*eb9ad377SManos Pitsidianakis     uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
100*eb9ad377SManos Pitsidianakis     VirtIOSound *s;
101*eb9ad377SManos Pitsidianakis     bool flushing;
102*eb9ad377SManos Pitsidianakis     audsettings as;
103*eb9ad377SManos Pitsidianakis     union {
104*eb9ad377SManos Pitsidianakis         SWVoiceIn *in;
105*eb9ad377SManos Pitsidianakis         SWVoiceOut *out;
106*eb9ad377SManos Pitsidianakis     } voice;
107*eb9ad377SManos Pitsidianakis     bool active;
108*eb9ad377SManos Pitsidianakis };
109*eb9ad377SManos Pitsidianakis 
110*eb9ad377SManos Pitsidianakis /*
111*eb9ad377SManos Pitsidianakis  * PCM stream state machine.
112*eb9ad377SManos Pitsidianakis  * -------------------------
113*eb9ad377SManos Pitsidianakis  *
114*eb9ad377SManos Pitsidianakis  * 5.14.6.6.1 PCM Command Lifecycle
115*eb9ad377SManos Pitsidianakis  * ================================
116*eb9ad377SManos Pitsidianakis  *
117*eb9ad377SManos Pitsidianakis  * A PCM stream has the following command lifecycle:
118*eb9ad377SManos Pitsidianakis  * - `SET PARAMETERS`
119*eb9ad377SManos Pitsidianakis  *   The driver negotiates the stream parameters (format, transport, etc) with
120*eb9ad377SManos Pitsidianakis  *   the device.
121*eb9ad377SManos Pitsidianakis  *   Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
122*eb9ad377SManos Pitsidianakis  * - `PREPARE`
123*eb9ad377SManos Pitsidianakis  *   The device prepares the stream (allocates resources, etc).
124*eb9ad377SManos Pitsidianakis  *   Possible valid transitions: `SET PARAMETERS`, `PREPARE`, `START`,
125*eb9ad377SManos Pitsidianakis  *   `RELEASE`. Output only: the driver transfers data for pre-buffing.
126*eb9ad377SManos Pitsidianakis  * - `START`
127*eb9ad377SManos Pitsidianakis  *   The device starts the stream (unmute, putting into running state, etc).
128*eb9ad377SManos Pitsidianakis  *   Possible valid transitions: `STOP`.
129*eb9ad377SManos Pitsidianakis  *   The driver transfers data to/from the stream.
130*eb9ad377SManos Pitsidianakis  * - `STOP`
131*eb9ad377SManos Pitsidianakis  *   The device stops the stream (mute, putting into non-running state, etc).
132*eb9ad377SManos Pitsidianakis  *   Possible valid transitions: `START`, `RELEASE`.
133*eb9ad377SManos Pitsidianakis  * - `RELEASE`
134*eb9ad377SManos Pitsidianakis  *   The device releases the stream (frees resources, etc).
135*eb9ad377SManos Pitsidianakis  *   Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
136*eb9ad377SManos Pitsidianakis  *
137*eb9ad377SManos Pitsidianakis  * +---------------+ +---------+ +---------+ +-------+ +-------+
138*eb9ad377SManos Pitsidianakis  * | SetParameters | | Prepare | | Release | | Start | | Stop  |
139*eb9ad377SManos Pitsidianakis  * +---------------+ +---------+ +---------+ +-------+ +-------+
140*eb9ad377SManos Pitsidianakis  *         |-             |           |          |         |
141*eb9ad377SManos Pitsidianakis  *         ||             |           |          |         |
142*eb9ad377SManos Pitsidianakis  *         |<             |           |          |         |
143*eb9ad377SManos Pitsidianakis  *         |------------->|           |          |         |
144*eb9ad377SManos Pitsidianakis  *         |<-------------|           |          |         |
145*eb9ad377SManos Pitsidianakis  *         |              |-          |          |         |
146*eb9ad377SManos Pitsidianakis  *         |              ||          |          |         |
147*eb9ad377SManos Pitsidianakis  *         |              |<          |          |         |
148*eb9ad377SManos Pitsidianakis  *         |              |--------------------->|         |
149*eb9ad377SManos Pitsidianakis  *         |              |---------->|          |         |
150*eb9ad377SManos Pitsidianakis  *         |              |           |          |-------->|
151*eb9ad377SManos Pitsidianakis  *         |              |           |          |<--------|
152*eb9ad377SManos Pitsidianakis  *         |              |           |<-------------------|
153*eb9ad377SManos Pitsidianakis  *         |<-------------------------|          |         |
154*eb9ad377SManos Pitsidianakis  *         |              |<----------|          |         |
155*eb9ad377SManos Pitsidianakis  *
156*eb9ad377SManos Pitsidianakis  * CTRL in the VirtIOSound device
157*eb9ad377SManos Pitsidianakis  * ==============================
158*eb9ad377SManos Pitsidianakis  *
159*eb9ad377SManos Pitsidianakis  * The control messages that affect the state of a stream arrive in the
160*eb9ad377SManos Pitsidianakis  * `virtio_snd_handle_ctrl()` queue callback and are of type `struct
161*eb9ad377SManos Pitsidianakis  * virtio_snd_ctrl_command`. They are stored in a queue field in the device
162*eb9ad377SManos Pitsidianakis  * type, `VirtIOSound`. This allows deferring the CTRL request completion if
163*eb9ad377SManos Pitsidianakis  * it's not immediately possible due to locking/state reasons.
164*eb9ad377SManos Pitsidianakis  *
165*eb9ad377SManos Pitsidianakis  * The CTRL message is finally handled in `process_cmd()`.
166*eb9ad377SManos Pitsidianakis  */
167*eb9ad377SManos Pitsidianakis struct VirtIOSound {
1682880e676SManos Pitsidianakis     VirtIODevice parent_obj;
1692880e676SManos Pitsidianakis 
1702880e676SManos Pitsidianakis     VirtQueue *queues[VIRTIO_SND_VQ_MAX];
1712880e676SManos Pitsidianakis     uint64_t features;
172*eb9ad377SManos Pitsidianakis     VirtIOSoundPCM *pcm;
1732880e676SManos Pitsidianakis     QEMUSoundCard card;
1742880e676SManos Pitsidianakis     VMChangeStateEntry *vmstate;
1752880e676SManos Pitsidianakis     virtio_snd_config snd_conf;
176*eb9ad377SManos Pitsidianakis     QemuMutex cmdq_mutex;
177*eb9ad377SManos Pitsidianakis     QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq;
178*eb9ad377SManos Pitsidianakis     bool processing_cmdq;
179*eb9ad377SManos Pitsidianakis };
180*eb9ad377SManos Pitsidianakis 
181*eb9ad377SManos Pitsidianakis struct virtio_snd_ctrl_command {
182*eb9ad377SManos Pitsidianakis     VirtQueueElement *elem;
183*eb9ad377SManos Pitsidianakis     VirtQueue *vq;
184*eb9ad377SManos Pitsidianakis     virtio_snd_hdr ctrl;
185*eb9ad377SManos Pitsidianakis     virtio_snd_hdr resp;
186*eb9ad377SManos Pitsidianakis     QTAILQ_ENTRY(virtio_snd_ctrl_command) next;
187*eb9ad377SManos Pitsidianakis };
1882880e676SManos Pitsidianakis #endif
189