1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* |
3 | * virtio-snd: Virtio sound device |
4 | * Copyright (C) 2021 OpenSynergy GmbH |
5 | */ |
6 | #ifndef VIRTIO_SND_PCM_H |
7 | #define VIRTIO_SND_PCM_H |
8 | |
9 | #include <linux/atomic.h> |
10 | #include <linux/virtio_config.h> |
11 | #include <sound/pcm.h> |
12 | #include <sound/pcm-indirect.h> |
13 | |
14 | struct virtio_pcm; |
15 | struct virtio_pcm_msg; |
16 | |
17 | /** |
18 | * struct virtio_pcm_substream - VirtIO PCM substream. |
19 | * @snd: VirtIO sound device. |
20 | * @nid: Function group node identifier. |
21 | * @sid: Stream identifier. |
22 | * @direction: Stream data flow direction (SNDRV_PCM_STREAM_XXX). |
23 | * @features: Stream VirtIO feature bit map (1 << VIRTIO_SND_PCM_F_XXX). |
24 | * @substream: Kernel ALSA substream. |
25 | * @pcm_indirect: Kernel indirect pcm structure. |
26 | * @hw: Kernel ALSA substream hardware descriptor. |
27 | * @elapsed_period: Kernel work to handle the elapsed period state. |
28 | * @lock: Spinlock that protects fields shared by interrupt handlers and |
29 | * substream operators. |
30 | * @buffer_bytes: Current buffer size in bytes. |
31 | * @hw_ptr: Substream hardware pointer value in bytes [0 ... buffer_bytes). |
32 | * @xfer_enabled: Data transfer state (0 - off, 1 - on). |
33 | * @xfer_xrun: Data underflow/overflow state (0 - no xrun, 1 - xrun). |
34 | * @stopped: True if the substream is stopped and must be released on the device |
35 | * side. |
36 | * @suspended: True if the substream is suspended and must be reconfigured on |
37 | * the device side at resume. |
38 | * @msgs: Allocated I/O messages. |
39 | * @nmsgs: Number of allocated I/O messages. |
40 | * @msg_last_enqueued: Index of the last I/O message added to the virtqueue. |
41 | * @msg_count: Number of pending I/O messages in the virtqueue. |
42 | * @msg_empty: Notify when msg_count is zero. |
43 | */ |
44 | struct virtio_pcm_substream { |
45 | struct virtio_snd *snd; |
46 | u32 nid; |
47 | u32 sid; |
48 | u32 direction; |
49 | u32 features; |
50 | struct snd_pcm_substream *substream; |
51 | struct snd_pcm_indirect pcm_indirect; |
52 | struct snd_pcm_hardware hw; |
53 | struct work_struct elapsed_period; |
54 | spinlock_t lock; |
55 | size_t buffer_bytes; |
56 | size_t hw_ptr; |
57 | bool xfer_enabled; |
58 | bool xfer_xrun; |
59 | bool stopped; |
60 | bool suspended; |
61 | struct virtio_pcm_msg **msgs; |
62 | unsigned int nmsgs; |
63 | unsigned int msg_count; |
64 | wait_queue_head_t msg_empty; |
65 | }; |
66 | |
67 | /** |
68 | * struct virtio_pcm_stream - VirtIO PCM stream. |
69 | * @substreams: VirtIO substreams belonging to the stream. |
70 | * @nsubstreams: Number of substreams. |
71 | * @chmaps: Kernel channel maps belonging to the stream. |
72 | * @nchmaps: Number of channel maps. |
73 | */ |
74 | struct virtio_pcm_stream { |
75 | struct virtio_pcm_substream **substreams; |
76 | u32 nsubstreams; |
77 | struct snd_pcm_chmap_elem *chmaps; |
78 | u32 nchmaps; |
79 | }; |
80 | |
81 | /** |
82 | * struct virtio_pcm - VirtIO PCM device. |
83 | * @list: VirtIO PCM list entry. |
84 | * @nid: Function group node identifier. |
85 | * @pcm: Kernel PCM device. |
86 | * @streams: VirtIO PCM streams (playback and capture). |
87 | */ |
88 | struct virtio_pcm { |
89 | struct list_head list; |
90 | u32 nid; |
91 | struct snd_pcm *pcm; |
92 | struct virtio_pcm_stream streams[SNDRV_PCM_STREAM_LAST + 1]; |
93 | }; |
94 | |
95 | extern const struct snd_pcm_ops virtsnd_pcm_ops[]; |
96 | |
97 | int virtsnd_pcm_validate(struct virtio_device *vdev); |
98 | |
99 | int virtsnd_pcm_parse_cfg(struct virtio_snd *snd); |
100 | |
101 | int virtsnd_pcm_build_devs(struct virtio_snd *snd); |
102 | |
103 | void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event); |
104 | |
105 | void virtsnd_pcm_tx_notify_cb(struct virtqueue *vqueue); |
106 | |
107 | void virtsnd_pcm_rx_notify_cb(struct virtqueue *vqueue); |
108 | |
109 | struct virtio_pcm *virtsnd_pcm_find(struct virtio_snd *snd, u32 nid); |
110 | |
111 | struct virtio_pcm *virtsnd_pcm_find_or_create(struct virtio_snd *snd, u32 nid); |
112 | |
113 | struct virtio_snd_msg * |
114 | virtsnd_pcm_ctl_msg_alloc(struct virtio_pcm_substream *vss, |
115 | unsigned int command, gfp_t gfp); |
116 | |
117 | int virtsnd_pcm_msg_alloc(struct virtio_pcm_substream *vss, |
118 | unsigned int periods, unsigned int period_bytes); |
119 | |
120 | void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss); |
121 | |
122 | int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss, unsigned long offset, |
123 | unsigned long bytes); |
124 | |
125 | unsigned int virtsnd_pcm_msg_pending_num(struct virtio_pcm_substream *vss); |
126 | |
127 | #endif /* VIRTIO_SND_PCM_H */ |
128 | |