// 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_DDI_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_DDI_H_

#include <lib/ddk/debug.h>
#include <zircon/assert.h>

#include <cstdint>
#include <optional>

#include <hwreg/bitfields.h>

#include "src/graphics/display/drivers/intel-i915/hardware-common.h"

namespace registers {

// Interrupt registers for the south (in the PCH) display engine.
//
// SINTERRUPT is made up of the interrupt registers below.
// - ISR (Interrupt Status Register), also abbreviated to SDE_ISR
// - IMR (Interrupt Mask Register), also abbreviated to SDE_IMR
// - IIR (Interrupt Identity Register), also abbreviated to SDE_IIR
// - IER (Interrupt Enable Register), also abbreviated to SDE_IER
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 1196-1197
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 820-821
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 pages 800-801
//
// The individual bits in each register are covered in the South Display Engine
// Interrupt Bit Definition, or SDE_INTERRUPT.
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 1262-1264
// DG1: IHD-OS-DG1-Vol 2c-2.21 Part 2 pages 1328-1329
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 874-875
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 pages 854-855
class SdeInterruptBase : public hwreg::RegisterBase<SdeInterruptBase, uint32_t> {
 public:
  // SDE_INTERRUPT documents the base MMIO offset. SINTERRUPT documents the
  // individual register offsets.
  static constexpr uint32_t kSdeIntMask = 0xc4004;
  static constexpr uint32_t kSdeIntIdentity = 0xc4008;
  static constexpr uint32_t kSdeIntEnable = 0xc400c;

  DEF_BIT(23, gmbus);

  hwreg::BitfieldRef<uint32_t> skl_ddi_bit(i915::DdiId ddi_id) {
    uint32_t bit;
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
        bit = 24;
        break;
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
      case i915::DdiId::DDI_D:
        bit = 20 + ddi_id;
        break;
      case i915::DdiId::DDI_E:
        bit = 25;
        break;
      default:
        bit = -1;
    }
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> icl_ddi_bit(i915::DdiId ddi_id) {
    uint32_t bit;
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
        bit = 16 + ddi_id - i915::DdiId::DDI_A;
        break;
      case i915::DdiId::DDI_TC_1:
      case i915::DdiId::DDI_TC_2:
      case i915::DdiId::DDI_TC_3:
      case i915::DdiId::DDI_TC_4:
      case i915::DdiId::DDI_TC_5:
      case i915::DdiId::DDI_TC_6:
        bit = 24 + ddi_id - i915::DdiId::DDI_TC_1;
        break;
      default:
        bit = -1;
    }
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get(uint32_t offset) { return hwreg::RegisterAddr<SdeInterruptBase>(offset); }
};

// DE_HPD_INTERRUPT : Display Engine HPD Interrupts for Type C / Thunderbolt (since gen11)
class HpdInterruptBase : public hwreg::RegisterBase<HpdInterruptBase, uint32_t> {
 public:
  static constexpr uint32_t kHpdIntMask = 0x44474;
  static constexpr uint32_t kHpdIntIdentity = 0x44478;
  static constexpr uint32_t kHpdIntEnable = 0x4447c;

  hwreg::BitfieldRef<uint32_t> tc_hotplug(i915::DdiId ddi_id) {
    ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_TC_1);
    ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6);
    uint32_t bit = 16 + ddi_id - i915::DdiId::DDI_TC_1;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> tbt_hotplug(i915::DdiId ddi_id) {
    ZX_DEBUG_ASSERT(ddi_id >= i915::DdiId::DDI_TC_1);
    ZX_DEBUG_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6);
    uint32_t bit = ddi_id - i915::DdiId::DDI_TC_1;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get(uint32_t offset) { return hwreg::RegisterAddr<HpdInterruptBase>(offset); }
};

// TBT_HOTPLUG_CTL : Thunderbolt Hot Plug Control (since gen11)
class TbtHotplugCtrl : public hwreg::RegisterBase<TbtHotplugCtrl, uint32_t> {
 public:
  hwreg::BitfieldRef<uint32_t> hpd_enable(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdEnableBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_long_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdLongPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_short_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdShortPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get() { return hwreg::RegisterAddr<TbtHotplugCtrl>(kOffset); }

 private:
  static constexpr uint32_t kOffset = 0x44030;

  static constexpr uint32_t kHpdShortPulseBitSubOffset = 0;
  static constexpr uint32_t kHpdLongPulseBitSubOffset = 1;
  static constexpr uint32_t kHpdEnableBitSubOffset = 3;

  static uint32_t ddi_id_to_first_bit(i915::DdiId ddi_id) {
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
        ZX_DEBUG_ASSERT_MSG(false, "Use south display hot plug registers for DDI A-C");
        return -1;
      case i915::DdiId::DDI_TC_1:
      case i915::DdiId::DDI_TC_2:
      case i915::DdiId::DDI_TC_3:
      case i915::DdiId::DDI_TC_4:
      case i915::DdiId::DDI_TC_5:
      case i915::DdiId::DDI_TC_6:
        return 4 * (ddi_id - i915::DdiId::DDI_TC_1);
    }
  }
};

// TC_HOTPLUG_CTL : Type-C Hot Plug Control (since gen11)
class TcHotplugCtrl : public hwreg::RegisterBase<TcHotplugCtrl, uint32_t> {
 public:
  hwreg::BitfieldRef<uint32_t> hpd_enable(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdEnableBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_long_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdLongPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_short_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdShortPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get() { return hwreg::RegisterAddr<TcHotplugCtrl>(kOffset); }

 private:
  static constexpr uint32_t kOffset = 0x44038;

  static constexpr uint32_t kHpdShortPulseBitSubOffset = 0;
  static constexpr uint32_t kHpdLongPulseBitSubOffset = 1;
  static constexpr uint32_t kHpdEnableBitSubOffset = 3;

  static uint32_t ddi_id_to_first_bit(i915::DdiId ddi_id) {
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
        ZX_DEBUG_ASSERT_MSG(false, "Use south display hot plug registers for DDI A-C");
        return -1;
      case i915::DdiId::DDI_TC_1:
      case i915::DdiId::DDI_TC_2:
      case i915::DdiId::DDI_TC_3:
      case i915::DdiId::DDI_TC_4:
      case i915::DdiId::DDI_TC_5:
      case i915::DdiId::DDI_TC_6:
        return 4 * (ddi_id - i915::DdiId::DDI_TC_1);
    }
  }
};

// SHOTPLUG_CTL_DDI + SHOTPLUG_CTL_TC
class IclSouthHotplugCtrl : public hwreg::RegisterBase<IclSouthHotplugCtrl, uint32_t> {
 public:
  hwreg::BitfieldRef<uint32_t> hpd_enable(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdEnableBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_long_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdLongPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_short_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdShortPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get(i915::DdiId ddi_id) {
    return hwreg::RegisterAddr<IclSouthHotplugCtrl>(ddi_id >= i915::DdiId::DDI_TC_1 ? kTcOffset
                                                                                    : kDdiOffset);
  }

 private:
  static constexpr uint32_t kDdiOffset = 0xc4030;
  static constexpr uint32_t kTcOffset = 0xc4034;

  static constexpr uint32_t kHpdShortPulseBitSubOffset = 0;
  static constexpr uint32_t kHpdLongPulseBitSubOffset = 1;
  static constexpr uint32_t kHpdEnableBitSubOffset = 3;

  static uint32_t ddi_id_to_first_bit(i915::DdiId ddi_id) {
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
        return 4 * (ddi_id - i915::DdiId::DDI_A);  // SHOTPLUG_CTL_DDI
      case i915::DdiId::DDI_TC_1:
      case i915::DdiId::DDI_TC_2:
      case i915::DdiId::DDI_TC_3:
      case i915::DdiId::DDI_TC_4:
      case i915::DdiId::DDI_TC_5:
      case i915::DdiId::DDI_TC_6:
        return 4 * (ddi_id - i915::DdiId::DDI_TC_1);  // SHOTPLUG_CTL_TC
      default:
        return -1;
    }
  }
};

// SHOTPLUG_CTL + SHOTPLUG_CTL2
class SouthHotplugCtrl : public hwreg::RegisterBase<SouthHotplugCtrl, uint32_t> {
 public:
  hwreg::BitfieldRef<uint32_t> hpd_enable(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdEnableBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_long_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdLongPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  hwreg::BitfieldRef<uint32_t> hpd_short_pulse(i915::DdiId ddi_id) {
    uint32_t bit = ddi_id_to_first_bit(ddi_id) + kHpdShortPulseBitSubOffset;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit, bit);
  }

  static auto Get(i915::DdiId ddi_id) {
    return hwreg::RegisterAddr<SouthHotplugCtrl>(ddi_id == i915::DdiId::DDI_E ? kOffset2 : kOffset);
  }

 private:
  static constexpr uint32_t kOffset = 0xc4030;
  static constexpr uint32_t kOffset2 = 0xc403c;

  static constexpr uint32_t kHpdShortPulseBitSubOffset = 0;
  static constexpr uint32_t kHpdLongPulseBitSubOffset = 1;
  static constexpr uint32_t kHpdEnableBitSubOffset = 4;

  static uint32_t ddi_id_to_first_bit(i915::DdiId ddi_id) {
    switch (ddi_id) {
      case i915::DdiId::DDI_A:
        return 24;
      case i915::DdiId::DDI_B:
      case i915::DdiId::DDI_C:
      case i915::DdiId::DDI_D:
        return 8 * (ddi_id - 1);
      case i915::DdiId::DDI_E:
        return 0;
      default:
        return -1;
    }
  }
};

// SFUSE_STRAP (South / PCH Fuses and Straps)
//
// This register is not documented on DG1.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 page 1185
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 811
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 791
class PchDisplayFuses : public hwreg::RegisterBase<PchDisplayFuses, uint32_t> {
 public:
  // On Tiger Lake, indicates whether RawClk should be clocked at 24MHz or
  // 19.2MHz.
  DEF_BIT(8, rawclk_is_24mhz);

  // Not present (set to zero) on Tiger Lake. The driver is expected to use the
  // VBT (Video BIOS Table) or hotplug detection to figure out which ports are
  // present.
  DEF_BIT(2, port_b_present);
  DEF_BIT(1, port_c_present);
  DEF_BIT(0, port_d_present);

  static auto Get() { return hwreg::RegisterAddr<PchDisplayFuses>(0xc2014); }
};

// DDI_BUF_CTL (DDI Buffer Control)
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 1 pages 352-355
// DG1: IHD-OS-DG1-Vol 2c-2.21 pages 331-334
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 442-445
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 438-441
class DdiBufferControl : public hwreg::RegisterBase<DdiBufferControl, uint32_t> {
 public:
  // If true, the DDI buffer is enabled.
  DEF_BIT(31, enabled);

  // If true, the DDI ignores PHY parameter changes during link training.
  //
  // The impacted PHY parameters include voltage swing and pre-emphasis. This
  // field is generally set when using specific PHY parameters for the DDI.
  //
  // This field does not exist (is reserved) on Kaby Lake and Skylake.
  DEF_BIT(29, override_training_tiger_lake);

  // If true, the DDI uses adjusted PHY parameter values.
  //
  // The value is ignored if `override_training` is false.
  //
  // This field does not exist (is reserved) on Kaby Lake and Skylake.
  DEF_BIT(28, adjust_phy_parameters_tiger_lake);

  // Selects one of the DisplayPort PHY configurations set up in DDI_BUF_TRANS.
  //
  // DDIs A and E support indexes 0 through 9. DDIs B-D only support indexes 0
  // through 8, because the 9th PHY configuration is used for HDMI.
  //
  // This field is meaningless for HDMI and DVI.
  //
  // This field does not exist (is reserved) on Tiger Lake and DG1.
  DEF_FIELD(27, 24, display_port_phy_config_kaby_lake);

  // If true, data is swapped on the lanes output by the port.
  //
  // This field must not be changed while the DDI is enabled.
  //
  // Tiger Lake and DG1:
  //
  // FIA handles lane reversal for Thunderbolt and USB-C DisplayPort Alt Mode,
  // and this field should be set to false in those cases. Static and fixed
  // connections (DisplayPort, HDMI) through the FIA only use this field in
  // "No pin Assignment (Non Type-C DP)" static configurations. Other
  // connections use the field.
  //
  // Kaby Lake and Skylake:
  //
  // For DDIs B-D, enabling swaps lanes 0 <-> 3 and lanes 1 <-> 2. If DDI E is
  // enabled (in DDI A Lane Capability Control), then DDI A reversal swaps its
  // two remaining lanes (0 <-> 1). If DDI E is disabled, DDI A reversal acts
  // the same as B-D reversal (lanes 0 <-> 3 and 1 <->2 are swapped). DDI E does
  // not support port reversal.
  DEF_BIT(16, port_reversal);

  // Delay used to stagger the assertion/deassertion of the port lane enables.
  //
  // The value is expressed in multiples of the symbol clock period, so it
  // depends on the link frequency.
  //
  // The delay should be at least 100ns when the port is used in USB Type C
  // mode. In all other cases, the delay should be zero.
  //
  // This field does not exist (is reserved) on Kaby Lake and Skylake, which
  // don't have Type C DDIs.
  DEF_FIELD(15, 8, type_c_display_port_lane_staggering_delay_tiger_lake);

  // If true, the DDI is idle.
  DEF_BIT(7, is_idle);

  // If false, two lanes from DDI A are repurposed to form DDI E.
  //
  // If true, DDI A has four lanes, and behaves similarly to DDIs B-D. If false,
  //
  // This field is only meaningful on DDI A, whose lanes get redistributed to
  // DDI E. The field must be programmed at boot time (based on the board
  // configuration) and must not be changed afterwards.
  //
  // This field does not exist (is reserved) on Tiger Lake or DG1.
  DEF_BIT(4, ddi_e_disabled_kaby_lake);

  // Selects the number of DisplayPort lanes enabled.
  //
  // The field's value is the number of lanes minus 1. 0 = x1 lane, 1 = x2
  // lanes, 3 = x4 lanes. display_port_lane_count() and
  // set_display_port_lane_count() take care of this encoding detail.
  DEF_FIELD(3, 1, display_port_lane_count_selection);

  // The number of DisplayPort lanes enabled.
  //
  // This field is not meaningful for HDMI, which always uses all the lanes.
  //
  // When the DDI is in DisplayPort mode, the field must match the corresponding
  // setting in TRANS_DDI_FUNC_CTL for the transcoder attached to this DDI.
  //
  // On Kaby Lake and Skylake, DDI E only supports 1 and 2 lanes
  // (if it's enabled), since it takes two lanes from DDI A. On the same
  // hardware, DDI A always supports x1 and x2, and supports x4 if DDI E is
  // disabled (and therefore not taking away 2 lanes from DDI A).
  uint8_t display_port_lane_count() const {
    // The addition will not overflow and the cast is lossless because
    // display_port_lane_count_selection() is a 3-bit field.
    return static_cast<int8_t>(display_port_lane_count_selection() + 1);
  }

  // See display_port_lane_count() for details.
  DdiBufferControl& set_display_port_lane_count(uint8_t lane_count) {
    switch (lane_count) {
      case 1:
      case 2:
      case 4:
        set_display_port_lane_count_selection(lane_count - 1);
        return *this;
    }
    ZX_ASSERT_MSG(false, "Unsupported lane count: %d", lane_count);
    return *this;
  }

  // The level of the port detect pin at boot time.
  //
  // This field is only meaningful on DDI A. On Skylake and Kaby Lake, the other
  // DDIs' port detect pin status is communicated in SFUSE_STRAP.
  DEF_BIT(0, boot_time_port_detect_pin_status);

  // For Kaby Lake and Skylake DDI A - DDI E.
  static auto GetForKabyLakeDdi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiBufferControl>(0x64000 + 0x100 * ddi_index);
  }

  // For Tiger Lake and DG1.
  static auto GetForTigerLakeDdi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiBufferControl>(0x64000 + 0x100 * ddi_index);
  }
};

// Part 1 of DDI_BUF_TRANS (DDI Buffer Translation)
//
// Each DDI has 10 instances of the DDI_BUF_TRANS register, storing 10 entries
// of the port's PHY configuration table. The MMIO addresses for the 10
// instances are consecutive. The active entry is selected using the DDI_BUF_CTL
// register.
//
// Each DDI_BUF_TRANS register instance (storing one entry in the PHY
// configuration table) consists of two 32-bit parts (double-words). We don't
// know if it's safe to use 64-bit MMIO accesses with the registers.
//
// DDI_BUF_TRANS is not documented on Tiger Lake or DG1.
//
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 446-447
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 442-441
class DdiPhyConfigEntry1 : public hwreg::RegisterBase<DdiPhyConfigEntry1, uint32_t> {
 public:
  // The PRMs do not go in depth on the meanings of the fields.
  DEF_BIT(31, balance_leg_enable);
  DEF_FIELD(17, 0, deemphasis_level);

  static auto GetDdiInstance(i915::DdiId ddi_id, int instance_index) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);
    ZX_ASSERT(instance_index >= 0);
    ZX_ASSERT(instance_index < 10);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiPhyConfigEntry1>(0x64e00 + 0x60 * ddi_index + 8 * instance_index);
  }
};

// Part 2 of DDI_BUF_TRANS (DDI Buffer Translation)
//
// See Part 1 above for documentation.
class DdiPhyConfigEntry2 : public hwreg::RegisterBase<DdiPhyConfigEntry2, uint32_t> {
 public:
  // The PRMs do not go in depth on the meanings of the fields.
  DEF_FIELD(20, 16, voltage_reference_select);
  DEF_FIELD(10, 0, voltage_swing);

  static auto GetDdiInstance(i915::DdiId ddi_id, int instance_index) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);
    ZX_ASSERT(instance_index >= 0);
    ZX_ASSERT(instance_index < 10);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiPhyConfigEntry2>(0x64e04 + 0x60 * ddi_index + 8 * instance_index);
  }
};

// DISPIO_CR_TX_BMU_CR0
//
// Involved in PHY parameters for transmission on all DDIs.
//
// This register does not exist on Tiger Lake or DG1.
//
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 446-447
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 442-441
class DdiPhyBalanceControl : public hwreg::RegisterBase<DdiPhyBalanceControl, uint32_t> {
 public:
  // Not managed by driver software.
  DEF_FIELD(31, 29, digital_analog);

  // Not managed by driver software.
  DEF_BIT(28, global_vs_local_voltage_reference_select);

  // Must be zero for `balance_leg_select` fields to be used.
  DEF_FIELD(27, 23, disable_balance_leg);

  // For DDI4 - DDI E or DDI A when DDI E is disabled.
  DEF_FIELD(22, 20, balance_leg_select_ddi_e);

  // For DDI3 / DDI D.
  DEF_FIELD(19, 17, balance_leg_select_ddi_d);

  // For DDI2 / DDI C.
  DEF_FIELD(16, 14, balance_leg_select_ddi_c);

  // For DDI1 / DDI B.
  DEF_FIELD(13, 11, balance_leg_select_ddi_b);

  // For DDI0 / DDI A.
  DEF_FIELD(10, 8, balance_leg_select_ddi_a);

  // Not managed by driver software.
  DEF_FIELD(7, 0, h_mode);

  hwreg::BitfieldRef<uint32_t> balance_leg_select_for_ddi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    const int bit_index = 8 + 3 * ddi_index;
    return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit_index + 2, bit_index);
  }

  static auto Get() { return hwreg::RegisterAddr<DdiPhyBalanceControl>(0x6c00c); }
};

// DDI_AUX_CTL (DDI AUX Channel Control)
//
// Tiger Lake: IHD-OS-TGL-Vol2c-12.21 Part 1 pages 342-345
// DG1: IHD-OS-DG1-Vol 2c-2.21 Part 1 pages 321-323
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 436-438
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 432-434
class DdiAuxControl : public hwreg::RegisterBase<DdiAuxControl, uint32_t> {
 public:
  // True while the DDI is performing an AUX transaction.
  //
  // The driver sets this field to true to start an AUX transaction. The
  // hardware resets it back to false when the AUX transaction is completed.
  //
  // The register should not be modified while this field is true.
  //
  // On Kaby Lake and Skylake, DDI_AUX_MUTEX must be acquired before setting up
  // an AUX transaction.
  DEF_BIT(31, transaction_in_progress);

  // Set to true by hardware when it completes an AUX transaction.
  //
  // This bit is sticky Read/Write-Clear. It stays true until the driver resets
  // it by writing true to it.
  DEF_BIT(30, transaction_done);

  // If true, an interrupt is triggered when an AUX transaction is completed.
  DEF_BIT(29, interrupt_on_done);

  // Set to true by hardware when an AUX transaction times out.
  //
  // This bit is sticky Read/Write-Clear. It stays true until the driver resets
  // it by writing true to it.
  DEF_BIT(28, timeout);

  // Selects the AUX transaction timeout.
  //
  // The AUX transaction limit in the DisplayPort specification is 500us.
  //
  // The values are documented as 0 (400us, unsupported), 1 (600us), 2 (800us)
  DEF_FIELD(27, 26, timeout_timer_select);

  // Only documented on Kaby Lake and Skylake. The docs advise against using.
  static constexpr int kTimeoutUnsupported400us = 0;

  static constexpr int kTimeout600us = 1;
  static constexpr int kTimeout800us = 2;

  // 4,000 us on Tiger Lake and DG1. 1,600 us on Kaby Lake and Skylake.
  static constexpr int kTimeoutLarge = 3;

  // Set to true by hardware when an AUX transaction receives invalid data.
  //
  // The received data could be invalid due to: corruption detected, the bits
  // received don't add up to an integer number of bytes, more than 20 bytes
  // received.
  //
  // This bit is sticky Read/Write-Clear. It stays true until the driver resets
  // it by writing true to it.
  DEF_BIT(25, receive_error);

  // Total number of bytes in an AUX message, including the message header.
  //
  // The driver writes this field to indicate the message size for the next AUX
  // transaction. The hardware writes this field to indicate the response size
  // for the last AUX transaction.
  //
  // The message includes the header bytes (4 for command, 2 for reply). The
  // DisplayPort specification states that the maximum data size is 16 bytes,
  // leading to a 20-byte maximum message size.
  //
  // The driver must write values between 1 and 20. The value read from this
  // field is only valid and meaningful if `transaction_done` is true, and
  // `transaction_in_progress`, `timeout`, and `receive_error` are false.
  DEF_FIELD(24, 20, message_size);

  // Directs AUX transactions to the Thunderbolt IO, or the USB-C / Combo IO.
  //
  // If true, transactions will be performed via the Thunderbolt controller.
  // Otherwise, the transactions will be performed over USB-C (using the FIA) or
  // over the Combo DDI IO.
  //
  // This field is reserved (must be false) on Kaby Lake and Skylake, which
  // don't support Thunderbolt IO.
  DEF_BIT(11, use_thunderbolt);

  // Number of SYNC pulses sent during SYNC for eDP fast wake transactions.
  //
  // The value is the number of SYNC pulses minus 1.
  DEF_FIELD(9, 5, fast_wake_sync_pulse_count);

  // `fast_wake_sync_pulse_count` should be set to 7, to match the Embedded
  // DisplayPort standard requirement for 8 pre-charge pulses (zeros) in the
  // AUX_PHY_WAKE preamble.
  static constexpr int kFastWakeSyncPulseCount = 8 - 1;

  // Number of SYNC pulses sent during SYNC for standard transactions.
  //
  // The value is the number of SYNC pulses minus 1. This is the sum of the
  // 10-16 pre-charge pulses (zeros) and the 16 consecutive zeros at the start
  // of the AUX_SYNC pattern.
  DEF_FIELD(4, 0, sync_pulse_count);

  // `sync_pulse_count` should be set to at least 25, to meet the DisplayPort
  // 26-pulse minimum, which is equivalent to 10 pre-charge pulses.
  static constexpr int kMinSyncPulseCount = 26 - 1;

  // For Kaby Lake and Skylake DDI A - DDI E.
  //
  // The Kaby Lake and Skylake references only document the AUX registers for
  // DDIs A-D. Other manuals, such as IHD-OS-ICLLP-Vol 2c-1.20, document AUX
  // registers for DDIs E-F, and their MMIO addresses are what we'd expect.
  // For now, we assume DDI E has an AUX channel that works like the other DDIs.
  static auto GetForKabyLakeDdi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiAuxControl>(0x64010 + 0x100 * ddi_index);
  }

  // For Tiger Lake and DG1.
  static auto GetForTigerLakeDdi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_TC_6);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DdiAuxControl>(0x64010 + 0x100 * ddi_index);
  }
};

// DDI_AUX_DATA (DDI AUX Channel Data)
//
// Each DDI has 5 instances of the DDI_AUX_DATA register, making up a 20-byte
// buffer for storing AUX messages. The MMIO addresses for the 5 instances are
// consecutive.
//
// Tiger Lake: IHD-OS-TGL-Vol2c-12.21 Part 1 pages 346-351
// DG1: IHD-OS-DG1-Vol 2c-2.21 Part 1 pages 324-330
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 page 439
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 page 435
class DdiAuxData : public hwreg::RegisterBase<DdiAuxData, uint32_t> {
 public:
  // The most significant byte in each 32-bit register gets transmitted first.
  // Intel machines are little-endian, so the transmission order doesn't match
  // the memory order. The `swapped_` part of the name aims to draw attention
  // to this subtlety.
  //
  // The value is not meaningful while the corresponding DDI_AUX_CTL register's
  // `transaction_in_progress` field is true.
  DEF_FIELD(31, 0, swapped_bytes);

  // DDI_AUX_DATA_*_0 for the AUX channel with the given control register.
  //
  // The DDI_AUX_DATA_*_[1-4] data registers are accessed using direct MMIO
  // operations.
  //
  // We can get away with using DDI_AUX_CTL as the input because all DDI AUX
  // channels currently have the same MMIO layout. When this isn't the case
  // anymore, we'll replace this factory function with GetFor*Ddi() functions,
  // matching DdiAuxControl.
  static auto GetData0ForAuxControl(const DdiAuxControl& aux_control) {
    static constexpr uint32_t kAuxControlMmioBase = 0x64010;
    static constexpr uint32_t kAuxDataMmioBase = 0x64014;
    return hwreg::RegisterAddr<DdiAuxData>(aux_control.reg_addr() +
                                           (kAuxDataMmioBase - kAuxControlMmioBase));
  }
};

// DPCLKA_CFGCR0 (Display Clock Configuration Control Register 0?)
//
// This register controls which DPLL (Display PLL) is used as a clock source by
// each Combo DDI, and whether the DDI's clock is gated. Each Type C DDI has its
// own dedicated MGPLL, so this register only configures the clock gating for
// Type C DDIs.
//
// The Kaby Lake and Skylake equivalent of this register is
// `DisplayPllDdiMapKabyLake` (DPLL_CTRL2).
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 1, pages 608-610
// Lakefield: IHD-OS-LKF-Vol 2c-5.21 Part 1, pages 561-563
class DdiClockConfig : public hwreg::RegisterBase<DdiClockConfig, uint32_t> {
 public:
  DEF_BIT(24, ddi_c_clock_disabled);
  DEF_BIT(23, ddi_type_c_6_clock_disabled);
  DEF_BIT(22, ddi_type_c_5_clock_disabled);
  DEF_BIT(21, ddi_type_c_4_clock_disabled);

  DEF_BIT(14, ddi_type_c_3_clock_disabled);
  DEF_BIT(13, ddi_type_c_2_clock_disabled);
  DEF_BIT(12, ddi_type_c_1_clock_disabled);
  DEF_BIT(11, ddi_b_clock_disabled);
  DEF_BIT(10, ddi_a_clock_disabled);

  // If true, the DDI's clock is disabled. This is accomplished by gating.
  bool ddi_clock_disabled(i915::DdiId ddi_id) const {
    static constexpr int kComboBitIndices[] = {10, 11, 24};
    static constexpr int kTypeCBitIndices[] = {12, 13, 14, 21, 22, 23};
    int bit_index;
    if (ddi_id >= i915::DdiId::DDI_TC_1 && ddi_id <= i915::DdiId::DDI_TC_6) {
      const int ddi_index = ddi_id - i915::DdiId::DDI_TC_1;
      bit_index = kTypeCBitIndices[ddi_index];
    } else {
      ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
      ZX_ASSERT(ddi_id <= i915::DdiId::DDI_C);
      const int ddi_index = ddi_id - i915::DdiId::DDI_A;
      bit_index = kComboBitIndices[ddi_index];
    }
    return static_cast<bool>(
        hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), bit_index, bit_index).get());
  }

  // See `ddi_clock_disabled()` for details.
  DdiClockConfig& set_ddi_clock_disabled(i915::DdiId ddi_id, bool clock_disabled) {
    static constexpr int kComboBitIndices[] = {10, 11, 24};
    static constexpr int kTypeCBitIndices[] = {12, 13, 14, 21, 22, 23};
    int bit_index;
    if (ddi_id >= i915::DdiId::DDI_TC_1 && ddi_id <= i915::DdiId::DDI_TC_6) {
      const int ddi_index = ddi_id - i915::DdiId::DDI_TC_1;
      bit_index = kTypeCBitIndices[ddi_index];
    } else {
      ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
      ZX_ASSERT(ddi_id <= i915::DdiId::DDI_C);
      const int ddi_index = ddi_id - i915::DdiId::DDI_A;
      bit_index = kComboBitIndices[ddi_index];
    }
    hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit_index, bit_index).set(clock_disabled ? 1 : 0);
    return *this;
  }

  // Documented values for `ddi_*_clock_display_pll_select` fields.
  enum class DdiClockDisplayPllSelect {
    kDisplayPll0 = 0b00,
    kDisplayPll1 = 0b01,
    kDisplayPll4 = 0b10,
  };

  // These fields have a non-trivial representation. They should be used via the
  // `ddi_clock_display_pll()` and `set_ddi_clock_display_pll()` helpers.
  DEF_ENUM_FIELD(DdiClockDisplayPllSelect, 5, 4, ddi_c_clock_display_pll_select);
  DEF_ENUM_FIELD(DdiClockDisplayPllSelect, 3, 2, ddi_b_clock_display_pll_select);
  DEF_ENUM_FIELD(DdiClockDisplayPllSelect, 1, 0, ddi_a_clock_display_pll_select);

  // The DPLL (Display PLL) used as a clock source for a DDI.
  //
  // Returns DPLL_INVALID if the field is set to an undocumented value.
  i915::PllId ddi_clock_display_pll(i915::DdiId ddi_id) const {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_C);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    const int bit_index = ddi_index * 2;
    const auto dpll_select = static_cast<DdiClockDisplayPllSelect>(
        hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), bit_index + 1, bit_index).get());

    switch (dpll_select) {
      case DdiClockDisplayPllSelect::kDisplayPll0:
        return i915::PllId::DPLL_0;
      case DdiClockDisplayPllSelect::kDisplayPll1:
        return i915::PllId::DPLL_1;
      case DdiClockDisplayPllSelect::kDisplayPll4:
        // TODO(https://fxbug.dev/42061706): Add support for DPLL4.
        break;
    }
    // The field is set to an undocumented value.
    return i915::PllId::DPLL_INVALID;
  }

  // See `ddi_clock_display_pll()` for details.
  DdiClockConfig& set_ddi_clock_display_pll(i915::DdiId ddi_id, i915::PllId pll_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_C);

    DdiClockDisplayPllSelect dpll_select;
    switch (pll_id) {
      case i915::PllId::DPLL_0:
        dpll_select = DdiClockDisplayPllSelect::kDisplayPll0;
        break;
      case i915::PllId::DPLL_1:
        dpll_select = DdiClockDisplayPllSelect::kDisplayPll1;
        break;

      // TODO(https://fxbug.dev/42061706): Add support for DPLL4.
      default:
        ZX_DEBUG_ASSERT_MSG(false, "Unsupported DDI PLL: %d", pll_id);
        dpll_select = DdiClockDisplayPllSelect::kDisplayPll0;
    }

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    const int bit_index = ddi_index * 2;
    hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit_index + 1, bit_index)
        .set(static_cast<uint32_t>(dpll_select));
    return *this;
  }

  static auto Get() { return hwreg::RegisterAddr<DdiClockConfig>(0x164280); }
};

// DDI_CLK_SEL
// Type C DDI Clock Selection
//
// Each Type-C DDI has 5 PLL inputs: Type-C PLL, and Thunderbolt PLL with 4
// different frequencies.
// Tiger Lake: IHD-OS-TGL-Vol 12-1.22-Rev 2.0, Page 169 "PLL Arrangement"
//
// This register selects the clock source for a given Type-C DDI.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev 2.0 Part 1, Page 356-357
class TypeCDdiClockSelect : public hwreg::RegisterBase<TypeCDdiClockSelect, uint32_t> {
 public:
  // Select which clock to use for this DDI.
  // Valid values are listed below in `ClockSelect` enum class.
  //
  // Driver can use `clock_select` and `set_clock_select` helper methods to
  // read / write to this field.
  DEF_FIELD(31, 28, clock_select_raw);

  enum class ClockSelect : uint32_t {
    kNone = 0b0000,
    kTypeCPll = 0b1000,
    kThunderbolt162MHz = 0b1100,
    kThunderbolt270MHz = 0b1101,
    kThunderbolt540MHz = 0b1110,
    kThunderbolt810MHz = 0b1111,
  };

  // Helper method to read the `clock_select_raw` field and check its validity.
  std::optional<ClockSelect> clock_select() const {
    auto raw = clock_select_raw();
    if (IsValidClockSelect(raw)) {
      return static_cast<ClockSelect>(raw);
    }
    zxlogf(WARNING, "Invalid clock_select field: 0x%x", raw);
    return std::nullopt;
  }

  // Helper method to set the `clock_select_raw` field using a strongly-typed
  // enum class.
  SelfType& set_clock_select(ClockSelect clock) {
    return set_clock_select_raw(static_cast<ValueType>(clock));
  }

  static auto GetForDdi(i915::DdiId ddi_id) {
    // Register address at
    // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev 2.0 Part 1, Page 356
    switch (ddi_id) {
      case i915::DdiId::DDI_TC_1:
        return hwreg::RegisterAddr<SelfType>(0x4610C);
      case i915::DdiId::DDI_TC_2:
        return hwreg::RegisterAddr<SelfType>(0x46110);
      case i915::DdiId::DDI_TC_3:
        return hwreg::RegisterAddr<SelfType>(0x46114);
      case i915::DdiId::DDI_TC_4:
        return hwreg::RegisterAddr<SelfType>(0x46118);
      case i915::DdiId::DDI_TC_5:
        return hwreg::RegisterAddr<SelfType>(0x4611C);
      case i915::DdiId::DDI_TC_6:
        return hwreg::RegisterAddr<SelfType>(0x46120);
      default:
        ZX_ASSERT_MSG(false, "DDI_CLK_SEL: Invalid DDI %d", ddi_id);
    }
  }

 private:
  static bool IsValidClockSelect(uint32_t clock_select_raw) {
    switch (clock_select_raw) {
      case 0b0000:
      case 0b1000:
      case 0b1100:
      case 0b1101:
      case 0b1110:
      case 0b1111:
        return true;
      default:
        return false;
    }
  }
};

// DDI_AUX_MUTEX (DDI AUX Channel Mutex)
//
// This register is not documented on Tiger Lake or DG1.
//
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 440-441
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 page 436-437
class DdiAuxMutex : public hwreg::RegisterBase<DdiAuxMutex, uint32_t> {
 public:
  // If true, the mutex is used to arbitrate AUX channel access.
  //
  // The mutex must be enabled and acquired if PSR 1/2 (Panel Self-Refresh) or
  // GTC (Global Time Code) are used. Otherwise, the mutex can remain disabled.
  DEF_BIT(31, enabled);

  // Reads acquire the mutex, writes release the mutex.
  //
  // Any read is an attempt to acquire the mutex. A successful attempt returns
  // true in this field. Once the driver acquires the mutex, it retains
  // ownership (reads continue to return true) until it explicitly releases the
  // mutex.
  //
  // This is a Write-Clear field. Writing true releases the mutex.
  //
  // The driver should release the mutex once it completes an AUX transaction,
  // so the hardware can use it as well.
  DEF_BIT(30, acquired);

  // We can get away with using DDI_AUX_CTL as the input because all DDI AUX
  // channels currently have the same MMIO layout. When this isn't the case
  // anymore, we'll replace this factory function with GetFor*Ddi() functions,
  // matching DdiAuxControl.
  static auto GetForAuxControl(const DdiAuxControl& aux_control) {
    static constexpr uint32_t kAuxControlMmioBase = 0x64010;
    static constexpr uint32_t kAuxMutexMmioBase = 0x6402c;
    return hwreg::RegisterAddr<DdiAuxData>(aux_control.reg_addr() +
                                           (kAuxMutexMmioBase - kAuxControlMmioBase));
  }
};

// DP_TP_CTL (DisplayPort Transport Control)
//
// Tiger Lake: IHD-OS-TGL-Vol2c-12.21 Part 1 pages 600-603
// DG1: IHD-OS-DG1-Vol 2c-2.21 Part 1 pages 572-575
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 517-520
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 515-518
class DpTransportControl : public hwreg::RegisterBase<DpTransportControl, uint32_t> {
 public:
  // If true, the DisplayPort transport function is enabled for the DDI.
  DEF_BIT(31, enabled);

  // If true, FEC (Forward Error Correction) coding is enabled.
  //
  // Must only be set to true after the `enabled` is set to true. Must only be
  // set to false after `enabled` is set to false.
  //
  // This field does not exist on Kaby Lake and Skylake.
  DEF_BIT(30, forward_error_correction_enabled_tiger_lake);

  // True for MST (Multi Stream) mode, false for SST (Single Stream) mode.
  //
  // Kaby Lake and Skylake DDI A (eDP) and DDI E do not support MST.
  //
  // Must match the mode in the Transcoder DDI Function Control registers. Must
  // not change while the DDI is enabled.
  DEF_BIT(27, is_multi_stream);

  // Forces MST ACT (Allocation Change Trigger) to be sent at the next link
  // frame boundary. After the ACT is sent (indicated by DP_TP_STATUS), the bit
  // can be reset and set again to force sending another ACT.
  DEF_BIT(25, force_allocation_change_trigger);

  // This field does not exist on Kaby Lake and Skylake.
  DEF_FIELD(20, 19, training_pattern4_tiger_lake);
  static constexpr int kTrainingPattern4a = 0;
  static constexpr int kTrainingPattern4b = 1;
  static constexpr int kTrainingPattern4c = 2;

  // True if enhanced framing is enabled for SST. Must be false in MST mode.
  //
  // Must not change while the DDI is enabled.
  DEF_BIT(18, sst_enhanced_framing);

  // Training pattern 1 must be selected when a port is enabled.
  //
  // To re-train a link, the port must be disabled and re-enabled (with
  // training pattern 1 selected).
  DEF_FIELD(10, 8, training_pattern);
  static constexpr int kTrainingPattern1 = 0;
  static constexpr int kTrainingPattern2 = 1;
  static constexpr int kIdlePattern = 2;
  static constexpr int kSendPixelData = 3;
  static constexpr int kTrainingPattern3 = 4;

  // Not supported on Kaby Lake and Skylake.
  static constexpr int kTrainingPattern4TigerLake = 5;

  // For eDP only. Must not change while the DDI is enabled.
  DEF_BIT(6, alternate_scrambler_reset);

  // For Kaby Lake and Skylake. The DisplayPort transport logic is in DDIs.
  static auto GetForKabyLakeDdi(i915::DdiId ddi_id) {
    ZX_ASSERT(ddi_id >= i915::DdiId::DDI_A);
    ZX_ASSERT(ddi_id <= i915::DdiId::DDI_E);

    const int ddi_index = ddi_id - i915::DdiId::DDI_A;
    return hwreg::RegisterAddr<DpTransportControl>(0x64040 + 0x100 * ddi_index);
  }

  // For Tiger Lake and DG1. The DisplayPort transport logic is in transcoders.
  static auto GetForTigerLakeTranscoder(i915::TranscoderId transcoder_id) {
    ZX_ASSERT(transcoder_id >= i915::TranscoderId::TRANSCODER_A);

    // TODO(https://fxbug.dev/42060657): Allow transcoder D, once we support it.
    ZX_ASSERT(transcoder_id <= i915::TranscoderId::TRANSCODER_C);

    const int transcoder_index = transcoder_id - i915::TranscoderId::TRANSCODER_A;
    return hwreg::RegisterAddr<DpTransportControl>(0x60540 + 0x1000 * transcoder_index);
  }
};

// An instance of DdiRegs represents the registers for a particular DDI.
class DdiRegs {
 public:
  explicit DdiRegs(i915::DdiId ddi_id) : ddi_id_(ddi_id) {}

  hwreg::RegisterAddr<DdiBufferControl> BufferControl() {
    // This works for Kaby Lake too, because the Ddi integer mapping takes
    // advantage of MMIO address space.
    return DdiBufferControl::GetForTigerLakeDdi(ddi_id_);
  }
  hwreg::RegisterAddr<DpTransportControl> DpTransportControl() {
    // This does not work for Tiger Lake.
    return DpTransportControl::GetForKabyLakeDdi(ddi_id_);
  }
  hwreg::RegisterAddr<DdiPhyConfigEntry1> PhyConfigEntry1(int entry_index) const {
    return DdiPhyConfigEntry1::GetDdiInstance(ddi_id_, entry_index);
  }
  hwreg::RegisterAddr<DdiPhyConfigEntry2> PhyConfigEntry2(int entry_index) const {
    return DdiPhyConfigEntry2::GetDdiInstance(ddi_id_, entry_index);
  }

 private:
  template <class RegType>
  hwreg::RegisterAddr<RegType> GetReg() {
    return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x100 * ddi_id_);
  }

  i915::DdiId ddi_id_;
};

}  // namespace registers

#endif  // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_DDI_H_
