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 if (unlikely(virtqueue_is_broken(vqueue
)))
96 } while (!virtqueue_enable_cb(vqueue
));
97 spin_unlock_irqrestore(&queue
->lock
, flags
);
101 * virtsnd_find_vqs() - Enumerate and initialize all virtqueues.
102 * @snd: VirtIO sound device.
104 * After calling this function, the event queue is disabled.
106 * Context: Any context.
107 * Return: 0 on success, -errno on failure.
109 static int virtsnd_find_vqs(struct virtio_snd
*snd
)
111 struct virtio_device
*vdev
= snd
->vdev
;
112 static vq_callback_t
*callbacks
[VIRTIO_SND_VQ_MAX
] = {
113 [VIRTIO_SND_VQ_CONTROL
] = virtsnd_ctl_notify_cb
,
114 [VIRTIO_SND_VQ_EVENT
] = virtsnd_event_notify_cb
,
115 [VIRTIO_SND_VQ_TX
] = virtsnd_pcm_tx_notify_cb
,
116 [VIRTIO_SND_VQ_RX
] = virtsnd_pcm_rx_notify_cb
118 static const char *names
[VIRTIO_SND_VQ_MAX
] = {
119 [VIRTIO_SND_VQ_CONTROL
] = "virtsnd-ctl",
120 [VIRTIO_SND_VQ_EVENT
] = "virtsnd-event",
121 [VIRTIO_SND_VQ_TX
] = "virtsnd-tx",
122 [VIRTIO_SND_VQ_RX
] = "virtsnd-rx"
124 struct virtqueue
*vqs
[VIRTIO_SND_VQ_MAX
] = { 0 };
129 rc
= virtio_find_vqs(vdev
, VIRTIO_SND_VQ_MAX
, vqs
, callbacks
, names
,
132 dev_err(&vdev
->dev
, "failed to initialize virtqueues\n");
136 for (i
= 0; i
< VIRTIO_SND_VQ_MAX
; ++i
)
137 snd
->queues
[i
].vqueue
= vqs
[i
];
139 /* Allocate events and populate the event queue */
140 virtqueue_disable_cb(vqs
[VIRTIO_SND_VQ_EVENT
]);
142 n
= virtqueue_get_vring_size(vqs
[VIRTIO_SND_VQ_EVENT
]);
144 snd
->event_msgs
= kmalloc_array(n
, sizeof(*snd
->event_msgs
),
146 if (!snd
->event_msgs
)
149 for (i
= 0; i
< n
; ++i
)
150 virtsnd_event_send(vqs
[VIRTIO_SND_VQ_EVENT
],
151 &snd
->event_msgs
[i
], false, GFP_KERNEL
);
157 * virtsnd_enable_event_vq() - Enable the event virtqueue.
158 * @snd: VirtIO sound device.
160 * Context: Any context.
162 static void virtsnd_enable_event_vq(struct virtio_snd
*snd
)
164 struct virtio_snd_queue
*queue
= virtsnd_event_queue(snd
);
166 if (!virtqueue_enable_cb(queue
->vqueue
))
167 virtsnd_event_notify_cb(queue
->vqueue
);
171 * virtsnd_disable_event_vq() - Disable the event virtqueue.
172 * @snd: VirtIO sound device.
174 * Context: Any context.
176 static void virtsnd_disable_event_vq(struct virtio_snd
*snd
)
178 struct virtio_snd_queue
*queue
= virtsnd_event_queue(snd
);
179 struct virtio_snd_event
*event
;
184 spin_lock_irqsave(&queue
->lock
, flags
);
185 virtqueue_disable_cb(queue
->vqueue
);
186 while ((event
= virtqueue_get_buf(queue
->vqueue
, &length
)))
187 virtsnd_event_dispatch(snd
, event
);
188 spin_unlock_irqrestore(&queue
->lock
, flags
);
193 * virtsnd_build_devs() - Read configuration and build ALSA devices.
194 * @snd: VirtIO sound device.
196 * Context: Any context that permits to sleep.
197 * Return: 0 on success, -errno on failure.
199 static int virtsnd_build_devs(struct virtio_snd
*snd
)
201 struct virtio_device
*vdev
= snd
->vdev
;
202 struct device
*dev
= &vdev
->dev
;
205 rc
= snd_card_new(dev
, SNDRV_DEFAULT_IDX1
, SNDRV_DEFAULT_STR1
,
206 THIS_MODULE
, 0, &snd
->card
);
210 snd
->card
->private_data
= snd
;
212 strscpy(snd
->card
->driver
, VIRTIO_SND_CARD_DRIVER
,
213 sizeof(snd
->card
->driver
));
214 strscpy(snd
->card
->shortname
, VIRTIO_SND_CARD_NAME
,
215 sizeof(snd
->card
->shortname
));
216 if (dev
->parent
->bus
)
217 snprintf(snd
->card
->longname
, sizeof(snd
->card
->longname
),
218 VIRTIO_SND_CARD_NAME
" at %s/%s/%s",
219 dev
->parent
->bus
->name
, dev_name(dev
->parent
),
222 snprintf(snd
->card
->longname
, sizeof(snd
->card
->longname
),
223 VIRTIO_SND_CARD_NAME
" at %s/%s",
224 dev_name(dev
->parent
), dev_name(dev
));
226 rc
= virtsnd_jack_parse_cfg(snd
);
230 rc
= virtsnd_pcm_parse_cfg(snd
);
234 rc
= virtsnd_chmap_parse_cfg(snd
);
239 rc
= virtsnd_jack_build_devs(snd
);
244 if (snd
->nsubstreams
) {
245 rc
= virtsnd_pcm_build_devs(snd
);
251 rc
= virtsnd_chmap_build_devs(snd
);
256 return snd_card_register(snd
->card
);
260 * virtsnd_validate() - Validate if the device can be started.
261 * @vdev: VirtIO parent device.
263 * Context: Any context.
264 * Return: 0 on success, -EINVAL on failure.
266 static int virtsnd_validate(struct virtio_device
*vdev
)
268 if (!vdev
->config
->get
) {
269 dev_err(&vdev
->dev
, "configuration access disabled\n");
273 if (!virtio_has_feature(vdev
, VIRTIO_F_VERSION_1
)) {
275 "device does not comply with spec version 1.x\n");
279 if (!virtsnd_msg_timeout_ms
) {
280 dev_err(&vdev
->dev
, "msg_timeout_ms value cannot be zero\n");
284 if (virtsnd_pcm_validate(vdev
))
291 * virtsnd_probe() - Create and initialize the device.
292 * @vdev: VirtIO parent device.
294 * Context: Any context that permits to sleep.
295 * Return: 0 on success, -errno on failure.
297 static int virtsnd_probe(struct virtio_device
*vdev
)
299 struct virtio_snd
*snd
;
303 snd
= devm_kzalloc(&vdev
->dev
, sizeof(*snd
), GFP_KERNEL
);
308 INIT_LIST_HEAD(&snd
->ctl_msgs
);
309 INIT_LIST_HEAD(&snd
->pcm_list
);
313 for (i
= 0; i
< VIRTIO_SND_VQ_MAX
; ++i
)
314 spin_lock_init(&snd
->queues
[i
].lock
);
316 rc
= virtsnd_find_vqs(snd
);
320 virtio_device_ready(vdev
);
322 rc
= virtsnd_build_devs(snd
);
326 virtsnd_enable_event_vq(snd
);
330 virtsnd_remove(vdev
);
336 * virtsnd_remove() - Remove VirtIO and ALSA devices.
337 * @vdev: VirtIO parent device.
339 * Context: Any context that permits to sleep.
341 static void virtsnd_remove(struct virtio_device
*vdev
)
343 struct virtio_snd
*snd
= vdev
->priv
;
346 virtsnd_disable_event_vq(snd
);
347 virtsnd_ctl_msg_cancel_all(snd
);
350 snd_card_free(snd
->card
);
352 vdev
->config
->del_vqs(vdev
);
353 vdev
->config
->reset(vdev
);
355 for (i
= 0; snd
->substreams
&& i
< snd
->nsubstreams
; ++i
) {
356 struct virtio_pcm_substream
*vss
= &snd
->substreams
[i
];
358 cancel_work_sync(&vss
->elapsed_period
);
359 virtsnd_pcm_msg_free(vss
);
362 kfree(snd
->event_msgs
);
365 #ifdef CONFIG_PM_SLEEP
367 * virtsnd_freeze() - Suspend device.
368 * @vdev: VirtIO parent device.
370 * Context: Any context.
371 * Return: 0 on success, -errno on failure.
373 static int virtsnd_freeze(struct virtio_device
*vdev
)
375 struct virtio_snd
*snd
= vdev
->priv
;
378 virtsnd_disable_event_vq(snd
);
379 virtsnd_ctl_msg_cancel_all(snd
);
381 vdev
->config
->del_vqs(vdev
);
382 vdev
->config
->reset(vdev
);
384 for (i
= 0; i
< snd
->nsubstreams
; ++i
)
385 cancel_work_sync(&snd
->substreams
[i
].elapsed_period
);
387 kfree(snd
->event_msgs
);
388 snd
->event_msgs
= NULL
;
394 * virtsnd_restore() - Resume device.
395 * @vdev: VirtIO parent device.
397 * Context: Any context.
398 * Return: 0 on success, -errno on failure.
400 static int virtsnd_restore(struct virtio_device
*vdev
)
402 struct virtio_snd
*snd
= vdev
->priv
;
405 rc
= virtsnd_find_vqs(snd
);
409 virtio_device_ready(vdev
);
411 virtsnd_enable_event_vq(snd
);
415 #endif /* CONFIG_PM_SLEEP */
417 static const struct virtio_device_id id_table
[] = {
418 { VIRTIO_ID_SOUND
, VIRTIO_DEV_ANY_ID
},
422 static struct virtio_driver virtsnd_driver
= {
423 .driver
.name
= KBUILD_MODNAME
,
424 .driver
.owner
= THIS_MODULE
,
425 .id_table
= id_table
,
426 .validate
= virtsnd_validate
,
427 .probe
= virtsnd_probe
,
428 .remove
= virtsnd_remove
,
429 #ifdef CONFIG_PM_SLEEP
430 .freeze
= virtsnd_freeze
,
431 .restore
= virtsnd_restore
,
435 module_virtio_driver(virtsnd_driver
);
437 MODULE_DEVICE_TABLE(virtio
, id_table
);
438 MODULE_DESCRIPTION("Virtio sound card driver");
439 MODULE_LICENSE("GPL");