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> 12*fe981e67SMatias Ezequiel Vara Larsen #include <sound/pcm-indirect.h> 1329b96bf5SAnton Yakovlev 1429b96bf5SAnton Yakovlev struct virtio_pcm; 1529b96bf5SAnton Yakovlev struct virtio_pcm_msg; 1629b96bf5SAnton Yakovlev 1729b96bf5SAnton Yakovlev /** 1829b96bf5SAnton Yakovlev * struct virtio_pcm_substream - VirtIO PCM substream. 1929b96bf5SAnton Yakovlev * @snd: VirtIO sound device. 2029b96bf5SAnton Yakovlev * @nid: Function group node identifier. 2129b96bf5SAnton Yakovlev * @sid: Stream identifier. 2229b96bf5SAnton Yakovlev * @direction: Stream data flow direction (SNDRV_PCM_STREAM_XXX). 2329b96bf5SAnton Yakovlev * @features: Stream VirtIO feature bit map (1 << VIRTIO_SND_PCM_F_XXX). 2429b96bf5SAnton Yakovlev * @substream: Kernel ALSA substream. 25*fe981e67SMatias Ezequiel Vara Larsen * @pcm_indirect: Kernel indirect pcm structure. 2629b96bf5SAnton Yakovlev * @hw: Kernel ALSA substream hardware descriptor. 2729b96bf5SAnton Yakovlev * @elapsed_period: Kernel work to handle the elapsed period state. 28f40a2867SAnton Yakovlev * @lock: Spinlock that protects fields shared by interrupt handlers and 29f40a2867SAnton Yakovlev * substream operators. 30f40a2867SAnton Yakovlev * @buffer_bytes: Current buffer size in bytes. 31f40a2867SAnton Yakovlev * @hw_ptr: Substream hardware pointer value in bytes [0 ... buffer_bytes). 32f40a2867SAnton Yakovlev * @xfer_enabled: Data transfer state (0 - off, 1 - on). 33f40a2867SAnton Yakovlev * @xfer_xrun: Data underflow/overflow state (0 - no xrun, 1 - xrun). 34da76e9f3SAnton Yakovlev * @stopped: True if the substream is stopped and must be released on the device 35da76e9f3SAnton Yakovlev * side. 36575483e9SAnton Yakovlev * @suspended: True if the substream is suspended and must be reconfigured on 37575483e9SAnton Yakovlev * the device side at resume. 38f40a2867SAnton Yakovlev * @msgs: Allocated I/O messages. 39f40a2867SAnton Yakovlev * @nmsgs: Number of allocated I/O messages. 40f40a2867SAnton Yakovlev * @msg_last_enqueued: Index of the last I/O message added to the virtqueue. 41f40a2867SAnton Yakovlev * @msg_count: Number of pending I/O messages in the virtqueue. 42f40a2867SAnton Yakovlev * @msg_empty: Notify when msg_count is zero. 4329b96bf5SAnton Yakovlev */ 4429b96bf5SAnton Yakovlev struct virtio_pcm_substream { 4529b96bf5SAnton Yakovlev struct virtio_snd *snd; 4629b96bf5SAnton Yakovlev u32 nid; 4729b96bf5SAnton Yakovlev u32 sid; 4829b96bf5SAnton Yakovlev u32 direction; 4929b96bf5SAnton Yakovlev u32 features; 5029b96bf5SAnton Yakovlev struct snd_pcm_substream *substream; 51*fe981e67SMatias Ezequiel Vara Larsen struct snd_pcm_indirect pcm_indirect; 5229b96bf5SAnton Yakovlev struct snd_pcm_hardware hw; 5329b96bf5SAnton Yakovlev struct work_struct elapsed_period; 54f40a2867SAnton Yakovlev spinlock_t lock; 55f40a2867SAnton Yakovlev size_t buffer_bytes; 56f40a2867SAnton Yakovlev size_t hw_ptr; 57f40a2867SAnton Yakovlev bool xfer_enabled; 58f40a2867SAnton Yakovlev bool xfer_xrun; 59da76e9f3SAnton Yakovlev bool stopped; 60575483e9SAnton Yakovlev bool suspended; 61f40a2867SAnton Yakovlev struct virtio_pcm_msg **msgs; 62f40a2867SAnton Yakovlev unsigned int nmsgs; 63f40a2867SAnton Yakovlev unsigned int msg_count; 64f40a2867SAnton Yakovlev wait_queue_head_t msg_empty; 6529b96bf5SAnton Yakovlev }; 6629b96bf5SAnton Yakovlev 6729b96bf5SAnton Yakovlev /** 6829b96bf5SAnton Yakovlev * struct virtio_pcm_stream - VirtIO PCM stream. 6929b96bf5SAnton Yakovlev * @substreams: VirtIO substreams belonging to the stream. 7029b96bf5SAnton Yakovlev * @nsubstreams: Number of substreams. 7119325fedSAnton Yakovlev * @chmaps: Kernel channel maps belonging to the stream. 7219325fedSAnton Yakovlev * @nchmaps: Number of channel maps. 7329b96bf5SAnton Yakovlev */ 7429b96bf5SAnton Yakovlev struct virtio_pcm_stream { 7529b96bf5SAnton Yakovlev struct virtio_pcm_substream **substreams; 7629b96bf5SAnton Yakovlev u32 nsubstreams; 7719325fedSAnton Yakovlev struct snd_pcm_chmap_elem *chmaps; 7819325fedSAnton Yakovlev u32 nchmaps; 7929b96bf5SAnton Yakovlev }; 8029b96bf5SAnton Yakovlev 8129b96bf5SAnton Yakovlev /** 8229b96bf5SAnton Yakovlev * struct virtio_pcm - VirtIO PCM device. 8329b96bf5SAnton Yakovlev * @list: VirtIO PCM list entry. 8429b96bf5SAnton Yakovlev * @nid: Function group node identifier. 8529b96bf5SAnton Yakovlev * @pcm: Kernel PCM device. 8629b96bf5SAnton Yakovlev * @streams: VirtIO PCM streams (playback and capture). 8729b96bf5SAnton Yakovlev */ 8829b96bf5SAnton Yakovlev struct virtio_pcm { 8929b96bf5SAnton Yakovlev struct list_head list; 9029b96bf5SAnton Yakovlev u32 nid; 9129b96bf5SAnton Yakovlev struct snd_pcm *pcm; 9229b96bf5SAnton Yakovlev struct virtio_pcm_stream streams[SNDRV_PCM_STREAM_LAST + 1]; 9329b96bf5SAnton Yakovlev }; 9429b96bf5SAnton Yakovlev 95*fe981e67SMatias Ezequiel Vara Larsen extern const struct snd_pcm_ops virtsnd_pcm_ops[]; 96da76e9f3SAnton Yakovlev 9729b96bf5SAnton Yakovlev int virtsnd_pcm_validate(struct virtio_device *vdev); 9829b96bf5SAnton Yakovlev 9929b96bf5SAnton Yakovlev int virtsnd_pcm_parse_cfg(struct virtio_snd *snd); 10029b96bf5SAnton Yakovlev 10129b96bf5SAnton Yakovlev int virtsnd_pcm_build_devs(struct virtio_snd *snd); 10229b96bf5SAnton Yakovlev 103f40a2867SAnton Yakovlev void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event); 104f40a2867SAnton Yakovlev 105f40a2867SAnton Yakovlev void virtsnd_pcm_tx_notify_cb(struct virtqueue *vqueue); 106f40a2867SAnton Yakovlev 107f40a2867SAnton Yakovlev void virtsnd_pcm_rx_notify_cb(struct virtqueue *vqueue); 108f40a2867SAnton Yakovlev 10929b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find(struct virtio_snd *snd, u32 nid); 11029b96bf5SAnton Yakovlev 11129b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find_or_create(struct virtio_snd *snd, u32 nid); 11229b96bf5SAnton Yakovlev 113f40a2867SAnton Yakovlev struct virtio_snd_msg * 114f40a2867SAnton Yakovlev virtsnd_pcm_ctl_msg_alloc(struct virtio_pcm_substream *vss, 115f40a2867SAnton Yakovlev unsigned int command, gfp_t gfp); 116f40a2867SAnton Yakovlev 117f40a2867SAnton Yakovlev int virtsnd_pcm_msg_alloc(struct virtio_pcm_substream *vss, 118f40a2867SAnton Yakovlev unsigned int periods, unsigned int period_bytes); 119f40a2867SAnton Yakovlev 120f40a2867SAnton Yakovlev void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss); 121f40a2867SAnton Yakovlev 122*fe981e67SMatias Ezequiel Vara Larsen int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss, unsigned long offset, 123*fe981e67SMatias Ezequiel Vara Larsen unsigned long bytes); 124f40a2867SAnton Yakovlev 125f40a2867SAnton Yakovlev unsigned int virtsnd_pcm_msg_pending_num(struct virtio_pcm_substream *vss); 126f40a2867SAnton Yakovlev 12729b96bf5SAnton Yakovlev #endif /* VIRTIO_SND_PCM_H */ 128