1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #pragma once
17 
18 #include <atomic>
19 #include <type_traits>
20 
21 #include "common/libs/utils/cf_endian.h"
22 
23 namespace cuttlefish {
24 // TODO (b/175151042): get these from the kernel headers when available
25 
26 enum class AudioCommandType : uint32_t {
27   /* jack control request types */
28   VIRTIO_SND_R_JACK_INFO = 1,
29   VIRTIO_SND_R_JACK_REMAP,
30 
31   /* PCM control request types */
32   VIRTIO_SND_R_PCM_INFO = 0x0100,
33   VIRTIO_SND_R_PCM_SET_PARAMS,
34   VIRTIO_SND_R_PCM_PREPARE,
35   VIRTIO_SND_R_PCM_RELEASE,
36   VIRTIO_SND_R_PCM_START,
37   VIRTIO_SND_R_PCM_STOP,
38 
39   /* channel map control request types */
40   VIRTIO_SND_R_CHMAP_INFO = 0x0200,
41 };
42 
43 enum class AudioStatus : uint32_t {
44   /* common status codes */
45   VIRTIO_SND_S_OK = 0x8000,
46   VIRTIO_SND_S_BAD_MSG,
47   VIRTIO_SND_S_NOT_SUPP,
48   VIRTIO_SND_S_IO_ERR,
49   // Not a virtio constant, but it's only used internally as an invalid value so
50   // it's safe.
51   NOT_SET = static_cast<uint32_t>(-1),
52 };
53 
54 enum class AudioStreamDirection : uint8_t {
55   VIRTIO_SND_D_OUTPUT = 0,
56   VIRTIO_SND_D_INPUT
57 };
58 
59 enum class AudioStreamFormat : uint8_t {
60   /* analog formats (width / physical width) */
61   VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0, /*  4 /  4 bits */
62   VIRTIO_SND_PCM_FMT_MU_LAW,        /*  8 /  8 bits */
63   VIRTIO_SND_PCM_FMT_A_LAW,         /*  8 /  8 bits */
64   VIRTIO_SND_PCM_FMT_S8,            /*  8 /  8 bits */
65   VIRTIO_SND_PCM_FMT_U8,            /*  8 /  8 bits */
66   VIRTIO_SND_PCM_FMT_S16,           /* 16 / 16 bits */
67   VIRTIO_SND_PCM_FMT_U16,           /* 16 / 16 bits */
68   VIRTIO_SND_PCM_FMT_S18_3,         /* 18 / 24 bits */
69   VIRTIO_SND_PCM_FMT_U18_3,         /* 18 / 24 bits */
70   VIRTIO_SND_PCM_FMT_S20_3,         /* 20 / 24 bits */
71   VIRTIO_SND_PCM_FMT_U20_3,         /* 20 / 24 bits */
72   VIRTIO_SND_PCM_FMT_S24_3,         /* 24 / 24 bits */
73   VIRTIO_SND_PCM_FMT_U24_3,         /* 24 / 24 bits */
74   VIRTIO_SND_PCM_FMT_S20,           /* 20 / 32 bits */
75   VIRTIO_SND_PCM_FMT_U20,           /* 20 / 32 bits */
76   VIRTIO_SND_PCM_FMT_S24,           /* 24 / 32 bits */
77   VIRTIO_SND_PCM_FMT_U24,           /* 24 / 32 bits */
78   VIRTIO_SND_PCM_FMT_S32,           /* 32 / 32 bits */
79   VIRTIO_SND_PCM_FMT_U32,           /* 32 / 32 bits */
80   VIRTIO_SND_PCM_FMT_FLOAT,         /* 32 / 32 bits */
81   VIRTIO_SND_PCM_FMT_FLOAT64,       /* 64 / 64 bits */
82   /* digital formats (width / physical width) */
83   VIRTIO_SND_PCM_FMT_DSD_U8,         /*  8 /  8 bits */
84   VIRTIO_SND_PCM_FMT_DSD_U16,        /* 16 / 16 bits */
85   VIRTIO_SND_PCM_FMT_DSD_U32,        /* 32 / 32 bits */
86   VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME /* 32 / 32 bits */
87 };
88 
89 /* supported PCM frame rates */
90 enum AudioStreamRate : uint8_t {
91   VIRTIO_SND_PCM_RATE_5512 = 0,
92   VIRTIO_SND_PCM_RATE_8000,
93   VIRTIO_SND_PCM_RATE_11025,
94   VIRTIO_SND_PCM_RATE_16000,
95   VIRTIO_SND_PCM_RATE_22050,
96   VIRTIO_SND_PCM_RATE_32000,
97   VIRTIO_SND_PCM_RATE_44100,
98   VIRTIO_SND_PCM_RATE_48000,
99   VIRTIO_SND_PCM_RATE_64000,
100   VIRTIO_SND_PCM_RATE_88200,
101   VIRTIO_SND_PCM_RATE_96000,
102   VIRTIO_SND_PCM_RATE_176400,
103   VIRTIO_SND_PCM_RATE_192000,
104   VIRTIO_SND_PCM_RATE_384000
105 };
106 
107 /* standard channel position definition */
108 enum AudioChannelMap : uint8_t {
109   VIRTIO_SND_CHMAP_NONE = 0,  /* undefined */
110   VIRTIO_SND_CHMAP_NA,        /* silent */
111   VIRTIO_SND_CHMAP_MONO,      /* mono stream */
112   VIRTIO_SND_CHMAP_FL,        /* front left */
113   VIRTIO_SND_CHMAP_FR,        /* front right */
114   VIRTIO_SND_CHMAP_RL,        /* rear left */
115   VIRTIO_SND_CHMAP_RR,        /* rear right */
116   VIRTIO_SND_CHMAP_FC,        /* front center */
117   VIRTIO_SND_CHMAP_LFE,       /* low frequency (LFE) */
118   VIRTIO_SND_CHMAP_SL,        /* side left */
119   VIRTIO_SND_CHMAP_SR,        /* side right */
120   VIRTIO_SND_CHMAP_RC,        /* rear center */
121   VIRTIO_SND_CHMAP_FLC,       /* front left center */
122   VIRTIO_SND_CHMAP_FRC,       /* front right center */
123   VIRTIO_SND_CHMAP_RLC,       /* rear left center */
124   VIRTIO_SND_CHMAP_RRC,       /* rear right center */
125   VIRTIO_SND_CHMAP_FLW,       /* front left wide */
126   VIRTIO_SND_CHMAP_FRW,       /* front right wide */
127   VIRTIO_SND_CHMAP_FLH,       /* front left high */
128   VIRTIO_SND_CHMAP_FCH,       /* front center high */
129   VIRTIO_SND_CHMAP_FRH,       /* front right high */
130   VIRTIO_SND_CHMAP_TC,        /* top center */
131   VIRTIO_SND_CHMAP_TFL,       /* top front left */
132   VIRTIO_SND_CHMAP_TFR,       /* top front right */
133   VIRTIO_SND_CHMAP_TFC,       /* top front center */
134   VIRTIO_SND_CHMAP_TRL,       /* top rear left */
135   VIRTIO_SND_CHMAP_TRR,       /* top rear right */
136   VIRTIO_SND_CHMAP_TRC,       /* top rear center */
137   VIRTIO_SND_CHMAP_TFLC,      /* top front left center */
138   VIRTIO_SND_CHMAP_TFRC,      /* top front right center */
139   VIRTIO_SND_CHMAP_TSL,       /* top side left */
140   VIRTIO_SND_CHMAP_TSR,       /* top side right */
141   VIRTIO_SND_CHMAP_LLFE,      /* left LFE */
142   VIRTIO_SND_CHMAP_RLFE,      /* right LFE */
143   VIRTIO_SND_CHMAP_BC,        /* bottom center */
144   VIRTIO_SND_CHMAP_BLC,       /* bottom left center */
145   VIRTIO_SND_CHMAP_BRC        /* bottom right center */
146 };
147 
148 struct virtio_snd_hdr {
149   Le32 code;
150 };
151 
152 struct virtio_snd_query_info {
153   struct virtio_snd_hdr hdr;
154   Le32 start_id;
155   Le32 count;
156   Le32 size;  // unused
157 };
158 
159 struct virtio_snd_info {
160   Le32 hda_fn_nid;
161 };
162 
163 /* supported jack features */
164 enum AudioJackFeatures: uint8_t {
165   VIRTIO_SND_JACK_F_REMAP = 0
166 };
167 
168 struct virtio_snd_jack_info {
169   struct virtio_snd_info hdr;
170   Le32 features; /* 1 << VIRTIO_SND_JACK_F_XXX */
171   Le32 hda_reg_defconf;
172   Le32 hda_reg_caps;
173   uint8_t connected;
174 
175   uint8_t padding[7];
176 };
177 
178 constexpr uint8_t VIRTIO_SND_CHMAP_MAX_SIZE = 18;
179 struct virtio_snd_chmap_info {
180   struct virtio_snd_info hdr;
181   uint8_t direction;
182   uint8_t channels;
183   uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
184 };
185 
186 struct virtio_snd_pcm_info {
187   struct virtio_snd_info hdr;
188   Le32 features; /* 1 << VIRTIO_SND_PCM_F_XXX */
189   Le64 formats;  /* 1 << VIRTIO_SND_PCM_FMT_XXX */
190   Le64 rates;    /* 1 << VIRTIO_SND_PCM_RATE_XXX */
191   uint8_t direction;
192   uint8_t channels_min;
193   uint8_t channels_max;
194 
195   uint8_t padding[5];
196 };
197 
198 struct virtio_snd_pcm_hdr {
199   struct virtio_snd_hdr hdr;
200   Le32 stream_id;
201 };
202 
203 struct virtio_snd_pcm_set_params {
204   struct virtio_snd_pcm_hdr hdr;
205   Le32 buffer_bytes;
206   Le32 period_bytes;
207   Le32 features; /* 1 << VIRTIO_SND_PCM_F_XXX */
208   uint8_t channels;
209   uint8_t format;
210   uint8_t rate;
211   uint8_t padding;
212 };
213 
214 struct virtio_snd_pcm_xfer {
215   Le32 stream_id;
216 };
217 
218 struct virtio_snd_pcm_status {
219   Le32 status;
220   Le32 latency_bytes;
221 };
222 
223 // Update this value when the msg layouts change
224 const uint32_t VIOS_VERSION = 2;
225 
226 struct VioSConfig {
227   uint32_t version;
228   uint32_t jacks;
229   uint32_t streams;
230   uint32_t chmaps;
231 };
232 
233 struct IoTransferMsg {
234   virtio_snd_pcm_xfer io_xfer;
235   uint32_t buffer_offset;
236   uint32_t buffer_len;
237 };
238 
239 struct IoStatusMsg {
240   virtio_snd_pcm_status status;
241   uint32_t buffer_offset;
242   uint32_t consumed_length;
243 };
244 
245 // Ensure all message structs have predictable sizes
246 #define ASSERT_VALID_MSG_TYPE(T, size) \
247   static_assert(sizeof(T) == (size), #T " has the wrong size")
248 ASSERT_VALID_MSG_TYPE(virtio_snd_query_info, 16);
249 ASSERT_VALID_MSG_TYPE(virtio_snd_jack_info, 24);
250 ASSERT_VALID_MSG_TYPE(virtio_snd_chmap_info, 24);
251 ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_info, 32);
252 ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_set_params, 24);
253 ASSERT_VALID_MSG_TYPE(virtio_snd_pcm_hdr, 8);
254 ASSERT_VALID_MSG_TYPE(IoTransferMsg, 12);
255 ASSERT_VALID_MSG_TYPE(IoStatusMsg, 16);
256 #undef ASSERT_VALID_MSG_TYPE
257 
258 }  // namespace cuttlefish
259