129b96bf5SAnton Yakovlev /* SPDX-License-Identifier: GPL-2.0+ */ 229b96bf5SAnton Yakovlev /* 329b96bf5SAnton Yakovlev * virtio-snd: Virtio sound device 429b96bf5SAnton Yakovlev * Copyright (C) 2021 OpenSynergy GmbH 529b96bf5SAnton Yakovlev */ 629b96bf5SAnton Yakovlev #ifndef VIRTIO_SND_PCM_H 729b96bf5SAnton Yakovlev #define VIRTIO_SND_PCM_H 829b96bf5SAnton Yakovlev 929b96bf5SAnton Yakovlev #include <linux/atomic.h> 1029b96bf5SAnton Yakovlev #include <linux/virtio_config.h> 1129b96bf5SAnton Yakovlev #include <sound/pcm.h> 1229b96bf5SAnton Yakovlev 1329b96bf5SAnton Yakovlev struct virtio_pcm; 1429b96bf5SAnton Yakovlev struct virtio_pcm_msg; 1529b96bf5SAnton Yakovlev 1629b96bf5SAnton Yakovlev /** 1729b96bf5SAnton Yakovlev * struct virtio_pcm_substream - VirtIO PCM substream. 1829b96bf5SAnton Yakovlev * @snd: VirtIO sound device. 1929b96bf5SAnton Yakovlev * @nid: Function group node identifier. 2029b96bf5SAnton Yakovlev * @sid: Stream identifier. 2129b96bf5SAnton Yakovlev * @direction: Stream data flow direction (SNDRV_PCM_STREAM_XXX). 2229b96bf5SAnton Yakovlev * @features: Stream VirtIO feature bit map (1 << VIRTIO_SND_PCM_F_XXX). 2329b96bf5SAnton Yakovlev * @substream: Kernel ALSA substream. 2429b96bf5SAnton Yakovlev * @hw: Kernel ALSA substream hardware descriptor. 2529b96bf5SAnton Yakovlev * @elapsed_period: Kernel work to handle the elapsed period state. 26f40a2867SAnton Yakovlev * @lock: Spinlock that protects fields shared by interrupt handlers and 27f40a2867SAnton Yakovlev * substream operators. 28f40a2867SAnton Yakovlev * @buffer_bytes: Current buffer size in bytes. 29f40a2867SAnton Yakovlev * @hw_ptr: Substream hardware pointer value in bytes [0 ... buffer_bytes). 30f40a2867SAnton Yakovlev * @xfer_enabled: Data transfer state (0 - off, 1 - on). 31f40a2867SAnton Yakovlev * @xfer_xrun: Data underflow/overflow state (0 - no xrun, 1 - xrun). 32da76e9f3SAnton Yakovlev * @stopped: True if the substream is stopped and must be released on the device 33da76e9f3SAnton Yakovlev * side. 34f40a2867SAnton Yakovlev * @msgs: Allocated I/O messages. 35f40a2867SAnton Yakovlev * @nmsgs: Number of allocated I/O messages. 36f40a2867SAnton Yakovlev * @msg_last_enqueued: Index of the last I/O message added to the virtqueue. 37f40a2867SAnton Yakovlev * @msg_count: Number of pending I/O messages in the virtqueue. 38f40a2867SAnton Yakovlev * @msg_empty: Notify when msg_count is zero. 3929b96bf5SAnton Yakovlev */ 4029b96bf5SAnton Yakovlev struct virtio_pcm_substream { 4129b96bf5SAnton Yakovlev struct virtio_snd *snd; 4229b96bf5SAnton Yakovlev u32 nid; 4329b96bf5SAnton Yakovlev u32 sid; 4429b96bf5SAnton Yakovlev u32 direction; 4529b96bf5SAnton Yakovlev u32 features; 4629b96bf5SAnton Yakovlev struct snd_pcm_substream *substream; 4729b96bf5SAnton Yakovlev struct snd_pcm_hardware hw; 4829b96bf5SAnton Yakovlev struct work_struct elapsed_period; 49f40a2867SAnton Yakovlev spinlock_t lock; 50f40a2867SAnton Yakovlev size_t buffer_bytes; 51f40a2867SAnton Yakovlev size_t hw_ptr; 52f40a2867SAnton Yakovlev bool xfer_enabled; 53f40a2867SAnton Yakovlev bool xfer_xrun; 54da76e9f3SAnton Yakovlev bool stopped; 55f40a2867SAnton Yakovlev struct virtio_pcm_msg **msgs; 56f40a2867SAnton Yakovlev unsigned int nmsgs; 57f40a2867SAnton Yakovlev int msg_last_enqueued; 58f40a2867SAnton Yakovlev unsigned int msg_count; 59f40a2867SAnton Yakovlev wait_queue_head_t msg_empty; 6029b96bf5SAnton Yakovlev }; 6129b96bf5SAnton Yakovlev 6229b96bf5SAnton Yakovlev /** 6329b96bf5SAnton Yakovlev * struct virtio_pcm_stream - VirtIO PCM stream. 6429b96bf5SAnton Yakovlev * @substreams: VirtIO substreams belonging to the stream. 6529b96bf5SAnton Yakovlev * @nsubstreams: Number of substreams. 66*19325fedSAnton Yakovlev * @chmaps: Kernel channel maps belonging to the stream. 67*19325fedSAnton Yakovlev * @nchmaps: Number of channel maps. 6829b96bf5SAnton Yakovlev */ 6929b96bf5SAnton Yakovlev struct virtio_pcm_stream { 7029b96bf5SAnton Yakovlev struct virtio_pcm_substream **substreams; 7129b96bf5SAnton Yakovlev u32 nsubstreams; 72*19325fedSAnton Yakovlev struct snd_pcm_chmap_elem *chmaps; 73*19325fedSAnton Yakovlev u32 nchmaps; 7429b96bf5SAnton Yakovlev }; 7529b96bf5SAnton Yakovlev 7629b96bf5SAnton Yakovlev /** 7729b96bf5SAnton Yakovlev * struct virtio_pcm - VirtIO PCM device. 7829b96bf5SAnton Yakovlev * @list: VirtIO PCM list entry. 7929b96bf5SAnton Yakovlev * @nid: Function group node identifier. 8029b96bf5SAnton Yakovlev * @pcm: Kernel PCM device. 8129b96bf5SAnton Yakovlev * @streams: VirtIO PCM streams (playback and capture). 8229b96bf5SAnton Yakovlev */ 8329b96bf5SAnton Yakovlev struct virtio_pcm { 8429b96bf5SAnton Yakovlev struct list_head list; 8529b96bf5SAnton Yakovlev u32 nid; 8629b96bf5SAnton Yakovlev struct snd_pcm *pcm; 8729b96bf5SAnton Yakovlev struct virtio_pcm_stream streams[SNDRV_PCM_STREAM_LAST + 1]; 8829b96bf5SAnton Yakovlev }; 8929b96bf5SAnton Yakovlev 90da76e9f3SAnton Yakovlev extern const struct snd_pcm_ops virtsnd_pcm_ops; 91da76e9f3SAnton Yakovlev 9229b96bf5SAnton Yakovlev int virtsnd_pcm_validate(struct virtio_device *vdev); 9329b96bf5SAnton Yakovlev 9429b96bf5SAnton Yakovlev int virtsnd_pcm_parse_cfg(struct virtio_snd *snd); 9529b96bf5SAnton Yakovlev 9629b96bf5SAnton Yakovlev int virtsnd_pcm_build_devs(struct virtio_snd *snd); 9729b96bf5SAnton Yakovlev 98f40a2867SAnton Yakovlev void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event); 99f40a2867SAnton Yakovlev 100f40a2867SAnton Yakovlev void virtsnd_pcm_tx_notify_cb(struct virtqueue *vqueue); 101f40a2867SAnton Yakovlev 102f40a2867SAnton Yakovlev void virtsnd_pcm_rx_notify_cb(struct virtqueue *vqueue); 103f40a2867SAnton Yakovlev 10429b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find(struct virtio_snd *snd, u32 nid); 10529b96bf5SAnton Yakovlev 10629b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find_or_create(struct virtio_snd *snd, u32 nid); 10729b96bf5SAnton Yakovlev 108f40a2867SAnton Yakovlev struct virtio_snd_msg * 109f40a2867SAnton Yakovlev virtsnd_pcm_ctl_msg_alloc(struct virtio_pcm_substream *vss, 110f40a2867SAnton Yakovlev unsigned int command, gfp_t gfp); 111f40a2867SAnton Yakovlev 112f40a2867SAnton Yakovlev int virtsnd_pcm_msg_alloc(struct virtio_pcm_substream *vss, 113f40a2867SAnton Yakovlev unsigned int periods, unsigned int period_bytes); 114f40a2867SAnton Yakovlev 115f40a2867SAnton Yakovlev void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss); 116f40a2867SAnton Yakovlev 117f40a2867SAnton Yakovlev int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss); 118f40a2867SAnton Yakovlev 119f40a2867SAnton Yakovlev unsigned int virtsnd_pcm_msg_pending_num(struct virtio_pcm_substream *vss); 120f40a2867SAnton Yakovlev 12129b96bf5SAnton Yakovlev #endif /* VIRTIO_SND_PCM_H */ 122