// 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.

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

#include <endian.h>
#include <lib/ddk/driver.h>
#include <math.h>
#include <string.h>
#include <zircon/assert.h>

#include <algorithm>
#include <iterator>
#include <variant>

#include <fbl/string_printf.h>

#include "src/graphics/display/drivers/intel-i915/dpll.h"
#include "src/graphics/display/drivers/intel-i915/intel-i915.h"
#include "src/graphics/display/drivers/intel-i915/macros.h"
#include "src/graphics/display/drivers/intel-i915/pci-ids.h"
#include "src/graphics/display/drivers/intel-i915/registers-ddi.h"
#include "src/graphics/display/drivers/intel-i915/registers-dpll.h"
#include "src/graphics/display/drivers/intel-i915/registers-pipe.h"
#include "src/graphics/display/drivers/intel-i915/registers-transcoder.h"
#include "src/graphics/display/drivers/intel-i915/registers.h"

#define MIN(a, b) (((a) < (b)) ? (a) : (b))

namespace i915 {
namespace {

constexpr uint32_t kBitsPerPixel = 24;  // kPixelFormat

// Recommended DDI buffer translation programming values

struct ddi_buf_trans_entry {
  uint32_t high_dword;
  uint32_t low_dword;
};

const ddi_buf_trans_entry dp_ddi_buf_trans_skl_hs[9] = {
    {0x000000a0, 0x00002016}, {0x0000009b, 0x00005012}, {0x00000088, 0x00007011},
    {0x000000c0, 0x80009010}, {0x0000009b, 0x00002016}, {0x00000088, 0x00005012},
    {0x000000c0, 0x80007011}, {0x000000df, 0x00002016}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry dp_ddi_buf_trans_skl_y[9] = {
    {0x000000a2, 0x00000018}, {0x00000088, 0x00005012}, {0x000000cd, 0x80007011},
    {0x000000c0, 0x80009010}, {0x0000009d, 0x00000018}, {0x000000c0, 0x80005012},
    {0x000000c0, 0x80007011}, {0x00000088, 0x00000018}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry dp_ddi_buf_trans_skl_u[9] = {
    {0x000000a2, 0x0000201b}, {0x00000088, 0x00005012}, {0x000000cd, 0x80007011},
    {0x000000c0, 0x80009010}, {0x0000009d, 0x0000201b}, {0x000000c0, 0x80005012},
    {0x000000c0, 0x80007011}, {0x00000088, 0x00002016}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry dp_ddi_buf_trans_kbl_hs[9] = {
    {0x000000a0, 0x00002016}, {0x0000009b, 0x00005012}, {0x00000088, 0x00007011},
    {0x000000c0, 0x80009010}, {0x0000009b, 0x00002016}, {0x00000088, 0x00005012},
    {0x000000c0, 0x80007011}, {0x00000097, 0x00002016}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry dp_ddi_buf_trans_kbl_y[9] = {
    {0x000000a1, 0x00001017}, {0x00000088, 0x00005012}, {0x000000cd, 0x80007011},
    {0x000000c0, 0x8000800f}, {0x0000009d, 0x00001017}, {0x000000c0, 0x80005012},
    {0x000000c0, 0x80007011}, {0x0000004c, 0x00001017}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry dp_ddi_buf_trans_kbl_u[9] = {
    {0x000000a1, 0x0000201b}, {0x00000088, 0x00005012}, {0x000000cd, 0x80007011},
    {0x000000c0, 0x80009010}, {0x0000009d, 0x0000201b}, {0x000000c0, 0x80005012},
    {0x000000c0, 0x80007011}, {0x0000004f, 0x00002016}, {0x000000c0, 0x80005012},
};

const ddi_buf_trans_entry edp_ddi_buf_trans_skl_hs[10] = {
    {0x000000a8, 0x00000018}, {0x000000a9, 0x00004013}, {0x000000a2, 0x00007011},
    {0x0000009c, 0x00009010}, {0x000000a9, 0x00000018}, {0x000000a2, 0x00006013},
    {0x000000a6, 0x00007011}, {0x000000ab, 0x00000018}, {0x0000009f, 0x00007013},
    {0x000000df, 0x00000018},
};

const ddi_buf_trans_entry edp_ddi_buf_trans_skl_y[10] = {
    {0x000000a8, 0x00000018}, {0x000000ab, 0x00004013}, {0x000000a4, 0x00007011},
    {0x000000df, 0x00009010}, {0x000000aa, 0x00000018}, {0x000000a4, 0x00006013},
    {0x0000009d, 0x00007011}, {0x000000a0, 0x00000018}, {0x000000df, 0x00006012},
    {0x0000008a, 0x00000018},
};

const ddi_buf_trans_entry edp_ddi_buf_trans_skl_u[10] = {
    {0x000000a8, 0x00000018}, {0x000000a9, 0x00004013}, {0x000000a2, 0x00007011},
    {0x0000009c, 0x00009010}, {0x000000a9, 0x00000018}, {0x000000a2, 0x00006013},
    {0x000000a6, 0x00007011}, {0x000000ab, 0x00002016}, {0x0000009f, 0x00005013},
    {0x000000df, 0x00000018},
};

void GetDpDdiBufTransEntries(uint16_t device_id, const ddi_buf_trans_entry** entries,
                             uint8_t* i_boost, unsigned* count) {
  if (is_skl(device_id)) {
    if (is_skl_u(device_id)) {
      *entries = dp_ddi_buf_trans_skl_u;
      *i_boost = 0x1;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_skl_u));
    } else if (is_skl_y(device_id)) {
      *entries = dp_ddi_buf_trans_skl_y;
      *i_boost = 0x3;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_skl_y));
    } else {
      *entries = dp_ddi_buf_trans_skl_hs;
      *i_boost = 0x1;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_skl_hs));
    }
  } else if (is_kbl(device_id)) {
    if (is_kbl_u(device_id)) {
      *entries = dp_ddi_buf_trans_kbl_u;
      *i_boost = 0x1;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_kbl_u));
    } else if (is_kbl_y(device_id)) {
      *entries = dp_ddi_buf_trans_kbl_y;
      *i_boost = 0x3;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_kbl_y));
    } else {
      *entries = dp_ddi_buf_trans_kbl_hs;
      *i_boost = 0x3;
      *count = static_cast<unsigned>(std::size(dp_ddi_buf_trans_kbl_hs));
    }
  } else {
    zxlogf(ERROR, "Unrecognized i915 device id: %#.4x", device_id);
    *count = 0;
    *i_boost = 0;
  }
}

void GetEdpDdiBufTransEntries(uint16_t device_id, const ddi_buf_trans_entry** entries,
                              unsigned* count) {
  if (is_skl_u(device_id) || is_kbl_u(device_id)) {
    *entries = edp_ddi_buf_trans_skl_u;
    *count = static_cast<int>(std::size(edp_ddi_buf_trans_skl_u));
  } else if (is_skl_y(device_id) || is_kbl_y(device_id)) {
    *entries = edp_ddi_buf_trans_skl_y;
    *count = static_cast<int>(std::size(edp_ddi_buf_trans_skl_y));
  } else {
    *entries = edp_ddi_buf_trans_skl_hs;
    *count = static_cast<int>(std::size(edp_ddi_buf_trans_skl_hs));
  }
}

// Aux port functions

// 4-bit request type in Aux channel request messages.
enum {
  DP_REQUEST_I2C_WRITE = 0,
  DP_REQUEST_I2C_READ = 1,
  DP_REQUEST_NATIVE_WRITE = 8,
  DP_REQUEST_NATIVE_READ = 9,
};

// 4-bit statuses in Aux channel reply messages.
enum {
  DP_REPLY_AUX_ACK = 0,
  DP_REPLY_AUX_NACK = 1,
  DP_REPLY_AUX_DEFER = 2,
  DP_REPLY_I2C_NACK = 4,
  DP_REPLY_I2C_DEFER = 8,
};

std::string DpcdRevisionToString(dpcd::Revision rev) {
  switch (rev) {
    case dpcd::Revision::k1_0:
      return "DPCD r1.0";
    case dpcd::Revision::k1_1:
      return "DPCD r1.1";
    case dpcd::Revision::k1_2:
      return "DPCD r1.2";
    case dpcd::Revision::k1_3:
      return "DPCD r1.3";
    case dpcd::Revision::k1_4:
      return "DPCD r1.4";
  }
  return "unknown";
}

std::string EdpDpcdRevisionToString(dpcd::EdpRevision rev) {
  switch (rev) {
    case dpcd::EdpRevision::k1_1:
      return "eDP v1.1 or lower";
    case dpcd::EdpRevision::k1_2:
      return "eDP v1.2";
    case dpcd::EdpRevision::k1_3:
      return "eDP v1.3";
    case dpcd::EdpRevision::k1_4:
      return "eDP v1.4";
    case dpcd::EdpRevision::k1_4a:
      return "eDP v1.4a";
    case dpcd::EdpRevision::k1_4b:
      return "eDP v1.4b";
  }
  return "unknown";
}

}  // namespace

// This represents a message sent over DisplayPort's Aux channel, including
// reply messages.
class DpAuxMessage {
 public:
  // Sizes in bytes.  DisplayPort Aux messages are quite small.
  static constexpr uint32_t kMaxTotalSize = 20;
  static constexpr uint32_t kMaxBodySize = 16;

  uint8_t data[kMaxTotalSize];
  uint32_t size;

  // Fill out the header of a DisplayPort Aux message.  For write operations,
  // |body_size| is the size of the body of the message to send.  For read
  // operations, |body_size| is the size of our receive buffer.
  bool SetDpAuxHeader(uint32_t addr, uint32_t dp_cmd, uint32_t body_size) {
    if (body_size > DpAuxMessage::kMaxBodySize) {
      zxlogf(WARNING, "DP aux: Message too large");
      return false;
    }
    // Addresses should fit into 20 bits.
    if (addr >= (1 << 20)) {
      zxlogf(WARNING, "DP aux: Address is too large: 0x%x", addr);
      return false;
    }
    // For now, we don't handle messages with empty bodies.  (However, they
    // can be used for checking whether there is an I2C device at a given
    // address.)
    if (body_size == 0) {
      zxlogf(WARNING, "DP aux: Empty message not supported");
      return false;
    }
    data[0] = static_cast<uint8_t>((dp_cmd << 4) | ((addr >> 16) & 0xf));
    data[1] = static_cast<uint8_t>(addr >> 8);
    data[2] = static_cast<uint8_t>(addr);
    // For writes, the size of the message will be encoded twice:
    //  * The msg->size field contains the total message size (header and
    //    body).
    //  * If the body of the message is non-empty, the header contains an
    //    extra field specifying the body size (in bytes minus 1).
    // For reads, the message to send is a header only.
    size = 4;
    data[3] = static_cast<uint8_t>(body_size - 1);
    return true;
  }
};

zx_status_t DpAux::SendDpAuxMsg(const DpAuxMessage& request, DpAuxMessage* reply) {
  registers::DdiRegs ddi_regs(ddi_);
  uint32_t data_reg = ddi_regs.DdiAuxData().addr();

  // Write the outgoing message to the hardware.
  for (uint32_t offset = 0; offset < request.size; offset += 4) {
    // For some reason intel made these data registers big endian...
    const uint32_t* data = reinterpret_cast<const uint32_t*>(request.data + offset);
    mmio_space_->Write<uint32_t>(htobe32(*data), data_reg + offset);
  }

  auto status = ddi_regs.DdiAuxControl().ReadFrom(mmio_space_);
  status.set_message_size(request.size);
  // Reset R/W Clear bits
  status.set_done(1);
  status.set_timeout(1);
  status.set_rcv_error(1);
  // The documentation says to not use setting 0 (400us), so use 3 (1600us).
  status.set_timeout_timer_value(3);
  // TODO(fxbug.dev/31313): Support interrupts
  status.set_interrupt_on_done(1);
  // Send busy starts the transaction
  status.set_send_busy(1);
  status.WriteTo(mmio_space_);

  // Poll for the reply message.
  const int kNumTries = 10000;
  for (int tries = 0; tries < kNumTries; ++tries) {
    auto status = ddi_regs.DdiAuxControl().ReadFrom(mmio_space_);
    if (!status.send_busy()) {
      if (status.timeout()) {
        return ZX_ERR_TIMED_OUT;
      }
      if (status.rcv_error()) {
        zxlogf(DEBUG, "DP aux: rcv error");
        return ZX_ERR_IO;
      }
      if (!status.done()) {
        continue;
      }

      reply->size = status.message_size();
      if (!reply->size || reply->size > DpAuxMessage::kMaxTotalSize) {
        zxlogf(TRACE, "DP aux: Invalid reply size %d", reply->size);
        return ZX_ERR_IO;
      }
      // Read the reply message from the hardware.
      for (uint32_t offset = 0; offset < reply->size; offset += 4) {
        // For some reason intel made these data registers big endian...
        *reinterpret_cast<uint32_t*>(reply->data + offset) =
            be32toh(mmio_space_->Read32(data_reg + offset));
      }
      return ZX_OK;
    }
    zx_nanosleep(zx_deadline_after(ZX_USEC(1)));
  }
  zxlogf(TRACE, "DP aux: No reply after %d tries", kNumTries);
  return ZX_ERR_TIMED_OUT;
}

zx_status_t DpAux::SendDpAuxMsgWithRetry(const DpAuxMessage& request, DpAuxMessage* reply) {
  // If the DisplayPort sink device isn't ready to handle an Aux message,
  // it can return an AUX_DEFER reply, which means we should retry the
  // request. The spec added a requirement for >=7 defer retries in v1.3,
  // but there are no requirements before that nor is there a max value. 16
  // retries is pretty arbitrary and might need to be increased for slower
  // displays.
  const int kMaxDefers = 16;

  // Per table 2-43 in v1.1a, we need to retry >3 times, since some
  // DisplayPort sink devices time out on the first DP aux request
  // but succeed on later requests.
  const int kMaxTimeouts = 5;

  unsigned defers_seen = 0;
  unsigned timeouts_seen = 0;

  for (;;) {
    zx_status_t res = SendDpAuxMsg(request, reply);
    if (res != ZX_OK) {
      if (res == ZX_ERR_TIMED_OUT) {
        if (++timeouts_seen == kMaxTimeouts) {
          zxlogf(DEBUG, "DP aux: Got too many timeouts (%d)", kMaxTimeouts);
          return ZX_ERR_TIMED_OUT;
        }
        // Retry on timeout.
        continue;
      }
      // We do not retry if sending the raw message failed for
      // an unexpected reason.
      return ZX_ERR_IO;
    }

    uint8_t header_byte = reply->data[0];
    uint8_t padding = header_byte & 0xf;
    uint8_t status = static_cast<uint8_t>(header_byte >> 4);
    // Sanity check: The padding should be zero.  If it's not, we
    // shouldn't return an error, in case this space gets used for some
    // later extension to the protocol.  But report it, in case this
    // indicates some problem.
    if (padding) {
      zxlogf(INFO, "DP aux: Reply header padding is non-zero (header byte: 0x%x)", header_byte);
    }

    switch (status) {
      case DP_REPLY_AUX_ACK:
        // The AUX_ACK implies that we got an I2C ACK too.
        return ZX_OK;
      case DP_REPLY_AUX_DEFER:
        if (++defers_seen == kMaxDefers) {
          zxlogf(TRACE, "DP aux: Received too many AUX DEFERs (%d)", kMaxDefers);
          return ZX_ERR_TIMED_OUT;
        }
        // Go around the loop again to retry.
        continue;
      case DP_REPLY_AUX_NACK:
        zxlogf(TRACE, "DP aux: Reply was not an ack (got AUX_NACK)");
        return ZX_ERR_IO_REFUSED;
      case DP_REPLY_I2C_NACK:
        zxlogf(TRACE, "DP aux: Reply was not an ack (got I2C_NACK)");
        return ZX_ERR_IO_REFUSED;
      case DP_REPLY_I2C_DEFER:
        // TODO(fxbug.dev/31313): Implement handling of I2C_DEFER.
        zxlogf(TRACE, "DP aux: Received I2C_DEFER (not implemented)");
        return ZX_ERR_NEXT;
      default:
        // We got a reply that is not defined by the DisplayPort spec.
        zxlogf(TRACE, "DP aux: Unrecognized reply (header byte: 0x%x)", header_byte);
        return ZX_ERR_IO;
    }
  }
}

zx_status_t DpAux::DpAuxRead(uint32_t dp_cmd, uint32_t addr, uint8_t* buf, size_t size) {
  while (size > 0) {
    uint32_t chunk_size = static_cast<uint32_t>(MIN(size, DpAuxMessage::kMaxBodySize));
    size_t bytes_read = 0;
    zx_status_t status = DpAuxReadChunk(dp_cmd, addr, buf, chunk_size, &bytes_read);
    if (status != ZX_OK) {
      return status;
    }
    if (bytes_read == 0) {
      // We failed to make progress on the last call.  To avoid the
      // risk of getting an infinite loop from that happening
      // continually, we return.
      return ZX_ERR_IO;
    }
    buf += bytes_read;
    size -= bytes_read;
  }
  return ZX_OK;
}

zx_status_t DpAux::DpAuxReadChunk(uint32_t dp_cmd, uint32_t addr, uint8_t* buf, uint32_t size_in,
                                  size_t* size_out) {
  DpAuxMessage msg;
  DpAuxMessage reply;
  if (!msg.SetDpAuxHeader(addr, dp_cmd, size_in)) {
    return ZX_ERR_INVALID_ARGS;
  }
  zx_status_t status = SendDpAuxMsgWithRetry(msg, &reply);
  if (status != ZX_OK) {
    return status;
  }
  size_t bytes_read = reply.size - 1;
  if (bytes_read > size_in) {
    zxlogf(WARNING, "DP aux read: Reply was larger than requested");
    return ZX_ERR_IO;
  }
  memcpy(buf, &reply.data[1], bytes_read);
  *size_out = bytes_read;
  return ZX_OK;
}

zx_status_t DpAux::DpAuxWrite(uint32_t dp_cmd, uint32_t addr, const uint8_t* buf, size_t size) {
  // Implement this if it's ever needed
  ZX_ASSERT_MSG(size <= 16, "message too large");

  DpAuxMessage msg;
  DpAuxMessage reply;
  if (!msg.SetDpAuxHeader(addr, dp_cmd, static_cast<uint32_t>(size))) {
    return ZX_ERR_INVALID_ARGS;
  }
  memcpy(&msg.data[4], buf, size);
  msg.size = static_cast<uint32_t>(size + 4);
  zx_status_t status = SendDpAuxMsgWithRetry(msg, &reply);
  if (status != ZX_OK) {
    return status;
  }
  // TODO(fxbug.dev/31313): Handle the case where the hardware did a short write,
  // for which we could send the remaining bytes.
  if (reply.size != 1) {
    zxlogf(WARNING, "DP aux write: Unexpected reply size");
    return ZX_ERR_IO;
  }
  return ZX_OK;
}

zx_status_t DpAux::I2cTransact(const i2c_impl_op_t* ops, size_t count) {
  fbl::AutoLock lock(&lock_);
  for (unsigned i = 0; i < count; i++) {
    uint8_t* buf = static_cast<uint8_t*>(ops[i].data_buffer);
    uint8_t len = static_cast<uint8_t>(ops[i].data_size);
    zx_status_t status = ops[i].is_read
                             ? DpAuxRead(DP_REQUEST_I2C_READ, ops[i].address, buf, len)
                             : DpAuxWrite(DP_REQUEST_I2C_WRITE, ops[i].address, buf, len);
    if (status != ZX_OK) {
      return status;
    }
  }
  return ZX_OK;
}

bool DpAux::DpcdRead(uint32_t addr, uint8_t* buf, size_t size) {
  fbl::AutoLock lock(&lock_);
  constexpr uint32_t kReadAttempts = 3;
  for (unsigned i = 0; i < kReadAttempts; i++) {
    if (DpAuxRead(DP_REQUEST_NATIVE_READ, addr, buf, size) == ZX_OK) {
      return true;
    }
    zx_nanosleep(zx_deadline_after(ZX_MSEC(5)));
  }
  return false;
}

bool DpAux::DpcdWrite(uint32_t addr, const uint8_t* buf, size_t size) {
  fbl::AutoLock lock(&lock_);
  return DpAuxWrite(DP_REQUEST_NATIVE_WRITE, addr, buf, size) == ZX_OK;
}

DpAux::DpAux(registers::Ddi ddi, fdf::MmioBuffer* mmio_space) : ddi_(ddi), mmio_space_(mmio_space) {
  ZX_ASSERT(mtx_init(&lock_, mtx_plain) == thrd_success);
}

DpCapabilities::DpCapabilities() { dpcd_.fill(0); }

DpCapabilities::Edp::Edp() { bytes.fill(0); }

DpCapabilities::DpCapabilities(inspect::Node* parent_node) {
  dpcd_.fill(0);
  node_ = parent_node->CreateChild("dpcd-capabilities");
}

// static
fpromise::result<DpCapabilities> DpCapabilities::Read(DpcdChannel* dp_aux,
                                                      inspect::Node* parent_node) {
  DpCapabilities caps(parent_node);

  if (!dp_aux->DpcdRead(dpcd::DPCD_CAP_START, caps.dpcd_.data(), caps.dpcd_.size())) {
    zxlogf(TRACE, "Failed to read dpcd capabilities");
    return fpromise::error();
  }

  auto dsp_present =
      caps.dpcd_reg<dpcd::DownStreamPortPresent, dpcd::DPCD_DOWN_STREAM_PORT_PRESENT>();
  if (dsp_present.is_branch()) {
    auto dsp_count = caps.dpcd_reg<dpcd::DownStreamPortCount, dpcd::DPCD_DOWN_STREAM_PORT_COUNT>();
    zxlogf(DEBUG, "Found branch with %d ports", dsp_count.count());
  }

  if (!dp_aux->DpcdRead(dpcd::DPCD_SINK_COUNT, caps.sink_count_.reg_value_ptr(), 1)) {
    zxlogf(ERROR, "Failed to read DisplayPort sink count");
    return fpromise::error();
  }

  caps.max_lane_count_ = caps.dpcd_reg<dpcd::LaneCount, dpcd::DPCD_MAX_LANE_COUNT>();
  if (caps.max_lane_count() != 1 && caps.max_lane_count() != 2 && caps.max_lane_count() != 4) {
    zxlogf(ERROR, "Unsupported DisplayPort lane count: %u", caps.max_lane_count());
    return fpromise::error();
  }

  if (!caps.ProcessEdp(dp_aux)) {
    return fpromise::error();
  }

  if (!caps.ProcessSupportedLinkRates(dp_aux)) {
    return fpromise::error();
  }

  ZX_ASSERT(!caps.supported_link_rates_mbps_.empty());
  caps.PublishInspect();

  return fpromise::ok(std::move(caps));
}

bool DpCapabilities::ProcessEdp(DpcdChannel* dp_aux) {
  // Check if the Display Control registers reserved for eDP are available.
  auto edp_config = dpcd_reg<dpcd::EdpConfigCap, dpcd::DPCD_EDP_CONFIG>();
  if (!edp_config.dpcd_display_ctrl_capable()) {
    return true;
  }

  zxlogf(TRACE, "eDP registers are available");

  edp_dpcd_.emplace();
  if (!dp_aux->DpcdRead(dpcd::DPCD_EDP_CAP_START, edp_dpcd_->bytes.data(),
                        edp_dpcd_->bytes.size())) {
    zxlogf(ERROR, "Failed to read eDP capabilities");
    return false;
  }

  edp_dpcd_->revision = dpcd::EdpRevision(edp_dpcd_at(dpcd::DPCD_EDP_REV));

  auto general_cap1 = edp_dpcd_reg<dpcd::EdpGeneralCap1, dpcd::DPCD_EDP_GENERAL_CAP1>();
  auto backlight_cap = edp_dpcd_reg<dpcd::EdpBacklightCap, dpcd::DPCD_EDP_BACKLIGHT_CAP>();

  edp_dpcd_->backlight_aux_power =
      general_cap1.tcon_backlight_adjustment_cap() && general_cap1.backlight_aux_enable_cap();
  edp_dpcd_->backlight_aux_brightness =
      general_cap1.tcon_backlight_adjustment_cap() && backlight_cap.brightness_aux_set_cap();

  return true;
}

bool DpCapabilities::ProcessSupportedLinkRates(DpcdChannel* dp_aux) {
  ZX_ASSERT(supported_link_rates_mbps_.empty());

  // According to eDP v1.4b, Table 4-24, a device supporting eDP version v1.4 and higher can support
  // link rate selection by way of both the DPCD MAX_LINK_RATE register and the "Link Rate Table"
  // method via DPCD SUPPORTED_LINK_RATES registers.
  //
  // The latter method can represent more values than the former (which is limited to only 4
  // discrete values). Hence we attempt to use the "Link Rate Table" method first.
  use_link_rate_table_ = false;
  if (edp_dpcd_ && edp_dpcd_->revision >= dpcd::EdpRevision::k1_4) {
    constexpr size_t kBufferSize =
        dpcd::DPCD_SUPPORTED_LINK_RATE_END - dpcd::DPCD_SUPPORTED_LINK_RATE_START + 1;
    std::array<uint8_t, kBufferSize> link_rates;
    if (dp_aux->DpcdRead(dpcd::DPCD_SUPPORTED_LINK_RATE_START, link_rates.data(), kBufferSize)) {
      for (size_t i = 0; i < link_rates.size(); i += 2) {
        uint16_t value = link_rates[i] | (static_cast<uint16_t>(link_rates[i + 1]) << 8);

        // From the eDP specification: "A table entry containing the value 0 indicates that the
        // entry and all entries at higher DPCD addressess contain invalid link rates."
        if (value == 0) {
          break;
        }

        // Each valid entry indicates a nominal per-lane link rate equal to `value * 200kHz`. We
        // convert value to MHz: `value * 200 / 1000 ==> value / 5`.
        supported_link_rates_mbps_.push_back(value / 5);
      }
    }

    use_link_rate_table_ = !supported_link_rates_mbps_.empty();
  }

  // Fall back to the MAX_LINK_RATE register if the Link Rate Table method is not supported.
  if (supported_link_rates_mbps_.empty()) {
    uint32_t max_link_rate = dpcd_reg<dpcd::LinkBw, dpcd::DPCD_MAX_LINK_RATE>().link_bw();

    // All link rates including and below the maximum are supported.
    switch (max_link_rate) {
      case dpcd::LinkBw::k8100Mbps:
        supported_link_rates_mbps_.push_back(8100);
        __FALLTHROUGH;
      case dpcd::LinkBw::k5400Mbps:
        supported_link_rates_mbps_.push_back(5400);
        __FALLTHROUGH;
      case dpcd::LinkBw::k2700Mbps:
        supported_link_rates_mbps_.push_back(2700);
        __FALLTHROUGH;
      case dpcd::LinkBw::k1620Mbps:
        supported_link_rates_mbps_.push_back(1620);
        break;
      case 0:
        zxlogf(ERROR, "Device did not report supported link rates");
        return false;
      default:
        zxlogf(ERROR, "Unsupported max link rate: %u", max_link_rate);
        return false;
    }

    // Make sure the values are in ascending order.
    std::reverse(supported_link_rates_mbps_.begin(), supported_link_rates_mbps_.end());
  }

  return true;
}

void DpCapabilities::PublishInspect() {
  node_.RecordString("dpcd_revision", DpcdRevisionToString(dpcd_revision()));
  node_.RecordUint("sink_count", sink_count());
  node_.RecordUint("max_lane_count", max_lane_count());

  {
    auto node = node_.CreateUintArray("supported_link_rates_mbps_per_lane",
                                      supported_link_rates_mbps_.size());
    for (size_t i = 0; i < supported_link_rates_mbps_.size(); ++i) {
      node.Add(i, supported_link_rates_mbps_[i]);
    }
    node_.Record(std::move(node));
  }

  {
    std::string value =
        edp_dpcd_.has_value() ? EdpDpcdRevisionToString(edp_dpcd_->revision) : "not supported";
    node_.RecordString("edp_revision", std::move(value));
  }
}

bool DpDisplay::DpcdWrite(uint32_t addr, const uint8_t* buf, size_t size) {
  return dp_aux_->DpcdWrite(addr, buf, size);
}

bool DpDisplay::DpcdRead(uint32_t addr, uint8_t* buf, size_t size) {
  return dp_aux_->DpcdRead(addr, buf, size);
}

// Link training functions

// Tell the sink device to start link training.
bool DpDisplay::DpcdRequestLinkTraining(const dpcd::TrainingPatternSet& tp_set,
                                        const dpcd::TrainingLaneSet lane[]) {
  // The DisplayPort spec says that we are supposed to write these
  // registers with a single operation: "The AUX CH burst write must be
  // used for writing to TRAINING_LANEx_SET bytes of the enabled lanes."
  // (From section 3.5.1.3, "Link Training", in v1.1a.)
  uint8_t reg_bytes[1 + dp_lane_count_];
  reg_bytes[0] = static_cast<uint8_t>(tp_set.reg_value());
  for (unsigned i = 0; i < dp_lane_count_; i++) {
    reg_bytes[i + 1] = static_cast<uint8_t>(lane[i].reg_value());
  }
  constexpr int kAddr = dpcd::DPCD_TRAINING_PATTERN_SET;
  static_assert(kAddr + 1 == dpcd::DPCD_TRAINING_LANE0_SET, "");
  static_assert(kAddr + 2 == dpcd::DPCD_TRAINING_LANE1_SET, "");
  static_assert(kAddr + 3 == dpcd::DPCD_TRAINING_LANE2_SET, "");
  static_assert(kAddr + 4 == dpcd::DPCD_TRAINING_LANE3_SET, "");

  if (!DpcdWrite(kAddr, reg_bytes, 1 + dp_lane_count_)) {
    zxlogf(ERROR, "Failure setting TRAINING_PATTERN_SET");
    return false;
  }

  return true;
}

template <uint32_t addr, typename T>
bool DpDisplay::DpcdReadPairedRegs(hwreg::RegisterBase<T, typename T::ValueType>* regs) {
  static_assert(addr == dpcd::DPCD_LANE0_1_STATUS || addr == dpcd::DPCD_ADJUST_REQUEST_LANE0_1,
                "Bad register address");
  uint32_t num_bytes = dp_lane_count_ == 4 ? 2 : 1;
  uint8_t reg_byte[num_bytes];
  if (!DpcdRead(addr, reg_byte, num_bytes)) {
    zxlogf(ERROR, "Failure reading addr %d", addr);
    return false;
  }

  for (unsigned i = 0; i < dp_lane_count_; i++) {
    regs[i].set_reg_value(reg_byte[i / 2]);
  }

  return true;
}

bool DpDisplay::DpcdHandleAdjustRequest(dpcd::TrainingLaneSet* training,
                                        dpcd::AdjustRequestLane* adjust) {
  bool voltage_change = false;
  uint8_t v = 0;
  uint8_t pe = 0;
  for (unsigned i = 0; i < dp_lane_count_; i++) {
    if (adjust[i].voltage_swing(i).get() > v) {
      v = static_cast<uint8_t>(adjust[i].voltage_swing(i).get());
    }
    if (adjust[i].pre_emphasis(i).get() > pe) {
      pe = static_cast<uint8_t>(adjust[i].pre_emphasis(i).get());
    }
  }

  // In the Recommended buffer translation programming for DisplayPort from the intel display
  // doc, the max voltage swing is 2/3 for DP/eDP and the max (voltage swing + pre-emphasis) is
  // 3. According to the v1.1a of the DP docs, if v + pe is too large then v should be reduced
  // to the highest supported value for the pe level (section 3.5.1.3)
  static constexpr uint32_t kMaxVPlusPe = 3;
  uint8_t max_v = controller()->igd_opregion().IsLowVoltageEdp(ddi()) ? 3 : 2;
  if (v + pe > kMaxVPlusPe) {
    v = static_cast<uint8_t>(kMaxVPlusPe - pe);
  }
  if (v > max_v) {
    v = max_v;
  }

  for (unsigned i = 0; i < dp_lane_count_; i++) {
    voltage_change |= (training[i].voltage_swing_set() != v);
    training[i].set_voltage_swing_set(v);
    training[i].set_max_swing_reached(v == max_v);
    training[i].set_pre_emphasis_set(pe);
    training[i].set_max_pre_emphasis_set(pe + v == kMaxVPlusPe);
  }

  // Compute the index into the programmed table
  int level;
  if (v == 0) {
    level = pe;
  } else if (v == 1) {
    level = 4 + pe;
  } else if (v == 2) {
    level = 7 + pe;
  } else {
    level = 9;
  }

  registers::DdiRegs ddi_regs(ddi());
  auto buf_ctl = ddi_regs.DdiBufControl().ReadFrom(mmio_space());
  buf_ctl.set_dp_vswing_emp_sel(level);
  buf_ctl.WriteTo(mmio_space());

  return voltage_change;
}

bool DpDisplay::LinkTrainingSetup() {
  ZX_ASSERT(capabilities_);

  registers::DdiRegs ddi_regs(ddi());

  // Tell the source device to emit the training pattern.
  auto dp_tp = ddi_regs.DdiDpTransportControl().ReadFrom(mmio_space());
  dp_tp.set_transport_enable(1);
  dp_tp.set_transport_mode_select(0);
  dp_tp.set_enhanced_framing_enable(capabilities_->enhanced_frame_capability());
  dp_tp.set_dp_link_training_pattern(dp_tp.kTrainingPattern1);
  dp_tp.WriteTo(mmio_space());

  // Configure ddi voltage swing
  // TODO(fxbug.dev/31313): Read the VBT to handle unique motherboard configs for kaby lake
  unsigned count;
  uint8_t i_boost;
  const ddi_buf_trans_entry* entries;
  if (controller()->igd_opregion().IsLowVoltageEdp(ddi())) {
    i_boost = 0;
    GetEdpDdiBufTransEntries(controller()->device_id(), &entries, &count);
  } else {
    GetDpDdiBufTransEntries(controller()->device_id(), &entries, &i_boost, &count);
  }
  uint8_t i_boost_override = controller()->igd_opregion().GetIBoost(ddi(), true /* is_dp */);

  for (unsigned i = 0; i < count; i++) {
    auto ddi_buf_trans_high = ddi_regs.DdiBufTransHi(i).ReadFrom(mmio_space());
    auto ddi_buf_trans_low = ddi_regs.DdiBufTransLo(i).ReadFrom(mmio_space());
    ddi_buf_trans_high.set_reg_value(entries[i].high_dword);
    ddi_buf_trans_low.set_reg_value(entries[i].low_dword);
    if (i_boost_override) {
      ddi_buf_trans_low.set_balance_leg_enable(1);
    }
    ddi_buf_trans_high.WriteTo(mmio_space());
    ddi_buf_trans_low.WriteTo(mmio_space());
  }

  const uint8_t i_boost_val = i_boost_override ? i_boost_override : i_boost;
  auto disio_cr_tx_bmu = registers::DisplayIoCtrlRegTxBmu::Get().ReadFrom(mmio_space());
  disio_cr_tx_bmu.set_disable_balance_leg(!i_boost && !i_boost_override);
  disio_cr_tx_bmu.tx_balance_leg_select(ddi()).set(i_boost_val);
  if (ddi() == registers::DDI_A && dp_lane_count_ == 4) {
    disio_cr_tx_bmu.tx_balance_leg_select(registers::DDI_E).set(i_boost_val);
  }
  disio_cr_tx_bmu.WriteTo(mmio_space());

  // Enable and wait for DDI_BUF_CTL
  auto buf_ctl = ddi_regs.DdiBufControl().ReadFrom(mmio_space());
  buf_ctl.set_ddi_buffer_enable(1);
  buf_ctl.set_dp_vswing_emp_sel(0);
  buf_ctl.set_dp_port_width_selection(dp_lane_count_ - 1);
  buf_ctl.WriteTo(mmio_space());
  zx_nanosleep(zx_deadline_after(ZX_USEC(518)));

  uint16_t link_rate_reg;
  uint8_t link_rate_val;
  if (dp_link_rate_table_idx_) {
    dpcd::LinkRateSet link_rate_set;
    link_rate_set.set_link_rate_idx(static_cast<uint8_t>(dp_link_rate_table_idx_.value()));
    link_rate_reg = dpcd::DPCD_LINK_RATE_SET;
    link_rate_val = link_rate_set.reg_value();
  } else {
    uint8_t target_bw;
    if (dp_link_rate_mhz_ == 1620) {
      target_bw = dpcd::LinkBw::k1620Mbps;
    } else if (dp_link_rate_mhz_ == 2700) {
      target_bw = dpcd::LinkBw::k2700Mbps;
    } else {
      ZX_ASSERT(dp_link_rate_mhz_ == 5400);
      target_bw = dpcd::LinkBw::k5400Mbps;
    }

    dpcd::LinkBw bw_setting;
    bw_setting.set_link_bw(target_bw);
    link_rate_reg = dpcd::DPCD_LINK_BW_SET;
    link_rate_val = bw_setting.reg_value();
  }

  // Configure the bandwidth and lane count settings
  dpcd::LaneCount lc_setting;
  lc_setting.set_lane_count_set(dp_lane_count_);
  lc_setting.set_enhanced_frame_enabled(capabilities_->enhanced_frame_capability());
  if (!DpcdWrite(link_rate_reg, &link_rate_val, 1) ||
      !DpcdWrite(dpcd::DPCD_COUNT_SET, lc_setting.reg_value_ptr(), 1)) {
    zxlogf(ERROR, "DP: Link training: failed to configure settings");
    return false;
  }

  return true;
}

// Number of times to poll with the same voltage level configured, as
// specified by the DisplayPort spec.
static const int kPollsPerVoltageLevel = 5;

bool DpDisplay::LinkTrainingStage1(dpcd::TrainingPatternSet* tp_set, dpcd::TrainingLaneSet* lanes) {
  ZX_ASSERT(capabilities_);

  // Tell the sink device to look for the training pattern.
  tp_set->set_training_pattern_set(tp_set->kTrainingPattern1);
  tp_set->set_scrambling_disable(1);

  dpcd::AdjustRequestLane adjust_req[dp_lane_count_];
  dpcd::LaneStatus lane_status[dp_lane_count_];

  int poll_count = 0;
  auto delay =
      capabilities_->dpcd_reg<dpcd::TrainingAuxRdInterval, dpcd::DPCD_TRAINING_AUX_RD_INTERVAL>();
  for (;;) {
    if (!DpcdRequestLinkTraining(*tp_set, lanes)) {
      return false;
    }

    zx_nanosleep(
        zx_deadline_after(ZX_USEC(delay.clock_recovery_delay_us(capabilities_->dpcd_revision()))));

    // Did the sink device receive the signal successfully?
    if (!DpcdReadPairedRegs<dpcd::DPCD_LANE0_1_STATUS, dpcd::LaneStatus>(lane_status)) {
      return false;
    }
    bool done = true;
    for (unsigned i = 0; i < dp_lane_count_; i++) {
      done &= lane_status[i].lane_cr_done(i).get();
    }
    if (done) {
      break;
    }

    for (unsigned i = 0; i < dp_lane_count_; i++) {
      if (lanes[i].max_swing_reached()) {
        zxlogf(ERROR, "DP: Link training: max voltage swing reached");
        return false;
      }
    }

    if (!DpcdReadPairedRegs<dpcd::DPCD_ADJUST_REQUEST_LANE0_1, dpcd::AdjustRequestLane>(
            adjust_req)) {
      return false;
    }

    if (DpcdHandleAdjustRequest(lanes, adjust_req)) {
      poll_count = 0;
    } else if (++poll_count == kPollsPerVoltageLevel) {
      zxlogf(ERROR, "DP: Link training: clock recovery step failed");
      return false;
    }
  }

  return true;
}

bool DpDisplay::LinkTrainingStage2(dpcd::TrainingPatternSet* tp_set, dpcd::TrainingLaneSet* lanes) {
  ZX_ASSERT(capabilities_);

  registers::DdiRegs ddi_regs(ddi());
  auto dp_tp = ddi_regs.DdiDpTransportControl().ReadFrom(mmio_space());

  dpcd::AdjustRequestLane adjust_req[dp_lane_count_];
  dpcd::LaneStatus lane_status[dp_lane_count_];

  dp_tp.set_dp_link_training_pattern(dp_tp.kTrainingPattern2);
  dp_tp.WriteTo(mmio_space());

  tp_set->set_training_pattern_set(tp_set->kTrainingPattern2);
  int poll_count = 0;
  auto delay =
      capabilities_->dpcd_reg<dpcd::TrainingAuxRdInterval, dpcd::DPCD_TRAINING_AUX_RD_INTERVAL>();
  for (;;) {
    // lane0_training and lane1_training can change in the loop
    if (!DpcdRequestLinkTraining(*tp_set, lanes)) {
      return false;
    }

    zx_nanosleep(zx_deadline_after(ZX_USEC(delay.channel_eq_delay_us())));

    // Did the sink device receive the signal successfully?
    if (!DpcdReadPairedRegs<dpcd::DPCD_LANE0_1_STATUS, dpcd::LaneStatus>(lane_status)) {
      return false;
    }
    for (unsigned i = 0; i < dp_lane_count_; i++) {
      if (!lane_status[i].lane_cr_done(i).get()) {
        zxlogf(ERROR, "DP: Link training: clock recovery regressed");
        return false;
      }
    }

    bool symbol_lock_done = true;
    bool channel_eq_done = true;
    for (unsigned i = 0; i < dp_lane_count_; i++) {
      symbol_lock_done &= lane_status[i].lane_symbol_locked(i).get();
      channel_eq_done &= lane_status[i].lane_channel_eq_done(i).get();
    }
    if (symbol_lock_done && channel_eq_done) {
      break;
    }

    // The training attempt has not succeeded yet.
    if (++poll_count == kPollsPerVoltageLevel) {
      if (symbol_lock_done) {
        zxlogf(ERROR, "DP: Link training: symbol lock failed");
        return false;
      } else {
        zxlogf(ERROR, "DP: Link training: channel equalization failed");
        return false;
      }
    }

    if (!DpcdReadPairedRegs<dpcd::DPCD_ADJUST_REQUEST_LANE0_1, dpcd::AdjustRequestLane>(
            adjust_req)) {
      return false;
    }
    DpcdHandleAdjustRequest(lanes, adjust_req);
  }

  dp_tp.set_dp_link_training_pattern(dp_tp.kSendPixelData);
  dp_tp.WriteTo(mmio_space());

  return true;
}

bool DpDisplay::DoLinkTraining() {
  // TODO(fxbug.dev/31313): If either of the two training steps fails, we're
  // supposed to try with a reduced bit rate.
  bool result = LinkTrainingSetup();
  if (result) {
    dpcd::TrainingPatternSet tp_set;
    dpcd::TrainingLaneSet lanes[dp_lane_count_];
    result = LinkTrainingStage1(&tp_set, lanes) && LinkTrainingStage2(&tp_set, lanes);
  }

  // Tell the sink device to end its link training attempt.
  //
  // If link training was successful, we need to do this so that the sink
  // device will accept pixel data from the source device.
  //
  // If link training was not successful, we want to do this so that
  // subsequent link training attempts can work.  If we don't unset this
  // register, subsequent link training attempts can also fail.  (This
  // can be important during development.  The sink device won't
  // necessarily get reset when the computer is reset.  This means that a
  // bad version of the driver can leave the sink device in a state where
  // good versions subsequently don't work.)
  uint32_t addr = dpcd::DPCD_TRAINING_PATTERN_SET;
  uint8_t reg_byte = 0;
  if (!DpcdWrite(addr, &reg_byte, sizeof(reg_byte))) {
    zxlogf(ERROR, "Failure setting TRAINING_PATTERN_SET");
    return false;
  }

  return result;
}

}  // namespace i915

namespace {

// Convert ratio x/y into the form used by the Link/Data M/N ratio registers.
void CalculateRatio(uint32_t x, uint32_t y, uint32_t* m_out, uint32_t* n_out) {
  // The exact values of N and M shouldn't matter too much.  N and M can be
  // up to 24 bits, and larger values will tend to represent the ratio more
  // accurately. However, large values of N (e.g. 1 << 23) cause some monitors
  // to inexplicably fail. Pick a relatively arbitrary value for N that works
  // well in practice.
  *n_out = 1 << 20;
  *m_out = static_cast<uint32_t>(static_cast<uint64_t>(x) * *n_out / y);
}

}  // namespace

namespace i915 {

DpDisplay::DpDisplay(Controller* controller, uint64_t id, registers::Ddi ddi, DpcdChannel* dp_aux,
                     inspect::Node* parent_node)
    : DisplayDevice(controller, id, ddi), dp_aux_(dp_aux) {
  ZX_ASSERT(dp_aux);
  inspect_node_ = parent_node->CreateChild(fbl::StringPrintf("dp-display-%lu", id));
  dp_lane_count_inspect_ = inspect_node_.CreateUint("dp_lane_count", 0);
  dp_link_rate_mhz_inspect_ = inspect_node_.CreateUint("dp_link_rate_mhz", 0);
}

bool DpDisplay::Query() {
  // For eDP displays, assume that the BIOS has enabled panel power, given
  // that we need to rely on it properly configuring panel power anyway. For
  // general DP displays, the default power state is D0, so we don't have to
  // worry about AUX failures because of power saving mode.
  {
    auto capabilities = DpCapabilities::Read(dp_aux_, &inspect_node_);
    if (capabilities.is_error()) {
      return false;
    }

    capabilities_ = capabilities.take_value();
  }

  // TODO(fxbug.dev/31313): Add support for MST
  if (capabilities_->sink_count() != 1) {
    zxlogf(ERROR, "MST not supported");
    return false;
  }

  uint8_t lane_count = 0;
  if ((ddi() == registers::DDI_A || ddi() == registers::DDI_E) &&
      capabilities_->max_lane_count() == 4 &&
      !registers::DdiRegs(registers::DDI_A)
           .DdiBufControl()
           .ReadFrom(mmio_space())
           .ddi_a_lane_capability_control()) {
    lane_count = 2;
  } else {
    lane_count = capabilities_->max_lane_count();
  }

  dp_lane_count_ = lane_count;
  dp_lane_count_inspect_.Set(lane_count);

  ZX_ASSERT(!dp_link_rate_table_idx_.has_value());
  ZX_ASSERT(!capabilities_->supported_link_rates_mbps().empty());

  uint8_t last = static_cast<uint8_t>(capabilities_->supported_link_rates_mbps().size() - 1);
  zxlogf(INFO, "Found %s monitor (max link rate: %d MHz, lane count: %d)",
         (controller()->igd_opregion().IsEdp(ddi()) ? "eDP" : "DP"),
         capabilities_->supported_link_rates_mbps()[last], dp_lane_count_);

  return true;
}

bool DpDisplay::InitDdi() {
  ZX_ASSERT(capabilities_);

  bool is_edp = controller()->igd_opregion().IsEdp(ddi());
  if (is_edp) {
    auto panel_ctrl = registers::PanelPowerCtrl::Get().ReadFrom(mmio_space());
    auto panel_status = registers::PanelPowerStatus::Get().ReadFrom(mmio_space());

    if (!panel_status.on_status() ||
        panel_status.pwr_seq_progress() == panel_status.kPrwSeqPwrDown) {
      panel_ctrl.set_power_state_target(1).set_pwr_down_on_reset(1).WriteTo(mmio_space());
    }

    // Per eDP 1.4, the panel must be on and ready to accept AUX messages
    // within T1 + T3, which is at most 90 ms.
    // TODO(fxbug.dev/31313): Read the hardware's actual value for T1 + T3.
    zx_nanosleep(zx_deadline_after(ZX_MSEC(90)));

    if (!panel_status.ReadFrom(mmio_space()).on_status() ||
        panel_status.pwr_seq_progress() != panel_status.kPrwSeqNone) {
      zxlogf(ERROR, "Failed to enable panel!");
      return false;
    }
  }

  if (capabilities_->dpcd_revision() >= dpcd::Revision::k1_1) {
    // If the device is in a low power state, the first write can fail. It should be ready
    // within 1ms, but try a few extra times to be safe.
    dpcd::SetPower set_pwr;
    set_pwr.set_set_power_state(set_pwr.kOn);
    int count = 0;
    while (!DpcdWrite(dpcd::DPCD_SET_POWER, set_pwr.reg_value_ptr(), 1) && ++count < 5) {
      zx_nanosleep(zx_deadline_after(ZX_MSEC(1)));
    }
    if (count >= 5) {
      zxlogf(ERROR, "Failed to set dp power state");
      return ZX_ERR_INTERNAL;
    }
  }

  dpcd::LaneAlignStatusUpdate status;
  if (!DpcdRead(dpcd::DPCD_LANE_ALIGN_STATUS_UPDATED, status.reg_value_ptr(), 1)) {
    zxlogf(WARNING, "Failed to read align status on hotplug");
    return false;
  }

  // If the link is already trained, assume output is working
  if (status.interlane_align_done()) {
    return true;
  }

  // Determine the current link rate if one hasn't been assigned.
  if (dp_link_rate_mhz_ == 0) {
    ZX_ASSERT(!capabilities_->supported_link_rates_mbps().empty());

    // Pick the maximum supported link rate.
    uint8_t index = static_cast<uint8_t>(capabilities_->supported_link_rates_mbps().size() - 1);
    uint32_t link_rate = capabilities_->supported_link_rates_mbps()[index];

    zxlogf(INFO, "Selected maximum supported DisplayPort link rate: %u Mbps/lane", link_rate);
    SetLinkRate(link_rate);
    if (capabilities_->use_link_rate_table()) {
      dp_link_rate_table_idx_ = index;
    }
  }

  DpllState state = DpDpllState{
      .dp_bit_rate_mhz = dp_link_rate_mhz_,
  };

  DisplayPll* dpll = controller()->dpll_manager()->Map(ddi(), is_edp, state);
  if (dpll == nullptr) {
    zxlogf(ERROR, "Cannot find an available DPLL for DP display on DDI %d", ddi());
    return false;
  }

  // Enable power for this DDI.
  controller()->power()->SetDdiIoPowerState(ddi(), /* enable */ true);
  if (!WAIT_ON_US(controller()->power()->GetDdiIoPowerState(ddi()), 20)) {
    zxlogf(ERROR, "Failed to enable IO power for ddi");
    return false;
  }

  // Do link training
  if (!DoLinkTraining()) {
    zxlogf(ERROR, "DDI %d: DisplayPort link training failed", ddi());
    return false;
  }

  return true;
}

void DpDisplay::InitWithDpllState(const DpllState* dpll_state) {
  if (dpll_state == nullptr) {
    return;
  }

  ZX_DEBUG_ASSERT(std::holds_alternative<DpDpllState>(*dpll_state));
  if (!std::holds_alternative<DpDpllState>(*dpll_state)) {
    zxlogf(ERROR, "Non DP dpll_state is given to DpDisplay!");
    return;
  }

  auto dp_state = std::get_if<DpDpllState>(dpll_state);
  // Some display (e.g. eDP) may have already been configured by the bootloader with a
  // link clock. Assign the link rate based on the already enabled DPLL.
  if (dp_link_rate_mhz_ == 0) {
    // Since the link rate is read from the register directly, we can guarantee
    // that it is always valid.
    zxlogf(INFO, "Selected pre-configured DisplayPort link rate: %u Mbps/lane",
           dp_state->dp_bit_rate_mhz);
    SetLinkRate(dp_state->dp_bit_rate_mhz);
  }
}

bool DpDisplay::ComputeDpllState(uint32_t pixel_clock_10khz, DpllState* config) {
  *config = DpDpllState{
      .dp_bit_rate_mhz = dp_link_rate_mhz_,
  };
  return true;
}

bool DpDisplay::DdiModeset(const display_mode_t& mode, registers::Pipe pipe,
                           registers::Trans trans) {
  return true;
}

bool DpDisplay::PipeConfigPreamble(const display_mode_t& mode, registers::Pipe pipe,
                                   registers::Trans trans) {
  registers::TranscoderRegs trans_regs(trans);

  // Configure Transcoder Clock Select
  if (trans != registers::TRANS_EDP) {
    auto clock_select = trans_regs.ClockSelect().ReadFrom(mmio_space());
    clock_select.set_trans_clock_select(ddi() + 1);
    clock_select.WriteTo(mmio_space());
  }

  // Pixel clock rate: The rate at which pixels are sent, in pixels per
  // second (Hz), divided by 10000.
  uint32_t pixel_clock_rate = mode.pixel_clock_10khz;

  // This is the rate at which bits are sent on a single DisplayPort
  // lane, in raw bits per second, divided by 10000.
  uint32_t link_raw_bit_rate = dp_link_rate_mhz_ * 100;
  // Link symbol rate: The rate at which link symbols are sent on a
  // single DisplayPort lane.  A link symbol is 10 raw bits (using 8b/10b
  // encoding, which usually encodes an 8-bit data byte).
  uint32_t link_symbol_rate = link_raw_bit_rate / 10;

  // Configure ratios between pixel clock/bit rate and symbol clock/bit rate
  uint32_t link_m;
  uint32_t link_n;
  CalculateRatio(pixel_clock_rate, link_symbol_rate, &link_m, &link_n);

  uint32_t pixel_bit_rate = pixel_clock_rate * kBitsPerPixel;
  uint32_t total_link_bit_rate = link_symbol_rate * 8 * dp_lane_count_;
  ZX_DEBUG_ASSERT(pixel_bit_rate <= total_link_bit_rate);  // Should be caught by CheckPixelRate

  uint32_t data_m;
  uint32_t data_n;
  CalculateRatio(pixel_bit_rate, total_link_bit_rate, &data_m, &data_n);

  auto data_m_reg = trans_regs.DataM().FromValue(0);
  data_m_reg.set_tu_or_vcpayload_size(63);  // Size - 1, default TU size is 64
  data_m_reg.set_data_m_value(data_m);
  data_m_reg.WriteTo(mmio_space());

  auto data_n_reg = trans_regs.DataN().FromValue(0);
  data_n_reg.set_data_n_value(data_n);
  data_n_reg.WriteTo(mmio_space());

  auto link_m_reg = trans_regs.LinkM().FromValue(0);
  link_m_reg.set_link_m_value(link_m);
  link_m_reg.WriteTo(mmio_space());

  auto link_n_reg = trans_regs.LinkN().FromValue(0);
  link_n_reg.set_link_n_value(link_n);
  link_n_reg.WriteTo(mmio_space());

  return true;
}

bool DpDisplay::PipeConfigEpilogue(const display_mode_t& mode, registers::Pipe pipe,
                                   registers::Trans trans) {
  registers::TranscoderRegs trans_regs(trans);
  auto msa_misc = trans_regs.MsaMisc().FromValue(0);
  msa_misc.set_sync_clock(1);
  msa_misc.set_bits_per_color(msa_misc.k8Bbc);  // kPixelFormat
  msa_misc.set_color_format(msa_misc.kRgb);     // kPixelFormat
  msa_misc.WriteTo(mmio_space());

  auto ddi_func = trans_regs.DdiFuncControl().ReadFrom(mmio_space());
  ddi_func.set_trans_ddi_function_enable(1);
  ddi_func.set_ddi_select(ddi());
  ddi_func.set_trans_ddi_mode_select(ddi_func.kModeDisplayPortSst);
  ddi_func.set_bits_per_color(ddi_func.k8bbc);  // kPixelFormat
  ddi_func.set_sync_polarity((!!(mode.flags & MODE_FLAG_VSYNC_POSITIVE)) << 1 |
                             (!!(mode.flags & MODE_FLAG_HSYNC_POSITIVE)));
  ddi_func.set_port_sync_mode_enable(0);
  ddi_func.set_dp_vc_payload_allocate(0);
  ddi_func.set_edp_input_select(
      pipe == registers::PIPE_A ? ddi_func.kPipeA
                                : (pipe == registers::PIPE_B ? ddi_func.kPipeB : ddi_func.kPipeC));
  ddi_func.set_dp_port_width_selection(dp_lane_count_ - 1);
  ddi_func.WriteTo(mmio_space());

  auto trans_conf = trans_regs.Conf().FromValue(0);
  trans_conf.set_transcoder_enable(1);
  trans_conf.set_interlaced_mode(!!(mode.flags & MODE_FLAG_INTERLACED));
  trans_conf.WriteTo(mmio_space());

  return true;
}

bool DpDisplay::InitBacklightHw() {
  if (capabilities_ && capabilities_->backlight_aux_brightness()) {
    dpcd::EdpBacklightModeSet mode;
    mode.set_brightness_ctrl_mode(mode.kAux);
    if (!DpcdWrite(dpcd::DPCD_EDP_BACKLIGHT_MODE_SET, mode.reg_value_ptr(), 1)) {
      zxlogf(ERROR, "Failed to init backlight");
      return false;
    }
  }
  return true;
}

bool DpDisplay::SetBacklightOn(bool on) {
  if (!controller()->igd_opregion().IsEdp(ddi())) {
    return true;
  }

  if (capabilities_ && capabilities_->backlight_aux_power()) {
    dpcd::EdpDisplayCtrl ctrl;
    ctrl.set_backlight_enable(true);
    if (!DpcdWrite(dpcd::DPCD_EDP_DISPLAY_CTRL, ctrl.reg_value_ptr(), 1)) {
      zxlogf(ERROR, "Failed to enable backlight");
      return false;
    }
  } else {
    registers::PanelPowerCtrl::Get()
        .ReadFrom(mmio_space())
        .set_backlight_enable(on)
        .WriteTo(mmio_space());
    registers::SouthBacklightCtl1::Get()
        .ReadFrom(mmio_space())
        .set_enable(on)
        .WriteTo(mmio_space());
  }

  return !on || SetBacklightBrightness(backlight_brightness_);
}

bool DpDisplay::IsBacklightOn() {
  // If there is no embedded display, return false.
  if (!controller()->igd_opregion().IsEdp(ddi())) {
    return false;
  }

  if (capabilities_ && capabilities_->backlight_aux_power()) {
    dpcd::EdpDisplayCtrl ctrl;

    if (!DpcdRead(dpcd::DPCD_EDP_DISPLAY_CTRL, ctrl.reg_value_ptr(), 1)) {
      zxlogf(ERROR, "Failed to read backlight");
      return false;
    }

    return ctrl.backlight_enable();
  } else {
    return registers::PanelPowerCtrl::Get().ReadFrom(mmio_space()).backlight_enable() ||
           registers::SouthBacklightCtl1::Get().ReadFrom(mmio_space()).enable();
  }
}

bool DpDisplay::SetBacklightBrightness(double val) {
  if (!controller()->igd_opregion().IsEdp(ddi())) {
    return true;
  }

  backlight_brightness_ = std::max(val, controller()->igd_opregion().GetMinBacklightBrightness());
  backlight_brightness_ = std::min(backlight_brightness_, 1.0);

  if (capabilities_ && capabilities_->backlight_aux_brightness()) {
    uint16_t percent = static_cast<uint16_t>(0xffff * backlight_brightness_ + .5);

    uint8_t lsb = static_cast<uint8_t>(percent & 0xff);
    uint8_t msb = static_cast<uint8_t>(percent >> 8);
    if (!DpcdWrite(dpcd::DPCD_EDP_BACKLIGHT_BRIGHTNESS_MSB, &msb, 1) ||
        !DpcdWrite(dpcd::DPCD_EDP_BACKLIGHT_BRIGHTNESS_LSB, &lsb, 1)) {
      zxlogf(ERROR, "Failed to set backlight brightness");
      return false;
    }
  } else {
    auto backlight_ctrl = registers::SouthBacklightCtl2::Get().ReadFrom(mmio_space());
    uint16_t max = static_cast<uint16_t>(backlight_ctrl.modulation_freq());
    backlight_ctrl.set_duty_cycle(static_cast<uint16_t>(max * backlight_brightness_ + .5));
    backlight_ctrl.WriteTo(mmio_space());
  }

  return true;
}

double DpDisplay::GetBacklightBrightness() {
  if (!HasBacklight()) {
    return 0;
  }

  double percent = 0;

  if (capabilities_ && capabilities_->backlight_aux_brightness()) {
    uint8_t lsb;
    uint8_t msb;
    if (!DpcdRead(dpcd::DPCD_EDP_BACKLIGHT_BRIGHTNESS_MSB, &msb, 1) ||
        !DpcdRead(dpcd::DPCD_EDP_BACKLIGHT_BRIGHTNESS_LSB, &lsb, 1)) {
      zxlogf(ERROR, "Failed to read backlight brightness");
      return 0;
    }

    uint16_t brightness = static_cast<uint16_t>((lsb & 0xff) | (msb << 8));

    percent = (brightness * 1.0f) / 0xffff;

  } else {
    auto backlight_ctrl = registers::SouthBacklightCtl2::Get().ReadFrom(mmio_space());
    uint16_t max = static_cast<uint16_t>(backlight_ctrl.modulation_freq());
    uint16_t duty_cycle = static_cast<uint16_t>(backlight_ctrl.duty_cycle());

    percent = (duty_cycle * 1.0f) / max;
  }

  return percent;
}

bool DpDisplay::HandleHotplug(bool long_pulse) {
  if (!long_pulse) {
    dpcd::SinkCount sink_count;
    if (!DpcdRead(dpcd::DPCD_SINK_COUNT, sink_count.reg_value_ptr(), 1)) {
      zxlogf(WARNING, "Failed to read sink count on hotplug");
      return false;
    }

    // The pulse was from a downstream monitor being connected
    // TODO(fxbug.dev/31313): Add support for MST
    if (sink_count.count() > 1) {
      return true;
    }

    // The pulse was from a downstream monitor disconnecting
    if (sink_count.count() == 0) {
      return false;
    }

    dpcd::LaneAlignStatusUpdate status;
    if (!DpcdRead(dpcd::DPCD_LANE_ALIGN_STATUS_UPDATED, status.reg_value_ptr(), 1)) {
      zxlogf(WARNING, "Failed to read align status on hotplug");
      return false;
    }

    if (status.interlane_align_done()) {
      zxlogf(DEBUG, "HPD event for trained link");
      return true;
    }

    return DoLinkTraining();
  }
  return false;
}

bool DpDisplay::HasBacklight() { return controller()->igd_opregion().IsEdp(ddi()); }

namespace FidlBacklight = fuchsia_hardware_backlight;

zx_status_t DpDisplay::SetBacklightState(bool power, double brightness) {
  SetBacklightOn(power);

  brightness = std::max(brightness, 0.0);
  brightness = std::min(brightness, 1.0);

  double range = 1.0f - controller()->igd_opregion().GetMinBacklightBrightness();
  if (!SetBacklightBrightness((range * brightness) +
                              controller()->igd_opregion().GetMinBacklightBrightness())) {
    return ZX_ERR_IO;
  }
  return ZX_OK;
}

zx_status_t DpDisplay::GetBacklightState(bool* power, double* brightness) {
  *power = IsBacklightOn();
  *brightness = GetBacklightBrightness();
  return ZX_OK;
}

void DpDisplay::SetLinkRate(uint32_t value) {
  dp_link_rate_mhz_ = value;
  dp_link_rate_mhz_inspect_.Set(value);
}

bool DpDisplay::CheckPixelRate(uint64_t pixel_rate) {
  uint64_t bit_rate = (dp_link_rate_mhz_ * 1000000lu) * dp_lane_count_;
  // Multiply by 8/10 because of 8b/10b encoding
  uint64_t max_pixel_rate = (bit_rate * 8 / 10) / kBitsPerPixel;
  return pixel_rate <= max_pixel_rate;
}

uint32_t DpDisplay::LoadClockRateForTranscoder(registers::Trans transcoder) {
  registers::TranscoderRegs trans_regs(transcoder);
  uint32_t data_m = trans_regs.DataM().ReadFrom(mmio_space()).data_m_value();
  uint32_t data_n = trans_regs.DataN().ReadFrom(mmio_space()).data_n_value();

  double total_link_bit_rate_10khz = dp_link_rate_mhz_ * 100. * (8. / 10.) * dp_lane_count_;
  double res = (data_m * total_link_bit_rate_10khz) / (data_n * kBitsPerPixel);
  return static_cast<uint32_t>(round(res));
}

}  // namespace i915
