1 // SPDX-License-Identifier: GPL-2.0+
3 * virtio-snd: Virtio sound device
4 * Copyright (C) 2021 OpenSynergy GmbH
6 #include <linux/module.h>
7 #include <linux/moduleparam.h>
8 #include <linux/virtio_config.h>
9 #include <sound/initval.h>
10 #include <uapi/linux/virtio_ids.h>
12 #include "virtio_card.h"
14 u32 virtsnd_msg_timeout_ms = MSEC_PER_SEC;
15 module_param_named(msg_timeout_ms, virtsnd_msg_timeout_ms, uint, 0644);
16 MODULE_PARM_DESC(msg_timeout_ms, "Message completion timeout in milliseconds");
18 static void virtsnd_remove(struct virtio_device *vdev);
21 * virtsnd_event_send() - Add an event to the event queue.
22 * @vqueue: Underlying event virtqueue.
24 * @notify: Indicates whether or not to send a notification to the device.
25 * @gfp: Kernel flags for memory allocation.
27 * Context: Any context.
29 static void virtsnd_event_send(struct virtqueue *vqueue,
30 struct virtio_snd_event *event, bool notify,
33 struct scatterlist sg;
34 struct scatterlist *psgs[1] = { &sg };
36 /* reset event content */
37 memset(event, 0, sizeof(*event));
39 sg_init_one(&sg, event, sizeof(*event));
41 if (virtqueue_add_sgs(vqueue, psgs, 0, 1, event, gfp) || !notify)
44 if (virtqueue_kick_prepare(vqueue))
45 virtqueue_notify(vqueue);
49 * virtsnd_event_dispatch() - Dispatch an event from the device side.
50 * @snd: VirtIO sound device.
51 * @event: VirtIO sound event.
53 * Context: Any context.
55 static void virtsnd_event_dispatch(struct virtio_snd *snd,
56 struct virtio_snd_event *event)
58 switch (le32_to_cpu(event->hdr.code)) {
59 case VIRTIO_SND_EVT_JACK_CONNECTED:
60 case VIRTIO_SND_EVT_JACK_DISCONNECTED:
61 virtsnd_jack_event(snd, event);
63 case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED:
64 case VIRTIO_SND_EVT_PCM_XRUN:
65 virtsnd_pcm_event(snd, event);
71 * virtsnd_event_notify_cb() - Dispatch all reported events from the event queue.
72 * @vqueue: Underlying event virtqueue.
74 * This callback function is called upon a vring interrupt request from the
77 * Context: Interrupt context.
79 static void virtsnd_event_notify_cb(struct virtqueue *vqueue)
81 struct virtio_snd *snd = vqueue->vdev->priv;
82 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
83 struct virtio_snd_event *event;
87 spin_lock_irqsave(&queue->lock, flags);
89 virtqueue_disable_cb(vqueue);
90 while ((event = virtqueue_get_buf(vqueue, &length))) {
91 virtsnd_event_dispatch(snd, event);
92 virtsnd_event_send(vqueue, event, true, GFP_ATOMIC);
94 } while (!virtqueue_enable_cb(vqueue));
95 spin_unlock_irqrestore(&queue->lock, flags);
99 * virtsnd_find_vqs() - Enumerate and initialize all virtqueues.
100 * @snd: VirtIO sound device.
102 * After calling this function, the event queue is disabled.
104 * Context: Any context.
105 * Return: 0 on success, -errno on failure.
107 static int virtsnd_find_vqs(struct virtio_snd *snd)
109 struct virtio_device *vdev = snd->vdev;
110 static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = {
111 [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb,
112 [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb,
113 [VIRTIO_SND_VQ_TX] = virtsnd_pcm_tx_notify_cb,
114 [VIRTIO_SND_VQ_RX] = virtsnd_pcm_rx_notify_cb
116 static const char *names[VIRTIO_SND_VQ_MAX] = {
117 [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl",
118 [VIRTIO_SND_VQ_EVENT] = "virtsnd-event",
119 [VIRTIO_SND_VQ_TX] = "virtsnd-tx",
120 [VIRTIO_SND_VQ_RX] = "virtsnd-rx"
122 struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 };
127 rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, callbacks, names,
130 dev_err(&vdev->dev, "failed to initialize virtqueues\n");
134 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i)
135 snd->queues[i].vqueue = vqs[i];
137 /* Allocate events and populate the event queue */
138 virtqueue_disable_cb(vqs[VIRTIO_SND_VQ_EVENT]);
140 n = virtqueue_get_vring_size(vqs[VIRTIO_SND_VQ_EVENT]);
142 snd->event_msgs = kmalloc_array(n, sizeof(*snd->event_msgs),
144 if (!snd->event_msgs)
147 for (i = 0; i < n; ++i)
148 virtsnd_event_send(vqs[VIRTIO_SND_VQ_EVENT],
149 &snd->event_msgs[i], false, GFP_KERNEL);
155 * virtsnd_enable_event_vq() - Enable the event virtqueue.
156 * @snd: VirtIO sound device.
158 * Context: Any context.
160 static void virtsnd_enable_event_vq(struct virtio_snd *snd)
162 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
164 if (!virtqueue_enable_cb(queue->vqueue))
165 virtsnd_event_notify_cb(queue->vqueue);
169 * virtsnd_disable_event_vq() - Disable the event virtqueue.
170 * @snd: VirtIO sound device.
172 * Context: Any context.
174 static void virtsnd_disable_event_vq(struct virtio_snd *snd)
176 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
177 struct virtio_snd_event *event;
182 spin_lock_irqsave(&queue->lock, flags);
183 virtqueue_disable_cb(queue->vqueue);
184 while ((event = virtqueue_get_buf(queue->vqueue, &length)))
185 virtsnd_event_dispatch(snd, event);
186 spin_unlock_irqrestore(&queue->lock, flags);
191 * virtsnd_build_devs() - Read configuration and build ALSA devices.
192 * @snd: VirtIO sound device.
194 * Context: Any context that permits to sleep.
195 * Return: 0 on success, -errno on failure.
197 static int virtsnd_build_devs(struct virtio_snd *snd)
199 struct virtio_device *vdev = snd->vdev;
200 struct device *dev = &vdev->dev;
203 rc = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
204 THIS_MODULE, 0, &snd->card);
208 snd->card->private_data = snd;
210 strscpy(snd->card->driver, VIRTIO_SND_CARD_DRIVER,
211 sizeof(snd->card->driver));
212 strscpy(snd->card->shortname, VIRTIO_SND_CARD_NAME,
213 sizeof(snd->card->shortname));
214 if (dev->parent->bus)
215 snprintf(snd->card->longname, sizeof(snd->card->longname),
216 VIRTIO_SND_CARD_NAME " at %s/%s/%s",
217 dev->parent->bus->name, dev_name(dev->parent),
220 snprintf(snd->card->longname, sizeof(snd->card->longname),
221 VIRTIO_SND_CARD_NAME " at %s/%s",
222 dev_name(dev->parent), dev_name(dev));
224 rc = virtsnd_jack_parse_cfg(snd);
228 rc = virtsnd_pcm_parse_cfg(snd);
232 rc = virtsnd_chmap_parse_cfg(snd);
237 rc = virtsnd_jack_build_devs(snd);
242 if (snd->nsubstreams) {
243 rc = virtsnd_pcm_build_devs(snd);
249 rc = virtsnd_chmap_build_devs(snd);
254 return snd_card_register(snd->card);
258 * virtsnd_validate() - Validate if the device can be started.
259 * @vdev: VirtIO parent device.
261 * Context: Any context.
262 * Return: 0 on success, -EINVAL on failure.
264 static int virtsnd_validate(struct virtio_device *vdev)
266 if (!vdev->config->get) {
267 dev_err(&vdev->dev, "configuration access disabled\n");
271 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
273 "device does not comply with spec version 1.x\n");
277 if (!virtsnd_msg_timeout_ms) {
278 dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n");
282 if (virtsnd_pcm_validate(vdev))
289 * virtsnd_probe() - Create and initialize the device.
290 * @vdev: VirtIO parent device.
292 * Context: Any context that permits to sleep.
293 * Return: 0 on success, -errno on failure.
295 static int virtsnd_probe(struct virtio_device *vdev)
297 struct virtio_snd *snd;
301 snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL);
306 INIT_LIST_HEAD(&snd->ctl_msgs);
307 INIT_LIST_HEAD(&snd->pcm_list);
311 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i)
312 spin_lock_init(&snd->queues[i].lock);
314 rc = virtsnd_find_vqs(snd);
318 virtio_device_ready(vdev);
320 rc = virtsnd_build_devs(snd);
324 virtsnd_enable_event_vq(snd);
328 virtsnd_remove(vdev);
334 * virtsnd_remove() - Remove VirtIO and ALSA devices.
335 * @vdev: VirtIO parent device.
337 * Context: Any context that permits to sleep.
339 static void virtsnd_remove(struct virtio_device *vdev)
341 struct virtio_snd *snd = vdev->priv;
344 virtsnd_disable_event_vq(snd);
345 virtsnd_ctl_msg_cancel_all(snd);
348 snd_card_free(snd->card);
350 vdev->config->del_vqs(vdev);
351 virtio_reset_device(vdev);
353 for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) {
354 struct virtio_pcm_substream *vss = &snd->substreams[i];
356 cancel_work_sync(&vss->elapsed_period);
357 virtsnd_pcm_msg_free(vss);
360 kfree(snd->event_msgs);
363 #ifdef CONFIG_PM_SLEEP
365 * virtsnd_freeze() - Suspend device.
366 * @vdev: VirtIO parent device.
368 * Context: Any context.
369 * Return: 0 on success, -errno on failure.
371 static int virtsnd_freeze(struct virtio_device *vdev)
373 struct virtio_snd *snd = vdev->priv;
376 virtsnd_disable_event_vq(snd);
377 virtsnd_ctl_msg_cancel_all(snd);
379 vdev->config->del_vqs(vdev);
380 virtio_reset_device(vdev);
382 for (i = 0; i < snd->nsubstreams; ++i)
383 cancel_work_sync(&snd->substreams[i].elapsed_period);
385 kfree(snd->event_msgs);
386 snd->event_msgs = NULL;
392 * virtsnd_restore() - Resume device.
393 * @vdev: VirtIO parent device.
395 * Context: Any context.
396 * Return: 0 on success, -errno on failure.
398 static int virtsnd_restore(struct virtio_device *vdev)
400 struct virtio_snd *snd = vdev->priv;
403 rc = virtsnd_find_vqs(snd);
407 virtio_device_ready(vdev);
409 virtsnd_enable_event_vq(snd);
413 #endif /* CONFIG_PM_SLEEP */
415 static const struct virtio_device_id id_table[] = {
416 { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID },
420 static struct virtio_driver virtsnd_driver = {
421 .driver.name = KBUILD_MODNAME,
422 .driver.owner = THIS_MODULE,
423 .id_table = id_table,
424 .validate = virtsnd_validate,
425 .probe = virtsnd_probe,
426 .remove = virtsnd_remove,
427 #ifdef CONFIG_PM_SLEEP
428 .freeze = virtsnd_freeze,
429 .restore = virtsnd_restore,
433 module_virtio_driver(virtsnd_driver);
435 MODULE_DEVICE_TABLE(virtio, id_table);
436 MODULE_DESCRIPTION("Virtio sound card driver");
437 MODULE_LICENSE("GPL");