diff options
author | Anton Yakovlev <anton.yakovlev@opensynergy.com> | 2021-03-02 19:47:05 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-03-07 11:07:44 +0300 |
commit | f40a28679e0b7cb3a9cc6627a8dbb40961990f0a (patch) | |
tree | f3666982bba98fc53612b03b559b80206d6bd7c9 /sound/virtio/virtio_card.c | |
parent | 29b96bf50ba958eb5f097cdc3fbd4c1acf9547a2 (diff) | |
download | linux-f40a28679e0b7cb3a9cc6627a8dbb40961990f0a.tar.xz |
ALSA: virtio: handling control and I/O messages for the PCM device
The driver implements a message-based transport for I/O substream
operations. Before the start of the substream, the hardware buffer is
sliced into I/O messages, the number of which is equal to the current
number of periods. The size of each message is equal to the current
size of one period.
I/O messages are organized in an ordered queue. The completion of the
I/O message indicates an elapsed period (the only exception is the end
of the stream for the capture substream). Upon completion, the message
is automatically re-added to the end of the queue.
Signed-off-by: Anton Yakovlev <anton.yakovlev@opensynergy.com>
Link: https://lore.kernel.org/r/20210302164709.3142702-6-anton.yakovlev@opensynergy.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/virtio/virtio_card.c')
-rw-r--r-- | sound/virtio/virtio_card.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/sound/virtio/virtio_card.c b/sound/virtio/virtio_card.c index 11c76ee311b7..57b9b7f3a9c0 100644 --- a/sound/virtio/virtio_card.c +++ b/sound/virtio/virtio_card.c @@ -55,6 +55,12 @@ static void virtsnd_event_send(struct virtqueue *vqueue, static void virtsnd_event_dispatch(struct virtio_snd *snd, struct virtio_snd_event *event) { + switch (le32_to_cpu(event->hdr.code)) { + case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED: + case VIRTIO_SND_EVT_PCM_XRUN: + virtsnd_pcm_event(snd, event); + break; + } } /** @@ -101,11 +107,15 @@ static int virtsnd_find_vqs(struct virtio_snd *snd) struct virtio_device *vdev = snd->vdev; static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = { [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb, - [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb + [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb, + [VIRTIO_SND_VQ_TX] = virtsnd_pcm_tx_notify_cb, + [VIRTIO_SND_VQ_RX] = virtsnd_pcm_rx_notify_cb }; static const char *names[VIRTIO_SND_VQ_MAX] = { [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl", - [VIRTIO_SND_VQ_EVENT] = "virtsnd-event" + [VIRTIO_SND_VQ_EVENT] = "virtsnd-event", + [VIRTIO_SND_VQ_TX] = "virtsnd-tx", + [VIRTIO_SND_VQ_RX] = "virtsnd-rx" }; struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 }; unsigned int i; @@ -318,8 +328,12 @@ static void virtsnd_remove(struct virtio_device *vdev) vdev->config->del_vqs(vdev); vdev->config->reset(vdev); - for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) - cancel_work_sync(&snd->substreams[i].elapsed_period); + for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) { + struct virtio_pcm_substream *vss = &snd->substreams[i]; + + cancel_work_sync(&vss->elapsed_period); + virtsnd_pcm_msg_free(vss); + } kfree(snd->event_msgs); } |