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

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

#include <lib/ddk/debug.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/time.h>
#include <zircon/assert.h>

#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <tuple>

#include "src/graphics/display/drivers/intel-i915/pci-ids.h"
#include "src/graphics/display/drivers/intel-i915/poll-until.h"
#include "src/graphics/display/drivers/intel-i915/registers-ddi.h"
#include "src/graphics/display/drivers/intel-i915/registers-pch.h"

namespace i915 {

namespace {

// The frequency of the (inferred) PCH clock used for panel power sequencing.
//
// This is the value requested in the Kaby Lake and Skylake PRMs. The register
// reference (Vol 2c) in the Tiger Lake and DG1 PRMs mention the same
// resolution, but doesn't describe any method for changing it.
//
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 629
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 623
constexpr int32_t kPrescribedPanelPowerClockHz = 10'000;

}  // namespace

bool operator==(const PchClockParameters& lhs, const PchClockParameters& rhs) noexcept {
  return std::make_tuple(lhs.raw_clock_hz, lhs.panel_power_clock_hz) ==
         std::make_tuple(rhs.raw_clock_hz, rhs.panel_power_clock_hz);
}

void PchPanelParameters::Fix() {
  if (power_cycle_delay_micros == 0) {
    // Maximum values based on eDP and SPWG Notebook Panel standards.
    power_cycle_delay_micros = 500'000;

    // eDP T1+T3 max.
    if (power_on_to_hpd_aux_ready_delay_micros == 0) {
      power_on_to_hpd_aux_ready_delay_micros = 90'000;
    }

    // SPWG T1+T2+T5 max/min.
    if (power_on_to_backlight_on_delay_micros == 0) {
      power_on_to_backlight_on_delay_micros = 260'000;
    }

    // SPWG T6 min
    if (backlight_off_to_video_end_delay_micros == 0) {
      backlight_off_to_video_end_delay_micros = 200'000;
    }

    // eDP T10 max
    if (video_end_to_power_off_delay_micros == 0) {
      video_end_to_power_off_delay_micros = 500'000;
    }
  }

  if (backlight_pwm_frequency_hz < 1'000) {
    backlight_pwm_frequency_hz = 1'000;
  }

  // Always recommended.
  power_down_on_reset = true;
}

bool operator==(const PchPanelParameters& lhs, const PchPanelParameters& rhs) noexcept {
  return std::make_tuple(
             lhs.power_on_to_hpd_aux_ready_delay_micros, lhs.power_on_to_backlight_on_delay_micros,
             lhs.backlight_off_to_video_end_delay_micros, lhs.video_end_to_power_off_delay_micros,
             lhs.power_cycle_delay_micros, lhs.backlight_pwm_frequency_hz, lhs.power_down_on_reset,
             lhs.backlight_pwm_inverted) ==
         std::make_tuple(
             rhs.power_on_to_hpd_aux_ready_delay_micros, rhs.power_on_to_backlight_on_delay_micros,
             rhs.backlight_off_to_video_end_delay_micros, rhs.video_end_to_power_off_delay_micros,
             rhs.power_cycle_delay_micros, rhs.backlight_pwm_frequency_hz, rhs.power_down_on_reset,
             rhs.backlight_pwm_inverted);
}

bool operator==(const PchPanelPowerTarget& lhs, const PchPanelPowerTarget& rhs) noexcept {
  return std::make_tuple(lhs.power_on, lhs.backlight_on, lhs.force_power_on,
                         lhs.brightness_pwm_counter_on) ==
         std::make_tuple(rhs.power_on, rhs.backlight_on, rhs.force_power_on,
                         rhs.brightness_pwm_counter_on);
}

PchEngine::PchEngine(fdf::MmioBuffer* mmio_buffer, uint16_t device_id)
    : mmio_buffer_(mmio_buffer), device_id_(device_id) {
  ZX_DEBUG_ASSERT(mmio_buffer);

  // Register reads are ordered by MMIO address. There are no other ordering
  // requirements, and this ordering might have a slight performance advantage,
  // if the range is prefetchable.

  misc_ = registers::PchChicken1::Get().ReadFrom(mmio_buffer);
  clock_ = registers::PchRawClock::Get().ReadFrom(mmio_buffer);

  panel_power_control_ = registers::PchPanelPowerControl::Get().ReadFrom(mmio_buffer);
  panel_power_on_delays_ = registers::PchPanelPowerOnDelays::Get().ReadFrom(mmio_buffer);
  panel_power_off_delays_ = registers::PchPanelPowerOffDelays::Get().ReadFrom(mmio_buffer);
  if (is_skl(device_id) || is_kbl(device_id)) {
    panel_power_clock_delay_ = registers::PchPanelPowerClockDelay::Get().ReadFrom(mmio_buffer);
  }

  backlight_control_ = registers::PchBacklightControl::Get().ReadFrom(mmio_buffer);
  if (is_skl(device_id) || is_kbl(device_id)) {
    backlight_freq_duty_ = registers::PchBacklightFreqDuty::Get().ReadFrom(mmio_buffer);
  }
  if (is_tgl(device_id)) {
    backlight_pwm_freq_ = registers::PchBacklightFreq::Get().ReadFrom(mmio_buffer);
    backlight_pwm_duty_ = registers::PchBacklightDuty::Get().ReadFrom(mmio_buffer);
  }
}

void PchEngine::SetPchResetHandshake(bool enabled) {
  auto display_reset_options = registers::DisplayResetOptions::Get().ReadFrom(mmio_buffer_);
  if (display_reset_options.pch_reset_handshake() == enabled)
    return;
  display_reset_options.set_pch_reset_handshake(enabled).WriteTo(mmio_buffer_);
}

void PchEngine::RestoreClockParameters() {
  clock_.WriteTo(mmio_buffer_);
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    panel_power_clock_delay_.WriteTo(mmio_buffer_);
  }

  if (is_tgl(device_id_)) {
    // The restore side of the workaround for the PCH display engine clock
    // remaining enabled during suspend. The PRM documents two version of the
    // workaround. We implement the version that resets the
    // `pch_display_clock_disable` field during restore, because this version is
    // resilient to the boot firmware changing the field.
    //
    // Lakefield: IHD-OS-LKF-Vol 14-4.21 page 15
    // Tiger Lake: IHD-OS-TGL-Vol 14-12.21 page 18 and page 50
    // Ice Lake: IHD-OS-ICLLP-Vol 14-1.20 page 33
    misc_.set_pch_display_clock_disable(0);
  }
  // The workaround above suggests that the `misc` register may re-enable the
  // PCH display engine clock. To be safe, we restore it after restoring the
  // clock configuration registers.
  misc_.WriteTo(mmio_buffer_);
}

void PchEngine::RestoreNonClockParameters() {
  // At this stage, the panel must remain powered down, and the brightness PWM
  // must be disabled. The pipes and transcoders are not yet restored. Later in
  // the recovery process, the panel and brightness will be restored, if
  // necessary.
  panel_power_control_.set_power_state_target(0).set_backlight_enabled(0);
  backlight_control_.set_pwm_counter_enabled(0);

  panel_power_on_delays_.WriteTo(mmio_buffer_);
  panel_power_off_delays_.WriteTo(mmio_buffer_);

  // The panel power sequence delays must be configured before turning on the
  // panel. This requirement is met if we restore `panel_control_` after
  // restoring all the other registers that configure the panel power sequence.
  //
  // On Kaby Lake and Skylake, the dependencies include the `misc_` and
  // `panel_power_clock_delay_` registers. These registers are handled by
  // RestoreClockParameters(), which must have been called earlier.
  //
  // Writing to `panel_control_` is currently guaranteed not to turn on
  // the panel. Our restore code will continue working if this changes.
  panel_power_control_.WriteTo(mmio_buffer_);

  if (is_skl(device_id_) || is_kbl(device_id_)) {
    backlight_freq_duty_.WriteTo(mmio_buffer_);
  }
  if (is_tgl(device_id_)) {
    backlight_pwm_freq_.WriteTo(mmio_buffer_);
    backlight_pwm_duty_.WriteTo(mmio_buffer_);
  }

  // The brightness PWM frequency and duty cycle must be configured before
  // enabling the PWM. This requirement is met if we restore
  // `backlight_control_` after restoring all other backlight PWM registers.
  //
  // Writing to `backlight_control_` is currently guaranteed not to enable the
  // PWM. Our restore code will continue working if this changes.
  backlight_control_.WriteTo(mmio_buffer_);
}

PchPanelPowerState PchEngine::PanelPowerState() {
  auto status = registers::PchPanelPowerStatus::Get().ReadFrom(mmio_buffer_);

  auto power_transition = status.PowerTransition();
  if (power_transition == registers::PchPanelPowerStatus::Transition::kPoweringDown) {
    // According to Intel's PRM, status.panel_on() should be 1.
    return PchPanelPowerState::kPoweringDown;
  }

  if (power_transition == registers::PchPanelPowerStatus::Transition::kPoweringUp) {
    // According to Intel's PRM, status.panel_on() should be 0.

    // The power up sequence includes waiting for a T12 (power cycle) delay.
    if (status.power_cycle_delay_active())
      return PchPanelPowerState::kWaitingForPowerCycleDelay;
    return PchPanelPowerState::kPoweringUp;
  }

  if (status.panel_on())
    return PchPanelPowerState::kPoweredUp;

  if (status.power_cycle_delay_active())
    return PchPanelPowerState::kWaitingForPowerCycleDelay;

  return PchPanelPowerState::kPoweredDown;
}

bool PchEngine::WaitForPanelPowerState(PchPanelPowerState power_state, int timeout_us) {
  ZX_ASSERT(timeout_us > 0);

  // Typical timeout values are hundreds of ms. A granularity of 10ms strikes a
  // decent balance between unnecessarily waiting, and taking the CPU away from
  // other tasks.
  static constexpr int wait_granularity_us = 10'000;
  static constexpr zx::duration wait_granularity = zx::usec(wait_granularity_us);

  // The subtraction and division are safe because `wait_granularity_us` is
  // guaranteed to be non-negative.
  int poll_intervals = (timeout_us + wait_granularity_us - 1) / wait_granularity_us;
  return PollUntil([&] { return PanelPowerState() == power_state; }, wait_granularity,
                   poll_intervals);
}

PchClockParameters PchEngine::ClockParameters() const {
  return PchClockParameters{
      .raw_clock_hz = RawClockHz(),
      .panel_power_clock_hz = PanelPowerClockHz(),
  };
}

void PchEngine::SetClockParameters(const PchClockParameters& parameters) {
  SetRawClockHz(parameters.raw_clock_hz);
  SetPanelPowerClockHz(parameters.panel_power_clock_hz);
}

void PchEngine::FixClockParameters(PchClockParameters& parameters) const {
  if (parameters.panel_power_clock_hz == 0) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 629
    // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 623
    //
    // On devices where the panel power sequencing clock is not configurable,
    // ClockParameters() returns the correct value.
    parameters.panel_power_clock_hz = kPrescribedPanelPowerClockHz;
  }

  if (is_skl(device_id_) || is_kbl(device_id_) || is_test_device(device_id_)) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 712
    // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 705

    if (parameters.raw_clock_hz == 0) {
      // The boot firmware should really have set the PCH raw clock. Use the
      // documented default.
      parameters.raw_clock_hz = 24'000'000;
    }
    return;
  }

  if (is_tgl(device_id_)) {
    // IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 page 1185 and pages 1083-1084

    auto pch_fuses = registers::PchDisplayFuses::Get().ReadFrom(mmio_buffer_);
    parameters.raw_clock_hz = pch_fuses.rawclk_is_24mhz() ? 24'000'000 : 19'200'000;
    return;
  }

  ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
}

int32_t PchEngine::RawClockHz() const {
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 712
    // Skylake:  IHD-OS-SKL-Vol 2c-05.16 Part 2 page 705

    // The cast does not cause UB, because mhz() is a 10-bit field.
    //
    // For the same reason, the maximum configurable frequency is 1023MHz, which
    // fits in 30 bits when expressed in Hertz. So, the multiplication is
    // guaranteed not to overflow (which would cause UB).
    return static_cast<int32_t>(clock_.mhz()) * 1'000'000;
  }

  if (is_tgl(device_id_)) {
    // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 1083-1084
    // DG1: IHD-OS-DG1-Vol 2c-2.21 Part 2 pages 1131-1132
    //
    // The Tiger Lake and DG1 PRMs document different patterns for the
    // integer part of the frequency (the microsecond counter divider). The
    // Tiger Lake manual suggests that the integer is stored exactly as-is. The
    // DG1 manual suggests that the integer field stores the real value - 1.
    //
    // The production Tiger Lake devices we've encountered (NUC11, Dell 5420)
    // use the approach documented in the DG1 manual.

    // The cast does not cause UB, because integer() is a 10-bit field.
    //
    // For the same reason, the maximum configurable frequency is 1024MHz, which
    // fits in 30 bits when expressed in Hertz. So, the multiplication is
    // guaranteed not to overflow (which would cause UB).
    const int32_t integer = (static_cast<int32_t>(clock_.integer()) + 1) * 1'000'000;

    // The cast does not cause UB because fraction_numerator() is a 3-bit field.
    //
    // For the same reason, the maximum configurable numerator is 7, which fits
    // in 13 bits when expressed in Hertz. So, the multiplication is guaranteed
    // not to overflow (which would cause UB).
    const int32_t numerator = static_cast<int32_t>(clock_.fraction_numerator()) * 1'000'000;

    // The cast does not cause UB, because fraction_denominator() is a 4-bit field.
    //
    // For the same reason, range of configurable denominators is 1-16. So, the
    // addition is guaranteed not to overflow (which would cause UB).
    const int32_t denominator = static_cast<int32_t>(clock_.fraction_denominator()) + 1;

    // The division does not cause UB, because the denominator is >= 1.
    //
    // The range of results is from 0 (0 / 1) to 7,000,000 (7,000,000 / 1). So,
    // the division is guaranteed not to overflow (which would cause UB).
    const int32_t fraction = numerator / denominator;

    // The maximum addition result is 1,031,000,000 which fits in 31 bits. So,
    // the addition will not overflow.
    return integer + fraction;
  }

  if (is_test_device(device_id_)) {
    return 24'000'000;  // Kaby Lake default raw clock.
  }

  ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  return 0;
}

void PchEngine::SetRawClockHz(int32_t raw_clock_hz) {
  ZX_ASSERT(raw_clock_hz >= 1'000'000);

  const uint32_t old_clock = clock_.reg_value();

  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 712
    // Skylake:  IHD-OS-SKL-Vol 2c-05.16 Part 2 page 705

    // `mhz` is a 10-bit field.
    static constexpr int32_t kMaxRawMhz = (1 << 10) - 1;
    const int32_t raw_mhz = std::min(raw_clock_hz / 1'000'000, kMaxRawMhz);

    clock_.set_mhz(raw_mhz);
  } else if (is_tgl(device_id_)) {
    // Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 1083-1084
    // DG1: IHD-OS-DG1-Vol 2c-2.21 Part 2 pages 1131-1132
    //
    // The Tiger Lake code uses the relationships suggested in the DG1 manual.
    // See the RawClockHz() comments for a detailed justification.

    // `integer` is a 10-bit field.
    static constexpr int32_t kMaxRawInteger = (1 << 10) - 1;
    // The subtraction result is non-negative, because `raw_clock_hz` is at
    // least 1,000,000, so the division result is at least 1.
    const int32_t raw_integer = std::min(raw_clock_hz / 1'000'000 - 1, kMaxRawInteger);

    const int32_t target_fraction_hz = raw_clock_hz % 1'000'000;

    // Find the `numerator` and `denominator` that yield a fraction closest to
    // the target fraction. The first guess is 0 / 1.
    int32_t raw_numerator = 0, raw_denominator = 0;

    // std::abs(0 - target_fraction_hz) is `target_fraction_hz`.
    int32_t min_diff_hz = target_fraction_hz;

    static constexpr int32_t kMaxNumerator = (1 << 3) - 1;  // 3-bit field
    static constexpr int32_t kMaxDenominator = (1 << 4);    // 4-bit field, offset by 1
    for (int32_t numerator = 1; numerator <= kMaxNumerator; ++numerator) {
      // The multiplication will not overflow (causing UB) because `numerator`
      // is a 3-bit unsigned integer. So the result is at most 7,000,000.
      const int32_t numerator_hz = numerator * 1'000'000;

      // The fraction must always be less than 1.
      for (int32_t denominator = numerator + 1; denominator <= kMaxDenominator; ++denominator) {
        const int32_t fraction_hz = numerator_hz / denominator;

        // The subtraction result will not overflow 32 bits (causing UB) because
        // `fraction_hz` is between 0 and 7,000,000 and `target_fraction_hz` is
        // between 0 and 1,000,000.
        const int32_t diff_hz = std::abs(fraction_hz - target_fraction_hz);

        if (diff_hz < min_diff_hz) {
          min_diff_hz = diff_hz;
          raw_numerator = numerator;
          raw_denominator = denominator - 1;
        }
      }
    }

    clock_.set_integer(raw_integer)
        .set_fraction_numerator(raw_numerator)
        .set_fraction_denominator(raw_denominator);
  } else if (is_test_device(device_id_)) {
    // Stubbed out for integration tests.
  } else {
    ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  }

  if (clock_.reg_value() != old_clock) {
    clock_.WriteTo(mmio_buffer_);
  }
}

int32_t PchEngine::PanelPowerClockHz() const {
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 629
    // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 623

    // The cast does not cause UB because clock_divider() is a 24-bit field.
    const int32_t raw_divider = static_cast<int32_t>(panel_power_clock_delay_.clock_divider());

    // clock_divider() is a 24-bit field, so the addition result will fit in 25
    // bits, and the multiplication result will fit in 26 bits. So, the
    // multiplication is guaranteed not to overflow (causing UB).
    const int32_t divider = (raw_divider + 1) * 2;

    // The division will not cause UB because divider is >= 2. The division
    // result is guaranteed to be non-negative, because both operands are
    // non-negative.
    //
    // The maximum result (configurable value) is 515Mhz. The maximum result
    // without breaking documented invariants is 512.4375Mhz.
    return RawClockHz() / divider;
  }

  if (is_tgl(device_id_)) {
    // No documented register for changing the panel power clock divider on
    // Tiger Lake. The clock should always be set to 10kHz.
    return kPrescribedPanelPowerClockHz;
  }

  if (is_test_device(device_id_)) {
    return kPrescribedPanelPowerClockHz;
  }

  ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  return kPrescribedPanelPowerClockHz;
}

void PchEngine::SetPanelPowerClockHz(int32_t panel_power_clock_hz) {
  ZX_ASSERT(panel_power_clock_hz > 0);

  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 629
    // Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 623

    // The division will not cause UB because `panel_power_clock_hz` must be
    // non-negative. The division result is non-negative because both inputs are
    // non-negative.
    const int32_t divider = RawClockHz() / panel_power_clock_hz;

    // `clock_divider` is a 24-bit field and must not be set to zero.
    static constexpr int32_t kMaxRawDivider = (1 << 24) - 1;
    // The subtraction result fits in 32 bits (will not cause UB) because the
    // left-hand side is the result of a division by 2, so its range is at most
    // half of the range of int32_t.
    const int32_t raw_divider = std::max(std::min(divider / 2 - 1, kMaxRawDivider), 1);

    const uint32_t old_panel_power_clock_delay = panel_power_clock_delay_.reg_value();
    panel_power_clock_delay_.set_clock_divider(raw_divider);
    if (panel_power_clock_delay_.reg_value() != old_panel_power_clock_delay) {
      panel_power_clock_delay_.WriteTo(mmio_buffer_);
    }
    return;
  }

  if (is_tgl(device_id_)) {
    // No documented register for changing the panel power clock divider on
    // Tiger Lake. The clock should always be set to 10kHz.
    return;
  }

  if (is_test_device(device_id_)) {
    // Stubbed out for integration tests.
    return;
  }
  ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
}

PchPanelParameters PchEngine::PanelParameters() const {
  // Return zeros instead of crashing if the PCH is not clocked correctly. This
  // lets us log the PCH configuration even when it's invalid.
  const int32_t panel_power_clock_hz = PanelPowerClockHz();
  const int32_t multiplier = (panel_power_clock_hz == 0) ? 0 : 1'000'000 / panel_power_clock_hz;

  // The casts do not cause UB because the register fields are 13-bit values.
  const int32_t raw_power_on_to_hpd_aux_ready_delay =
      static_cast<int32_t>(panel_power_on_delays_.power_on_to_hpd_aux_ready_delay());
  const int32_t raw_power_on_to_backlight_on_delay =
      static_cast<int32_t>(panel_power_on_delays_.power_on_to_backlight_on_delay());
  const int32_t raw_backlight_off_to_video_end_delay =
      static_cast<int32_t>(panel_power_off_delays_.backlight_off_to_video_end_delay());
  const int32_t raw_video_end_to_power_off_delay =
      static_cast<int32_t>(panel_power_off_delays_.video_end_to_power_off_delay());

  int32_t raw_power_cycle_delay;
  uint32_t backlight_pwm_divider;
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // The cast is not UB because power_cycle_delay() is a 5-bit field.
    raw_power_cycle_delay = static_cast<int32_t>(panel_power_clock_delay_.power_cycle_delay());
    if (raw_power_cycle_delay > 1)
      raw_power_cycle_delay -= 1;

    const uint32_t pwm_divider_granularity = misc_.backlight_pwm_multiplier() ? 128 : 16;

    // The cast does not cause UB because freq_divider() is a 16-bit field. The
    // multiplication will not overflow (causing UB) because maximum result fits
    // in 23 bits (16-bit unsigned integer multiplied by 128).
    backlight_pwm_divider = backlight_freq_duty_.freq_divider() * pwm_divider_granularity;
  } else if (is_tgl(device_id_)) {
    // The cast does not cause UB because power_cycle_delay() is a 5-bit field.
    raw_power_cycle_delay = static_cast<int32_t>(panel_power_control_.power_cycle_delay());
    if (raw_power_cycle_delay > 1)
      raw_power_cycle_delay -= 1;

    // The cast does not cause UB because freq_divider() is a 32-bit field.
    backlight_pwm_divider = static_cast<uint32_t>(backlight_pwm_freq_.divider());
  } else if (is_test_device(device_id_)) {
    raw_power_cycle_delay = 0;
    backlight_pwm_divider = 0;
  } else {
    ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  }

  // The cast does not cause UB because RawClockHz() fits in 30 bits.
  const uint32_t raw_clock_hz = static_cast<uint32_t>(RawClockHz());

  const int32_t backlight_pwm_frequency_hz =
      // The multiplication will not overflow (causing UB) because
      // `raw_clock_hz` fits in 30 bits.
      (backlight_pwm_divider == 0 || raw_clock_hz * 2 < backlight_pwm_divider)
          ? 0
          // The golden results in the unit tests, which are lifted from the PRMs,
          // require rounding. The addition will not overflow (causing UB) because
          // `raw_clock_hz` fits in 30 bits, and `backlight_pwm_divider` can be at
          // most twice as large.
          : (raw_clock_hz + backlight_pwm_divider / 2) / backlight_pwm_divider;

  return PchPanelParameters{
      // The maximum theoretical multiplication result is 8191
      // The multiplication results fit in 33 bits, because `multiplier` fits in
      // 20 bits, and the raw delay values fit in 13 bits.
      .power_on_to_hpd_aux_ready_delay_micros =
          raw_power_on_to_hpd_aux_ready_delay * static_cast<int64_t>(multiplier),
      .power_on_to_backlight_on_delay_micros =
          raw_power_on_to_backlight_on_delay * static_cast<int64_t>(multiplier),
      .backlight_off_to_video_end_delay_micros =
          raw_backlight_off_to_video_end_delay * static_cast<int64_t>(multiplier),
      .video_end_to_power_off_delay_micros =
          raw_video_end_to_power_off_delay * static_cast<int64_t>(multiplier),

      // The first multiplication result is at most 31,000 because
      // `raw_power_cycle_delay` fits in 5 bits. So, int32_t is sufficient for
      // the multiplication result, and no overflow (UB) will occur.
      //
      //
      // The second multiplication result fits in 35 bits, because `multiplier`
      // fits in 20 bits, and the first multiplication result fits in 15 bits.
      .power_cycle_delay_micros = static_cast<int64_t>(raw_power_cycle_delay * 1'000) * multiplier,

      .backlight_pwm_frequency_hz = backlight_pwm_frequency_hz,

      // The casts are safe because they involve 1-bit fields.
      .power_down_on_reset = static_cast<bool>(panel_power_control_.power_down_on_reset()),
      .backlight_pwm_inverted = static_cast<bool>(backlight_control_.pwm_polarity_inverted()),
  };
}

void PchEngine::SetPanelParameters(const PchPanelParameters& parameters) {
  SetPanelPowerSequenceParameters(parameters);
  SetPanelBacklightPwmParameters(parameters);
}

void PchEngine::SetPanelPowerSequenceParameters(const PchPanelParameters& parameters) {
  ZX_ASSERT(parameters.power_on_to_hpd_aux_ready_delay_micros >= 0);
  ZX_ASSERT(parameters.power_on_to_backlight_on_delay_micros >= 0);
  ZX_ASSERT(parameters.backlight_off_to_video_end_delay_micros >= 0);
  ZX_ASSERT(parameters.video_end_to_power_off_delay_micros >= 0);
  ZX_ASSERT(parameters.power_cycle_delay_micros >= 0);

  const int32_t panel_power_clock_hz = PanelPowerClockHz();
  ZX_ASSERT_MSG(panel_power_clock_hz > 0, "PCH not clocked correctly");

  const int32_t power_delay_divider = 1'000'000 / panel_power_clock_hz;
  ZX_ASSERT_MSG(power_delay_divider > 0, "PCH not clocked correctly");

  const uint32_t old_power_on_delays = panel_power_on_delays_.reg_value();
  const uint32_t old_power_off_delays = panel_power_off_delays_.reg_value();

  // The raw delays are written into 13-bit register fields.
  constexpr int64_t kMaxRawDelay = (1 << 13) - 1;

  // The casts do not cause UB because the std::min() results fit in 13 bits.
  const int32_t raw_power_on_to_hpd_aux_ready_delay = static_cast<int32_t>(std::min(
      parameters.power_on_to_hpd_aux_ready_delay_micros / power_delay_divider, kMaxRawDelay));
  const int32_t raw_power_on_to_backlight_on_delay = static_cast<int32_t>(std::min(
      parameters.power_on_to_backlight_on_delay_micros / power_delay_divider, kMaxRawDelay));
  const int32_t raw_backlight_off_to_video_end_delay = static_cast<int32_t>(std::min(
      parameters.backlight_off_to_video_end_delay_micros / power_delay_divider, kMaxRawDelay));
  const int32_t raw_video_end_to_power_off_delay = static_cast<int32_t>(
      std::min(parameters.video_end_to_power_off_delay_micros / power_delay_divider, kMaxRawDelay));

  panel_power_on_delays_.set_power_on_to_hpd_aux_ready_delay(raw_power_on_to_hpd_aux_ready_delay)
      .set_power_on_to_backlight_on_delay(raw_power_on_to_backlight_on_delay);
  panel_power_off_delays_.set_backlight_off_to_video_end_delay(raw_backlight_off_to_video_end_delay)
      .set_video_end_to_power_off_delay(raw_video_end_to_power_off_delay);

  if (panel_power_on_delays_.reg_value() != old_power_on_delays) {
    panel_power_on_delays_.WriteTo(mmio_buffer_);
  }
  if (panel_power_off_delays_.reg_value() != old_power_off_delays) {
    panel_power_off_delays_.WriteTo(mmio_buffer_);
  }

  // This delay is written in a 5-bit register field.
  constexpr int64_t kMaxRawPowerCycleDelay = (1 << 5) - 1;

  // The multiplication will not overflow (causing UB), because
  // `power_delay_divider` fits in 20 bits. So, the multiplication result will
  // fit in 30 bits.
  const int32_t raw_power_delay_divider = power_delay_divider * 1'000;

  // The division is not UB because we ensure that `power_delay_divider` is
  // positive above. The addition will not overflow (causing UB), because the
  // previous division's result is at most 1,000 times less than the maximum
  // integer. The cast does not cause UB because the std::min() result fits in 5
  // bits.
  const int32_t raw_power_cycle_delay = static_cast<int32_t>(std::min(
      parameters.power_cycle_delay_micros / raw_power_delay_divider + 1, kMaxRawPowerCycleDelay));

  const uint32_t old_panel_power_control = panel_power_control_.reg_value();

  if (is_kbl(device_id_) || is_skl(device_id_)) {
    const uint32_t old_panel_power_clock_delay = panel_power_clock_delay_.reg_value();
    panel_power_clock_delay_.set_power_cycle_delay(raw_power_cycle_delay);
    if (panel_power_clock_delay_.reg_value() != old_panel_power_clock_delay) {
      panel_power_clock_delay_.WriteTo(mmio_buffer_);
    }
  } else if (is_tgl(device_id_)) {
    panel_power_control_.set_power_cycle_delay(raw_power_cycle_delay);
  } else if (is_test_device(device_id_)) {
    // Stubbed out for integration tests.
  } else {
    ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  }

  panel_power_control_.set_power_down_on_reset(parameters.power_down_on_reset);
  if (panel_power_control_.reg_value() != old_panel_power_control) {
    panel_power_control_.WriteTo(mmio_buffer_);
  }
}

namespace {

// Computes the PWM duty cycle to be used with a new frequency.
//
// The return value is guaranteed to be <= `frequency_divider`.
//
// It's safe to pass un-validated register contents directly to this function.
// Returns zero (0% brightness) if `old_frequency_divider` is zero
// (un-configured PWM). Returns `frequency_divider` if `old_duty_cycle` exceeds
// `old_frequency_divider`, clamping the brightness to 100% in case the PWM is
// configured incorrectly.
//
// The arguments and return types must be uint32_t because some display engines
// (currently Tiger Lake and DG1) use 32-bit (unsigned) register fields to
// represent the frequency divider and duty cycle.
uint32_t ScaledPwmDutyCycle(uint32_t frequency_divider, uint32_t old_duty_cycle,
                            uint32_t old_frequency_divider) {
  if (old_frequency_divider == 0)
    return 0;

  // The multiplication will not overflow because both factors are 32-bit
  // integers.
  const uint64_t scaled_duty_cycle =
      (uint64_t{old_duty_cycle} * frequency_divider) / old_frequency_divider;

  // The cast is safe because std::min()'s result will be at most
  // `frequency_divider`, which fits in 32 bits.
  const uint32_t clamped_duty_cycle =
      static_cast<uint32_t>(std::min<uint64_t>(scaled_duty_cycle, frequency_divider));
  return clamped_duty_cycle;
}

}  // namespace

void PchEngine::SetPanelBacklightPwmParameters(const PchPanelParameters& parameters) {
  ZX_ASSERT(parameters.backlight_pwm_frequency_hz > 0);

  // This implements the sections "Panel Power and Backlight" > "Backlight
  // Enabling Sequence" and "Backlight Frequency Change Sequence" under  section
  // in the display engine PRMs.
  //
  // Tiger Lake: IHD-OS-TGL-Vol 12-1.22-Rev2.0 pages 426-427
  // DG1: IHD-OS-DG1-Vol 12-2.21 pages 349-350
  // Ice Lake: IHD-OS-ICLLP-Vol 12-1.22-Rev2.0 pages 370-371

  // The backlight PWM must be disabled while changing the PWM frequency. This
  // is not a theoretical issue -- we observed a panel whose backlight remains
  // off for minutes if we attempt to change the PWM frequency while the PWM
  // remains enabled. We also want to avoid disabling and re-enabling the PWM if
  // we're only going to change the duty cycle (brightness).
  //
  // To accomplish this, the SetPanelBacklightPwmParameters*() methods called
  // below disable the PWM if necessary. `old_backlight_control` captures the
  // PWM enablement state before we make any changes, so it is correctly
  // restored before the end of the method.
  //
  // Disabling the brightness PWM while the panel backlight is enabled is
  // supported, and results in well-defined behavior. The backlight goes to 100%
  // brightness. (As an aside, this seems like the best failure mode we could
  // have hoped for. A flicker of brightness seems better than a flicker of
  // complete darkness, which is the other plausible alternative.)
  const uint32_t old_backlight_control = backlight_control_.reg_value();

  if (is_kbl(device_id_) || is_skl(device_id_)) {
    SetPanelBacklightPwmParametersKabyLake(parameters);
  } else if (is_tgl(device_id_)) {
    SetPanelBacklightPwmParametersTigerLake(parameters);
  } else if (is_test_device(device_id_)) {
    // Stubbed out for integration tests.
    return;
  } else {
    ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  }

  // `set_reg_value()` undoes any changes that SetPanelBacklightPwmParameters*()
  // might have applied.
  backlight_control_.set_reg_value(old_backlight_control)
      .set_pwm_polarity_inverted(parameters.backlight_pwm_inverted);
  if (backlight_control_.reg_value() != old_backlight_control) {
    backlight_control_.WriteTo(mmio_buffer_);
  }
}

void PchEngine::SetPanelBacklightPwmParametersKabyLake(const PchPanelParameters& parameters) {
  const int32_t pwm_divider_granularity = misc_.backlight_pwm_multiplier() ? 128 : 16;

  // std::min() explicitly clamps one of the multipliers so that the
  // multiplication will not overflow, which would cause UB.
  //
  // Clamping is sufficient (as opposed to using int64_t) because the dividend
  // is the PCH clock frequency, which fits in 30 bits.
  //
  // The result is positive because the caller ensures that
  // `backlight_pwm_frequency_hz` is positive.
  const int32_t pwm_divider =
      std::min(parameters.backlight_pwm_frequency_hz,
               std::numeric_limits<int32_t>::max() / pwm_divider_granularity) *
      pwm_divider_granularity;

  // The frequency divider and duty cycle are 16-bit fields.
  static constexpr int32_t kMaxRawField = (1 << 16) - 1;

  // The division will not cause UB because `pwm_divider` is positive. The Intel
  // PRMs don't explicitly state that the PWM frequency divider shouldn't be
  // zero. We assume this is a good idea.
  const int32_t new_frequency_divider =
      std::max(1, std::min(RawClockHz() / pwm_divider, kMaxRawField));
  ZX_DEBUG_ASSERT(new_frequency_divider > 0);
  const uint32_t raw_frequency_divider = static_cast<uint32_t>(new_frequency_divider);

  // The cast does not cause UB because `raw_frequncy_divider` fits in 16 bits.
  const uint32_t raw_duty_cycle =
      ScaledPwmDutyCycle(static_cast<uint32_t>(raw_frequency_divider),
                         backlight_freq_duty_.duty_cycle(), backlight_freq_duty_.freq_divider());
  ZX_ASSERT(raw_duty_cycle <= raw_frequency_divider);
  ZX_ASSERT(raw_duty_cycle <= kMaxRawField);  // Implied by the check above.

  const uint32_t old_backlight_freq_duty = backlight_freq_duty_.reg_value();
  if (backlight_freq_duty_.freq_divider() != raw_frequency_divider) {
    // The backlight PWM must be turned off while changing the frequency. The
    // SetPanelBacklightPwmParameters() implementation has a deeper explanation.
    if (backlight_control_.pwm_counter_enabled()) {
      backlight_control_.set_pwm_counter_enabled(false).WriteTo(mmio_buffer_);
    }
  }

  backlight_freq_duty_.set_freq_divider(raw_frequency_divider);
  backlight_freq_duty_.set_duty_cycle(raw_duty_cycle);
  if (backlight_freq_duty_.reg_value() != old_backlight_freq_duty) {
    backlight_freq_duty_.WriteTo(mmio_buffer_);
  }
}

void PchEngine::SetPanelBacklightPwmParametersTigerLake(const PchPanelParameters& parameters) {
  // The cast is safe because RawClockHz() is non-negative and fits in 32 bits,
  // so the division result will also fit in 32 bits.
  const uint32_t raw_frequency_divider =
      static_cast<uint32_t>(std::max(1, RawClockHz() / parameters.backlight_pwm_frequency_hz));

  // We use the logical values in diffing (instead of the raw register values)
  // because the logical values perfectly map to the register values.
  const uint32_t old_frequency_divider = backlight_pwm_freq_.divider();
  const uint32_t old_duty_cycle = backlight_pwm_duty_.value();

  if (old_frequency_divider != raw_frequency_divider) {
    // The backlight PWM must be turned off while changing the frequency. The
    // SetPanelBacklightPwmParameters() implementation has a deeper explanation.
    //
    // Doing this here means we don't need to worry about possibly (briefly)
    // breaking the invariant that the PWM duty cycle must not exceed the PWM
    // frequency divider.
    if (backlight_control_.pwm_counter_enabled()) {
      backlight_control_.set_pwm_counter_enabled(false).WriteTo(mmio_buffer_);
    }
    backlight_pwm_freq_.set_divider(raw_frequency_divider).WriteTo(mmio_buffer_);
  }

  const uint32_t raw_duty_cycle =
      ScaledPwmDutyCycle(raw_frequency_divider, old_duty_cycle, old_frequency_divider);
  ZX_ASSERT(raw_duty_cycle <= raw_frequency_divider);
  if (old_duty_cycle != raw_duty_cycle) {
    backlight_pwm_duty_.set_value(raw_duty_cycle).WriteTo(mmio_buffer_);
  }
}

PchPanelPowerTarget PchEngine::PanelPowerTarget() const {
  return PchPanelPowerTarget{
      // The casts are safe because these are all 1-bit fields.
      .power_on = static_cast<bool>(panel_power_control_.power_state_target()),
      .backlight_on = static_cast<bool>(panel_power_control_.backlight_enabled()),
      .force_power_on = static_cast<bool>(panel_power_control_.vdd_always_on()),
      .brightness_pwm_counter_on = static_cast<bool>(backlight_control_.pwm_counter_enabled()),
  };
}

void PchEngine::SetPanelPowerTarget(const PchPanelPowerTarget& power_target) {
  const uint32_t old_panel_power_control = panel_power_control_.reg_value();
  panel_power_control_.set_power_state_target(power_target.power_on)
      .set_backlight_enabled(power_target.backlight_on)
      .set_vdd_always_on(power_target.force_power_on);

  const uint32_t old_backlight_control = backlight_control_.reg_value();
  backlight_control_.set_pwm_counter_enabled(power_target.brightness_pwm_counter_on);

  if (panel_power_control_.reg_value() != old_panel_power_control) {
    panel_power_control_.WriteTo(mmio_buffer_);
  }
  if (backlight_control_.reg_value() != old_backlight_control) {
    backlight_control_.WriteTo(mmio_buffer_);
  }
}

double PchEngine::PanelBrightness() const {
  uint32_t pwm_duty;
  uint32_t pwm_freq_divider;

  if (is_skl(device_id_) || is_kbl(device_id_)) {
    pwm_duty = backlight_freq_duty_.duty_cycle();
    pwm_freq_divider = backlight_freq_duty_.freq_divider();
  } else if (is_tgl(device_id_)) {
    pwm_duty = backlight_pwm_duty_.value();
    pwm_freq_divider = backlight_pwm_freq_.divider();
  } else if (is_test_device(device_id_)) {
    pwm_duty = 0;
    pwm_freq_divider = 1;
  } else {
    ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
  }

  if (pwm_freq_divider == 0) {
    // This matches the brightness level "preserved" by SetPanelParameters().
    return 0;
  }

  ZX_ASSERT_MSG(pwm_duty <= pwm_freq_divider, "Brightness PWM is configured incorrectly");
  return static_cast<double>(pwm_duty) / static_cast<double>(pwm_freq_divider);
}

void PchEngine::SetPanelBrightness(double brightness) {
  ZX_ASSERT(brightness >= 0.0);
  ZX_ASSERT(brightness <= 1.0);

  if (is_skl(device_id_) || is_kbl(device_id_)) {
    // The cast is safe because freq_divider() is a 16-bit field.
    const int32_t pwm_freq_divider = static_cast<int32_t>(backlight_freq_duty_.freq_divider());
    if (pwm_freq_divider == 0) {
      return;
    }
    const int32_t pwm_duty = std::min(
        // The cast is not UB because `brightness` is between 0 and 1, so the
        // rounding result should be between 0 and `pwm_freq_divider`.
        static_cast<int32_t>(std::round(static_cast<double>(pwm_freq_divider) * brightness)),
        pwm_freq_divider);

    const uint32_t old_backlight_freq_duty = backlight_freq_duty_.reg_value();
    backlight_freq_duty_.set_duty_cycle(pwm_duty);
    if (backlight_freq_duty_.reg_value() != old_backlight_freq_duty) {
      backlight_freq_duty_.WriteTo(mmio_buffer_);
    }
    return;
  }

  if (is_tgl(device_id_)) {
    const uint32_t pwm_freq_divider = backlight_pwm_freq_.divider();
    if (pwm_freq_divider == 0) {
      return;
    }
    const uint32_t pwm_duty = std::min(
        // The cast to uint32_t is safe because `brightness` is between 0 and 1,
        // so the rounding result should be between 0 and `pwm_freq_divider`.
        static_cast<uint32_t>(std::round(static_cast<double>(pwm_freq_divider) * brightness)),
        pwm_freq_divider);

    // We use the logical value in diffing (instead of the raw register values)
    // because the logical value perfectly maps to the register value.
    if (pwm_duty != backlight_pwm_duty_.value()) {
      backlight_pwm_duty_.set_value(pwm_duty).WriteTo(mmio_buffer_);
    }
    return;
  }

  if (is_test_device(device_id_)) {
    return;  // Stubbed out for integration tests.
  }

  ZX_ASSERT_MSG(false, "Unsupported PCI device ID %d", device_id_);
}

void PchEngine::Log() {
  const PchClockParameters clock_parameters = ClockParameters();
  zxlogf(TRACE, "PCH Raw Clock: %d Hz", clock_parameters.raw_clock_hz);
  zxlogf(TRACE, "PCH Panel Power Clock frequency: %d Hz", clock_parameters.panel_power_clock_hz);

  const char* state_text = "bug";
  switch (PanelPowerState()) {
    case PchPanelPowerState::kPoweredDown:
      state_text = "powered down";
      break;
    case PchPanelPowerState::kWaitingForPowerCycleDelay:
      state_text = "power cycle delay";
      break;
    case PchPanelPowerState::kPoweringUp:
      state_text = "powering up";
      break;
    case PchPanelPowerState::kPoweredUp:
      state_text = "powered up";
      break;
    case PchPanelPowerState::kPoweringDown:
      state_text = "powering down";
      break;
  }
  zxlogf(TRACE, "PCH Panel power state: %s", state_text);

  const PchPanelPowerTarget power_target = PanelPowerTarget();
  zxlogf(TRACE, "PCH Panel power target: %s", power_target.power_on ? "on" : "off");
  zxlogf(TRACE, "PCH Panel backlight: %s", power_target.backlight_on ? "enabled" : "disabled");
  zxlogf(TRACE, "PCH Panel VDD operation: %s",
         power_target.force_power_on ? "forced on" : "standard");
  zxlogf(TRACE, "PCH Backlight counter %s",
         power_target.brightness_pwm_counter_on ? "enabled" : "disabled");

  const PchPanelParameters panel_parameters = PanelParameters();
  zxlogf(TRACE, "PCH Panel T2 delay: %" PRId64 " us",
         panel_parameters.power_on_to_backlight_on_delay_micros);
  zxlogf(TRACE, "PCH Panel T3 delay: %" PRId64 " us",
         panel_parameters.power_on_to_hpd_aux_ready_delay_micros);
  zxlogf(TRACE, "PCH Panel T9 delay: %" PRId64 " us",
         panel_parameters.backlight_off_to_video_end_delay_micros);
  zxlogf(TRACE, "PCH Panel T10 delay: %" PRId64 " us",
         panel_parameters.video_end_to_power_off_delay_micros);
  zxlogf(TRACE, "PCH Panel T12 delay: %" PRId64 " us", panel_parameters.power_cycle_delay_micros);
  zxlogf(TRACE, "PCH Panel power down on reset: %s",
         panel_parameters.power_down_on_reset ? "on" : "off");
  zxlogf(TRACE, "PCH Backlight PWM frequency: %" PRId32 " Hz",
         panel_parameters.backlight_pwm_frequency_hz);
  zxlogf(TRACE, "PCH Backlight PWM polarity: %s",
         panel_parameters.backlight_pwm_inverted ? "inverted" : "not inverted");

  zxlogf(TRACE, "NDE_RSTWRN_OPT: %" PRIx32,
         registers::DisplayResetOptions::Get().ReadFrom(mmio_buffer_).reg_value());
  zxlogf(TRACE, "SCHICKEN_1: %" PRIx32, misc_.reg_value());
  zxlogf(TRACE, "RAWCLK_FREQ: %" PRIx32, clock_.reg_value());

  zxlogf(TRACE, "PP_CONTROL: %" PRIx32, panel_power_control_.reg_value());
  zxlogf(TRACE, "PP_ON_DELAYS: %" PRIx32, panel_power_on_delays_.reg_value());
  zxlogf(TRACE, "PP_OFF_DELAYS: %" PRIx32, panel_power_off_delays_.reg_value());
  zxlogf(TRACE, "PP_STATUS: %" PRIx32,
         registers::PchPanelPowerStatus::Get().ReadFrom(mmio_buffer_).reg_value());
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    zxlogf(TRACE, "PP_DIVISOR: %" PRIx32, panel_power_clock_delay_.reg_value());
  }

  zxlogf(TRACE, "SBLC_PWM_CTL1: %" PRIx32, backlight_control_.reg_value());
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    zxlogf(TRACE, "SBLC_PWM_CTL2: %" PRIx32, backlight_freq_duty_.reg_value());
  }
  if (is_tgl(device_id_)) {
    zxlogf(TRACE, "SBLC_PWM_FREQ: %" PRIx32, backlight_pwm_freq_.reg_value());
    zxlogf(TRACE, "SBLC_PWM_DUTY: %" PRIx32, backlight_pwm_duty_.reg_value());
  }
}

}  // namespace i915
