1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #pragma once
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <type_traits>
10 #include <zircon/assert.h>
11 #include <zircon/compiler.h>
12 #include <zircon/types.h>
13
14 /**
15 * Register definitions taken from
16 *
17 * Intel High Definition Audio Specification
18 * Revision 1.0a
19 * June 17, 2010
20 *
21 * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/high-definition-audio-specification.pdf
22 */
23
24 // TODO(johngro)
25 //
26 // Consider moving these structures and their associated flags into a more C++
27 // style, where the flags can either be static constexpr members of the
28 // structures, or in their own namespace. Also, consider moving away from the
29 // underscore separated typedef declarations, and to LeadingUpperCamelCased
30 // declarations made without typedef and the _t suffix.
31 //
32 // Currently, we have to keep the register structures C compatible, because they
33 // are used in the response for the CONTROLLER_SNAPSHOT_REGS command. When we
34 // can send back a read-only VMO to provide debug access to the registers, we
35 // can do away with this.
36 typedef struct hda_stream_desc_regs {
37 // (0x00) Control (0x03) Status
38 union {
39 uint32_t w; // 32-bit word access to the Control/Status registers
40 struct {
41 uint8_t ctl[3]; // Control register byte access
42 uint8_t sts; // Status register byte access
43 } b;
44 } ctl_sts;
45 uint32_t lpib; // (0x04) SD_n Link Position in Current Buffer
46 uint32_t cbl; // (0x08) SD_n Cyclic Buffer Length
47 uint16_t lvi; // (0x0C) SD_n Last Valid Index
48 uint8_t __rsvd0[2]; // (0x8E) Reserved
49 uint16_t fifod; // (0x10) SD_n FIFO Size
50 uint16_t fmt; // (0x12) SD_n Format
51 uint8_t __rsvd1[4]; // (0x14) Reserved
52 uint32_t bdpl; // (0x18) SD_n Buffer Descriptor List Pointer - Lower
53 uint32_t bdpu; // (0x1C) SD_n Buffer Descriptor List Pointer - Upper
54 } __PACKED hda_stream_desc_regs_t;
55
56 typedef struct hda_registers {
57 uint16_t gcap; // (0x00) Global Capabilities
58 uint8_t vmin; // (0x02) Minor Version
59 uint8_t vmaj; // (0x03) Major Version
60 uint16_t outpay; // (0x04) Output Payload Capability
61 uint16_t inpay; // (0x06) Input Payload Capability
62 uint32_t gctl; // (0x08) Global Control
63 uint16_t wakeen; // (0x0C) Wake Enable
64 uint16_t statests; // (0x0E) State Change Status
65 uint16_t gsts; // (0x10) Global Status
66 uint16_t gcap2; // (0x12) Global Capabilities 2
67 uint16_t llch; // (0x14) Linked List Capabilities Header
68 uint8_t __rsvd[2]; // (0x16) Reserved
69 uint16_t outstrmpay; // (0x18) Output Stream Payload Capability
70 uint16_t instrmpay; // (0x1A) Input Stream Payload Capability
71 uint8_t __rsvd1[4]; // (0x1C) Reserved
72 uint32_t intctl; // (0x20) Interrupt Control
73 uint32_t intsts; // (0x24) Interrupt Status
74 uint8_t __rsvd2[8]; // (0x28) Reserved
75 uint32_t walclk; // (0x30) Wall Clock Counter
76 uint8_t __rsvd3[4]; // (0x34) Reserved
77 uint32_t ssync; // (0x38) Stream Synchronization
78 uint8_t __rsvd4[4]; // (0x3C) Reserved
79 uint32_t corblbase; // (0x40) CORB Lower Base Address
80 uint32_t corbubase; // (0x44) CORB Upper Base Address
81 uint16_t corbwp; // (0x48) CORB Write Pointer
82 uint16_t corbrp; // (0x4A) CORB Read Pointer
83 uint8_t corbctl; // (0x4C) CORB Control
84 uint8_t corbsts; // (0x4D) CORB Status
85 uint8_t corbsize; // (0x4E) CORB Size
86 uint8_t __rsvd5[1]; // (0x4F) Reserved
87 uint32_t rirblbase; // (0x50) RIRB Lower Base Address
88 uint32_t rirbubase; // (0x54) RIRB Upper Base Address
89 uint16_t rirbwp; // (0x58) RIRB Write Pointer
90 uint16_t rintcnt; // (0x5A) Response Interrupt Count
91 uint8_t rirbctl; // (0x5C) RIRB Control
92 uint8_t rirbsts; // (0x5D) RIRB Status
93 uint8_t rirbsize; // (0x5E) RIRB Size
94 uint8_t __rsvd6[1]; // (0x5F) Reserved
95 uint32_t icoi; // (0x60) Immediate Command Output Interface
96 uint32_t icii; // (0x64) Immediate Command Input Interface
97 uint16_t icis; // (0x68) Immediate Command Status
98 uint8_t __rsvd7[6]; // (0x6A) Reserved
99 uint32_t dpiblbase; // (0x70) DMA Position Buffer Lower Base
100 uint32_t dpibubase; // (0x74) DMA Position Buffer Upper Base
101 uint8_t __rsvd8[8]; // (0x78) Reserved
102
103 // A max of 30 streams may be present in the system at any point in time (no
104 // more than 15 input and 15 output). The stream descriptor registers start
105 // at 0x80, and are layed out as Input, then Output, then Bidirectional.
106 // The number of each type of stream present in the hardware can be
107 // determined using the GCAP register.
108 hda_stream_desc_regs_t stream_desc[30]; // (0x80)
109 uint8_t __rsvd9[0x1BC0]; // (0x440 - 0x1FFF)
110 } __PACKED hda_registers_t;
111
112 typedef struct hda_stream_desc_alias_regs {
113 uint8_t __rsvd0[0x04]; // (0x00) Reserved
114 uint32_t lpib; // (0x04) SD_n Link Position in Current Buffer Alias
115 uint8_t __rsvd1[0x18]; // (0x08) Reserved
116 } __PACKED hda_stream_desc_alias_regs_t;
117
118 typedef struct hda_alias_registers {
119 uint8_t __rsvd0[0x30]; // (0x00) Reserved
120 uint32_t wallclk; // (0x30) Wall Clock Counter Alias
121 uint8_t __rsvd1[0x4C]; // (0x34) Reserved
122 hda_stream_desc_alias_regs_t stream_desc[30]; // (0x80)
123 uint8_t __rsvd9[0x1BC0]; // (0x440 - 0x1FFF)
124 } __PACKED hda_alias_registers_t;
125
126 typedef struct hda_pp_registers {
127 uint32_t ppch; // (0x00) Processing Pipe Capability Header
128 uint32_t ppctl; // (0x04) Processing Pipe Control
129 uint32_t ppsts; // (0x08) Processing Pipe Status
130 } __PACKED hda_pp_registers_t;
131
132 typedef struct hda_all_registers {
133 hda_registers_t regs;
134 hda_alias_registers_t alias_regs;
135 } __PACKED hda_all_registers_t;
136
137 // The Intel HD Audio stream registers and Intel HD Audio Software
138 // Position Based FIFO capability structure is duplicated for
139 // DSP FW loading. There is no need to have the Intel HD Audio
140 // Processing Pipe capability structure, as it is always treated
141 // as a host DMA operating in de-coupled mode (without link DMA).
142 typedef struct adsp_code_loader_registers {
143 hda_stream_desc_regs_t stream;
144 uint32_t spbfch;
145 uint32_t spbfctl;
146 uint32_t spib;
147 uint32_t maxfifos;
148 } __PACKED adsp_code_loader_registers_t;
149
150 typedef struct adsp_registers {
151 uint8_t __rsvd0[4]; // (0x00) Reserved
152 uint32_t adspcs; // (0x04) Audio DSP Control and Status
153 uint32_t adspic; // (0x08) Audio DSP Interrupt Control
154 uint32_t adspis; // (0x0C) Audio DSP Interrupt Status
155 uint32_t adspic2; // (0x10) Audio DSP Interrupt Control 2
156 uint32_t adspis2; // (0x14) Audio DSP Interrupt Status 2
157 uint8_t __rsvd1[0x28]; // (0x18 - 0x3F)
158 uint32_t hipct; // (0x40) Host IPC Target
159 uint32_t hipcte; // (0x44) Host IPC Target Extension
160 uint32_t hipci; // (0x48) Host IPC Initiator
161 uint32_t hipcie; // (0x4C) Host IPC Initiator Extension
162 uint32_t hipcctl; // (0x50) Host IPC Control
163 uint8_t __rsvd2[0x2c]; // (0x54 - 0x7F)
164
165 adsp_code_loader_registers_t cldma; // (0x80 - 0xAF)
166
167 uint8_t _rsvd3[0xFF50];// (0xB0 - 0xFFFF)
168 } __PACKED adsp_registers_t;
169
170 typedef struct adsp_fw_registers {
171 uint32_t fw_status; // (0x00) Current ROM/FW status
172 uint32_t error_code; // (0x04) Last ROM/FW error code
173 uint32_t fw_pwr_status; // (0x08) Current DSP clock status
174 uint8_t __rsvd0[12]; // (0x0C - 0x17)
175 uint32_t rom_info; // (0x18) Basic platform configuration reported by ROM
176 } __PACKED adsp_fw_registers_t;
177
178 #ifdef __cplusplus
179
180 namespace audio {
181 namespace intel_hda {
182
183 /**
184 * Bitfield definitions for various registers
185 */
186
187 /* Global Capabilities Reigster (GCAP - offset 0x00) */
188 #define _SIC_ static inline constexpr
189
HDA_REG_GCAP_64OK(uint16_t val)190 _SIC_ bool HDA_REG_GCAP_64OK(uint16_t val) { return (val & 1u) != 0; }
HDA_REG_GCAP_NSDO(uint16_t val)191 _SIC_ uint16_t HDA_REG_GCAP_NSDO(uint16_t val) { return (val >> 1) & 0x03; }
HDA_REG_GCAP_BSS(uint16_t val)192 _SIC_ uint16_t HDA_REG_GCAP_BSS (uint16_t val) { return (val >> 3) & 0x1F; }
HDA_REG_GCAP_ISS(uint16_t val)193 _SIC_ uint16_t HDA_REG_GCAP_ISS (uint16_t val) { return (val >> 8) & 0x0F; }
HDA_REG_GCAP_OSS(uint16_t val)194 _SIC_ uint16_t HDA_REG_GCAP_OSS (uint16_t val) { return (val >> 12) & 0x0F; }
195
196 /* Global Control Reigster (GCTL - offset 0x08) */
197 constexpr uint32_t HDA_REG_GCTL_HWINIT = 0x0001u;
198 constexpr uint32_t HDA_REG_GCTL_FCNTRL = 0x0002u;
199 constexpr uint32_t HDA_REG_GCTL_UNSOL = 0x0100u;
200
201 /* Wake Enable and State Status (WAKEEN/STATESTS - offsets 0x0C,0x0E) */
202 static constexpr uint16_t HDA_REG_STATESTS_MASK = 0x7FFFu;
203
204 /* Interrupt Control Register (INTCTL - offset 0x20) */
205 constexpr uint32_t HDA_REG_INTCTL_GIE = 0x80000000u;
206 constexpr uint32_t HDA_REG_INTCTL_CIE = 0x40000000u;
207 constexpr uint32_t HDA_REG_INTCTL_SIE_MASK = 0x3FFFFFFFu;
HDA_REG_INTCTL_SIE(unsigned int n)208 _SIC_ uint32_t HDA_REG_INTCTL_SIE(unsigned int n) { return (0x1u << n) & HDA_REG_INTCTL_SIE_MASK; }
209
210 /* Command Output Ring Buffer Read Ptr (CORBRP - offset 0x4a) */
211 constexpr uint16_t HDA_REG_CORBRP_RST = 0x8000u;
212
213 /* Command Output Ring Buffer Control (CORBCTL - offset 0x4c) */
214 constexpr uint8_t HDA_REG_CORBCTL_MEIE = 0x01u; // Mem Error Int Enable
215 constexpr uint8_t HDA_REG_CORBCTL_DMA_EN = 0x02u; // DMA Enable
216
217 /* Command Output Ring Buffer Status (CORBSTS - offset 0x4d) */
218 constexpr uint8_t HDA_REG_CORBSTS_MEI = 0x01u; // Memory Error Indicator
219
220 /* Command Output Ring Buffer Size (CORBSIZE - offset 0x4e) */
221 constexpr uint8_t HDA_REG_CORBSIZE_CFG_2ENT = 0x00u;
222 constexpr uint8_t HDA_REG_CORBSIZE_CFG_16ENT = 0x01u;
223 constexpr uint8_t HDA_REG_CORBSIZE_CFG_256ENT = 0x02u;
224 constexpr uint8_t HDA_REG_CORBSIZE_CAP_2ENT = 0x10u;
225 constexpr uint8_t HDA_REG_CORBSIZE_CAP_16ENT = 0x20u;
226 constexpr uint8_t HDA_REG_CORBSIZE_CAP_256ENT = 0x40u;
227
228 /* Response Input Ring Buffer Write Ptr (RIRBWP - offset 0x58) */
229 constexpr uint16_t HDA_REG_RIRBWP_RST = 0x1000u;
230
231 /* Response Input Ring Buffer Control (RIRBCTL - offset 0x5c) */
232 constexpr uint8_t HDA_REG_RIRBCTL_INTCTL = 0x01u; // Interrupt Control
233 constexpr uint8_t HDA_REG_RIRBCTL_DMA_EN = 0x02u; // DMA Enable
234 constexpr uint8_t HDA_REG_RIRBCTL_OIC = 0x04u; // Overrun Interrupt Control
235
236 /* Response Input Ring Buffer Status (RIRBSTS - offset 0x5d) */
237 constexpr uint8_t HDA_REG_RIRBSTS_INTFL = 0x01u; // Response Interrupt Flag
238 constexpr uint8_t HDA_REG_RIRBSTS_OIS = 0x04u; // Overrun Interrupt Status
239
240 /* Response Input Ring Buffer Size (RIRBSIZE - offset 0x5e) */
241 constexpr uint8_t HDA_REG_RIRBSIZE_CFG_2ENT = 0x00u;
242 constexpr uint8_t HDA_REG_RIRBSIZE_CFG_16ENT = 0x01u;
243 constexpr uint8_t HDA_REG_RIRBSIZE_CFG_256ENT = 0x02u;
244 constexpr uint8_t HDA_REG_RIRBSIZE_CAP_2ENT = 0x10u;
245 constexpr uint8_t HDA_REG_RIRBSIZE_CAP_16ENT = 0x20u;
246 constexpr uint8_t HDA_REG_RIRBSIZE_CAP_256ENT = 0x40u;
247
248 // Stream Descriptor Control Register bits.
249 constexpr uint32_t HDA_SD_REG_CTRL_SRST = (1u << 0); // Stream Reset
250 constexpr uint32_t HDA_SD_REG_CTRL_RUN = (1u << 1); // Stream Run
251 constexpr uint32_t HDA_SD_REG_CTRL_IOCE = (1u << 2); // Interrupt on Completion Enable
252 constexpr uint32_t HDA_SD_REG_CTRL_FEIE = (1u << 3); // FIFO Error Interrupt Enable
253 constexpr uint32_t HDA_SD_REG_CTRL_DEIE = (1u << 4); // Descripto Error Interrupt Enable
254 constexpr uint32_t HDA_SD_REG_CTRL_STRIPE1 = (0u << 16); // 1 SDO line
255 constexpr uint32_t HDA_SD_REG_CTRL_STRIPE2 = (1u << 16); // 2 SDO lines
256 constexpr uint32_t HDA_SD_REG_CTRL_STRIPE4 = (2u << 16); // 4 SDO lines
257 constexpr uint32_t HDA_SD_REG_CTRL_TP = (1u << 18); // Traffic Priority
258 constexpr uint32_t HDA_SD_REG_CTRL_DIR_IN = (0u << 19); // Direction Control
259 constexpr uint32_t HDA_SD_REG_CTRL_DIR_OUT = (1u << 19); // Direction Control
HDA_SD_REG_CTRL_STRM_TAG(uint8_t tag)260 _SIC_ uint32_t HDA_SD_REG_CTRL_STRM_TAG(uint8_t tag) { // Stream Tag
261 return static_cast<uint32_t>(tag & 0xF) << 20;
262 }
263
264 // Stream Descriptor Status Register bits arranged for both 8 and 32 bit access.
265 constexpr uint8_t HDA_SD_REG_STS8_BCIS = (1u << 2); // Buffer Complete IRQ Status
266 constexpr uint8_t HDA_SD_REG_STS8_FIFOE = (1u << 3); // FIFO error IRQ Status
267 constexpr uint8_t HDA_SD_REG_STS8_DESE = (1u << 4); // Descriptor Error IRQ Status
268 constexpr uint8_t HDA_SD_REG_STS8_FIFORDY = (1u << 5); // FIFO ready
269 constexpr uint8_t HDA_SD_REG_STS8_ACK = HDA_SD_REG_STS8_BCIS |
270 HDA_SD_REG_STS8_FIFOE |
271 HDA_SD_REG_STS8_DESE;
272 constexpr uint8_t HDA_SD_REG_STS8_MASK = HDA_SD_REG_STS8_ACK |
273 HDA_SD_REG_STS8_FIFORDY;
274
275 constexpr uint32_t HDA_SD_REG_STS32_BCIS = static_cast<uint32_t>(HDA_SD_REG_STS8_BCIS) << 24;
276 constexpr uint32_t HDA_SD_REG_STS32_FIFOE = static_cast<uint32_t>(HDA_SD_REG_STS8_FIFOE) << 24;
277 constexpr uint32_t HDA_SD_REG_STS32_DESE = static_cast<uint32_t>(HDA_SD_REG_STS8_DESE) << 24;
278 constexpr uint32_t HDA_SD_REG_STS32_FIFORDY = static_cast<uint32_t>(HDA_SD_REG_STS8_FIFORDY) << 24;
279 constexpr uint32_t HDA_SD_REG_STS32_ACK = static_cast<uint32_t>(HDA_SD_REG_STS8_ACK) << 24;
280 constexpr uint32_t HDA_SD_REG_STS32_MASK = static_cast<uint32_t>(HDA_SD_REG_STS8_MASK) << 24;
281
282 // Stream Descriptor Status Register bits.
283
284 // Multiple Links Capability Header/Pipe Processing Capability Header bits.
285 constexpr uint32_t HDA_CAP_ID_MASK = (0xFFF << 16);
286 constexpr uint32_t HDA_CAP_PP_ID = (0x003 << 16);
287 constexpr uint32_t HDA_CAP_PTR_MASK = 0xFFFF;
288
289 // Processing Pipe Control bits
290 constexpr uint32_t HDA_PPCTL_PIE = (1 << 31);
291 constexpr uint32_t HDA_PPCTL_GPROCEN = (1 << 30);
292
293 // Processing Pipe Status bits
294 constexpr uint32_t HDA_PPSTS_PIS = (1 << 31);
295
296 // Audio DSP Control and Status (ADSPCS - offset 0x04)
ADSP_REG_ADSPCS_CRST(uint32_t core_mask)297 _SIC_ uint32_t ADSP_REG_ADSPCS_CRST (uint32_t core_mask) { return (core_mask & 0xFF); }
ADSP_REG_ADSPCS_CSTALL(uint32_t core_mask)298 _SIC_ uint32_t ADSP_REG_ADSPCS_CSTALL(uint32_t core_mask) { return (core_mask & 0xFF) << 8; }
ADSP_REG_ADSPCS_SPA(uint32_t core_mask)299 _SIC_ uint32_t ADSP_REG_ADSPCS_SPA (uint32_t core_mask) { return (core_mask & 0xFF) << 16; }
ADSP_REG_ADSPCS_CPA(uint32_t core_mask)300 _SIC_ uint32_t ADSP_REG_ADSPCS_CPA (uint32_t core_mask) { return (core_mask & 0xFF) << 24; }
301
302 constexpr uint8_t ADSP_REG_ADSPCS_CORE0_MASK = (1u << 0);
303
304 // Audio DSP Interrupt Control (ADSPIC - offset 0x08)
305 constexpr uint32_t ADSP_REG_ADSPIC_CLDMA = (1 << 1);
306 constexpr uint32_t ADSP_REG_ADSPIC_IPC = (1 << 0);
307
308 // Audio DSP Host IPC Target - (HIPCT - offset 0x40)
309 constexpr uint32_t ADSP_REG_HIPCT_BUSY = (1 << 31);
310
311 // Audio DSP Host Inter Processor Communication Initiator - (HIPCI - offset 0x48)
312 constexpr uint32_t ADSP_REG_HIPCI_BUSY = (1 << 31);
313
314 // Audio DSP Host Inter Processor Communication Initiator Extension - (HIPCIE - offset 0x4C)
315 constexpr uint32_t ADSP_REG_HIPCIE_ERR = (1 << 31);
316 constexpr uint32_t ADSP_REG_HIPCIE_DONE = (1 << 30);
317
318 // Audio DSP Host IPC Control - (HIPCCTL - offset 0x50)
319 constexpr uint32_t ADSP_REG_HIPCCTL_IPCTDIE = (1 << 1);
320 constexpr uint32_t ADSP_REG_HIPCCTL_IPCTBIE = (1 << 0);
321
322 // Audio DSP Code Loader Software Based Position FIFO Control - (SPBFCTL)
323 constexpr uint32_t ADSP_REG_CL_SPBFCTL_SPIBE = (1 << 0);
324
325 // Audio DSP ROM Status bits
326 constexpr uint32_t ADSP_FW_STATUS_STATE_INITIALIZATION_DONE = 0x1;
327 constexpr uint32_t ADSP_FW_STATUS_STATE_ENTER_BASE_FW = 0xF;
328 constexpr uint32_t ADSP_FW_STATUS_STATE_MASK = 0x0FFFFFFF;
329
330 #undef _SIC_
331
332 // The definition of a Buffer Descriptor List entry. See Section 3.6.3 and
333 // Table 50.
334 //
335 // TODO(johngro) : Figure out what the endianness requirements are for these
336 // structures. Intel specs the memory mapped controller registers as being
337 // strictly little endian, but they do not go seem into details about in memory
338 // control structures (like the CORB/RIRB, packed samples, BDL entries, etc..)
339 //
340 // For now, I assume that they are expecting little endian (just like they are
341 // for their registers). Also, this will probably not be an issue until the day
342 // that there is a big endian system with an Intel HDA controller embedded in it
343 // (which does not seem likely, any time soon).
344 struct IntelHDABDLEntry {
345 uint64_t address;
346 uint32_t length;
347 uint32_t flags;
348
349 // Interrupt-on-complete flag.
350 static constexpr uint32_t IOC_FLAG = 0x1u;
351 } __PACKED;
352
353 // TODO(johngro) : Intel specs its controller registers as little endian.
354 // Someday, we should update these template/macros to deal with conversion
355 // to/from host endian instead of assuming a little endian host.
356 template <typename T>
REG_RD(const T * reg)357 static inline T REG_RD(const T* reg) {
358 return *(reinterpret_cast<const volatile T*>(reg));
359 }
360
361 template <typename T, typename U>
REG_WR(T * reg,U val)362 static inline void REG_WR(T* reg, U val) {
363 static_assert(std::is_unsigned_v<T>, "");
364 ZX_DEBUG_ASSERT(static_cast<T>(-1) >= val);
365 *(reinterpret_cast<volatile T*>(reg)) = static_cast<T>(val);
366 }
367
368 template <typename T>
REG_MOD(T * reg,T clr_bits,T set_bits)369 static inline void REG_MOD(T* reg, T clr_bits, T set_bits) {
370 REG_WR(reg, static_cast<T>((REG_RD(reg) & ~clr_bits) | set_bits));
371 }
372
REG_SET_BITS(T * reg,T bits)373 template <typename T> static inline void REG_SET_BITS(T* reg, T bits) {
374 REG_MOD(reg, static_cast<T>(0), bits);
375 }
376
REG_CLR_BITS(T * reg,T bits)377 template <typename T> static inline void REG_CLR_BITS(T* reg, T bits) {
378 REG_MOD(reg, bits, static_cast<T>(0));
379 }
380
381 } // namespace intel_hda
382 } // namespace audio
383
384 #endif // __cplusplus
385