// Copyright 2021 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/amlogic-display/hdmi-host.h"

#include <fidl/fuchsia.hardware.platform.device/cpp/wire.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/result.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <fbl/alloc_checker.h>

#include "src/graphics/display/drivers/amlogic-display/board-resources.h"
#include "src/graphics/display/drivers/amlogic-display/clock-regs.h"
#include "src/graphics/display/drivers/amlogic-display/common.h"
#include "src/graphics/display/drivers/amlogic-display/encoder-regs.h"
#include "src/graphics/display/drivers/amlogic-display/gpio-mux-regs.h"
#include "src/graphics/display/drivers/amlogic-display/hhi-regs.h"
#include "src/graphics/display/drivers/amlogic-display/power-regs.h"
#include "src/graphics/display/drivers/amlogic-display/vpu-regs.h"
#include "src/graphics/display/lib/api-types-cpp/display-timing.h"
#include "src/graphics/display/lib/designware-hdmi/hdmi-transmitter-controller-impl.h"
#include "src/graphics/display/lib/designware-hdmi/hdmi-transmitter-controller.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/logging/zxlogf.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/namespace/namespace.h"

namespace amlogic_display {

namespace {

// Range of valid frequencies of the DCO (digitally controlled oscillator) of a
// certain PLL (phase-locked loop).
struct ValidDcoFrequencyRange {
  int64_t minimum_frequency_hz;
  int64_t maximum_frequency_hz;
};

ValidDcoFrequencyRange GetHdmiPllValidDcoFrequencyRange(int64_t pixel_clock_hz) {
  // Amlogic datasheets (A311D, S905D2 and S905D3) specify that the frequency
  // of the DCO in the HDMI PLL must be between 3 GHz and 6 GHz.
  //
  // However, [1] Amlogic-provided code uses 2.97 GHz for some common display
  // resolutions; [2] Experiments on Khadas VIM3 (Amlogic A311D) also shows
  // that 2.9 GHz is a valid DCO frequency for all the display timings we have
  // tested and has fewer display glitches than using 5.8 GHz. So, we use
  // 2.9 GHz rather than 3 GHz as the minimum valid DCO frequency for default
  // cases.
  static constexpr int64_t kDefaultMinimumValidHdmiPllDcoFrequencyHz = 2'900'000'000;
  static constexpr int64_t kDefaultMaximumValidHdmiPllDcoFrequencyHz = 6'000'000'000;

  // For display timings with a very low pixel clock rate (for example, on
  // Surenoo SUR480480Y021A, it has a pixel clock of 16.96 MHz), in our
  // experiments, we had to lower the minimum allowed DCO frequency to 2.7 GHz
  // in order to keep the correct display aspect ratio.
  //
  // Since this is not a valid frequency documented in the datasheets, this
  // should only be used as an exception when the pixel clock rate is very
  // low. Thus, we only set the minimum allowed DCO frequency to 2.7 GHz, if
  // the pixel clock is lower than 20 MHz (which is lower than the pixel clock
  // of DMT timing of 640x480p@60Hz) so that it won't affect "normal" display
  // modes.
  static constexpr int64_t kLowPixelClockMinimumValidHdmiPllDcoFrequencyHz = 2'700'000'000;
  static constexpr int64_t kLowPixelClockThresholdHz = 20'000'000;
  if (pixel_clock_hz <= kLowPixelClockThresholdHz) {
    return {
        .minimum_frequency_hz = kLowPixelClockMinimumValidHdmiPllDcoFrequencyHz,
        .maximum_frequency_hz = kDefaultMaximumValidHdmiPllDcoFrequencyHz,
    };
  }

  return {
      .minimum_frequency_hz = kDefaultMinimumValidHdmiPllDcoFrequencyHz,
      .maximum_frequency_hz = kDefaultMaximumValidHdmiPllDcoFrequencyHz,
  };
}

// `timing` must be a timing supported by `HdmiHost`.
pll_param CalculateClockParameters(const display::DisplayTiming& timing) {
  pll_param params;

  // TODO: We probably need a more sophisticated method for calculating
  // clocks. This will do for now.
  params.viu_channel = 1;
  params.viu_type = VIU_ENCP;

  params.hdmi_clock_tree_vid_pll_divider = 5;
  params.video_clock1_divider = 2;
  params.hdmi_transmitter_pixel_clock_divider = 1;
  params.encp_clock_divider = 1;

  params.output_divider1 = 1;
  params.output_divider2 = 1;
  params.output_divider3 = 1;

  params.hdmi_pll_vco_output_frequency_hz = timing.pixel_clock_frequency_hz * 10;

  const ValidDcoFrequencyRange valid_dco_frequency_range =
      GetHdmiPllValidDcoFrequencyRange(timing.pixel_clock_frequency_hz);
  while (params.hdmi_pll_vco_output_frequency_hz < valid_dco_frequency_range.minimum_frequency_hz) {
    if (params.output_divider1 < 4) {
      params.output_divider1 *= 2;
      params.hdmi_pll_vco_output_frequency_hz *= 2;
    } else if (params.output_divider2 < 4) {
      params.output_divider2 *= 2;
      params.hdmi_pll_vco_output_frequency_hz *= 2;
    } else if (params.output_divider3 < 4) {
      params.output_divider3 *= 2;
      params.hdmi_pll_vco_output_frequency_hz *= 2;
    } else {
      ZX_DEBUG_ASSERT_MSG(
          false,
          "Failed to set HDMI PLL to a valid VCO frequency range for pixel clock %" PRId64
          " Hz. This should never happen since IsDisplayTimingSupported() "
          "returned true.",
          timing.pixel_clock_frequency_hz);
    }
  }
  ZX_DEBUG_ASSERT_MSG(
      params.hdmi_pll_vco_output_frequency_hz <= valid_dco_frequency_range.maximum_frequency_hz,
      "Calculated HDMI PLL VCO frequency (%" PRId64 " Hz) exceeds the VCO frequency limit %" PRId64
      " Hz. This should never happen since IsDisplayTimingSupported() returned true.",
      params.hdmi_pll_vco_output_frequency_hz, valid_dco_frequency_range.maximum_frequency_hz);
  return params;
}

zx::result<std::unique_ptr<HdmiTransmitter>> CreateHdmiTransmitter(
    fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) {
  if (!platform_device.is_valid()) {
    zxlogf(ERROR, "PDev protocol is invalid");
    return zx::error(ZX_ERR_NO_RESOURCES);
  }

  zx::result<fdf::MmioBuffer> hdmi_tx_mmio_result =
      MapMmio(MmioResourceIndex::kHdmiTxController, platform_device);
  if (hdmi_tx_mmio_result.is_error()) {
    return hdmi_tx_mmio_result.take_error();
  }

  fbl::AllocChecker alloc_checker;
  std::unique_ptr<designware_hdmi::HdmiTransmitterController> designware_controller =
      fbl::make_unique_checked<designware_hdmi::HdmiTransmitterControllerImpl>(
          &alloc_checker, std::move(hdmi_tx_mmio_result).value());
  if (!alloc_checker.check()) {
    zxlogf(ERROR, "Could not allocate memory for DesignWare HdmiTransmitterControllerImpl");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  zx::result<fdf::MmioBuffer> hdmi_top_mmio_result =
      MapMmio(MmioResourceIndex::kHdmiTxTop, platform_device);
  if (hdmi_top_mmio_result.is_error()) {
    return hdmi_top_mmio_result.take_error();
  }

  zx::result<zx::resource> smc_result =
      GetSecureMonitorCall(SecureMonitorCallResourceIndex::kSiliconProvider, platform_device);
  if (smc_result.is_error()) {
    return smc_result.take_error();
  }

  std::unique_ptr<HdmiTransmitter> hdmi_transmitter = fbl::make_unique_checked<HdmiTransmitter>(
      &alloc_checker, std::move(designware_controller), std::move(hdmi_top_mmio_result).value(),
      std::move(smc_result).value());
  if (!alloc_checker.check()) {
    zxlogf(ERROR, "Could not allocate memory for HdmiTransmitter");
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  return zx::ok(std::move(hdmi_transmitter));
}

}  // namespace

HdmiHost::HdmiHost(std::unique_ptr<HdmiTransmitter> hdmi_transmitter, fdf::MmioBuffer vpu_mmio,
                   fdf::MmioBuffer hhi_mmio, fdf::MmioBuffer gpio_mux_mmio)
    : hdmi_transmitter_(std::move(hdmi_transmitter)),
      vpu_mmio_(std::move(vpu_mmio)),
      hhi_mmio_(std::move(hhi_mmio)),
      gpio_mux_mmio_(std::move(gpio_mux_mmio)) {
  ZX_DEBUG_ASSERT(hdmi_transmitter_ != nullptr);
}

// static
zx::result<std::unique_ptr<HdmiHost>> HdmiHost::Create(display::Namespace& incoming) {
  static constexpr char kPdevFragmentName[] = "pdev";
  zx::result<fidl::ClientEnd<fuchsia_hardware_platform_device::Device>> pdev_result =
      incoming.Connect<fuchsia_hardware_platform_device::Service::Device>(kPdevFragmentName);
  if (pdev_result.is_error()) {
    zxlogf(ERROR, "Failed to get the pdev client: %s", pdev_result.status_string());
    return pdev_result.take_error();
  }
  fidl::ClientEnd<fuchsia_hardware_platform_device::Device> platform_device =
      std::move(pdev_result).value();

  if (!platform_device.is_valid()) {
    zxlogf(ERROR, "Could not get the platform device client.");
    return zx::error(ZX_ERR_INTERNAL);
  }

  zx::result<fdf::MmioBuffer> vpu_mmio_result = MapMmio(MmioResourceIndex::kVpu, platform_device);
  if (vpu_mmio_result.is_error()) {
    return vpu_mmio_result.take_error();
  }

  zx::result<fdf::MmioBuffer> hhi_mmio_result = MapMmio(MmioResourceIndex::kHhi, platform_device);
  if (hhi_mmio_result.is_error()) {
    return hhi_mmio_result.take_error();
  }

  zx::result<fdf::MmioBuffer> gpio_mux_mmio_result =
      MapMmio(MmioResourceIndex::kGpioMux, platform_device);
  if (gpio_mux_mmio_result.is_error()) {
    return gpio_mux_mmio_result.take_error();
  }

  zx::result<std::unique_ptr<HdmiTransmitter>> hdmi_transmitter =
      CreateHdmiTransmitter(platform_device);
  if (hdmi_transmitter.is_error()) {
    zxlogf(ERROR, "Could not create HDMI transmitter: %s", hdmi_transmitter.status_string());
    return hdmi_transmitter.take_error();
  }
  ZX_ASSERT(hdmi_transmitter.value() != nullptr);

  fbl::AllocChecker alloc_checker;
  std::unique_ptr<HdmiHost> hdmi_host = fbl::make_unique_checked<HdmiHost>(
      &alloc_checker, std::move(hdmi_transmitter).value(), std::move(vpu_mmio_result).value(),
      std::move(hhi_mmio_result).value(), std::move(gpio_mux_mmio_result).value());
  if (!alloc_checker.check()) {
    zxlogf(ERROR, "Could not allocate memory for the HdmiHost instance.");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  return zx::ok(std::move(hdmi_host));
}

zx_status_t HdmiHost::HostOn() {
  /* Step 1: Initialize various clocks related to the HDMI Interface*/
  gpio_mux_mmio_.Write32(
      SetFieldValue32(gpio_mux_mmio_.Read32(PAD_PULL_UP_EN_REG3), /*field_begin_bit=*/0,
                      /*field_size_bits=*/2, /*field_value=*/0),
      PAD_PULL_UP_EN_REG3);
  gpio_mux_mmio_.Write32(
      SetFieldValue32(gpio_mux_mmio_.Read32(PAD_PULL_UP_REG3), /*field_begin_bit=*/0,
                      /*field_size_bits=*/2, /*field_value=*/0),
      PAD_PULL_UP_REG3);
  gpio_mux_mmio_.Write32(
      SetFieldValue32(gpio_mux_mmio_.Read32(P_PREG_PAD_GPIO3_EN_N), /*field_begin_bit=*/0,
                      /*field_size_bits=*/2, /*field_value=*/3),
      P_PREG_PAD_GPIO3_EN_N);
  gpio_mux_mmio_.Write32(
      SetFieldValue32(gpio_mux_mmio_.Read32(PERIPHS_PIN_MUX_B), /*field_begin_bit=*/0,
                      /*field_size_bits=*/8, /*field_value=*/0x11),
      PERIPHS_PIN_MUX_B);

  // enable clocks
  HdmiClockControl::Get()
      .ReadFrom(&hhi_mmio_)
      .SetHdmiTxSystemClockDivider(1)
      .set_hdmi_tx_system_clock_enabled(true)
      .set_hdmi_tx_system_clock_selection(
          HdmiClockControl::HdmiTxSystemClockSource::kExternalOscillator24Mhz)
      .WriteTo(&hhi_mmio_);

  // enable clk81 (needed for HDMI module and a bunch of other modules)
  HhiGclkMpeg2Reg::Get().ReadFrom(&hhi_mmio_).set_clk81_en(1).WriteTo(&hhi_mmio_);

  // TODO(fxbug.com/132123): HDMI memory was supposed to be powered on during
  // the VPU power sequence. The AMLogic-supplied bringup code pauses for 5us
  // between each bit flip.
  auto memory_power0 = MemoryPower0::Get().ReadFrom(&hhi_mmio_);
  memory_power0.set_hdmi_memory0_powered_off(false);
  memory_power0.set_hdmi_memory1_powered_off(false);
  memory_power0.set_hdmi_memory2_powered_off(false);
  memory_power0.set_hdmi_memory3_powered_off(false);
  memory_power0.set_hdmi_memory4_powered_off(false);
  memory_power0.set_hdmi_memory5_powered_off(false);
  memory_power0.set_hdmi_memory6_powered_off(false);
  memory_power0.set_hdmi_memory7_powered_off(false);
  memory_power0.WriteTo(&hhi_mmio_);

  zx::result<> reset_result = hdmi_transmitter_->Reset();  // only supports 1 display for now
  if (reset_result.is_error()) {
    zxlogf(ERROR, "Failed to reset the HDMI transmitter: %s", reset_result.status_string());
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

void HdmiHost::HostOff() {
  /* Close HDMITX PHY */
  hhi_mmio_.Write32(0, HHI_HDMI_PHY_CNTL0);
  hhi_mmio_.Write32(0, HHI_HDMI_PHY_CNTL3);
  /* Disable HPLL */
  hhi_mmio_.Write32(0, HHI_HDMI_PLL_CNTL0);
}

zx_status_t HdmiHost::ModeSet(const display::DisplayTiming& timing) {
  if (!IsDisplayTimingSupported(timing)) {
    zxlogf(
        ERROR,
        "Display timing (%" PRIu32 " x %" PRIu32 " @ pixel rate %" PRId64 " Hz) is not supported.",
        timing.horizontal_active_px, timing.vertical_active_lines, timing.pixel_clock_frequency_hz);
    return ZX_ERR_NOT_SUPPORTED;
  }

  pll_param clock_params = CalculateClockParameters(timing);
  ConfigurePll(clock_params);

  vpu_mmio_.Write32(0, VPU_ENCP_VIDEO_EN);
  vpu_mmio_.Write32(0, VPU_ENCI_VIDEO_EN);
  // Connect both VIUs (Video Input Units) to the Progressive Encoder (ENCP),
  // assuming the display is progressive.
  VideoInputUnitEncoderMuxControl::Get()
      .ReadFrom(&vpu_mmio_)
      .set_vsync_shared_by_viu_blocks(false)
      .set_viu1_encoder_selection(VideoInputUnitEncoderMuxControl::Encoder::kProgressive)
      .set_viu2_encoder_selection(VideoInputUnitEncoderMuxControl::Encoder::kProgressive)
      .WriteTo(&vpu_mmio_);

  // Configure Encoder with detailed timing info (based on resolution)
  ConfigEncoder(timing);

  // Configure VDAC
  hhi_mmio_.Write32(0, HHI_VDAC_CNTL0_G12A);
  hhi_mmio_.Write32(8, HHI_VDAC_CNTL1_G12A);  // set Cdac_pwd [whatever that is]

  static constexpr designware_hdmi::ColorParam kColorParams{
      .input_color_format = designware_hdmi::ColorFormat::kCf444,

      // We choose the RGB 4:4:4 encoding unconditionally for the HDMI output
      // signals. This implies that we avoid YCbCr encodings, even if they are
      // unsupported.
      //
      // The HDMI specificiaton v1.4b, Section 6.2.3 "Pixel Encoding
      // Requirements" (page 106) requires that all HDMI sources and sinks
      // support RGB 4:4:4 encoding. Thus we think this approach will work with
      // all of our devices.
      //
      // Also, we encountered hardware (Yongxing HDMI to MIPI-DSI converters
      // board v1.2, using the Toshiba TC358870XBG converter chip, provided with
      // the Amelin AML028-30MB-A1 assembly) that claims support for the YCbCr
      // 4:4:4 pixel encoding in EDID, but does not display colors correctly
      // when we use that encoding. That hardware should be considered when
      // changing this strategy.
      .output_color_format = designware_hdmi::ColorFormat::kCfRgb,

      .color_depth = designware_hdmi::ColorDepth::kCd24B,
  };
  zx::result<> modeset_result = hdmi_transmitter_->ModeSet(timing, kColorParams);
  if (modeset_result.is_error()) {
    zxlogf(ERROR, "Failed to set display mode: %s", modeset_result.status_string());
    return modeset_result.status_value();
  }

  // Setup HDMI related registers in VPU
  // not really needed since we are not converting from 420/422. but set anyways
  VpuHdmiFmtCtrlReg::Get()
      .FromValue(0)
      .set_cntl_chroma_dnsmp(2)
      .set_cntl_hdmi_dith_en(0)
      .set_rounding_enable(1)
      .WriteTo(&vpu_mmio_);

  // setup some magic registers
  VpuHdmiDithCntlReg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_cntl_hdmi_dith_en(1)
      .set_hsync_invert(0)
      .set_vsync_invert(0)
      .WriteTo(&vpu_mmio_);

  // reset vpu bridge
  uint32_t wr_rate = VpuHdmiSettingReg::Get().ReadFrom(&vpu_mmio_).wr_rate();
  vpu_mmio_.Write32(0, VPU_ENCP_VIDEO_EN);
  VpuHdmiSettingReg::Get().ReadFrom(&vpu_mmio_).set_src_sel(0).set_wr_rate(0).WriteTo(&vpu_mmio_);
  usleep(1);
  vpu_mmio_.Write32(1, VPU_ENCP_VIDEO_EN);
  usleep(1);
  VpuHdmiSettingReg::Get().ReadFrom(&vpu_mmio_).set_wr_rate(wr_rate).WriteTo(&vpu_mmio_);
  usleep(1);
  VpuHdmiSettingReg::Get().ReadFrom(&vpu_mmio_).set_src_sel(2).WriteTo(&vpu_mmio_);

  // setup hdmi phy
  ConfigPhy();

  zxlogf(INFO, "done!!");
  return ZX_OK;
}

zx_status_t HdmiHost::EdidTransfer(const i2c_impl_op_t* op_list, size_t op_count) {
  zx::result<> i2c_transact_result = hdmi_transmitter_->I2cTransact(op_list, op_count);
  if (i2c_transact_result.is_error()) {
    zxlogf(ERROR, "Failed to transfer EDID: %s", i2c_transact_result.status_string());
    return i2c_transact_result.status_value();
  }
  return ZX_OK;
}

namespace {

// Returns true iff the display PLL and clock trees can be programmed to
// generate a pixel clock of `pixel_clock_hz`.
bool IsPixelClockSupported(int64_t pixel_clock_hz) {
  const ValidDcoFrequencyRange valid_dco_frequency_range =
      GetHdmiPllValidDcoFrequencyRange(pixel_clock_hz);

  // Fixed divisor values.
  //
  // HDMI clock tree divisor `vid_pll_div` == 5,
  // Video tree divisor /N0 `vid_clk_div` == 2,
  // Video tree ENCP clock selector `encp_div` == 1.
  //
  // TODO(https://fxbug.dev/42083149): Factor this out for pixel clock checking and
  // calculation logics.
  constexpr int kFixedPllDivisionFactor = 5 * 2 * 1;

  // TODO(https://fxbug.dev/42083149): Factor out ranges for each output frequency
  // divider so that they can be used for both clock checking and calculation.
  // OD1 = OD2 = OD3 = 1.
  constexpr int kMinimumPllDivisionFactor = 1 * 1 * 1;
  // OD1 = OD2 = OD3 = 4.
  constexpr int kMaximumPllDivisionFactor = 4 * 4 * 4;

  // The adjustable dividers OD1 / OD2 / OD3 cannot be calculated if the output
  // frequency using `kMinimumPllDivisionFactor` still exceeds the maximum
  // allowed value.
  const int64_t maximum_allowed_pixel_clock_hz =
      valid_dco_frequency_range.maximum_frequency_hz /
      (kFixedPllDivisionFactor * kMinimumPllDivisionFactor);
  if (pixel_clock_hz > maximum_allowed_pixel_clock_hz) {
    return false;
  }

  // The adjustable dividers OD1 / OD2 / OD3 cannot be calculated if the output
  // frequency using `kMaximumPllDivisionFactor` is still less than the minimum
  // allowed value.

  // ceil(kMinimumValidHdmiPllVcoFrequencyHz / (kFixedPllDivisionFactor *
  // kMaximumPllDivisionFactor))
  const int64_t minimum_allowed_pixel_clock_hz =
      (valid_dco_frequency_range.minimum_frequency_hz +
       kFixedPllDivisionFactor * kMaximumPllDivisionFactor - 1) /
      (kFixedPllDivisionFactor * kMaximumPllDivisionFactor);
  if (pixel_clock_hz < minimum_allowed_pixel_clock_hz) {
    return false;
  }

  return true;
}

}  // namespace

bool HdmiHost::IsDisplayTimingSupported(const display::DisplayTiming& timing) const {
  // TODO(https://fxbug.dev/42075808): High-resolution display modes (4K or more) are not
  // supported.
  const int kMaximumAllowedWidthPixels = 2560;
  const int kMaximumAllowedHeightPixels = 1600;

  if (timing.horizontal_active_px > kMaximumAllowedWidthPixels ||
      timing.vertical_active_lines > kMaximumAllowedHeightPixels) {
    return false;
  }

  // TODO(https://fxbug.dev/42083230): Interlaced modes are not supported.
  if (timing.fields_per_frame == display::FieldsPerFrame::kInterlaced) {
    return false;
  }

  // TODO(https://fxbug.dev/42083230): Interlaced modes with alternating vblanks are not
  // supported.
  if (timing.vblank_alternates) {
    return false;
  }

  // TODO(https://fxbug.dev/42084414): Modes with pixel repetition are not supported.
  if (timing.pixel_repetition != 0) {
    return false;
  }

  if (!IsPixelClockSupported(timing.pixel_clock_frequency_hz)) {
    return false;
  }

  return true;
}

void HdmiHost::ReplaceEncoderPixelColorWithBlack(bool enabled) {
  if (enabled) {
    EncoderBuiltInSelfTestModeSelection::Get()
        .FromValue(0)
        .set_mode(EncoderBuiltInSelfTestMode::kFixedColor)
        .WriteTo(&vpu_mmio_);

    // Sets the 10-bit YCbCr color value that replaces the Video Input Unit
    // output.
    //
    // Black (R = 0, G = 0, B = 0) is (Y = 0, Cb = 512, Cr = 512) in YCbCr.
    EncoderBuiltInSelfTestFixedColorLuminance::Get().FromValue(0).set_luminance(0).WriteTo(
        &vpu_mmio_);
    EncoderBuiltInSelfTestFixedColorChrominanceBlue::Get()
        .FromValue(0)
        .set_chrominance_blue(0x200)
        .WriteTo(&vpu_mmio_);
    EncoderBuiltInSelfTestFixedColorChrominanceRed::Get()
        .FromValue(0)
        .set_chrominance_red(0x200)
        .WriteTo(&vpu_mmio_);
  }

  HdmiEncoderAdvancedModeConfig::Get()
      .ReadFrom(&vpu_mmio_)
      .set_viu_fifo_enabled(!enabled)
      .WriteTo(&vpu_mmio_);
  EncoderBuiltInSelfTestEnabled::Get().FromValue(0).set_enabled(enabled).WriteTo(&vpu_mmio_);
}

void HdmiHost::ConfigEncoder(const display::DisplayTiming& timing) {
  // TODO(https://fxbug.dev/42084909): For timings that have repetitive pixels
  // (for example, 1440x480p60 and 1440x480i60), the Amlogic-provided code has
  // contradictory and (in most cases) incomplete configurations. Thus, we'll
  // reject all such formats.
  ZX_DEBUG_ASSERT(timing.pixel_repetition == 0);

  // TODO(https://fxbug.dev/42084909): The current code assumes the timing is for
  // progressive fields.
  ZX_DEBUG_ASSERT(timing.fields_per_frame == display::FieldsPerFrame::kProgressive);

  vpu_mmio_.Write32(timing.horizontal_total_px() - 1, VPU_ENCP_VIDEO_MAX_PXCNT);
  vpu_mmio_.Write32(timing.vertical_total_lines() - 1, VPU_ENCP_VIDEO_MAX_LNCNT);

  vpu_mmio_.Write32(0, VPU_ENCI_VIDEO_EN);
  vpu_mmio_.Write32(1, VPU_ENCP_VIDEO_EN);

  vpu_mmio_.Write32(0x4040, VPU_ENCP_VIDEO_MODE);
  vpu_mmio_.Write32(0x18, VPU_ENCP_VIDEO_MODE_ADV);

  vpu_mmio_.Write32(SetFieldValue32(vpu_mmio_.Read32(VPU_ENCP_VIDEO_MODE), /*field_begin_bit=*/14,
                                    /*field_size_bits=*/1, /*field_value=*/1),
                    VPU_ENCP_VIDEO_MODE);  // DE Signal polarity

  const int video_horizontal_sync_begin_px = 0;
  const int video_horizontal_sync_end_px =
      video_horizontal_sync_begin_px + timing.horizontal_sync_width_px - 1;
  const int video_horizontal_active_begin_px =
      video_horizontal_sync_end_px + 1 + timing.horizontal_back_porch_px;
  const int video_horizontal_active_end_px =
      video_horizontal_active_begin_px + timing.horizontal_active_px - 1;
  const int video_horizontal_period_px = timing.horizontal_total_px();

  // Experiments on Khadas VIM3 (using Amlogic A311D) show that HAVON_*
  // registers must be set before HSO_* registers, otherwise the encoder
  // won't work.
  vpu_mmio_.Write32(video_horizontal_active_begin_px, VPU_ENCP_VIDEO_HAVON_BEGIN);
  vpu_mmio_.Write32(video_horizontal_active_end_px, VPU_ENCP_VIDEO_HAVON_END);
  vpu_mmio_.Write32(video_horizontal_sync_begin_px, VPU_ENCP_VIDEO_HSO_BEGIN);
  vpu_mmio_.Write32(video_horizontal_sync_end_px + 1, VPU_ENCP_VIDEO_HSO_END);

  const int video_vertical_sync_begin_line = 0;
  const int video_vertical_sync_end_line =
      video_vertical_sync_begin_line + timing.vertical_sync_width_lines - 1;
  const int video_vertical_active_begin_line =
      video_vertical_sync_end_line + 1 + timing.vertical_back_porch_lines;
  const int video_vertical_active_end_line =
      video_vertical_active_begin_line + timing.vertical_active_lines - 1;

  // Experiments on Khadas VIM3 (using Amlogic A311D) show that VAVON_*
  // registers must be set before VSO_* registers, otherwise the encoder
  // won't work.
  vpu_mmio_.Write32(video_vertical_active_begin_line, VPU_ENCP_VIDEO_VAVON_BLINE);
  vpu_mmio_.Write32(video_vertical_active_end_line, VPU_ENCP_VIDEO_VAVON_ELINE);
  vpu_mmio_.Write32(video_vertical_sync_begin_line, VPU_ENCP_VIDEO_VSO_BLINE);
  vpu_mmio_.Write32(video_vertical_sync_end_line + 1, VPU_ENCP_VIDEO_VSO_ELINE);
  vpu_mmio_.Write32(16, VPU_ENCP_VIDEO_VSO_BEGIN);
  vpu_mmio_.Write32(32, VPU_ENCP_VIDEO_VSO_END);

  // The latency between HDMI timing signals (DE, VSYNC, HSYNC) and the video
  // signal (from VFIFO).
  static constexpr int hdmi_signal_horizontal_offset = 2;

  const int hdmi_horizontal_sync_begin_px =
      (video_horizontal_sync_begin_px + hdmi_signal_horizontal_offset) % video_horizontal_period_px;
  const int hdmi_horizontal_sync_end_px =
      (video_horizontal_sync_end_px + hdmi_signal_horizontal_offset) % video_horizontal_period_px;
  const int hdmi_horizontal_active_begin_px =
      (video_horizontal_active_begin_px + hdmi_signal_horizontal_offset) %
      video_horizontal_period_px;
  const int hdmi_horizontal_active_end_px =
      (video_horizontal_active_end_px + hdmi_signal_horizontal_offset) % video_horizontal_period_px;

  vpu_mmio_.Write32(hdmi_horizontal_active_begin_px, VPU_ENCP_DE_H_BEGIN);
  vpu_mmio_.Write32(hdmi_horizontal_active_end_px + 1, VPU_ENCP_DE_H_END);
  vpu_mmio_.Write32(hdmi_horizontal_sync_begin_px, VPU_ENCP_DVI_HSO_BEGIN);
  vpu_mmio_.Write32(hdmi_horizontal_sync_end_px + 1, VPU_ENCP_DVI_HSO_END);

  const int hdmi_vertical_sync_begin_line = video_vertical_sync_begin_line;
  const int hdmi_vertical_sync_end_line = video_vertical_sync_end_line;
  const int hdmi_vertical_active_begin_line = video_vertical_active_begin_line;
  const int hdmi_vertical_active_end_line = video_vertical_active_end_line;

  vpu_mmio_.Write32(hdmi_vertical_active_begin_line, VPU_ENCP_DE_V_BEGIN_EVEN);
  vpu_mmio_.Write32(hdmi_vertical_active_end_line + 1, VPU_ENCP_DE_V_END_EVEN);
  vpu_mmio_.Write32(hdmi_vertical_sync_begin_line, VPU_ENCP_DVI_VSO_BLINE_EVN);
  vpu_mmio_.Write32(hdmi_vertical_sync_end_line + 1, VPU_ENCP_DVI_VSO_ELINE_EVN);
  vpu_mmio_.Write32(hdmi_horizontal_sync_begin_px, VPU_ENCP_DVI_VSO_BEGIN_EVN);
  vpu_mmio_.Write32(hdmi_horizontal_sync_begin_px, VPU_ENCP_DVI_VSO_END_EVN);

  // hsync, vsync active high. output CbYCr (GRB)
  // TODO: output desired format is hardcoded here to CbYCr (GRB)
  uint32_t vpu_hdmi_setting = 0b100 << 5;
  if (timing.hsync_polarity == display::SyncPolarity::kPositive) {
    vpu_hdmi_setting |= (1 << 2);
  }
  if (timing.vsync_polarity == display::SyncPolarity::kPositive) {
    vpu_hdmi_setting |= (1 << 3);
  }
  vpu_mmio_.Write32(vpu_hdmi_setting, VPU_HDMI_SETTING);

  // Select ENCP data to HDMI
  VpuHdmiSettingReg::Get().ReadFrom(&vpu_mmio_).set_src_sel(2).WriteTo(&vpu_mmio_);

  zxlogf(INFO, "done");
}

void HdmiHost::ConfigPhy() {
  HhiHdmiPhyCntl0Reg::Get().FromValue(0).WriteTo(&hhi_mmio_);
  HhiHdmiPhyCntl1Reg::Get()
      .ReadFrom(&hhi_mmio_)
      .set_hdmi_tx_phy_soft_reset(0)
      .set_hdmi_tx_phy_clk_en(0)
      .set_hdmi_fifo_enable(0)
      .set_hdmi_fifo_wr_enable(0)
      .set_msb_lsb_swap(0)
      .set_bit_invert(0)
      .set_ch0_swap(0)
      .set_ch1_swap(1)
      .set_ch2_swap(2)
      .set_ch3_swap(3)
      .set_new_prbs_en(0)
      .set_new_prbs_sel(0)
      .set_new_prbs_prbsmode(0)
      .set_new_prbs_mode(0)
      .WriteTo(&hhi_mmio_);

  HhiHdmiPhyCntl1Reg::Get()
      .ReadFrom(&hhi_mmio_)
      .set_hdmi_tx_phy_soft_reset(1)
      .set_hdmi_tx_phy_clk_en(1)
      .set_hdmi_fifo_enable(1)
      .set_hdmi_fifo_wr_enable(1)
      .WriteTo(&hhi_mmio_);
  usleep(2);
  HhiHdmiPhyCntl1Reg::Get()
      .ReadFrom(&hhi_mmio_)
      .set_hdmi_tx_phy_soft_reset(0)
      .set_hdmi_tx_phy_clk_en(1)
      .set_hdmi_fifo_enable(1)
      .set_hdmi_fifo_wr_enable(1)
      .WriteTo(&hhi_mmio_);
  usleep(2);
  HhiHdmiPhyCntl1Reg::Get()
      .ReadFrom(&hhi_mmio_)
      .set_hdmi_tx_phy_soft_reset(1)
      .set_hdmi_tx_phy_clk_en(1)
      .set_hdmi_fifo_enable(1)
      .set_hdmi_fifo_wr_enable(1)
      .WriteTo(&hhi_mmio_);
  usleep(2);
  HhiHdmiPhyCntl1Reg::Get()
      .ReadFrom(&hhi_mmio_)
      .set_hdmi_tx_phy_soft_reset(0)
      .set_hdmi_tx_phy_clk_en(1)
      .set_hdmi_fifo_enable(1)
      .set_hdmi_fifo_wr_enable(1)
      .WriteTo(&hhi_mmio_);
  usleep(2);

  // The following configuration for HDMI PHY control register 0, 3 and 5 only
  // works for display modes where the display resolution is lower than
  // 3840 x 2160. The configuration currently works for all display modes
  // supported by this driver.
  //
  // TODO(https://fxbug.dev/42075808): Set the PHY control registers properly if the
  // display uses a 4k resolution (3840 x 2160 or higher).
  HhiHdmiPhyCntl0Reg::Get().FromValue(0).set_hdmi_ctl1(0x33eb).set_hdmi_ctl2(0x4242).WriteTo(
      &hhi_mmio_);
  HhiHdmiPhyCntl3Reg::Get().FromValue(0x2ab0ff3b).WriteTo(&hhi_mmio_);
  HhiHdmiPhyCntl5Reg::Get().FromValue(0x00000003).WriteTo(&hhi_mmio_);

  usleep(20);
  zxlogf(INFO, "done!");
}

}  // namespace amlogic_display
