// 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-display/pch-engine.h"

#include <lib/driver/logging/cpp/logger.h>
#include <lib/driver/mmio/cpp/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-display/pci-ids.h"
#include "src/graphics/display/drivers/intel-display/registers-ddi.h"
#include "src/graphics/display/drivers/intel-display/registers-pch.h"
#include "src/graphics/display/lib/driver-utils/poll-until.h"

namespace intel_display {

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 display::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();
  fdf::trace("PCH Raw Clock: {} Hz", clock_parameters.raw_clock_hz);
  fdf::trace("PCH Panel Power Clock frequency: {} 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;
  }
  fdf::trace("PCH Panel power state: {}", state_text);

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

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

  fdf::trace("NDE_RSTWRN_OPT: {:x}",
             registers::DisplayResetOptions::Get().ReadFrom(mmio_buffer_).reg_value());
  fdf::trace("SCHICKEN_1: {:x}", misc_.reg_value());
  fdf::trace("RAWCLK_FREQ: {:x}", clock_.reg_value());

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

  fdf::trace("SBLC_PWM_CTL1: {:x}", backlight_control_.reg_value());
  if (is_skl(device_id_) || is_kbl(device_id_)) {
    fdf::trace("SBLC_PWM_CTL2: {:x}", backlight_freq_duty_.reg_value());
  }
  if (is_tgl(device_id_)) {
    fdf::trace("SBLC_PWM_FREQ: {:x}", backlight_pwm_freq_.reg_value());
    fdf::trace("SBLC_PWM_DUTY: {:x}", backlight_pwm_duty_.reg_value());
  }
}

}  // namespace intel_display
