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