// Copyright 2018 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/vpu.h"

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

#include <cstdint>
#include <utility>

#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/power-regs.h"
#include "src/graphics/display/drivers/amlogic-display/video-input-regs.h"
#include "src/graphics/display/drivers/amlogic-display/vpp-regs.h"
#include "src/graphics/display/drivers/amlogic-display/vpu-regs.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/logging/zxlogf.h"

namespace amlogic_display {

namespace {
constexpr uint32_t kFirstTimeLoadMagicNumber = 0x304e65;  // 0Ne

constexpr int16_t RGB709_to_YUV709l_coeff[24] = {
    0x0000, 0x0000, 0x0000, 0x00bb, 0x0275, 0x003f, 0x1f99, 0x1ea6, 0x01c2, 0x01c2, 0x1e67, 0x1fd7,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0040, 0x0200, 0x0200, 0x0000, 0x0000, 0x0000,
};

// Below co-efficients are used to convert 709L to RGB. The table is provided
// by Amlogic
//    ycbcr limit range, 709 to RGB
//    -16      1.164  0      1.793  0
//    -128     1.164 -0.213 -0.534  0
//    -128     1.164  2.115  0      0
constexpr uint32_t capture_yuv2rgb_coeff[3][3] = {
    {0x04a8, 0x0000, 0x072c}, {0x04a8, 0x1f26, 0x1ddd}, {0x04a8, 0x0876, 0x0000}};
constexpr uint32_t capture_yuv2rgb_preoffset[3] = {0x7c0, 0x600, 0x600};
constexpr uint32_t capture_yuv2rgb_offset[3] = {0, 0, 0};

constexpr VideoInputModuleId kVideoInputModuleId = VideoInputModuleId::kVideoInputModule1;

}  // namespace

// EE Reset registers on the CBUS (regular power-gated config registers domain).
//
// A311D datasheet section 8.8.2.1 "Register Description" > "EE Reset" describes
// the bits under the RESET{0,7}_REGISTER sections. The RESET{0,7}_MASK and
// RESET{0,7}_LEVEL sections describe the interactions between the registers,
// the watchdog timer, and the reset condition.
//
// A311D datasheet section 8.8.2.1 has full MMIO addresses. S905D3 datasheet
// section 6.8.2 with the same title covers the same registers, and also
// explicitly states that the base for all registers is 0xffd0'1000. This
// address is listed under the RESET entry in A311D section 8.1 "System" >
// "Memory Map" and S905D3 datasheet section 6.1 with the same name.
//
// The following datasheets have matching information.
// * S905D2, Section 6.7.2.1 "EE Reset", Section 6.1 "Memory Map"
// * T931, Section 6.8.2.1 "EE Reset", Section 6.1 "Memory Map"
#define RESET0_LEVEL 0x80
#define RESET1_LEVEL 0x84
#define RESET2_LEVEL 0x88
#define RESET4_LEVEL 0x90
#define RESET7_LEVEL 0x9c

// static
zx::result<std::unique_ptr<Vpu>> Vpu::Create(
    fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) {
  ZX_DEBUG_ASSERT(platform_device.is_valid());

  // Map VPU registers
  zx::result<fdf::MmioBuffer> vpu_mmio_result = MapMmio(MmioResourceIndex::kVpu, platform_device);
  if (vpu_mmio_result.is_error()) {
    return vpu_mmio_result.take_error();
  }
  fdf::MmioBuffer vpu_mmio = std::move(vpu_mmio_result).value();

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

  zx::result<fdf::MmioBuffer> aobus_mmio_result =
      MapMmio(MmioResourceIndex::kAonRti, platform_device);
  if (aobus_mmio_result.is_error()) {
    return aobus_mmio_result.take_error();
  }
  fdf::MmioBuffer aobus_mmio = std::move(aobus_mmio_result).value();

  zx::result<fdf::MmioBuffer> reset_mmio_result =
      MapMmio(MmioResourceIndex::kEeReset, platform_device);
  if (reset_mmio_result.is_error()) {
    return reset_mmio_result.take_error();
  }
  fdf::MmioBuffer reset_mmio = std::move(reset_mmio_result).value();

  fbl::AllocChecker alloc_checker;
  auto vpu = fbl::make_unique_checked<Vpu>(&alloc_checker, std::move(vpu_mmio), std::move(hhi_mmio),
                                           std::move(aobus_mmio), std::move(reset_mmio));
  if (!alloc_checker.check()) {
    zxlogf(ERROR, "Failed to allocate memory for Vpu");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

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

Vpu::Vpu(fdf::MmioBuffer vpu_mmio, fdf::MmioBuffer hhi_mmio, fdf::MmioBuffer aobus_mmio,
         fdf::MmioBuffer reset_mmio)
    : vpu_mmio_(std::move(vpu_mmio)),
      hhi_mmio_(std::move(hhi_mmio)),
      aobus_mmio_(std::move(aobus_mmio)),
      reset_mmio_(std::move(reset_mmio)),
      capture_state_(CAPTURE_RESET) {}

bool Vpu::CheckAndClaimHardwareOwnership() {
  uint32_t regVal = vpu_mmio_.Read32(VPP_DUMMY_DATA);
  if (regVal == kFirstTimeLoadMagicNumber) {
    // we have already been loaded once. don't set again.
    return false;
  }
  vpu_mmio_.Write32(kFirstTimeLoadMagicNumber, VPP_DUMMY_DATA);
  first_time_load_ = true;
  return true;
}

void Vpu::SetupPostProcessorOutputInterface() {
  // init vpu fifo control register
  vpu_mmio_.Write32(SetFieldValue32(vpu_mmio_.Read32(VPP_OFIFO_SIZE), /*field_begin_bit=*/0,
                                    /*field_size_bits=*/12, /*field_value=*/0xFFF),
                    VPP_OFIFO_SIZE);
  vpu_mmio_.Write32(0x08080808, VPP_HOLD_LINES);
  // default probe_sel, for highlight en
  vpu_mmio_.Write32(SetFieldValue32(vpu_mmio_.Read32(VPP_MATRIX_CTRL), /*field_begin_bit=*/12,
                                    /*field_size_bits=*/3, /*field_value=*/0x7),
                    VPP_MATRIX_CTRL);
}

void Vpu::SetupPostProcessorColorConversion(ColorSpaceConversionMode mode) {
  // TODO(https://fxbug.dev/42082404): Revise the selection of matrices used for color
  // conversion.
  switch (mode) {
    case ColorSpaceConversionMode::kRgbInternalRgbOut:
      // This deviates from the Amlogic-provided code which does an RGB ->
      // YUV conversion for all OSDs and a YUV -> RGB conversion after
      // blending.
      vpu_mmio_.Write32(
          SetFieldValue32(vpu_mmio_.Read32(VPP_WRAP_OSD1_MATRIX_EN_CTRL), /*field_begin_bit=*/0,
                          /*field_size_bits=*/1, /*field_value=*/0),
          VPP_WRAP_OSD1_MATRIX_EN_CTRL);
      break;
    case ColorSpaceConversionMode::kRgbInternalYuvOut: {
      // setting up os1 for rgb -> yuv limit
      const int16_t* m = RGB709_to_YUV709l_coeff;

      // VPP WRAP OSD1 matrix
      // TODO(https://fxbug.dev/42059021): Also set VPP_WRAP_OSD2/3 when OSD2/3 is
      // supported.
      vpu_mmio_.Write32(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
                        VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1);
      vpu_mmio_.Write32(m[2] & 0xfff, VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2);
      vpu_mmio_.Write32(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), VPP_WRAP_OSD1_MATRIX_COEF00_01);
      vpu_mmio_.Write32(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), VPP_WRAP_OSD1_MATRIX_COEF02_10);
      vpu_mmio_.Write32(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), VPP_WRAP_OSD1_MATRIX_COEF11_12);
      vpu_mmio_.Write32(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), VPP_WRAP_OSD1_MATRIX_COEF20_21);
      vpu_mmio_.Write32(m[11] & 0x1fff, VPP_WRAP_OSD1_MATRIX_COEF22);
      vpu_mmio_.Write32(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), VPP_WRAP_OSD1_MATRIX_OFFSET0_1);
      vpu_mmio_.Write32(m[20] & 0xfff, VPP_WRAP_OSD1_MATRIX_OFFSET2);
      vpu_mmio_.Write32(
          SetFieldValue32(vpu_mmio_.Read32(VPP_WRAP_OSD1_MATRIX_EN_CTRL), /*field_begin_bit=*/0,
                          /*field_size_bits=*/1, /*field_value=*/1),
          VPP_WRAP_OSD1_MATRIX_EN_CTRL);
      break;
    }
    default:
      ZX_ASSERT_MSG(false, "Invalid color conversion mode: %d", static_cast<int>(mode));
  }

  vpu_mmio_.Write32(0xf, DOLBY_PATH_CTRL);

  // Disables VPP POST2 matrix.
  vpu_mmio_.Write32(
      SetFieldValue32(vpu_mmio_.Read32(VPP_POST2_MATRIX_EN_CTRL), /*field_begin_bit=*/0,
                      /*field_size_bits=*/1, /*field_value=*/0),
      VPP_POST2_MATRIX_EN_CTRL);
}

void Vpu::ConfigureClock() {
  // vpu clock
  auto vpu_clock_control = VpuClockControl::Get().FromValue(0);
  vpu_clock_control.set_final_mux_selection(VpuClockControl::FinalMuxSource::kBranch0)
      .set_branch0_mux_source(VpuClockControl::ClockSource::kFixed666Mhz)
      .SetBranch0MuxDivider(1)
      .WriteTo(&hhi_mmio_);
  vpu_clock_control.ReadFrom(&hhi_mmio_).set_branch0_mux_enabled(true).WriteTo(&hhi_mmio_);

  // vpu clkb
  // bit 0 is set since kVpuClkFrequency > clkB max frequency (350MHz)
  VpuClockBControl::Get()
      .FromValue(0)
      .set_clock_source(VpuClockBControl::ClockSource::kFixed500Mhz)
      .SetDivider2(2)
      .WriteTo(&hhi_mmio_);

  // vapb clk
  // turn on ge2d clock since kVpuClkFrequency > 250MHz
  VideoAdvancedPeripheralBusClockControl::Get()
      .FromValue(0)
      .set_final_mux_selection(VideoAdvancedPeripheralBusClockControl::FinalMuxSource::kBranch0)
      .set_ge2d_clock_enabled(true)
      .set_branch0_mux_source(VideoAdvancedPeripheralBusClockControl::ClockSource::kFixed500Mhz)
      .SetBranch0MuxDivider(2)
      .WriteTo(&hhi_mmio_);
  VideoAdvancedPeripheralBusClockControl::Get()
      .ReadFrom(&hhi_mmio_)
      .set_branch0_mux_enabled(true)
      .WriteTo(&hhi_mmio_);

  VideoClockOutputControl::Get()
      .ReadFrom(&hhi_mmio_)
      .set_encoder_interlaced_enabled(false)
      .set_encoder_tv_enabled(false)
      .set_encoder_progressive_enabled(false)
      .set_encoder_lvds_enabled(false)
      .set_video_dac_clock_enabled(false)
      .set_hdmi_tx_pixel_clock_enabled(false)
      .set_lcd_analog_clock_phy3_enabled(false)
      .set_lcd_analog_clock_phy2_enabled(false)
      .WriteTo(&hhi_mmio_);

  // dmc_arb_config
  vpu_mmio_.Write32(0x0, VPU_RDARB_MODE_L1C1);
  vpu_mmio_.Write32(0x10000, VPU_RDARB_MODE_L1C2);
  vpu_mmio_.Write32(0x900000, VPU_RDARB_MODE_L2C1);
  vpu_mmio_.Write32(0x20000, VPU_WRARB_MODE_L2C1);
}

namespace {

template <typename RegisterType>
void SetPowerBits(fdf::MmioBuffer& mmio, bool powered_on, int begin_bit_index, int end_bit_index) {
  // TODO(fxbug.com/132123): AMLogic-supplied software flips each bit
  // individually, with a 5us delay between flips. The power sequences in the
  // datasheets have no mention of individual bits, and seem to suggest setting
  // each register to its final value in one operation. Carry out an experiment
  // to document if the datasheet sequences work, as the AMLogic software may
  // cater to older chips.  Document the result either way.
  RegisterType power_register = RegisterType::Get().ReadFrom(&mmio);
  const uint32_t bit_value = powered_on ? 0 : 1;
  for (int bit_index = begin_bit_index; bit_index < end_bit_index; ++bit_index) {
    const uint32_t bit_mask = bit_value << bit_index;
    power_register.set_reg_value(power_register.reg_value() & ~bit_mask).WriteTo(&mmio);
    zx::nanosleep(zx::deadline_after(zx::usec(5)));
  }
}

template <typename RegisterType>
void SetPowerUnits(fdf::MmioBuffer& mmio, bool powered_on, int begin_unit_index,
                   int end_unit_index) {
  // TODO(fxbug.com/132123): AMLogic-supplied software flips each unit
  // individually, with a 5us delay between flips. The power sequences in the
  // datasheets have no mention of individual bits, and seem to suggest setting
  // each register to its final value in one operation. Carry out an experiment
  // to document if the datasheet sequences work, as the AMLogic software may
  // cater to older chips.  Document the result either way.
  RegisterType power_register = RegisterType::Get().ReadFrom(&mmio);
  const MemoryPowerDomainMode mode =
      powered_on ? MemoryPowerDomainMode::kPoweredOn : MemoryPowerDomainMode::kPoweredOff;
  for (int unit_index = begin_unit_index; unit_index < end_unit_index; ++unit_index) {
    const uint32_t unit_mask = static_cast<uint32_t>(mode) << unit_index;
    power_register.set_reg_value(power_register.reg_value() & ~unit_mask).WriteTo(&mmio);
    zx::nanosleep(zx::deadline_after(zx::usec(5)));
  }
}

}  // namespace

void Vpu::PowerOn() {
  // Implements the power sequences documented below.
  //
  // A311D datasheet Section 8.2.3 "EE Top Level Power Modes", Table 8-6 "Power
  //     Sequence of VPU", page 88
  // S905D3 datasheet Section 6.2.3.2 "EE Top Level Power Modes" > "VPU",
  //     Table 6-3 "Power & Global Clock Control Summary", page 75
  // S905D2 datasheet Section 6.2.3 "EE Top Level Power Modes", Table 6-4 "Power
  //     Sequence of EE Domain", page 84

  auto general_power = AlwaysOnGeneralPowerSleep::Get().ReadFrom(&aobus_mmio_);
  general_power.set_vpu_hdmi_powered_off(false).WriteTo(&aobus_mmio_);

  // TODO(fxbug.com/132123): The A311D power sequence waits for bits 9-8 in
  // `AlwaysOnGeneralPowerAck`here. The S905D3 and S905D2 power sequences only
  // wait for bit 8 in the same register. AMLogic-supplied bringup code uses a
  // hard-coded 20us timeout instead.

  SetPowerUnits<VpuMemoryPower0>(hhi_mmio_, /*powered_on=*/true, 0, 16);
  SetPowerUnits<VpuMemoryPower1>(hhi_mmio_, /*powered_on=*/true, 0, 16);

  // The S905D2 power sequence does not include `VpuMemoryPower2`. However, the
  // datasheet has a register-level reference for it, which indicates that all
  // fields outside of `vpp_watermark_power` are unused. So, the sequence below
  // is harmless on S905D2.
  //
  // The A311D power sequence lists bits 0-31 of `VpuMemoryPower2`. We follow
  // the AMLogic-supplied bringup code, which only flips the bits below.

  // TODO(fxbug.com/132123): The S905D3 power sequence and AMLogic-supplied
  // bringup code flips bits 0-31 of `VpuMemoryPower2`.
  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/true, 0, 1);
  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/true, 2, 9);
  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/true, 15, 16);

  // TODO(fxbug.com/132123): The S905D3 power sequence also flips bits 0-31 of
  // registers `VpuMemoryPower3` and `VpuMemoryPower4`. The AMLogic-supplied
  // bringup code flips bits 0-31 of `VpuMemoryPower3` and bits 0-3 of
  // `VpuMemoryPower4`.

  SetPowerBits<MemoryPower0>(hhi_mmio_, /*powered_on=*/true, 8, 16);
  zx::nanosleep(zx::deadline_after(zx::usec(20)));

  // Reset VIU + VENC
  // Reset VENCI + VENCP + VADC + VENCL
  // Reset HDMI-APB + HDMI-SYS + HDMI-TX + HDMI-CEC
  reset_mmio_.Write32(
      reset_mmio_.Read32(RESET0_LEVEL) & ~((1 << 5) | (1 << 10) | (1 << 19) | (1 << 13)),
      RESET0_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET1_LEVEL) & ~(1 << 5), RESET1_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET2_LEVEL) & ~(1 << 15), RESET2_LEVEL);
  reset_mmio_.Write32(
      reset_mmio_.Read32(RESET4_LEVEL) &
          ~((1 << 6) | (1 << 7) | (1 << 13) | (1 << 5) | (1 << 9) | (1 << 4) | (1 << 12)),
      RESET4_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET7_LEVEL) & ~(1 << 7), RESET7_LEVEL);

  // TODO(fxbug.com/132123): The A311D and S905D3 power sequences disable output
  // isolation after VPU power ACK, and before changing the VPU memory power
  // registers. The AMLogic-supplied bringup code disables isolation after
  // completing the reset sequence.

  // TODO(fxbug.com/132123): The S905D3 power sequence and AMLogic-supplied
  // bringup code configure VPU/HDMI isolation in the
  // `AlwaysOnGeneralPowerIsolation` register instead.
  general_power.set_vpu_hdmi_isolation_enabled_s905d2_a311d(false).WriteTo(&aobus_mmio_);

  // release Reset
  reset_mmio_.Write32(
      reset_mmio_.Read32(RESET0_LEVEL) | ((1 << 5) | (1 << 10) | (1 << 19) | (1 << 13)),
      RESET0_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET1_LEVEL) | (1 << 5), RESET1_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET2_LEVEL) | (1 << 15), RESET2_LEVEL);
  reset_mmio_.Write32(
      reset_mmio_.Read32(RESET4_LEVEL) |
          ((1 << 6) | (1 << 7) | (1 << 13) | (1 << 5) | (1 << 9) | (1 << 4) | (1 << 12)),
      RESET4_LEVEL);
  reset_mmio_.Write32(reset_mmio_.Read32(RESET7_LEVEL) | (1 << 7), RESET7_LEVEL);

  ConfigureClock();
}

void Vpu::PowerOff() {
  // Implements the steps in Table 8-6 "Power Sequence of VPU" in A311D
  // datasheet Section 8.2.3 "EE Top Level Power Modes", in reverse order.

  auto general_power = AlwaysOnGeneralPowerSleep::Get().ReadFrom(&aobus_mmio_);
  general_power.set_vpu_hdmi_isolation_enabled_s905d2_a311d(true).WriteTo(&aobus_mmio_);
  zx::nanosleep(zx::deadline_after(zx::usec(20)));

  // TODO(fxbug.com/132123): The memories are powered down in exactly the same
  // order as powering up. If the order doesn't matter, we can unify the code.

  SetPowerUnits<VpuMemoryPower0>(hhi_mmio_, /*powered_on=*/false, 0, 16);
  SetPowerUnits<VpuMemoryPower1>(hhi_mmio_, /*powered_on=*/false, 0, 16);

  // The S905D2 power sequence does not include `VpuMemoryPower2`. However, the
  // datasheet has a register-level reference for it, which indicates that all
  // fields outside of `vpp_watermark_power` are unused. So, the sequence below
  // is harmless on S905D2.

  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/false, 0, 1);
  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/false, 2, 9);
  SetPowerUnits<VpuMemoryPower2>(hhi_mmio_, /*powered_on=*/false, 15, 16);

  SetPowerBits<MemoryPower0>(hhi_mmio_, /*powered_on=*/false, 8, 16);
  zx::nanosleep(zx::deadline_after(zx::usec(20)));

  // TODO(fxbug.com/132123): The A311D power sequence waits for bits 9-8 in
  // `AlwaysOnGeneralPowerAck`here. The S905D3 and S905D2 power sequences only
  // wait for bit 8 in the same register.

  general_power.set_vpu_hdmi_powered_off(true).WriteTo(&aobus_mmio_);

  VideoAdvancedPeripheralBusClockControl::Get()
      .ReadFrom(&hhi_mmio_)
      .set_branch0_mux_enabled(false)
      .WriteTo(&hhi_mmio_);
  VpuClockControl::Get().ReadFrom(&hhi_mmio_).set_branch0_mux_enabled(false).WriteTo(&hhi_mmio_);
}

void Vpu::AfbcPower(bool power_on) {
  auto vpu_memory_power2 = VpuMemoryPower2::Get().ReadFrom(&hhi_mmio_);
  vpu_memory_power2.set_mali_afbc_decoder_power(power_on ? MemoryPowerDomainMode::kPoweredOn
                                                         : MemoryPowerDomainMode::kPoweredOff);
  vpu_memory_power2.WriteTo(&hhi_mmio_);
  zx::nanosleep(zx::deadline_after(zx::usec(5)));
}

zx_status_t Vpu::CaptureInit(uint8_t canvas_idx, uint32_t height, uint32_t stride) {
  fbl::AutoLock lock(&capture_mutex_);
  if (capture_state_ == CAPTURE_ACTIVE) {
    zxlogf(ERROR, "Capture in progress");
    return ZX_ERR_UNAVAILABLE;
  }

  // Set up sources for writeback mux 0.
  WritebackMuxControl::Get()
      .ReadFrom(&vpu_mmio_)
      .SetMux0Selection(WritebackMuxSource::kDisabled)
      .WriteTo(&vpu_mmio_);
  WritebackMuxControl::Get()
      .ReadFrom(&vpu_mmio_)
      .SetMux0Selection(WritebackMuxSource::kViuWriteback0)
      .WriteTo(&vpu_mmio_);
  WrBackMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).set_chan0_hsync_enable(1).WriteTo(&vpu_mmio_);
  WrBackCtrlReg::Get().ReadFrom(&vpu_mmio_).set_chan0_sel(5).WriteTo(&vpu_mmio_);

  // setup hold lines and vdin selection to internal loopback
  VideoInputCommandControl::Get(kVideoInputModuleId)
      .ReadFrom(&vpu_mmio_)
      .set_hold_lines(0)
      .set_input_source_selection(VideoInputCommandControl::InputSource::kWritebackMux0)
      .WriteTo(&vpu_mmio_);
  VdinLFifoCtrlReg::Get().FromValue(0).set_fifo_buf_size(0x780).WriteTo(&vpu_mmio_);

  // Setup input channel FIFO.
  VideoInputChannelFifoControl3::Get(kVideoInputModuleId)
      .ReadFrom(&vpu_mmio_)
      .set_channel6_data_enabled(true)
      .set_channel6_go_field_signal_enabled(true)
      .set_channel6_go_line_signal_enabled(true)
      .set_channel6_input_vsync_is_negative(false)
      .set_channel6_input_hsync_is_negative(false)
      .set_channel6_async_fifo_software_reset_on_vsync(true)
      .set_channel6_clear_fifo_overflow_bit(false)
      .set_channel6_async_fifo_software_reset(false)
      .WriteTo(&vpu_mmio_);

  VdInMatrixCtrlReg::Get().ReadFrom(&vpu_mmio_).set_select(1).set_enable(1).WriteTo(&vpu_mmio_);

  VdinCoef00_01Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_coef00(capture_yuv2rgb_coeff[0][0])
      .set_coef01(capture_yuv2rgb_coeff[0][1])
      .WriteTo(&vpu_mmio_);

  VdinCoef02_10Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_coef02(capture_yuv2rgb_coeff[0][2])
      .set_coef10(capture_yuv2rgb_coeff[1][0])
      .WriteTo(&vpu_mmio_);

  VdinCoef11_12Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_coef11(capture_yuv2rgb_coeff[1][1])
      .set_coef12(capture_yuv2rgb_coeff[1][2])
      .WriteTo(&vpu_mmio_);

  VdinCoef20_21Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_coef20(capture_yuv2rgb_coeff[2][0])
      .set_coef21(capture_yuv2rgb_coeff[2][1])
      .WriteTo(&vpu_mmio_);

  VdinCoef22Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_coef22(capture_yuv2rgb_coeff[2][2])
      .WriteTo(&vpu_mmio_);

  VdinOffset0_1Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_offset0(capture_yuv2rgb_offset[0])
      .set_offset1(capture_yuv2rgb_offset[1])
      .WriteTo(&vpu_mmio_);

  VdinOffset2Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_offset2(capture_yuv2rgb_offset[2])
      .WriteTo(&vpu_mmio_);

  VdinPreOffset0_1Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_preoffset0(capture_yuv2rgb_preoffset[0])
      .set_preoffset1(capture_yuv2rgb_preoffset[1])
      .WriteTo(&vpu_mmio_);

  VdinPreOffset2Reg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_preoffset2(capture_yuv2rgb_preoffset[2])
      .WriteTo(&vpu_mmio_);

  // setup vdin input dimensions
  VdinIntfWidthM1Reg::Get().FromValue(stride - 1).WriteTo(&vpu_mmio_);

  // Configure memory size
  VdInWrHStartEndReg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_start(0)
      .set_end(stride - 1)
      .WriteTo(&vpu_mmio_);
  VdInWrVStartEndReg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_start(0)
      .set_end(height - 1)
      .WriteTo(&vpu_mmio_);

  // Write output canvas index, 128 bit endian, eol with width, enable 4:4:4 RGB888 mode
  VdInWrCtrlReg::Get()
      .ReadFrom(&vpu_mmio_)
      .set_eol_sel(1)
      .set_word_swap(1)
      .set_memory_format(1)
      .set_canvas_idx(canvas_idx)
      .WriteTo(&vpu_mmio_);

  // TODO(fxbug.com/132123): This seems unnecessary. Vpu::PowerOn() already
  // enables both `vdin0_memory_power` and `vdin1_memory_power`. The
  // AMLogic-supplied bringup code waits 5us after flipping a power gate.
  auto vpu_memory_power0 = VpuMemoryPower0::Get().ReadFrom(&hhi_mmio_);
  vpu_memory_power0.set_vdin1_memory_power(MemoryPowerDomainMode::kPoweredOn).WriteTo(&hhi_mmio_);

  // Capture state is now in IDLE mode
  capture_state_ = CAPTURE_IDLE;
  return ZX_OK;
}

zx_status_t Vpu::CaptureStart() {
  fbl::AutoLock lock(&capture_mutex_);
  if (capture_state_ != CAPTURE_IDLE) {
    zxlogf(ERROR, "Capture state is not idle! (%d)", capture_state_);
    return ZX_ERR_BAD_STATE;
  }

  // Now that loopback mode is configured, start capture
  // pause write output
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_write_ctrl(0).WriteTo(&vpu_mmio_);

  // disable vdin path
  VideoInputCommandControl::Get(kVideoInputModuleId)
      .ReadFrom(&vpu_mmio_)
      .set_video_input_enabled(false)
      .WriteTo(&vpu_mmio_);

  // reset mif
  VdInMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).set_mif_reset(1).WriteTo(&vpu_mmio_);
  zx_nanosleep(zx_deadline_after(ZX_USEC(10)));
  VdInMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).set_mif_reset(0).WriteTo(&vpu_mmio_);

  // resume write output
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_write_ctrl(1).WriteTo(&vpu_mmio_);

  // wait until resets finishes
  zx_nanosleep(zx_deadline_after(ZX_MSEC(20)));

  // Clear status bit
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_done_status_clear_bit(1).WriteTo(&vpu_mmio_);

  // Set as urgent
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_write_req_urgent(1).WriteTo(&vpu_mmio_);

  // Enable loopback
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_write_mem_enable(1).WriteTo(&vpu_mmio_);

  // enable vdin path
  VideoInputCommandControl::Get(kVideoInputModuleId)
      .ReadFrom(&vpu_mmio_)
      .set_video_input_enabled(true)
      .WriteTo(&vpu_mmio_);

  capture_state_ = CAPTURE_ACTIVE;
  return ZX_OK;
}

zx_status_t Vpu::CaptureDone() {
  fbl::AutoLock lock(&capture_mutex_);
  capture_state_ = CAPTURE_IDLE;
  // pause write output
  VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).set_write_ctrl(0).WriteTo(&vpu_mmio_);

  // disable vdin path
  VideoInputCommandControl::Get(kVideoInputModuleId)
      .ReadFrom(&vpu_mmio_)
      .set_video_input_enabled(0)
      .WriteTo(&vpu_mmio_);

  // reset mif
  VdInMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).set_mif_reset(1).WriteTo(&vpu_mmio_);
  zx_nanosleep(zx_deadline_after(ZX_USEC(10)));
  VdInMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).set_mif_reset(0).WriteTo(&vpu_mmio_);

  return ZX_OK;
}

void Vpu::CapturePrintRegisters() {
  zxlogf(INFO, "** Display Loopback Register Dump **");
  zxlogf(INFO, "VdInComCtrl0Reg = 0x%x",
         VideoInputCommandControl::Get(kVideoInputModuleId).ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInComStatus0Reg = 0x%x",
         VideoInputCommandStatus0::Get(kVideoInputModuleId).ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInMatrixCtrlReg = 0x%x",
         VdInMatrixCtrlReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinCoef00_01Reg = 0x%x", VdinCoef00_01Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinCoef02_10Reg = 0x%x", VdinCoef02_10Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinCoef11_12Reg = 0x%x", VdinCoef11_12Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinCoef20_21Reg = 0x%x", VdinCoef20_21Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinCoef22Reg = 0x%x", VdinCoef22Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinOffset0_1Reg = 0x%x", VdinOffset0_1Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinOffset2Reg = 0x%x", VdinOffset2Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinPreOffset0_1Reg = 0x%x",
         VdinPreOffset0_1Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinPreOffset2Reg = 0x%x",
         VdinPreOffset2Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinLFifoCtrlReg = 0x%x", VdinLFifoCtrlReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdinIntfWidthM1Reg = 0x%x",
         VdinIntfWidthM1Reg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInWrCtrlReg = 0x%x", VdInWrCtrlReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInWrHStartEndReg = 0x%x",
         VdInWrHStartEndReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInWrVStartEndReg = 0x%x",
         VdInWrVStartEndReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInAFifoCtrl3Reg = 0x%x",
         VideoInputChannelFifoControl3::Get(kVideoInputModuleId).ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInMiscCtrlReg = 0x%x", VdInMiscCtrlReg::Get().ReadFrom(&vpu_mmio_).reg_value());
  zxlogf(INFO, "VdInIfMuxCtrlReg = 0x%x",
         WritebackMuxControl::Get().ReadFrom(&vpu_mmio_).reg_value());

  zxlogf(INFO, "Dumping from 0x1300 to 0x1373");
  for (int i = 0x1300; i <= 0x1373; i++) {
    zxlogf(INFO, "reg[0x%x] = 0x%x", i, vpu_mmio_.Read32(i << 2));
  }
}

}  // namespace amlogic_display
