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. 34*575483e9SAnton Yakovlev * @suspended: True if the substream is suspended and must be reconfigured on 35*575483e9SAnton Yakovlev * the device side at resume. 36f40a2867SAnton Yakovlev * @msgs: Allocated I/O messages. 37f40a2867SAnton Yakovlev * @nmsgs: Number of allocated I/O messages. 38f40a2867SAnton Yakovlev * @msg_last_enqueued: Index of the last I/O message added to the virtqueue. 39f40a2867SAnton Yakovlev * @msg_count: Number of pending I/O messages in the virtqueue. 40f40a2867SAnton Yakovlev * @msg_empty: Notify when msg_count is zero. 4129b96bf5SAnton Yakovlev */ 4229b96bf5SAnton Yakovlev struct virtio_pcm_substream { 4329b96bf5SAnton Yakovlev struct virtio_snd *snd; 4429b96bf5SAnton Yakovlev u32 nid; 4529b96bf5SAnton Yakovlev u32 sid; 4629b96bf5SAnton Yakovlev u32 direction; 4729b96bf5SAnton Yakovlev u32 features; 4829b96bf5SAnton Yakovlev struct snd_pcm_substream *substream; 4929b96bf5SAnton Yakovlev struct snd_pcm_hardware hw; 5029b96bf5SAnton Yakovlev struct work_struct elapsed_period; 51f40a2867SAnton Yakovlev spinlock_t lock; 52f40a2867SAnton Yakovlev size_t buffer_bytes; 53f40a2867SAnton Yakovlev size_t hw_ptr; 54f40a2867SAnton Yakovlev bool xfer_enabled; 55f40a2867SAnton Yakovlev bool xfer_xrun; 56da76e9f3SAnton Yakovlev bool stopped; 57*575483e9SAnton Yakovlev bool suspended; 58f40a2867SAnton Yakovlev struct virtio_pcm_msg **msgs; 59f40a2867SAnton Yakovlev unsigned int nmsgs; 60f40a2867SAnton Yakovlev int msg_last_enqueued; 61f40a2867SAnton Yakovlev unsigned int msg_count; 62f40a2867SAnton Yakovlev wait_queue_head_t msg_empty; 6329b96bf5SAnton Yakovlev }; 6429b96bf5SAnton Yakovlev 6529b96bf5SAnton Yakovlev /** 6629b96bf5SAnton Yakovlev * struct virtio_pcm_stream - VirtIO PCM stream. 6729b96bf5SAnton Yakovlev * @substreams: VirtIO substreams belonging to the stream. 6829b96bf5SAnton Yakovlev * @nsubstreams: Number of substreams. 6919325fedSAnton Yakovlev * @chmaps: Kernel channel maps belonging to the stream. 7019325fedSAnton Yakovlev * @nchmaps: Number of channel maps. 7129b96bf5SAnton Yakovlev */ 7229b96bf5SAnton Yakovlev struct virtio_pcm_stream { 7329b96bf5SAnton Yakovlev struct virtio_pcm_substream **substreams; 7429b96bf5SAnton Yakovlev u32 nsubstreams; 7519325fedSAnton Yakovlev struct snd_pcm_chmap_elem *chmaps; 7619325fedSAnton Yakovlev u32 nchmaps; 7729b96bf5SAnton Yakovlev }; 7829b96bf5SAnton Yakovlev 7929b96bf5SAnton Yakovlev /** 8029b96bf5SAnton Yakovlev * struct virtio_pcm - VirtIO PCM device. 8129b96bf5SAnton Yakovlev * @list: VirtIO PCM list entry. 8229b96bf5SAnton Yakovlev * @nid: Function group node identifier. 8329b96bf5SAnton Yakovlev * @pcm: Kernel PCM device. 8429b96bf5SAnton Yakovlev * @streams: VirtIO PCM streams (playback and capture). 8529b96bf5SAnton Yakovlev */ 8629b96bf5SAnton Yakovlev struct virtio_pcm { 8729b96bf5SAnton Yakovlev struct list_head list; 8829b96bf5SAnton Yakovlev u32 nid; 8929b96bf5SAnton Yakovlev struct snd_pcm *pcm; 9029b96bf5SAnton Yakovlev struct virtio_pcm_stream streams[SNDRV_PCM_STREAM_LAST + 1]; 9129b96bf5SAnton Yakovlev }; 9229b96bf5SAnton Yakovlev 93da76e9f3SAnton Yakovlev extern const struct snd_pcm_ops virtsnd_pcm_ops; 94da76e9f3SAnton Yakovlev 9529b96bf5SAnton Yakovlev int virtsnd_pcm_validate(struct virtio_device *vdev); 9629b96bf5SAnton Yakovlev 9729b96bf5SAnton Yakovlev int virtsnd_pcm_parse_cfg(struct virtio_snd *snd); 9829b96bf5SAnton Yakovlev 9929b96bf5SAnton Yakovlev int virtsnd_pcm_build_devs(struct virtio_snd *snd); 10029b96bf5SAnton Yakovlev 101f40a2867SAnton Yakovlev void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event); 102f40a2867SAnton Yakovlev 103f40a2867SAnton Yakovlev void virtsnd_pcm_tx_notify_cb(struct virtqueue *vqueue); 104f40a2867SAnton Yakovlev 105f40a2867SAnton Yakovlev void virtsnd_pcm_rx_notify_cb(struct virtqueue *vqueue); 106f40a2867SAnton Yakovlev 10729b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find(struct virtio_snd *snd, u32 nid); 10829b96bf5SAnton Yakovlev 10929b96bf5SAnton Yakovlev struct virtio_pcm *virtsnd_pcm_find_or_create(struct virtio_snd *snd, u32 nid); 11029b96bf5SAnton Yakovlev 111f40a2867SAnton Yakovlev struct virtio_snd_msg * 112f40a2867SAnton Yakovlev virtsnd_pcm_ctl_msg_alloc(struct virtio_pcm_substream *vss, 113f40a2867SAnton Yakovlev unsigned int command, gfp_t gfp); 114f40a2867SAnton Yakovlev 115f40a2867SAnton Yakovlev int virtsnd_pcm_msg_alloc(struct virtio_pcm_substream *vss, 116f40a2867SAnton Yakovlev unsigned int periods, unsigned int period_bytes); 117f40a2867SAnton Yakovlev 118f40a2867SAnton Yakovlev void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss); 119f40a2867SAnton Yakovlev 120f40a2867SAnton Yakovlev int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss); 121f40a2867SAnton Yakovlev 122f40a2867SAnton Yakovlev unsigned int virtsnd_pcm_msg_pending_num(struct virtio_pcm_substream *vss); 123f40a2867SAnton Yakovlev 12429b96bf5SAnton Yakovlev #endif /* VIRTIO_SND_PCM_H */ 125