| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef INTEL_HDA_UTILS_INTEL_HDA_REGISTERS_H_ |
| #define INTEL_HDA_UTILS_INTEL_HDA_REGISTERS_H_ |
| |
| #include <lib/mmio-ptr/mmio-ptr.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <zircon/assert.h> |
| #include <zircon/compiler.h> |
| #include <zircon/types.h> |
| |
| #include <type_traits> |
| |
| /** |
| * Register definitions taken from |
| * |
| * Intel High Definition Audio Specification |
| * Revision 1.0a |
| * June 17, 2010 |
| * |
| * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/high-definition-audio-specification.pdf |
| */ |
| |
| // TODO(johngro) |
| // |
| // Consider moving these structures and their associated flags into a more C++ |
| // style, where the flags can either be static constexpr members of the |
| // structures, or in their own namespace. Also, consider moving away from the |
| // underscore separated typedef declarations, and to LeadingUpperCamelCased |
| // declarations made without typedef and the _t suffix. |
| // |
| // Currently, we have to keep the register structures C compatible, because they |
| // are used in the response for the CONTROLLER_SNAPSHOT_REGS command. When we |
| // can send back a read-only VMO to provide debug access to the registers, we |
| // can do away with this. |
| typedef struct hda_stream_desc_regs { |
| // clang-format off |
| // (0x00) Control (0x03) Status |
| union { |
| uint32_t w; // 32-bit word access to the Control/Status registers |
| struct { |
| uint8_t ctl[3]; // Control register byte access |
| uint8_t sts; // Status register byte access |
| } b; |
| } ctl_sts; |
| uint32_t lpib; // (0x04) SD_n Link Position in Current Buffer |
| uint32_t cbl; // (0x08) SD_n Cyclic Buffer Length |
| uint16_t lvi; // (0x0C) SD_n Last Valid Index |
| uint8_t __rsvd0[2]; // (0x8E) Reserved |
| uint16_t fifod; // (0x10) SD_n FIFO Size |
| uint16_t fmt; // (0x12) SD_n Format |
| uint8_t __rsvd1[4]; // (0x14) Reserved |
| uint32_t bdpl; // (0x18) SD_n Buffer Descriptor List Pointer - Lower |
| uint32_t bdpu; // (0x1C) SD_n Buffer Descriptor List Pointer - Upper |
| // clang-format on |
| } hda_stream_desc_regs_t; |
| static_assert(sizeof(hda_stream_desc_regs) == 32); |
| |
| typedef struct hda_registers { |
| // clang-format off |
| uint16_t gcap; // (0x00) Global Capabilities |
| uint8_t vmin; // (0x02) Minor Version |
| uint8_t vmaj; // (0x03) Major Version |
| uint16_t outpay; // (0x04) Output Payload Capability |
| uint16_t inpay; // (0x06) Input Payload Capability |
| uint32_t gctl; // (0x08) Global Control |
| uint16_t wakeen; // (0x0C) Wake Enable |
| uint16_t statests; // (0x0E) State Change Status |
| uint16_t gsts; // (0x10) Global Status |
| uint16_t gcap2; // (0x12) Global Capabilities 2 |
| uint16_t llch; // (0x14) Linked List Capabilities Header |
| uint8_t __rsvd[2]; // (0x16) Reserved |
| uint16_t outstrmpay; // (0x18) Output Stream Payload Capability |
| uint16_t instrmpay; // (0x1A) Input Stream Payload Capability |
| uint8_t __rsvd1[4]; // (0x1C) Reserved |
| uint32_t intctl; // (0x20) Interrupt Control |
| uint32_t intsts; // (0x24) Interrupt Status |
| uint8_t __rsvd2[8]; // (0x28) Reserved |
| uint32_t walclk; // (0x30) Wall Clock Counter |
| uint8_t __rsvd3[4]; // (0x34) Reserved |
| uint32_t ssync; // (0x38) Stream Synchronization |
| uint8_t __rsvd4[4]; // (0x3C) Reserved |
| uint32_t corblbase; // (0x40) CORB Lower Base Address |
| uint32_t corbubase; // (0x44) CORB Upper Base Address |
| uint16_t corbwp; // (0x48) CORB Write Pointer |
| uint16_t corbrp; // (0x4A) CORB Read Pointer |
| uint8_t corbctl; // (0x4C) CORB Control |
| uint8_t corbsts; // (0x4D) CORB Status |
| uint8_t corbsize; // (0x4E) CORB Size |
| uint8_t __rsvd5[1]; // (0x4F) Reserved |
| uint32_t rirblbase; // (0x50) RIRB Lower Base Address |
| uint32_t rirbubase; // (0x54) RIRB Upper Base Address |
| uint16_t rirbwp; // (0x58) RIRB Write Pointer |
| uint16_t rintcnt; // (0x5A) Response Interrupt Count |
| uint8_t rirbctl; // (0x5C) RIRB Control |
| uint8_t rirbsts; // (0x5D) RIRB Status |
| uint8_t rirbsize; // (0x5E) RIRB Size |
| uint8_t __rsvd6[1]; // (0x5F) Reserved |
| uint32_t icoi; // (0x60) Immediate Command Output Interface |
| uint32_t icii; // (0x64) Immediate Command Input Interface |
| uint16_t icis; // (0x68) Immediate Command Status |
| uint8_t __rsvd7[6]; // (0x6A) Reserved |
| uint32_t dpiblbase; // (0x70) DMA Position Buffer Lower Base |
| uint32_t dpibubase; // (0x74) DMA Position Buffer Upper Base |
| uint8_t __rsvd8[8]; // (0x78) Reserved |
| |
| // A max of 30 streams may be present in the system at any point in time (no |
| // more than 15 input and 15 output). The stream descriptor registers start |
| // at 0x80, and are layed out as Input, then Output, then Bidirectional. |
| // The number of each type of stream present in the hardware can be |
| // determined using the GCAP register. |
| hda_stream_desc_regs_t stream_desc[30]; // (0x80) |
| uint8_t __rsvd9[0x1BC0]; // (0x440 - 0x1FFF) |
| // clang-format on |
| } hda_registers_t; |
| static_assert(sizeof(hda_registers) == 8192); |
| |
| typedef struct hda_stream_desc_alias_regs { |
| // clang-format off |
| uint8_t __rsvd0[0x04]; // (0x00) Reserved |
| uint32_t lpib; // (0x04) SD_n Link Position in Current Buffer Alias |
| uint8_t __rsvd1[0x18]; // (0x08) Reserved |
| // clang-format on |
| } __PACKED hda_stream_desc_alias_regs_t; |
| |
| typedef struct hda_alias_registers { |
| // clang-format off |
| uint8_t __rsvd0[0x30]; // (0x00) Reserved |
| uint32_t wallclk; // (0x30) Wall Clock Counter Alias |
| uint8_t __rsvd1[0x4C]; // (0x34) Reserved |
| hda_stream_desc_alias_regs_t stream_desc[30]; // (0x80) |
| uint8_t __rsvd9[0x1BC0]; // (0x440 - 0x1FFF) |
| // clang-format on |
| } __PACKED hda_alias_registers_t; |
| |
| typedef struct hda_pp_registers { |
| // clang-format off |
| uint32_t ppch; // (0x00) Processing Pipe Capability Header |
| uint32_t ppctl; // (0x04) Processing Pipe Control |
| uint32_t ppsts; // (0x08) Processing Pipe Status |
| // clang-format on |
| } hda_pp_registers_t; |
| static_assert(sizeof(hda_pp_registers) == 12); |
| |
| typedef struct hda_all_registers { |
| // clang-format off |
| hda_registers_t regs; |
| hda_alias_registers_t alias_regs; |
| // clang-format on |
| } __PACKED hda_all_registers_t; |
| |
| // The Intel HD Audio stream registers and Intel HD Audio Software |
| // Position Based FIFO capability structure is duplicated for |
| // DSP FW loading. There is no need to have the Intel HD Audio |
| // Processing Pipe capability structure, as it is always treated |
| // as a host DMA operating in de-coupled mode (without link DMA). |
| typedef struct adsp_code_loader_registers { |
| // clang-format off |
| hda_stream_desc_regs_t stream; |
| uint32_t spbfch; |
| uint32_t spbfctl; |
| uint32_t spib; |
| uint32_t maxfifos; |
| // clang-format on |
| } __PACKED adsp_code_loader_registers_t; |
| |
| typedef struct adsp_registers { |
| // clang-format off |
| uint8_t __rsvd0[4]; // (0x00) Reserved |
| uint32_t adspcs; // (0x04) Audio DSP Control and Status |
| uint32_t adspic; // (0x08) Audio DSP Interrupt Control |
| uint32_t adspis; // (0x0C) Audio DSP Interrupt Status |
| uint32_t adspic2; // (0x10) Audio DSP Interrupt Control 2 |
| uint32_t adspis2; // (0x14) Audio DSP Interrupt Status 2 |
| uint8_t __rsvd1[0x28]; // (0x18 - 0x3F) |
| uint32_t hipct; // (0x40) Host IPC Target |
| uint32_t hipcte; // (0x44) Host IPC Target Extension |
| uint32_t hipci; // (0x48) Host IPC Initiator |
| uint32_t hipcie; // (0x4C) Host IPC Initiator Extension |
| uint32_t hipcctl; // (0x50) Host IPC Control |
| uint8_t __rsvd2[0x2c]; // (0x54 - 0x7F) |
| |
| adsp_code_loader_registers_t cldma; // (0x80 - 0xAF) |
| |
| uint8_t _rsvd3[0xFF50];// (0xB0 - 0xFFFF) |
| // clang-format on |
| } adsp_registers_t; |
| static_assert(sizeof(adsp_registers) == 65536); |
| |
| typedef struct adsp_fw_registers { |
| // clang-format off |
| uint32_t fw_status; // (0x00) Current ROM/FW status |
| uint32_t error_code; // (0x04) Last ROM/FW error code |
| uint32_t fw_pwr_status; // (0x08) Current DSP clock status |
| uint8_t __rsvd0[12]; // (0x0C - 0x17) |
| uint32_t rom_info; // (0x18) Basic platform configuration reported by ROM |
| // clang-format on |
| } __PACKED adsp_fw_registers_t; |
| static_assert(sizeof(adsp_fw_registers) == 28); |
| |
| #ifdef __cplusplus |
| |
| namespace audio { |
| namespace intel_hda { |
| |
| /** |
| * Bitfield definitions for various registers |
| */ |
| |
| /* Global Capabilities Reigster (GCAP - offset 0x00) */ |
| |
| static inline constexpr bool HDA_REG_GCAP_64OK(uint16_t val) { return (val & 1u) != 0; } |
| static inline constexpr uint16_t HDA_REG_GCAP_NSDO(uint16_t val) { return (val >> 1) & 0x03; } |
| static inline constexpr uint16_t HDA_REG_GCAP_BSS(uint16_t val) { return (val >> 3) & 0x1F; } |
| static inline constexpr uint16_t HDA_REG_GCAP_ISS(uint16_t val) { return (val >> 8) & 0x0F; } |
| static inline constexpr uint16_t HDA_REG_GCAP_OSS(uint16_t val) { return (val >> 12) & 0x0F; } |
| |
| /* Global Control Reigster (GCTL - offset 0x08) */ |
| constexpr uint32_t HDA_REG_GCTL_HWINIT = 0x0001u; |
| constexpr uint32_t HDA_REG_GCTL_FCNTRL = 0x0002u; |
| constexpr uint32_t HDA_REG_GCTL_UNSOL = 0x0100u; |
| |
| /* Wake Enable and State Status (WAKEEN/STATESTS - offsets 0x0C,0x0E) */ |
| static constexpr uint16_t HDA_REG_STATESTS_MASK = 0x7FFFu; |
| |
| /* Interrupt Control Register (INTCTL - offset 0x20) */ |
| constexpr uint32_t HDA_REG_INTCTL_GIE = 0x80000000u; |
| constexpr uint32_t HDA_REG_INTCTL_CIE = 0x40000000u; |
| constexpr uint32_t HDA_REG_INTCTL_SIE_MASK = 0x3FFFFFFFu; |
| static inline constexpr uint32_t HDA_REG_INTCTL_SIE(unsigned int n) { |
| return (0x1u << n) & HDA_REG_INTCTL_SIE_MASK; |
| } |
| |
| /* Command Output Ring Buffer Read Ptr (CORBRP - offset 0x4a) */ |
| constexpr uint16_t HDA_REG_CORBRP_RST = 0x8000u; |
| |
| /* Command Output Ring Buffer Control (CORBCTL - offset 0x4c) */ |
| constexpr uint8_t HDA_REG_CORBCTL_MEIE = 0x01u; // Mem Error Int Enable |
| constexpr uint8_t HDA_REG_CORBCTL_DMA_EN = 0x02u; // DMA Enable |
| |
| /* Command Output Ring Buffer Status (CORBSTS - offset 0x4d) */ |
| constexpr uint8_t HDA_REG_CORBSTS_MEI = 0x01u; // Memory Error Indicator |
| |
| /* Command Output Ring Buffer Size (CORBSIZE - offset 0x4e) */ |
| constexpr uint8_t HDA_REG_CORBSIZE_CFG_2ENT = 0x00u; |
| constexpr uint8_t HDA_REG_CORBSIZE_CFG_16ENT = 0x01u; |
| constexpr uint8_t HDA_REG_CORBSIZE_CFG_256ENT = 0x02u; |
| constexpr uint8_t HDA_REG_CORBSIZE_CAP_2ENT = 0x10u; |
| constexpr uint8_t HDA_REG_CORBSIZE_CAP_16ENT = 0x20u; |
| constexpr uint8_t HDA_REG_CORBSIZE_CAP_256ENT = 0x40u; |
| |
| /* Response Input Ring Buffer Write Ptr (RIRBWP - offset 0x58) */ |
| constexpr uint16_t HDA_REG_RIRBWP_RST = 0x1000u; |
| |
| /* Response Input Ring Buffer Control (RIRBCTL - offset 0x5c) */ |
| constexpr uint8_t HDA_REG_RIRBCTL_INTCTL = 0x01u; // Interrupt Control |
| constexpr uint8_t HDA_REG_RIRBCTL_DMA_EN = 0x02u; // DMA Enable |
| constexpr uint8_t HDA_REG_RIRBCTL_OIC = 0x04u; // Overrun Interrupt Control |
| |
| /* Response Input Ring Buffer Status (RIRBSTS - offset 0x5d) */ |
| constexpr uint8_t HDA_REG_RIRBSTS_INTFL = 0x01u; // Response Interrupt Flag |
| constexpr uint8_t HDA_REG_RIRBSTS_OIS = 0x04u; // Overrun Interrupt Status |
| |
| /* Response Input Ring Buffer Size (RIRBSIZE - offset 0x5e) */ |
| constexpr uint8_t HDA_REG_RIRBSIZE_CFG_2ENT = 0x00u; |
| constexpr uint8_t HDA_REG_RIRBSIZE_CFG_16ENT = 0x01u; |
| constexpr uint8_t HDA_REG_RIRBSIZE_CFG_256ENT = 0x02u; |
| constexpr uint8_t HDA_REG_RIRBSIZE_CAP_2ENT = 0x10u; |
| constexpr uint8_t HDA_REG_RIRBSIZE_CAP_16ENT = 0x20u; |
| constexpr uint8_t HDA_REG_RIRBSIZE_CAP_256ENT = 0x40u; |
| |
| // Stream Descriptor Control Register bits. |
| constexpr uint32_t HDA_SD_REG_CTRL_SRST = (1u << 0); // Stream Reset |
| constexpr uint32_t HDA_SD_REG_CTRL_RUN = (1u << 1); // Stream Run |
| constexpr uint32_t HDA_SD_REG_CTRL_IOCE = (1u << 2); // Interrupt on Completion Enable |
| constexpr uint32_t HDA_SD_REG_CTRL_FEIE = (1u << 3); // FIFO Error Interrupt Enable |
| constexpr uint32_t HDA_SD_REG_CTRL_DEIE = (1u << 4); // Descripto Error Interrupt Enable |
| constexpr uint32_t HDA_SD_REG_CTRL_STRIPE1 = (0u << 16); // 1 SDO line |
| constexpr uint32_t HDA_SD_REG_CTRL_STRIPE2 = (1u << 16); // 2 SDO lines |
| constexpr uint32_t HDA_SD_REG_CTRL_STRIPE4 = (2u << 16); // 4 SDO lines |
| constexpr uint32_t HDA_SD_REG_CTRL_TP = (1u << 18); // Traffic Priority |
| constexpr uint32_t HDA_SD_REG_CTRL_DIR_IN = (0u << 19); // Direction Control |
| constexpr uint32_t HDA_SD_REG_CTRL_DIR_OUT = (1u << 19); // Direction Control |
| static inline constexpr uint32_t HDA_SD_REG_CTRL_STRM_TAG(uint8_t tag) { // Stream Tag |
| return static_cast<uint32_t>(tag & 0xF) << 20; |
| } |
| |
| // Stream Descriptor Status Register bits arranged for both 8 and 32 bit access. |
| constexpr uint8_t HDA_SD_REG_STS8_BCIS = (1u << 2); // Buffer Complete IRQ Status |
| constexpr uint8_t HDA_SD_REG_STS8_FIFOE = (1u << 3); // FIFO error IRQ Status |
| constexpr uint8_t HDA_SD_REG_STS8_DESE = (1u << 4); // Descriptor Error IRQ Status |
| constexpr uint8_t HDA_SD_REG_STS8_FIFORDY = (1u << 5); // FIFO ready |
| constexpr uint8_t HDA_SD_REG_STS8_ACK = |
| HDA_SD_REG_STS8_BCIS | HDA_SD_REG_STS8_FIFOE | HDA_SD_REG_STS8_DESE; |
| constexpr uint8_t HDA_SD_REG_STS8_MASK = HDA_SD_REG_STS8_ACK | HDA_SD_REG_STS8_FIFORDY; |
| |
| constexpr uint32_t HDA_SD_REG_STS32_BCIS = static_cast<uint32_t>(HDA_SD_REG_STS8_BCIS) << 24; |
| constexpr uint32_t HDA_SD_REG_STS32_FIFOE = static_cast<uint32_t>(HDA_SD_REG_STS8_FIFOE) << 24; |
| constexpr uint32_t HDA_SD_REG_STS32_DESE = static_cast<uint32_t>(HDA_SD_REG_STS8_DESE) << 24; |
| constexpr uint32_t HDA_SD_REG_STS32_FIFORDY = static_cast<uint32_t>(HDA_SD_REG_STS8_FIFORDY) << 24; |
| constexpr uint32_t HDA_SD_REG_STS32_ACK = static_cast<uint32_t>(HDA_SD_REG_STS8_ACK) << 24; |
| constexpr uint32_t HDA_SD_REG_STS32_MASK = static_cast<uint32_t>(HDA_SD_REG_STS8_MASK) << 24; |
| |
| // Stream Descriptor Status Register bits. |
| |
| // Multiple Links Capability Header/Pipe Processing Capability Header bits. |
| constexpr uint32_t HDA_CAP_ID_MASK = (0xFFF << 16); |
| constexpr uint32_t HDA_CAP_PP_ID = (0x003 << 16); |
| constexpr uint32_t HDA_CAP_PTR_MASK = 0xFFFF; |
| |
| // Processing Pipe Control bits |
| constexpr uint32_t HDA_PPCTL_PIE = (1 << 31); |
| constexpr uint32_t HDA_PPCTL_GPROCEN = (1 << 30); |
| |
| // Processing Pipe Status bits |
| constexpr uint32_t HDA_PPSTS_PIS = (1 << 31); |
| |
| // Audio DSP Control and Status (ADSPCS - offset 0x04) |
| static inline constexpr uint32_t ADSP_REG_ADSPCS_CRST(uint32_t core_mask) { |
| return (core_mask & 0xFF); |
| } |
| static inline constexpr uint32_t ADSP_REG_ADSPCS_CSTALL(uint32_t core_mask) { |
| return (core_mask & 0xFF) << 8; |
| } |
| static inline constexpr uint32_t ADSP_REG_ADSPCS_SPA(uint32_t core_mask) { |
| return (core_mask & 0xFF) << 16; |
| } |
| static inline constexpr uint32_t ADSP_REG_ADSPCS_CPA(uint32_t core_mask) { |
| return (core_mask & 0xFF) << 24; |
| } |
| |
| constexpr uint8_t ADSP_REG_ADSPCS_CORE0_MASK = (1u << 0); |
| |
| // Audio DSP Interrupt Control (ADSPIC - offset 0x08) |
| constexpr uint32_t ADSP_REG_ADSPIC_CLDMA = (1 << 1); |
| constexpr uint32_t ADSP_REG_ADSPIC_IPC = (1 << 0); |
| |
| // Audio DSP Host IPC Target - (HIPCT - offset 0x40) |
| constexpr uint32_t ADSP_REG_HIPCT_BUSY = (1 << 31); |
| |
| // Audio DSP Host Inter Processor Communication Initiator - (HIPCI - offset 0x48) |
| constexpr uint32_t ADSP_REG_HIPCI_BUSY = (1 << 31); |
| |
| // Audio DSP Host Inter Processor Communication Initiator Extension - (HIPCIE - offset 0x4C) |
| constexpr uint32_t ADSP_REG_HIPCIE_ERR = (1 << 31); |
| constexpr uint32_t ADSP_REG_HIPCIE_DONE = (1 << 30); |
| |
| // Audio DSP Host IPC Control - (HIPCCTL - offset 0x50) |
| constexpr uint32_t ADSP_REG_HIPCCTL_IPCTDIE = (1 << 1); |
| constexpr uint32_t ADSP_REG_HIPCCTL_IPCTBIE = (1 << 0); |
| |
| // Audio DSP Code Loader Software Based Position FIFO Control - (SPBFCTL) |
| constexpr uint32_t ADSP_REG_CL_SPBFCTL_SPIBE = (1 << 0); |
| |
| // Audio DSP ROM Status bits |
| constexpr uint32_t ADSP_FW_STATUS_STATE_INITIALIZATION_DONE = 0x1; |
| constexpr uint32_t ADSP_FW_STATUS_STATE_ENTER_BASE_FW = 0xF; |
| constexpr uint32_t ADSP_FW_STATUS_STATE_MASK = 0x0FFFFFFF; |
| |
| // ADSP SRAM windows |
| constexpr size_t SKL_ADSP_SRAM0_OFFSET = 0x8000; // Shared between Skylake and Kabylake |
| constexpr size_t SKL_ADSP_SRAM1_OFFSET = 0xA000; |
| |
| // Mailbox offsets |
| constexpr size_t ADSP_MAILBOX_IN_OFFSET = 0x1000; // Section 5.5 Offset from SRAM0 |
| |
| // The definition of a Buffer Descriptor List entry. See Section 3.6.3 and |
| // Table 50. |
| // |
| // TODO(johngro) : Figure out what the endianness requirements are for these |
| // structures. Intel specs the memory mapped controller registers as being |
| // strictly little endian, but they do not go seem into details about in memory |
| // control structures (like the CORB/RIRB, packed samples, BDL entries, etc..) |
| // |
| // For now, I assume that they are expecting little endian (just like they are |
| // for their registers). Also, this will probably not be an issue until the day |
| // that there is a big endian system with an Intel HDA controller embedded in it |
| // (which does not seem likely, any time soon). |
| struct IntelHDABDLEntry { |
| uint64_t address; |
| uint32_t length; |
| uint32_t flags; |
| |
| // Interrupt-on-complete flag. |
| static constexpr uint32_t IOC_FLAG = 0x1u; |
| } __PACKED; |
| |
| // TODO(johngro) : Intel specs its controller registers as little endian. |
| // Someday, we should update these template/macros to deal with conversion |
| // to/from host endian instead of assuming a little endian host. |
| template <typename T> |
| static inline T REG_RD(const MMIO_PTR T* reg) { |
| if constexpr (sizeof(T) == sizeof(uint8_t)) { |
| return MmioRead8(reg); |
| } else if constexpr (sizeof(T) == sizeof(uint16_t)) { |
| return MmioRead16(reg); |
| } else if constexpr (sizeof(T) == sizeof(uint32_t)) { |
| return MmioRead32(reg); |
| } else if constexpr (sizeof(T) == sizeof(uint64_t)) { |
| return MmioRead64(reg); |
| } else { |
| static_assert(sizeof(T) < 0, "Unsupported type"); |
| } |
| } |
| |
| template <typename T, typename U> |
| static inline void REG_WR(MMIO_PTR T* reg, U val) { |
| static_assert(std::is_unsigned_v<T>, ""); |
| ZX_DEBUG_ASSERT(static_cast<T>(-1) >= val); |
| if constexpr (sizeof(T) == sizeof(uint8_t)) { |
| MmioWrite8(val, reg); |
| } else if constexpr (sizeof(T) == sizeof(uint16_t)) { |
| MmioWrite16(val, reg); |
| } else if constexpr (sizeof(T) == sizeof(uint32_t)) { |
| MmioWrite32(val, reg); |
| } else if constexpr (sizeof(T) == sizeof(uint64_t)) { |
| MmioWrite64(val, reg); |
| } else { |
| static_assert(sizeof(T) < 0, "Unsupported type"); |
| } |
| } |
| |
| template <typename T> |
| static inline void REG_MOD(MMIO_PTR T* reg, T clr_bits, T set_bits) { |
| REG_WR(reg, static_cast<T>((REG_RD(reg) & ~clr_bits) | set_bits)); |
| } |
| |
| template <typename T> |
| static inline void REG_SET_BITS(MMIO_PTR T* reg, T bits) { |
| REG_MOD(reg, static_cast<T>(0), bits); |
| } |
| |
| template <typename T> |
| static inline void REG_CLR_BITS(MMIO_PTR T* reg, T bits) { |
| REG_MOD(reg, bits, static_cast<T>(0)); |
| } |
| |
| } // namespace intel_hda |
| } // namespace audio |
| |
| #endif // __cplusplus |
| |
| #endif // INTEL_HDA_UTILS_INTEL_HDA_REGISTERS_H_ |