| // Copyright 2022 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 SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_H_ |
| #define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_H_ |
| |
| #include <zircon/assert.h> |
| |
| #include <limits> |
| |
| #include <hwreg/bitfields.h> |
| |
| #include "src/graphics/display/drivers/intel-i915/hardware-common.h" |
| |
| namespace registers { |
| |
| // Graphics & Memory Controller Hub Graphics Control - GGC_0_0_0_PCI |
| class GmchGfxControl : public hwreg::RegisterBase<GmchGfxControl, uint16_t> { |
| public: |
| static constexpr uint32_t kAddr = 0x50; // Address for the mirror |
| |
| DEF_FIELD(15, 8, gfx_mode_select); |
| DEF_FIELD(7, 6, gtt_size); |
| |
| inline uint32_t gtt_mappable_mem_size() { return gtt_size() ? 1 << (20 + gtt_size()) : 0; } |
| |
| inline uint32_t dsm_size() { |
| if (gfx_mode_select() <= 0x10) { |
| return gfx_mode_select() * 32 * 1024 * 1024; |
| } else if (gfx_mode_select() == 0x20) { |
| return 1024 * 1024 * 1024; |
| } else if (gfx_mode_select() == 0x30) { |
| return 1536 * 1024 * 1024; |
| } else if (gfx_mode_select() == 0x40) { |
| return 2048 * 1024 * 1024u; |
| } else if (0xf0 <= gfx_mode_select() && gfx_mode_select() < 0xff) { |
| return (gfx_mode_select() - 0xef) * 4 * 1024 * 1024; |
| } else { |
| return 0; |
| } |
| } |
| |
| static auto Get() { return hwreg::RegisterAddr<GmchGfxControl>(0); } |
| }; |
| |
| // Base Data of Stolen Memory - BDSM_0_0_0_PCI |
| class BaseDsm : public hwreg::RegisterBase<BaseDsm, uint32_t> { |
| public: |
| static constexpr uint32_t kAddr = 0x5c; // Address for the mirror |
| |
| DEF_FIELD(31, 20, base_phys_addr); |
| static constexpr uint32_t base_phys_addr_shift = 20; |
| DEF_RSVDZ_FIELD(19, 1); |
| DEF_BIT(0, lock); |
| |
| static auto Get() { return hwreg::RegisterAddr<BaseDsm>(0); } |
| }; |
| |
| // DFSM (Display Fuse) |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 432-434 |
| // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 497-499 |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 495-497 |
| class DisplayFuses : public hwreg::RegisterBase<DisplayFuses, uint32_t> { |
| public: |
| enum class CoreClockLimit : int { |
| k675Mhz = 0, |
| k540Mhz = 1, |
| k450Mhz = 2, |
| k337_5Mhz = 3, |
| }; |
| |
| // The registers names here use "_enabled" / "_disabled" prefixes |
| // inconsistently in order to reflect the semantics used in the hardware. |
| |
| // Not on Tiger Lake. |
| DEF_BIT(31, graphics_disabled); |
| |
| DEF_BIT(30, pipe_a_disabled); |
| DEF_BIT(28, pipe_c_disabled); |
| // FBC (Frame Buffer Compression) and DPST (Display Power Savings Technology). |
| DEF_BIT(27, power_management_disabled); |
| |
| // Tiger Lake: All combo PHY ports disabled. |
| // Kaby Lake and Skylake: DDIA eDP support disabled. |
| DEF_BIT(26, edp_disabled); |
| |
| // Not on Tiger Lake. |
| DEF_FIELD(24, 23, core_clock_limit_bits); |
| CoreClockLimit GetCoreClockLimit() const { |
| return static_cast<CoreClockLimit>(core_clock_limit_bits()); |
| } |
| |
| // Only Tiger Lake. |
| DEF_BIT(22, pipe_d_disabled); |
| |
| DEF_BIT(21, pipe_b_disabled); |
| // Display capture is called WD (Wireless Display) in Intel docs. |
| DEF_BIT(20, display_capture_disabled); |
| |
| // Only Tiger Lake. |
| DEF_BIT(16, isolated_decode_disabled); |
| DEF_FIELD(15, 8, audio_codec_id_low); |
| DEF_BIT(7, display_stream_compression_disabled); |
| |
| DEF_BIT(6, remote_screen_blanking_enabled); |
| DEF_BIT(0, audio_codec_disabled); |
| |
| static auto Get() { return hwreg::RegisterAddr<DisplayFuses>(0x51000); } |
| }; |
| |
| // DSSM (Display Strap State) |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 825-827 |
| // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 545-546 |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 545-546 |
| // |
| // This register is based on the Tiger Lake definition. |
| class DisplayStraps : public hwreg::RegisterBase<DisplayStraps, uint32_t> { |
| public: |
| // Documented values for the `reference_frequency_select` field. |
| enum class ReferenceFrequencySelectTigerLake : uint8_t { |
| k24Mhz = 0b00, |
| k19_2Mhz = 0b01, |
| k38_4Mhz = 0b10, |
| }; |
| |
| // Possible values for the `audio_io_location` field. |
| enum class AudioIoLocationTigerLake { |
| kSouth = 0, |
| kNorth = 1, |
| }; |
| |
| // This field has a non-trivial representation and should be accessed via the |
| // `reference_frequency_khz()` helper. |
| DEF_ENUM_FIELD(ReferenceFrequencySelectTigerLake, 31, 29, reference_frequency_select_tiger_lake); |
| |
| // If true, the maximum supported display width is 5120 pixels. |
| // |
| // The display width is the result of combinining the widths of all the pipes |
| // that make up the display. If this field is true, the hardware cannot drive |
| // displays above 5k, under any configuration. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_BIT(6, display_width_at_most_5120_pixels_tiger_lake); |
| |
| // If true, the Audio I/O flop is bypassed. |
| // |
| // This is enabled on dies where the path to I/O is unsuitably long. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_BIT(5, audio_io_flop_bypassed_tiger_lake); |
| |
| // The location where PCH audio is connected to the CPU die. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_ENUM_FIELD(AudioIoLocationTigerLake, 4, 4, audio_io_location_tiger_lake); |
| |
| // The WD (Wireless Display; display capture) behavior on page faults. |
| // |
| // If this field is true, the display capture functionality continues writing |
| // data after a page fault. If this field is false, page faults result stop |
| // display capture. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_BIT(3, continue_writes_on_display_capture_fault_tiger_lake); |
| |
| // If true, some LCPLL (LC-tank PLL) output frequencies are not available. |
| // |
| // This field is reserved on Tiger Lake. |
| DEF_BIT(2, lcpll_frequencies_disabled); |
| |
| // True for SoC (System-on-Chip) parts, false for non-SoC parts. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_BIT(1, is_system_on_chip_tiger_lake); |
| |
| // If true, (DisplayPort) DDI A was present during system initialization. |
| // |
| // This field is reserved on Kaby Lake and Skylake. |
| DEF_BIT(0, ddi_a_present); |
| |
| // The frequency of the display reference clock, in kHz. |
| // |
| // This frequency is used to compute the frequency multipliers for all the |
| // programmable clocks in the display engine. |
| // |
| // Returns 0 if the field has an undocumented value. |
| int32_t reference_frequency_khz_tiger_lake() const { |
| const ReferenceFrequencySelectTigerLake frequency_select = |
| reference_frequency_select_tiger_lake(); |
| switch (frequency_select) { |
| case ReferenceFrequencySelectTigerLake::k19_2Mhz: |
| return 19'200; |
| case ReferenceFrequencySelectTigerLake::k24Mhz: |
| return 24'000; |
| case ReferenceFrequencySelectTigerLake::k38_4Mhz: |
| return 38'400; |
| } |
| return 0; // The field is set to an undocumented value. |
| } |
| |
| static auto Get() { return hwreg::RegisterAddr<DisplayStraps>(0x51004); } |
| }; |
| |
| // DISPLAY_INT_CTL (Display Interrupt Control) |
| // |
| // Controls whether display interrupts propagate to the PCI device interrupt, |
| // and summarizes the pending display interrupts. |
| // |
| // This register is referred to as MASTER_INT_CTL (Master Interrupt Control) in |
| // the documentation for Kaby Lake and Skylake. |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 1 pages 1054-1055 |
| // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 9-11 |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 pages 10-12 |
| class DisplayInterruptControl : public hwreg::RegisterBase<DisplayInterruptControl, uint32_t> { |
| public: |
| // If true, display engine interrupts propagate to the next level. |
| // |
| // On Tiger Lake and DG1, display engine interrupts propagate to the graphics |
| // interrupt dispatcher, which is controlled by the GraphicsPrimaryInterrupt |
| // register. |
| // |
| // On Kaby Lake and Skylake, display engine interrupts propagate directly to |
| // the PCI device interrupt. |
| // |
| // The driver sets this bit when it is ready to process display interrupts. |
| DEF_BIT(31, interrupts_enabled); |
| |
| // True if there are pending interrupts from the PCU (Power Control Unit). |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(30, pcu_pending_kaby_lake); |
| |
| // True if there are pending interrupts from the audio codec. |
| DEF_BIT(24, audio_codec_pending); |
| |
| // True if there are pending interrupts from the PCH display engine. |
| // |
| // If this bit is set, the {{PCH interrupts register}} must be checked. |
| DEF_BIT(23, pch_engine_pending); |
| |
| // True if there are pending miscellaneous display engine interrupts. |
| DEF_BIT(22, misc_display_pending); |
| |
| // True if there are pending hotplug interrupts from the main display engine. |
| // |
| // This field only reflects hotplug events from the main / north display |
| // engine. Hotplug interrupts from the PCH / south display engine are recorded |
| // in the `pch_engine_pending` bit. |
| // |
| // This bit is not documented on Kaby Lake and Skylake, where the display |
| // engine does not handle hot plug for any port. |
| DEF_BIT(21, display_hot_plug_pending_tiger_lake); |
| |
| // True if there are pending port interrupts. |
| DEF_BIT(20, port_pending); |
| |
| // True if there are pending Pipe D interrupts. |
| // |
| // This field is not documented on Kaby Lake and Skylake. The underlying bit |
| // is reserved but not documented as MBZ (Must Be Zero). |
| DEF_BIT(19, pipe_d_pending_tiger_lake); |
| |
| // True if there are pending Pipe C interrupts. |
| DEF_BIT(18, pipe_c_pending); |
| |
| // True if there are pending Pipe B interrupts. |
| DEF_BIT(17, pipe_b_pending); |
| |
| // True if there are pending Pipe A interrupts. |
| DEF_BIT(16, pipe_a_pending); |
| |
| // True if there are pending VEBox (video encoding box) interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(6, video_encoding_box_pending_kaby_lake); |
| |
| // True if there are pending GTPM (GPU power management) interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(4, gpu_power_pending_kaby_lake); |
| |
| // True if there are pending VCS (Video Command Streamer) 2 interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(3, video_command_streamer_2_pending_kaby_lake); |
| |
| // True if there are pending VCS (Video Command Streamer) 1 interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(2, video_command_streamer_1_pending_kaby_lake); |
| |
| // True if there are pending blitter interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(1, blitter_pending_kaby_lake); |
| |
| // True if there are pending render interrupts. |
| // |
| // This is not documented on Tiger Lake. However, it has good read semantics. |
| // The underlying bit is reserved and documented as MBZ (must be zero), so |
| // reading it will always report that no interrupts are pending. |
| DEF_BIT(0, render_pending_kaby_lake); |
| |
| static auto Get() { return hwreg::RegisterAddr<DisplayInterruptControl>(0x44200); } |
| }; |
| |
| // GFX_MSTR_INTR (Graphics Primary Interrupt) |
| // |
| // Controls whether top-level graphics interrupts propagate to the PCI device |
| // interrupt, and summarizes the pending graphics-level interrupts. |
| // |
| // This register is not documented on Kaby Lake or Skylake. On those platforms, |
| // the display engine interrupts covered by DisplayInterruptControl propagate |
| // directly to the PCI device interrupt. |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 1 pages 1054-1055 |
| class GraphicsPrimaryInterrupt : public hwreg::RegisterBase<GraphicsPrimaryInterrupt, uint32_t> { |
| public: |
| // If true, graphics interrupts propagate to the PCI device interrupt. |
| // |
| // The driver sets this bit when it is ready to process graphics interrupts. |
| DEF_BIT(31, interrupts_enabled); |
| |
| // True if an interrupt from the display engine is pending. |
| DEF_BIT(16, display_interrupt_pending); |
| |
| // True if a GPU interrupt is pending. |
| DEF_BIT(1, gt1_interrupt_pending); |
| |
| // True if a GPU interrupt is pending. |
| DEF_BIT(0, gt0_interrupt_pending); |
| |
| static auto Get() { return hwreg::RegisterAddr<GraphicsPrimaryInterrupt>(0x190010); } |
| }; |
| |
| // PWR_WELL_CTL |
| // |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 690-693 |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 2 pages 1063-1065 |
| class PowerWellControl : public hwreg::RegisterBase<PowerWellControl, uint32_t> { |
| public: |
| hwreg::BitfieldRef<uint32_t> power_request(size_t index) { |
| ZX_DEBUG_ASSERT(index & 1); |
| ZX_DEBUG_ASSERT_MSG(index <= std::numeric_limits<uint32_t>::max(), "%zu overflows uint32_t", |
| index); |
| const uint32_t i = static_cast<uint32_t>(index); |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), i, i); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> power_state(size_t index) { |
| ZX_DEBUG_ASSERT((index & 1) == 0); |
| ZX_DEBUG_ASSERT_MSG(index <= std::numeric_limits<uint32_t>::max(), "%zu overflows uint32_t", |
| index); |
| const uint32_t i = static_cast<uint32_t>(index); |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), i, i); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> ddi_io_power_request_skylake(i915::DdiId ddi_id) { |
| int bit = |
| 2 + ((ddi_id == i915::DdiId::DDI_A || ddi_id == i915::DdiId::DDI_E) ? 0 : ddi_id * 2) + 1; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> ddi_io_power_state_skylake(i915::DdiId ddi_id) { |
| int bit = 2 + ((ddi_id == i915::DdiId::DDI_A || ddi_id == i915::DdiId::DDI_E) ? 0 : ddi_id * 2); |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| // Misc IO Power Request (on Skylake / Kaby Lake only) |
| // This field requests power for Miscellaneous IO to enable (1) or disable (0). |
| // This includes all AUX channels, audio pins, and utility pin. |
| hwreg::BitfieldRef<uint32_t> misc_io_power_request_skylake() { |
| int bit = kMiscIoBitsOffset + 1; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| // Misc IO Power State (on Skylake / Kaby Lake only): |
| // Enabled (1) or disabled (0). |
| hwreg::BitfieldRef<uint32_t> misc_io_power_state_skylake() { |
| int bit = kMiscIoBitsOffset; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| static auto Get() { |
| // The address below is for PWR_WELL_CTL2, which is provided for driver use. |
| // By contrast, PWR_WELL_CTL1 is intended for BIOS use. |
| return hwreg::RegisterAddr<PowerWellControl>(0x45404); |
| } |
| |
| private: |
| constexpr static size_t kMiscIoBitsOffset = 0; |
| }; |
| |
| // PWR_WELL_CTL_AUX2 (Power Well Control AUX2) |
| // Control display power for AUX IO for each DDI / Transport. |
| // This register is only available on Tiger Lake. |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 1072-1077 |
| class PowerWellControlAux : public hwreg::RegisterBase<PowerWellControlAux, uint32_t> { |
| public: |
| DEF_BIT(29, power_on_request_thunderbolt_6); |
| DEF_BIT(28, powered_on_thunderbolt_6); |
| |
| DEF_BIT(27, power_on_request_thunderbolt_5); |
| DEF_BIT(26, powered_on_thunderbolt_5); |
| |
| DEF_BIT(25, power_on_request_thunderbolt_4); |
| DEF_BIT(24, powered_on_thunderbolt_4); |
| |
| DEF_BIT(23, power_on_request_thunderbolt_3); |
| DEF_BIT(22, powered_on_thunderbolt_3); |
| |
| DEF_BIT(21, power_on_request_thunderbolt_2); |
| DEF_BIT(20, powered_on_thunderbolt_2); |
| |
| DEF_BIT(19, power_on_request_thunderbolt_1); |
| DEF_BIT(18, powered_on_thunderbolt_1); |
| |
| DEF_BIT(17, power_on_request_usb_c_6); |
| DEF_BIT(16, powered_on_usb_c_6); |
| |
| DEF_BIT(15, power_on_request_usb_c_5); |
| DEF_BIT(14, powered_on_usb_c_5); |
| |
| DEF_BIT(13, power_on_request_usb_c_4); |
| DEF_BIT(12, powered_on_usb_c_4); |
| |
| DEF_BIT(11, power_on_request_usb_c_3); |
| DEF_BIT(10, powered_on_usb_c_3); |
| |
| DEF_BIT(9, power_on_request_usb_c_2); |
| DEF_BIT(8, powered_on_usb_c_2); |
| |
| DEF_BIT(7, power_on_request_usb_c_1); |
| DEF_BIT(6, powered_on_usb_c_1); |
| |
| DEF_BIT(5, power_on_request_c); |
| DEF_BIT(4, powered_on_c); |
| |
| DEF_BIT(3, power_on_request_b); |
| DEF_BIT(2, powered_on_b); |
| |
| DEF_BIT(1, power_on_request_a); |
| DEF_BIT(0, powered_on_a); |
| |
| SelfType& set_power_on_request_combo_or_usb_c(i915::DdiId ddi_id, bool enabled) { |
| ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_A); |
| ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6); |
| const uint32_t bit = ddi_id * 2 + 1; |
| hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit).set(enabled); |
| return *this; |
| } |
| |
| bool powered_on_combo_or_usb_c(i915::DdiId ddi_id) const { |
| ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_A); |
| ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6); |
| const uint32_t bit = ddi_id * 2; |
| return hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), bit, bit).get(); |
| } |
| |
| SelfType& set_power_on_request_thunderbolt(i915::DdiId ddi_id, bool enabled) { |
| ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_TC_1); |
| ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6); |
| // The request_thunderbolt_* bits start from bit 19. |
| const uint32_t bit = (ddi_id - i915::DdiId::DDI_TC_1) * 2 + 19; |
| hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit).set(enabled); |
| return *this; |
| } |
| |
| bool powered_on_thunderbolt(i915::DdiId ddi_id) const { |
| ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_TC_1); |
| ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6); |
| // The state_thunderbolt_* bits start from bit 18. |
| const uint32_t bit = (ddi_id - i915::DdiId::DDI_TC_1) * 2 + 18; |
| return hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), bit, bit).get(); |
| } |
| |
| static auto Get() { |
| // The address below is for PWR_WELL_CTL_AUX2, which is provided for driver |
| // use. By contrast, PWR_WELL_CTL_AUX1 is intended for BIOS use. |
| return hwreg::RegisterAddr<PowerWellControlAux>(0x45444); |
| } |
| }; |
| |
| // PWR_WELL_CTL_DDI |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 2 pages 1072-1075 |
| class PowerWellControlDdi2 : public hwreg::RegisterBase<PowerWellControlDdi2, uint32_t> { |
| public: |
| hwreg::BitfieldRef<uint32_t> ddi_io_power_request_tiger_lake(i915::DdiId ddi_id) { |
| // DDI A-C: bits 1/3/5. DDI TC1-6: bits 7/9/11/13/15/17. |
| int bit = ddi_id * 2 + 1; |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| hwreg::BitfieldRef<uint32_t> ddi_io_power_state_tiger_lake(i915::DdiId ddi_id) { |
| int bit = ddi_id * 2; // DDI A-C: bits 0/2/4. DDI TC1-6: bits 6/8/10/12/14/16. |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit); |
| } |
| |
| static auto Get() { |
| // The address below is for PWR_WELL_CTL_DDI2, which is provided for driver |
| // use. By contrast, PWR_WELL_CTL_DDI1 is intended for BIOS use. |
| return hwreg::RegisterAddr<PowerWellControlDdi2>(0x45454); |
| } |
| }; |
| |
| // FUSE_STATUS |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 990-991 |
| class FuseStatus : public hwreg::RegisterBase<FuseStatus, uint32_t> { |
| public: |
| DEF_BIT(31, fuse_download_status); |
| DEF_BIT(27, pg0_dist_status); |
| DEF_BIT(26, pg1_dist_status); |
| DEF_BIT(25, pg2_dist_status); |
| DEF_BIT(24, pg3_dist_status); // Only for Icy lake or higher gen |
| DEF_BIT(23, pg4_dist_status); // Only for Icy lake or higher gen |
| DEF_BIT(22, pg5_dist_status); // Only for Tiger lake or higher gen |
| |
| uint32_t dist_status(uint32_t index) { |
| ZX_DEBUG_ASSERT(index >= 0 && index <= 31); |
| return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), index, index).get(); |
| } |
| |
| static auto Get() { return hwreg::RegisterAddr<FuseStatus>(0x42000); } |
| }; |
| |
| // CDCLK_CTL (CD Clock Control) |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 220-222 |
| // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 328-329 |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 325-326 |
| class CdClockCtl : public hwreg::RegisterBase<CdClockCtl, uint32_t> { |
| public: |
| DEF_FIELD(27, 26, skl_cd_freq_select); |
| static constexpr uint32_t kFreqSelect4XX = 0; |
| static constexpr uint32_t kFreqSelect540 = 1; |
| static constexpr uint32_t kFreqSelect3XX = 2; |
| static constexpr uint32_t kFreqSelect6XX = 3; |
| |
| DEF_FIELD(23, 22, icl_cd2x_divider_select); |
| static constexpr uint32_t kCd2xDivider1 = 0; |
| static constexpr uint32_t kCd2xDivider2 = 1; |
| |
| DEF_FIELD(21, 19, icl_cd2x_pipe_select); |
| |
| DEF_FIELD(10, 0, cd_freq_decimal); |
| // This returns binary representation of CD clock frequency (MHz) in |
| // U10.1 format (cd_freq_decimal field). To calculate its value, we first |
| // round the frequency to 0.5MHz and then minus it by one. |
| static constexpr uint32_t FreqDecimal(uint32_t khz) { |
| // Truncate the frequency to 0.25MHz for rounding. |
| uint32_t mhz_4x_trunc = khz / 250; |
| // Round the frequency to 0.5 MHz. |
| uint32_t mhz_2x_round = (mhz_4x_trunc + 1) / 2; |
| // Return rounded value minus 1 (0x2 in U10.1 format). |
| return mhz_2x_round - 2; |
| } |
| |
| static auto Get() { return hwreg::RegisterAddr<CdClockCtl>(0x46000); } |
| }; |
| |
| // CDCLK_PLL_ENABLE on ICL+ |
| class IclCdClkPllEnable : public hwreg::RegisterBase<IclCdClkPllEnable, uint32_t> { |
| public: |
| DEF_BIT(31, pll_enable); |
| DEF_BIT(30, pll_lock); |
| DEF_FIELD(7, 0, pll_ratio); |
| |
| static auto Get() { return hwreg::RegisterAddr<IclCdClkPllEnable>(0x46070); } |
| }; |
| |
| // DBUF_CTL (DBUF Slice Control) |
| // |
| // Some of the register's reserved are not documented as MBZ (must be zero). So, |
| // this register can only be safely updated using read-modify-write operations. |
| // |
| // The "Data Buffer" expansion for the DBUF acronym is implicitly documented in |
| // the "Shared Functions" > "Data Buffer" section of the display engine PRMs |
| // (Vol 12 for all recent display engines), which lists all the DBUF-related |
| // registers. |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 331-332 |
| // DG1: IHD-OS-DG1-Vol 2c-2.21 Part 1 pages 309-310 |
| // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 430-431 |
| // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 426-427 |
| class DataBufferControl : public hwreg::RegisterBase<DataBufferControl, uint32_t> { |
| public: |
| // The eventual state that `powered_on` will reach. |
| // |
| // If true, the DBUF (Data Buffer) slice will eventually power on. If false, |
| // the DBUF slice will eventually power off. |
| // |
| // The first DBUF slice must be powered on before using the display engine. |
| // Powering it on is a step in the "Sequences to Initialize Display". |
| DEF_BIT(31, powered_on_target); |
| |
| // If true, the DBUF (Data Buffer) slice is powered on. |
| DEF_BIT(30, powered_on); |
| |
| // Maximum number of clock cycles until the tracker state is serviced. |
| // |
| // This field is not documented on Kaby Lake and Skylake. The underlying bits |
| // are documented as reserved MBZ (must be zero). |
| DEF_FIELD(23, 19, maximum_tracker_state_delay_tiger_lake); |
| |
| // Maximum number of clock cycles until the CC block valid state is serviced. |
| // |
| // This field is not documented on Kaby Lake and Skylake. The underlying bits |
| // are documented as reserved MBZ (must be zero). |
| DEF_FIELD(15, 12, maximum_cc_block_valid_delay); |
| |
| // DBUF (Data Buffer) slice count varies by display engine. |
| // |
| // `slice_index` is 0-based. |
| static auto GetForSlice(int slice_index) { |
| ZX_ASSERT(slice_index >= 0); |
| ZX_ASSERT(slice_index < 2); |
| |
| static constexpr uint32_t kMmioAddress[] = {0x45008, 0x44fe8}; |
| return hwreg::RegisterAddr<DataBufferControl>(kMmioAddress[slice_index]); |
| } |
| }; |
| |
| // DBUF_CTL (DBUF Slice Control 2) |
| // |
| // All reserved bits are MBZ (must be zero), so this register can be written |
| // safely without reading it first. |
| // |
| // This register is not documented on Kaby Lake or Skylake. |
| // |
| // Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 page 333 |
| // DG1: IHD-OS-DG1-Vol 2c-2.21 Part 1 page 311 |
| class DataBufferControl2 : public hwreg::RegisterBase<DataBufferControl2, uint32_t> { |
| public: |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Number of time slots between servicing HPUTs. |
| // |
| // This field must not be set to zero. |
| DEF_FIELD(12, 8, hput_service_interval); |
| |
| // Number of time slots dedicated to servicing APUTs. |
| // |
| // This field must not be set to zero. |
| DEF_FIELD(7, 4, aput_service_time_slots); |
| |
| // Number of time slots dedicated to servicing BYPASS puts. |
| // |
| // This field must not be set to zero. |
| DEF_FIELD(3, 0, bypass_put_service_time_slots); |
| |
| // DBUF (Data Buffer) slice count varies by display engine. |
| // |
| // `slice_index` is 0-based. |
| static auto GetForSlice(int slice_index) { |
| ZX_ASSERT(slice_index >= 0); |
| ZX_ASSERT(slice_index < 2); |
| |
| static constexpr uint32_t kMmioAddress[] = {0x44ffc, 0x44fe4}; |
| return hwreg::RegisterAddr<DataBufferControl2>(kMmioAddress[slice_index]); |
| } |
| }; |
| |
| // VGA_CONTROL |
| class VgaCtl : public hwreg::RegisterBase<VgaCtl, uint32_t> { |
| public: |
| DEF_BIT(31, vga_display_disable); |
| |
| static auto Get() { return hwreg::RegisterAddr<VgaCtl>(0x41000); } |
| }; |
| |
| } // namespace registers |
| |
| #endif // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_H_ |