// 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 "amlogic-video.h"

#include <lib/trace/event.h>
#include <lib/zx/channel.h>
#include <memory.h>
#include <stdint.h>
#include <zircon/errors.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/smc.h>

#include <chrono>
#include <memory>
#include <optional>
#include <thread>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/device.h>
#include <ddktl/protocol/composite.h>
#include <hw/reg.h>
#include <hwreg/bitfields.h>
#include <hwreg/mmio.h>

#include "device_ctx.h"
#include "device_fidl.h"
#include "hevcdec.h"
#include "local_codec_factory.h"
#include "macros.h"
#include "mpeg12_decoder.h"
#include "pts_manager.h"
#include "registers.h"
#include "src/media/lib/memory_barriers/memory_barriers.h"
#include "util.h"
#include "vdec1.h"
#include "video_firmware_session.h"

// TODO(fxbug.dev/35200):
//
// AllocateIoBuffer() - only used by VP9 - switch to InternalBuffer when we do zero copy on input
// for VP9.
//
// (AllocateStreamBuffer() has been moved to InternalBuffer.)
// (VideoDecoder::Owner::ProtectableHardwareUnit::kParser pays attention to is_secure.)
//
// (Fine as io_buffer_t, at least for now (for both h264 and VP9):
//  search_pattern_ - HW only reads this
//  parser_input_ - not used when secure)

// TODO(fxbug.dev/41972): bti::release_quarantine() or zx_bti_release_quarantine() somewhere during
// startup, after HW is known idle, before we allocate anything from sysmem.

namespace {

// These match the regions exported when the bus device was added.
enum MmioRegion {
  kCbus,
  kDosbus,
  kHiubus,
  kAobus,
  kDmc,
};

enum Interrupt {
  kDemuxIrq,
  kParserIrq,
  kDosMbox0Irq,
  kDosMbox1Irq,
};

}  // namespace

AmlogicVideo::AmlogicVideo() {
  ZX_DEBUG_ASSERT(metrics_ == &default_nop_metrics_);
  vdec1_core_ = std::make_unique<Vdec1>(this);
  hevc_core_ = std::make_unique<HevcDec>(this);
}

AmlogicVideo::~AmlogicVideo() {
  LOG(INFO, "Tearing down AmlogicVideo");
  if (vdec0_interrupt_handle_) {
    zx_interrupt_destroy(vdec0_interrupt_handle_.get());
    if (vdec0_interrupt_thread_.joinable())
      vdec0_interrupt_thread_.join();
  }
  if (vdec1_interrupt_handle_) {
    zx_interrupt_destroy(vdec1_interrupt_handle_.get());
    if (vdec1_interrupt_thread_.joinable())
      vdec1_interrupt_thread_.join();
  }
  swapped_out_instances_.clear();
  current_instance_ = nullptr;
  core_ = nullptr;
  hevc_core_ = nullptr;
  vdec1_core_ = nullptr;
}

// TODO: Remove once we can add single-instance decoders through
// AddNewDecoderInstance.
void AmlogicVideo::SetDefaultInstance(std::unique_ptr<VideoDecoder> decoder, bool hevc) {
  DecoderCore* core = hevc ? hevc_core_.get() : vdec1_core_.get();
  assert(!stream_buffer_);
  assert(!current_instance_);
  current_instance_ = std::make_unique<DecoderInstance>(std::move(decoder), core);
  video_decoder_ = current_instance_->decoder();
  stream_buffer_ = current_instance_->stream_buffer();
  core_ = core;
}

void AmlogicVideo::AddNewDecoderInstance(std::unique_ptr<DecoderInstance> instance) {
  swapped_out_instances_.push_back(std::move(instance));
}

void AmlogicVideo::UngateClocks() {
  ToggleClock(ClockType::kClkDos, true);
  HhiGclkMpeg1::Get().ReadFrom(&*hiubus_).set_aiu(0xff).set_demux(true).set_audio_in(true).WriteTo(
      &*hiubus_);
  HhiGclkMpeg2::Get().ReadFrom(&*hiubus_).set_vpu_interrupt(true).WriteTo(&*hiubus_);
  UngateParserClock();
}

void AmlogicVideo::UngateParserClock() {
  is_parser_gated_ = false;
  HhiGclkMpeg1::Get().ReadFrom(&*hiubus_).set_u_parser_top(true).WriteTo(&*hiubus_);
}

void AmlogicVideo::GateClocks() {
  // Keep VPU interrupt enabled, as it's used for vsync by the display.
  HhiGclkMpeg1::Get()
      .ReadFrom(&*hiubus_)
      .set_u_parser_top(false)
      .set_aiu(0)
      .set_demux(false)
      .set_audio_in(false)
      .WriteTo(&*hiubus_);
  ToggleClock(ClockType::kClkDos, false);
  GateParserClock();
}

void AmlogicVideo::GateParserClock() {
  is_parser_gated_ = true;
  HhiGclkMpeg1::Get().ReadFrom(&*hiubus_).set_u_parser_top(false).WriteTo(&*hiubus_);
}

void AmlogicVideo::ClearDecoderInstance() {
  std::lock_guard<std::mutex> lock(video_decoder_lock_);
  assert(current_instance_);
  assert(swapped_out_instances_.size() == 0);
  LOG(DEBUG, "current_instance_.reset()...");
  current_instance_ = nullptr;
  core_ = nullptr;
  video_decoder_ = nullptr;
  stream_buffer_ = nullptr;
}

void AmlogicVideo::RemoveDecoder(VideoDecoder* decoder) {
  std::lock_guard<std::mutex> lock(video_decoder_lock_);
  RemoveDecoderLocked(decoder);
}

void AmlogicVideo::RemoveDecoderLocked(VideoDecoder* decoder) {
  DLOG("Removing decoder: %p", decoder);
  ZX_DEBUG_ASSERT(decoder);
  if (current_instance_ && current_instance_->decoder() == decoder) {
    current_instance_ = nullptr;
    video_decoder_ = nullptr;
    stream_buffer_ = nullptr;
    core_ = nullptr;
    TryToReschedule();
    return;
  }
  for (auto it = swapped_out_instances_.begin(); it != swapped_out_instances_.end(); ++it) {
    if ((*it)->decoder() != decoder)
      continue;
    swapped_out_instances_.erase(it);
    return;
  }
}

zx_status_t AmlogicVideo::AllocateStreamBuffer(StreamBuffer* buffer, uint32_t size, bool use_parser,
                                               bool is_secure) {
  // So far, is_secure can only be true if use_parser is also true.
  ZX_DEBUG_ASSERT(!is_secure || use_parser);
  // is_writable is always true because we either need to write into this buffer using the CPU, or
  // using the parser - either way we'll be writing.
  auto create_result =
      InternalBuffer::Create("AMLStreamBuffer", &sysmem_sync_ptr_, zx::unowned_bti(bti_), size,
                             is_secure, /*is_writable=*/true, /*is_mapping_needed=*/!use_parser);
  if (!create_result.is_ok()) {
    DECODE_ERROR("Failed to make video fifo: %d", create_result.error());
    return create_result.error();
  }
  buffer->optional_buffer().emplace(create_result.take_value());

  // Sysmem guarantees that the newly-allocated buffer starts out zeroed and cache clean, to the
  // extent possible based on is_secure.

  return ZX_OK;
}

zx_status_t AmlogicVideo::ConnectToTee(fuchsia::tee::DeviceSyncPtr* tee) {
  ZX_DEBUG_ASSERT(tee);

  zx::channel tee_client;
  zx::channel tee_server;
  zx_status_t status = zx::channel::create(/*flags=*/0, &tee_client, &tee_server);
  if (status != ZX_OK) {
    LOG(ERROR, "zx::channel::create() failed - status: %d", status);
    return status;
  }

  status = tee_.Connect(std::move(tee_server), /*service_provider=*/zx::channel());
  if (status != ZX_OK) {
    LOG(ERROR, "tee_connect() failed - status: %d", status);
    return status;
  }

  tee->Bind(std::move(tee_client));
  return ZX_OK;
}

zx_status_t AmlogicVideo::EnsureSecmemSessionIsConnected() {
  if (secmem_session_.has_value()) {
    return ZX_OK;
  }

  fuchsia::tee::DeviceSyncPtr tee_connection;
  zx_status_t status = ConnectToTee(&tee_connection);
  if (status != ZX_OK) {
    LOG(ERROR, "ConnectToTee() failed - status: %d", status);
    return status;
  }

  auto secmem_session_result = SecmemSession::TryOpen(std::move(tee_connection));
  if (!secmem_session_result.is_ok()) {
    // Logging handled in `SecmemSession::TryOpen`
    return ZX_ERR_INTERNAL;
  }

  secmem_session_.emplace(secmem_session_result.take_value());
  return ZX_OK;
}

void AmlogicVideo::InitializeStreamInput(bool use_parser) {
  uint32_t buffer_address = truncate_to_32(stream_buffer_->buffer().phys_base());
  auto buffer_size = stream_buffer_->buffer().size();
  core_->InitializeStreamInput(use_parser, buffer_address, buffer_size);
}

zx_status_t AmlogicVideo::InitializeStreamBuffer(bool use_parser, uint32_t size, bool is_secure) {
  zx_status_t status = AllocateStreamBuffer(stream_buffer_, size, use_parser, is_secure);
  if (status != ZX_OK) {
    return status;
  }

  status = SetProtected(VideoDecoder::Owner::ProtectableHardwareUnit::kParser, is_secure);
  if (status != ZX_OK) {
    return status;
  }

  InitializeStreamInput(use_parser);
  return ZX_OK;
}

std::unique_ptr<CanvasEntry> AmlogicVideo::ConfigureCanvas(io_buffer_t* io_buffer, uint32_t offset,
                                                           uint32_t width, uint32_t height,
                                                           uint32_t wrap, uint32_t blockmode) {
  assert(width % 8 == 0);
  assert(offset % 8 == 0);
  canvas_info_t info;
  info.height = height;
  info.stride_bytes = width;
  info.wrap = wrap;
  info.blkmode = blockmode;
  enum {
    kSwapBytes = 1,
    kSwapWords = 2,
    kSwapDoublewords = 4,
    kSwapQuadwords = 8,
  };
  info.endianness =
      kSwapBytes | kSwapWords | kSwapDoublewords;  // 64-bit big-endian to little-endian conversion.
  info.flags = CANVAS_FLAGS_READ | CANVAS_FLAGS_WRITE;

  zx::unowned_vmo vmo(io_buffer->vmo_handle);
  zx::vmo dup_vmo;
  zx_status_t status = vmo->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to duplicate handle, status: %d", status);
    return nullptr;
  }
  uint8_t idx;
  status = canvas_.Config(std::move(dup_vmo), offset, &info, &idx);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to configure canvas, status: %d", status);
    return nullptr;
  }

  return std::make_unique<CanvasEntry>(this, idx);
}

void AmlogicVideo::FreeCanvas(CanvasEntry* canvas) { canvas_.Free(canvas->index()); }

void AmlogicVideo::OnSignaledWatchdog() {
  std::lock_guard<std::mutex> lock(video_decoder_lock_);
  // Check after taking lock to ensure a cancel didn't just happen.
  if (!watchdog_.CheckAndResetTimeout())
    return;
  // The watchdog should never be valid if the decoder was disconnected.
  ZX_ASSERT(video_decoder_);
  video_decoder_->OnSignaledWatchdog();
}

zx_status_t AmlogicVideo::AllocateIoBuffer(io_buffer_t* buffer, size_t size,
                                           uint32_t alignment_log2, uint32_t flags,
                                           const char* name) {
  zx_status_t status = io_buffer_init_aligned(buffer, bti_.get(), size, alignment_log2, flags);
  if (status != ZX_OK)
    return status;

  SetIoBufferName(buffer, name);

  return ZX_OK;
}

fuchsia::sysmem::AllocatorSyncPtr& AmlogicVideo::SysmemAllocatorSyncPtr() {
  return sysmem_sync_ptr_;
}

// This parser handles MPEG elementary streams.
zx_status_t AmlogicVideo::InitializeEsParser() {
  std::lock_guard<std::mutex> lock(video_decoder_lock_);
  return parser_->InitializeEsParser(current_instance_.get());
}

uint32_t AmlogicVideo::GetStreamBufferEmptySpaceAfterWriteOffsetBeforeReadOffset(
    uint32_t write_offset, uint32_t read_offset) {
  uint32_t available_space;
  if (read_offset > write_offset) {
    available_space = read_offset - write_offset;
  } else {
    available_space = stream_buffer_->buffer().size() - write_offset + read_offset;
  }
  // Subtract 8 to ensure the read pointer doesn't become equal to the write
  // pointer, as that means the buffer is empty.
  available_space = available_space > 8 ? available_space - 8 : 0;
  return available_space;
}

uint32_t AmlogicVideo::GetStreamBufferEmptySpaceAfterOffset(uint32_t write_offset) {
  uint32_t read_offset = core_->GetReadOffset();
  return GetStreamBufferEmptySpaceAfterWriteOffsetBeforeReadOffset(write_offset, read_offset);
}

uint32_t AmlogicVideo::GetStreamBufferEmptySpace() {
  return GetStreamBufferEmptySpaceAfterOffset(core_->GetStreamInputOffset());
}

zx_status_t AmlogicVideo::ProcessVideoNoParser(const void* data, uint32_t len,
                                               uint32_t* written_out) {
  return ProcessVideoNoParserAtOffset(data, len, core_->GetStreamInputOffset(), written_out);
}

zx_status_t AmlogicVideo::ProcessVideoNoParserAtOffset(const void* data, uint32_t len,
                                                       uint32_t write_offset,
                                                       uint32_t* written_out) {
  TRACE_DURATION("media", "AmlogicVideo::ProcessVideoNoParserAtOffset");
  uint32_t available_space = GetStreamBufferEmptySpaceAfterOffset(write_offset);
  if (!written_out) {
    if (len > available_space) {
      DECODE_ERROR("Video too large");
      return ZX_ERR_OUT_OF_RANGE;
    }
  } else {
    len = std::min(len, available_space);
    *written_out = len;
  }

  stream_buffer_->set_data_size(stream_buffer_->data_size() + len);
  uint32_t input_offset = 0;
  while (len > 0) {
    uint32_t write_length = len;
    if (write_offset + len > stream_buffer_->buffer().size())
      write_length = stream_buffer_->buffer().size() - write_offset;
    memcpy(stream_buffer_->buffer().virt_base() + write_offset,
           static_cast<const uint8_t*>(data) + input_offset, write_length);
    stream_buffer_->buffer().CacheFlush(write_offset, write_length);
    write_offset += write_length;
    if (write_offset == stream_buffer_->buffer().size())
      write_offset = 0;
    len -= write_length;
    input_offset += write_length;
  }
  BarrierAfterFlush();
  core_->UpdateWritePointer(stream_buffer_->buffer().phys_base() + write_offset);
  return ZX_OK;
}

void AmlogicVideo::SwapOutCurrentInstance() {
  TRACE_DURATION("media", "AmlogicVideo::SwapOutCurrentInstance", "current_instance_",
                 current_instance_.get());
  ZX_DEBUG_ASSERT(!!current_instance_);

  // VP9:
  //
  // FrameWasOutput() is called during handling of kVp9CommandNalDecodeDone on the interrupt thread,
  // which means the decoder HW is currently paused, which means it's ok to save the state before
  // the stop+wait (without any explicit pause before the save here).  The decoder HW remains paused
  // after the save, and makes no further progress until later after the restore.
  //
  // h264_multi_decoder:
  //
  // ShouldSaveInputContext() is true if the h264_multi_decoder made useful progress (decoded a
  // picture).  If no useful progress was made, the lack of save here allows the state restore later
  // to effectively back up and try decoding from the same location again, with more data present.
  // This backing up to the previous saved state is the main way that separate SPS PPS and pictures
  // split across packets are handled.  In other words, it's how the h264_multi_decoder handles
  // stream-based input.
  bool should_save = current_instance_->decoder()->ShouldSaveInputContext();
  DLOG("should_save: %d", should_save);
  if (should_save) {
    if (!current_instance_->input_context()) {
      current_instance_->InitializeInputContext();
      if (core_->InitializeInputContext(current_instance_->input_context(),
                                        current_instance_->decoder()->is_secure()) != ZX_OK) {
        video_decoder_->CallErrorHandler();
        // Continue trying to swap out.
      }
    }
  }
  video_decoder_->SetSwappedOut();
  if (should_save) {
    if (current_instance_->input_context()) {
      if (core_->SaveInputContext(current_instance_->input_context()) != ZX_OK) {
        video_decoder_->CallErrorHandler();
        // Continue trying to swap out.
      }
    }
  }
  video_decoder_ = nullptr;
  stream_buffer_ = nullptr;
  core_->StopDecoding();
  core_->WaitForIdle();
  core_ = nullptr;
  // Round-robin; place at the back of the line.
  swapped_out_instances_.push_back(std::move(current_instance_));
}

void AmlogicVideo::TryToReschedule() {
  TRACE_DURATION("media", "AmlogicVideo::TryToReschedule");
  DLOG("AmlogicVideo::TryToReschedule");

  if (current_instance_ && !current_instance_->decoder()->CanBeSwappedOut()) {
    DLOG("Current instance can't be swapped out");
    return;
  }

  // This is used by h264_multi_decoder to swap out without saving, so that the next swap in will
  // restore a previously-saved state again to re-attempt decode from that saved state's logical
  // read start position.  Unlike the read position which backs up for re-decode, the write position
  // is adjusted after restore to avoid overwriting data written since that save state was
  // originally created.
  if (current_instance_ && current_instance_->decoder()->MustBeSwappedOut()) {
    DLOG("MustBeSwappedOut() is true");
    SwapOutCurrentInstance();
  }

  if (current_instance_ && current_instance_->decoder()->test_hooks().force_context_save_restore) {
    SwapOutCurrentInstance();
  }

  if (swapped_out_instances_.size() == 0) {
    DLOG("Nothing swapped out; returning");
    return;
  }

  // Round-robin; first in line that can be swapped in goes first.
  // TODO: Use some priority mechanism to determine which to swap in.
  auto other_instance = swapped_out_instances_.begin();
  for (; other_instance != swapped_out_instances_.end(); ++other_instance) {
    if ((*other_instance)->decoder()->CanBeSwappedIn()) {
      break;
    }
  }
  if (other_instance == swapped_out_instances_.end()) {
    DLOG("nothing to swap to");
    return;
  }

  ZX_ASSERT(!watchdog_.is_running());
  if (current_instance_) {
    SwapOutCurrentInstance();
  }
  current_instance_ = std::move(*other_instance);
  swapped_out_instances_.erase(other_instance);

  SwapInCurrentInstance();
}

void AmlogicVideo::PowerOffForError() {
  ZX_DEBUG_ASSERT(core_);
  core_ = nullptr;
  swapped_out_instances_.push_back(std::move(current_instance_));
  VideoDecoder* video_decoder = video_decoder_;
  video_decoder_ = nullptr;
  stream_buffer_ = nullptr;
  video_decoder->CallErrorHandler();
  // CallErrorHandler should have marked the decoder as having a fatal error
  // so it will never be rescheduled.
  TryToReschedule();
}

void AmlogicVideo::SwapInCurrentInstance() {
  TRACE_DURATION("media", "AmlogicVideo::SwapInCurrentInstance", "current_instance_",
                 current_instance_.get());
  ZX_DEBUG_ASSERT(current_instance_);

  core_ = current_instance_->core();
  video_decoder_ = current_instance_->decoder();
  DLOG("Swapping in %p", video_decoder_);
  stream_buffer_ = current_instance_->stream_buffer();
  {
    zx_status_t status = video_decoder_->SetupProtection();
    if (status != ZX_OK) {
      DECODE_ERROR("Failed to setup protection: %d", status);
      PowerOffForError();
      return;
    }
  }
  if (!current_instance_->input_context()) {
    InitializeStreamInput(false);
    core_->InitializeDirectInput();
    // If data has added to the stream buffer before the first swap in(only
    // relevant in tests right now) then ensure the write pointer's updated to
    // that spot.
    // Generally data will only be added after this decoder is swapped in, so
    // RestoreInputContext will handle that state.
    if (stream_buffer_->data_size() + stream_buffer_->padding_size() > 0) {
      core_->UpdateWritePointer(stream_buffer_->buffer().phys_base() + stream_buffer_->data_size() +
                                stream_buffer_->padding_size());
    }
  } else {
    if (core_->RestoreInputContext(current_instance_->input_context()) != ZX_OK) {
      PowerOffForError();
      return;
    }
  }

  // Do InitializeHardware after setting up the input context, since for H264Multi the vififo can
  // start reading as soon as PowerCtlVld is set up (inside InitializeHardware), and we don't want
  // it to read incorrect data as we gradually set it up later.
  zx_status_t status = video_decoder_->InitializeHardware();
  if (status != ZX_OK) {
    // Probably failed to load the right firmware.
    DECODE_ERROR("Failed to initialize hardware: %d", status);
    PowerOffForError();
    return;
  }
  video_decoder_->SwappedIn();
}

fidl::InterfaceHandle<fuchsia::sysmem::Allocator> AmlogicVideo::ConnectToSysmem() {
  fidl::InterfaceHandle<fuchsia::sysmem::Allocator> client_end;
  fidl::InterfaceRequest<fuchsia::sysmem::Allocator> server_end = client_end.NewRequest();
  zx_status_t connect_status = sysmem_.Connect(server_end.TakeChannel());
  if (connect_status != ZX_OK) {
    // failure
    return fidl::InterfaceHandle<fuchsia::sysmem::Allocator>();
  }
  return client_end;
}

namespace tee_smc {

enum CallType : uint8_t {
  kYieldingCall = 0,
  kFastCall = 1,
};

enum CallConvention : uint8_t {
  kSmc32CallConv = 0,
  kSmc64CallConv = 1,
};

enum Service : uint8_t {
  kArchService = 0x00,
  kCpuService = 0x01,
  kSipService = 0x02,
  kOemService = 0x03,
  kStandardService = 0x04,
  kTrustedOsService = 0x32,
  kTrustedOsServiceEnd = 0x3F,
};

constexpr uint8_t kCallTypeMask = 0x01;
constexpr uint8_t kCallTypeShift = 31;
constexpr uint8_t kCallConvMask = 0x01;
constexpr uint8_t kCallConvShift = 30;
constexpr uint8_t kServiceMask = ARM_SMC_SERVICE_CALL_NUM_MASK;
constexpr uint8_t kServiceShift = ARM_SMC_SERVICE_CALL_NUM_SHIFT;

static constexpr uint32_t CreateFunctionId(CallType call_type, CallConvention call_conv,
                                           Service service, uint16_t function_num) {
  return (((call_type & kCallTypeMask) << kCallTypeShift) |
          ((call_conv & kCallConvMask) << kCallConvShift) |
          ((service & kServiceMask) << kServiceShift) | function_num);
}
}  // namespace tee_smc

zx_status_t AmlogicVideo::SetProtected(ProtectableHardwareUnit unit, bool protect) {
  TRACE_DURATION("media", "AmlogicVideo::SetProtected", "unit", static_cast<uint32_t>(unit),
                 "protect", protect);
  if (!secure_monitor_)
    return protect ? ZX_ERR_INVALID_ARGS : ZX_OK;

  // Call into the TEE to mark a particular hardware unit as able to access
  // protected memory or not.
  zx_smc_parameters_t params = {};
  zx_smc_result_t result = {};
  constexpr uint32_t kFuncIdConfigDeviceSecure = 14;
  params.func_id = tee_smc::CreateFunctionId(tee_smc::kFastCall, tee_smc::kSmc32CallConv,
                                             tee_smc::kTrustedOsService, kFuncIdConfigDeviceSecure);
  params.arg1 = static_cast<uint32_t>(unit);
  params.arg2 = static_cast<uint32_t>(protect);
  zx_status_t status = zx_smc_call(secure_monitor_.get(), &params, &result);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to set unit %ld protected status %ld code: %d", params.arg1, params.arg2,
                 status);
    return status;
  }
  if (result.arg0 != 0) {
    DECODE_ERROR("Failed to set unit %ld protected status %ld: %lx", params.arg1, params.arg2,
                 result.arg0);
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

zx_status_t AmlogicVideo::TeeSmcLoadVideoFirmware(FirmwareBlob::FirmwareType index,
                                                  FirmwareBlob::FirmwareVdecLoadMode vdec) {
  ZX_DEBUG_ASSERT(is_tee_available());
  ZX_DEBUG_ASSERT(secure_monitor_);

  // Call into the TEE to tell the HW to use a particular piece of the previously pre-loaded overall
  // firmware blob.
  zx_smc_parameters_t params = {};
  zx_smc_result_t result = {};
  constexpr uint32_t kFuncIdLoadVideoFirmware = 15;
  params.func_id = tee_smc::CreateFunctionId(tee_smc::kFastCall, tee_smc::kSmc32CallConv,
                                             tee_smc::kTrustedOsService, kFuncIdLoadVideoFirmware);
  params.arg1 = static_cast<uint32_t>(index);
  params.arg2 = static_cast<uint32_t>(vdec);
  zx_status_t status = zx_smc_call(secure_monitor_.get(), &params, &result);
  if (status != ZX_OK) {
    LOG(ERROR, "Failed to kFuncIdLoadVideoFirmware - index: %u vdec: %u status: %d", index, vdec,
        status);
    return status;
  }
  if (result.arg0 != 0) {
    LOG(ERROR, "kFuncIdLoadVideoFirmware result.arg0 != 0 - value: %lu", result.arg0);
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

zx_status_t AmlogicVideo::TeeVp9AddHeaders(zx_paddr_t page_phys_base, uint32_t before_size,
                                           uint32_t max_after_size, uint32_t* after_size) {
  ZX_DEBUG_ASSERT(after_size);
  ZX_DEBUG_ASSERT(is_tee_available());

  // TODO(fxbug.dev/44674): Remove this retry loop once this issue is resolved.
  constexpr uint32_t kRetryCount = 20;
  zx_status_t status = ZX_OK;
  for (uint32_t i = 0; i < kRetryCount; ++i) {
    status = EnsureSecmemSessionIsConnected();
    if (status != ZX_OK) {
      continue;
    }

    status =
        secmem_session_->GetVp9HeaderSize(page_phys_base, before_size, max_after_size, after_size);
    if (status != ZX_OK) {
      LOG(ERROR, "secmem_session_->GetVp9HeaderSize() failed - status: %d", status);

      // Explicitly disconnect and clean up `secmem_session_`.
      secmem_session_ = std::nullopt;
      continue;
    }

    ZX_DEBUG_ASSERT(*after_size <= max_after_size);
    return ZX_OK;
  }

  return status;
}

void AmlogicVideo::ToggleClock(ClockType type, bool enable) {
  if (enable) {
    clocks_[static_cast<int>(type)].Enable();
  } else {
    clocks_[static_cast<int>(type)].Disable();
  }
}

void AmlogicVideo::SetMetrics(CodecMetrics* metrics) {
  ZX_DEBUG_ASSERT(metrics);
  ZX_DEBUG_ASSERT(metrics != &default_nop_metrics_);
  ZX_DEBUG_ASSERT(metrics_ == &default_nop_metrics_);
  metrics_ = metrics;
}

zx_status_t AmlogicVideo::InitRegisters(zx_device_t* parent) {
  parent_ = parent;

  ddk::CompositeProtocolClient composite(parent);
  if (!composite.is_valid()) {
    DECODE_ERROR("Could not get composite protocol");
    return ZX_ERR_NO_RESOURCES;
  }

  pdev_ = ddk::PDev(composite);
  if (!pdev_.is_valid()) {
    DECODE_ERROR("Failed to get pdev protocol");
    return ZX_ERR_NO_RESOURCES;
  }

  sysmem_ = ddk::SysmemProtocolClient(composite, "sysmem");
  if (!sysmem_.is_valid()) {
    DECODE_ERROR("Could not get SYSMEM protocol");
    return ZX_ERR_NO_RESOURCES;
  }

  canvas_ = ddk::AmlogicCanvasProtocolClient(composite, "canvas");
  if (!canvas_.is_valid()) {
    DECODE_ERROR("Could not get video CANVAS protocol");
    return ZX_ERR_NO_RESOURCES;
  }

  clocks_[static_cast<int>(ClockType::kGclkVdec)] =
      ddk::ClockProtocolClient(composite, "clock-dos-vdec");
  if (!clocks_[static_cast<int>(ClockType::kGclkVdec)].is_valid()) {
    DECODE_ERROR("Could not get CLOCK protocol\n");
    return ZX_ERR_NO_RESOURCES;
  }

  clocks_[static_cast<int>(ClockType::kClkDos)] = ddk::ClockProtocolClient(composite, "clock-dos");
  if (!clocks_[static_cast<int>(ClockType::kClkDos)].is_valid()) {
    DECODE_ERROR("Could not get CLOCK protocol\n");
    return ZX_ERR_NO_RESOURCES;
  }

  // If tee is available as a fragment, we require that we can get ZX_PROTOCOL_TEE.  It'd be nice
  // if there were a less fragile way to detect this.  Passing in driver metadata for this doesn't
  // seem worthwhile so far.  There's no tee on vim2.
  tee_ = ddk::TeeProtocolClient(composite, "tee");
  is_tee_available_ = tee_.is_valid();

  if (is_tee_available_) {
    // TODO(fxbug.dev/39808): remove log spam once we're loading firmware via video_firmware TA
    LOG(INFO, "Got ZX_PROTOCOL_TEE");
  } else {
    // TODO(fxbug.dev/39808): remove log spam once we're loading firmware via video_firmware TA
    LOG(INFO, "Skipped ZX_PROTOCOL_TEE");
  }

  pdev_device_info_t info;
  zx_status_t status = pdev_.GetDeviceInfo(&info);
  if (status != ZX_OK) {
    DECODE_ERROR("pdev_.GetDeviceInfo failed");
    return status;
  }

  switch (info.pid) {
    case PDEV_PID_AMLOGIC_S912:
      device_type_ = DeviceType::kGXM;
      break;
    case PDEV_PID_AMLOGIC_S905D2:
      device_type_ = DeviceType::kG12A;
      break;
    case PDEV_PID_AMLOGIC_T931:
      device_type_ = DeviceType::kG12B;
      break;
    default:
      DECODE_ERROR("Unknown soc pid: %d", info.pid);
      return ZX_ERR_INVALID_ARGS;
  }

  static constexpr uint32_t kTrustedOsSmcIndex = 0;
  status = pdev_.GetSmc(kTrustedOsSmcIndex, &secure_monitor_);
  if (status != ZX_OK) {
    // On systems where there's no protected memory it's fine if we can't get
    // a handle to the secure monitor.
    LOG(INFO, "amlogic-video: Unable to get secure monitor handle, assuming no protected memory");
  }

  std::optional<ddk::MmioBuffer> cbus_mmio;
  status = pdev_.MapMmio(kCbus, &cbus_mmio);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed map cbus");
    return ZX_ERR_NO_MEMORY;
  }

  std::optional<ddk::MmioBuffer> mmio;
  status = pdev_.MapMmio(kDosbus, &mmio);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed map dosbus");
    return ZX_ERR_NO_MEMORY;
  }
  dosbus_.emplace(*std::move(mmio));
  status = pdev_.MapMmio(kHiubus, &mmio);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed map hiubus");
    return ZX_ERR_NO_MEMORY;
  }
  hiubus_.emplace(*std::move(mmio));
  status = pdev_.MapMmio(kAobus, &mmio);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed map aobus");
    return ZX_ERR_NO_MEMORY;
  }
  aobus_.emplace(*std::move(mmio));
  status = pdev_.MapMmio(kDmc, &mmio);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed map dmc");
    return ZX_ERR_NO_MEMORY;
  }
  dmc_.emplace(*std::move(mmio));
  status = pdev_.GetInterrupt(kParserIrq, 0, &parser_interrupt_handle_);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed get parser interrupt");
    return ZX_ERR_NO_MEMORY;
  }
  status = pdev_.GetInterrupt(kDosMbox0Irq, 0, &vdec0_interrupt_handle_);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed get vdec0 interrupt");
    return ZX_ERR_NO_MEMORY;
  }
  status = pdev_.GetInterrupt(kDosMbox1Irq, 0, &vdec1_interrupt_handle_);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed get vdec interrupt");
    return ZX_ERR_NO_MEMORY;
  }
  status = pdev_.GetBti(0, &bti_);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed get bti");
    return ZX_ERR_NO_MEMORY;
  }

  int64_t reset_register_offset = 0x1100 * 4;
  int64_t parser_register_offset = 0;
  int64_t demux_register_offset = 0;
  if (IsDeviceAtLeast(device_type_, DeviceType::kG12A)) {
    // Some portions of the cbus moved in newer versions (TXL and later).
    reset_register_offset = 0x0400 * 4;
    parser_register_offset = (0x3800 - 0x2900) * 4;
    demux_register_offset = (0x1800 - 0x1600) * 4;
  }
  reset_.emplace(*cbus_mmio, reset_register_offset);
  parser_regs_.emplace(*cbus_mmio, parser_register_offset);
  demux_.emplace(*cbus_mmio, demux_register_offset);
  cbus_.emplace(*std::move(cbus_mmio));
  registers_ = std::unique_ptr<MmioRegisters>(new MmioRegisters{
      &*dosbus_, &*aobus_, &*dmc_, &*hiubus_, &*reset_, &*parser_regs_, &*demux_});

  firmware_ = std::make_unique<FirmwareBlob>();
  status = firmware_->LoadFirmware(parent_);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed load firmware");
    return status;
  }

  sysmem_sync_ptr_.Bind(ConnectToSysmem());
  if (!sysmem_sync_ptr_) {
    DECODE_ERROR("ConnectToSysmem() failed");
    status = ZX_ERR_INTERNAL;
    return status;
  }
  parser_ = std::make_unique<Parser>(this, std::move(parser_interrupt_handle_));

  if (is_tee_available()) {
    // TODO(fxbug.dev/44674): Remove this retry loop once this issue is resolved.
    constexpr uint32_t kRetryCount = 10;
    for (uint32_t i = 0; i < kRetryCount; i++) {
      status = EnsureSecmemSessionIsConnected();
      if (status == ZX_OK) {
        break;
      }
    }

    if (!secmem_session_.has_value()) {
      LOG(ERROR,
          "OpenSession to secmem failed too many times. Bootloader version may be incorrect.");
      return ZX_ERR_INTERNAL;
    }
  }

  return ZX_OK;
}

zx_status_t AmlogicVideo::PreloadFirmwareViaTee() {
  ZX_DEBUG_ASSERT(is_tee_available_);

  uint8_t* firmware_data;
  uint32_t firmware_size;
  firmware_->GetWholeBlob(&firmware_data, &firmware_size);

  // TODO(fxbug.dev/44764): Remove retry when video_firmware crash is fixed.
  zx_status_t status = ZX_OK;
  constexpr uint32_t kRetryCount = 10;
  for (uint32_t i = 0; i < kRetryCount; i++) {
    fuchsia::tee::DeviceSyncPtr tee_connection;
    status = ConnectToTee(&tee_connection);
    if (status != ZX_OK) {
      LOG(ERROR, "ConnectToTee() failed - status: %d", status);
      continue;
    }

    auto video_firmware_session_result = VideoFirmwareSession::TryOpen(std::move(tee_connection));
    if (!video_firmware_session_result.is_ok()) {
      // Logging handled in `VideoFirmwareSession::TryOpen`
      status = ZX_ERR_INTERNAL;
      continue;
    }

    VideoFirmwareSession video_firmware_session = video_firmware_session_result.take_value();
    status = video_firmware_session.LoadVideoFirmware(firmware_data, firmware_size);
    if (status != ZX_OK) {
      LOG(ERROR, "video_firmware_session.LoadVideoFirmware() failed - status: %d", status);
      continue;
    }

    LOG(INFO, "Firmware loaded via video_firmware TA");
    break;
  }

  return status;
}

void AmlogicVideo::InitializeInterrupts() {
  vdec0_interrupt_thread_ = std::thread([this]() {
    while (true) {
      zx_time_t time;
      zx_status_t status = zx_interrupt_wait(vdec0_interrupt_handle_.get(), &time);
      if (status != ZX_OK) {
        DECODE_ERROR("vdec0_interrupt_thread_ zx_interrupt_wait() failed - status: %d", status);
        return;
      }
      std::lock_guard<std::mutex> lock(video_decoder_lock_);
      if (video_decoder_) {
        video_decoder_->HandleInterrupt();
      }
    }
  });

  vdec1_interrupt_thread_ = std::thread([this]() {
    while (true) {
      zx_time_t time;
      zx_status_t status = zx_interrupt_wait(vdec1_interrupt_handle_.get(), &time);
      if (status == ZX_ERR_CANCELED) {
        // expected when zx_interrupt_destroy() is called
        return;
      }
      if (status != ZX_OK) {
        // unexpected errors
        DECODE_ERROR(
            "AmlogicVideo::InitializeInterrupts() zx_interrupt_wait() failed "
            "status: %d\n",
            status);
        return;
      }
      std::lock_guard<std::mutex> lock(video_decoder_lock_);
      if (video_decoder_) {
        video_decoder_->HandleInterrupt();
      }
    }
  });
}

zx_status_t AmlogicVideo::InitDecoder() {
  if (is_tee_available_) {
    zx_status_t status = PreloadFirmwareViaTee();
    if (status != ZX_OK) {
      is_tee_available_ = false;
      // TODO(jbauman): Fail this function when everyone's updated their bootloaders.
      LOG(INFO, "Preloading firmware failed with status %d. protected decode won't work.", status);
    } else {
      // TODO(dustingreen): Remove log spam after secure decode works.
      LOG(INFO, "PreloadFirmwareViaTee() succeeded.");
    }
  } else {
    LOG(INFO, "!is_tee_available_");
  }

  InitializeInterrupts();

  return ZX_OK;
}
