// Copyright 2023 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-transmitter.h"

#include <lib/zx/result.h>

#include <algorithm>
#include <iterator>
#include <list>
#include <memory>

#include <gtest/gtest.h>
#include <mock-mmio-range/mock-mmio-range.h>

#include "src/graphics/display/lib/api-types-cpp/display-timing.h"
#include "src/graphics/display/lib/designware-hdmi/hdmi-transmitter-controller.h"
#include "src/lib/testing/predicates/status.h"

namespace amlogic_display {

enum class HdmiTransmitterControllerCall : uint8_t {
  kConfigHdmitx,
  kSetupInterrupts,
  kReset,
  kSetupScdc,
  kResetFc,
  kSetFcScramblerCtrl,
};

// TODO(https://fxbug.dev/42085847): Consider replacing the mock class with a fake
// HdmiTransmitterController implementation.
class MockHdmiTransmitterController : public designware_hdmi::HdmiTransmitterController {
 public:
  MockHdmiTransmitterController() = default;
  ~MockHdmiTransmitterController() { EXPECT_TRUE(expected_calls_.empty()); }

  zx_status_t InitHw() override { return ZX_OK; }
  zx_status_t EdidTransfer(const i2c_impl_op_t* op_list, size_t op_count) override { return ZX_OK; }

  void ConfigHdmitx(const designware_hdmi::ColorParam& color_param,
                    const display::DisplayTiming& mode,
                    const designware_hdmi::hdmi_param_tx& p) override {
    OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kConfigHdmitx);
  }
  void SetupInterrupts() override {
    OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kSetupInterrupts);
  }
  void Reset() override { OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kReset); }
  void SetupScdc(bool is4k) override {
    OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kSetupScdc);
  }
  void ResetFc() override {
    OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kResetFc);
  }
  void SetFcScramblerCtrl(bool is4k) override {
    OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall::kSetFcScramblerCtrl);
  }

  void OnHdmiTransmitterControllerCall(HdmiTransmitterControllerCall call) {
    ASSERT_FALSE(expected_calls_.empty());
    EXPECT_EQ(expected_calls_.front(), call);
    expected_calls_.pop_front();
  }

  void ExpectCalls(const cpp20::span<const HdmiTransmitterControllerCall> expected_calls) {
    std::copy(expected_calls.begin(), expected_calls.end(), std::back_inserter(expected_calls_));
  }

  void PrintRegisters() override {}

 private:
  std::list<HdmiTransmitterControllerCall> expected_calls_;
};

class HdmiTransmitterTest : public testing::Test {
 public:
  void SetUp() override {
    std::unique_ptr<MockHdmiTransmitterController> mock_hdmitx_controller =
        std::make_unique<MockHdmiTransmitterController>();
    mock_hdmitx_controller_ = mock_hdmitx_controller.get();

    // TODO(https://fxbug.dev/42074342): Use a fake SMC resource, when the
    // implementation lands.
    dut_ = std::make_unique<HdmiTransmitter>(std::move(mock_hdmitx_controller),
                                             top_level_mmio_range_.GetMmioBuffer(),
                                             /*smc=*/zx::resource{});
    ASSERT_TRUE(dut_);
  }

  void TearDown() override { top_level_mmio_range_.CheckAllAccessesReplayed(); }

 protected:
  constexpr static int kTopLevelMmioRangeSize = 0x8000;
  ddk_mock::MockMmioRange top_level_mmio_range_{kTopLevelMmioRangeSize,
                                                ddk_mock::MockMmioRange::Size::k32};

  std::unique_ptr<HdmiTransmitter> dut_;

  // Owned by `dut_`.
  MockHdmiTransmitterController* mock_hdmitx_controller_ = nullptr;
};

// Register addresses from the A311D datasheet section 10.2.3.44 "HDCP2.2 IP
// Register Access".
constexpr int kHdmiTxTopSwResetOffset = 0x00 * 4;
constexpr int kHdmiTxTopClkCntlOffset = 0x01 * 4;
constexpr int kHdmiTxTopIntrMaskn = 0x03 * 4;
constexpr int kHdmiTxTopIntrStatClr = 0x05 * 4;
constexpr int kHdmiTxTopBistCntl = 0x06 * 4;
constexpr int kHdmiTxTopTmdsClkPttn01 = 0x0a * 4;
constexpr int kHdmiTxTopTmdsClkPttn23 = 0x0b * 4;
constexpr int kHdmiTxTopTmdsClkPttnCntl = 0x0c * 4;

TEST_F(HdmiTransmitterTest, ResetTest) {
  top_level_mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({
      {.address = kHdmiTxTopSwResetOffset, .value = 0, .write = true},
      {.address = kHdmiTxTopClkCntlOffset, .value = 0xff, .write = true},
  }));
  zx::result<> result = dut_->Reset();
  EXPECT_OK(result.status_value());
}

TEST_F(HdmiTransmitterTest, ModeSetTest) {
  // TODO(https://fxbug.dev/42085738): Use valid synthetic values for timings.
  display::DisplayTiming display_timing = {
      .horizontal_active_px = 0,
      .horizontal_front_porch_px = 0,
      .horizontal_sync_width_px = 0,
      .horizontal_back_porch_px = 0,
      .vertical_active_lines = 0,
      .vertical_front_porch_lines = 0,
      .vertical_sync_width_lines = 0,
      .vertical_back_porch_lines = 0,
      .pixel_clock_frequency_hz = 0,
      .fields_per_frame = display::FieldsPerFrame::kProgressive,
      .hsync_polarity = display::SyncPolarity::kNegative,
      .vsync_polarity = display::SyncPolarity::kNegative,
      .vblank_alternates = false,
      .pixel_repetition = 0,
  };
  designware_hdmi::ColorParam color_param = {
      .input_color_format = designware_hdmi::ColorFormat::kCfRgb,
      .output_color_format = designware_hdmi::ColorFormat::kCfRgb,
      .color_depth = designware_hdmi::ColorDepth::kCd24B,
  };

  top_level_mmio_range_.Expect(ddk_mock::MockMmioRange::AccessList({
      {.address = kHdmiTxTopBistCntl, .value = 1 << 12, .write = true},
      {.address = kHdmiTxTopIntrStatClr, .value = 0x1f, .write = true},
      {.address = kHdmiTxTopIntrMaskn, .value = 0x9f, .write = true},
      {.address = kHdmiTxTopTmdsClkPttn01, .value = 0x001f'001f, .write = true},
      {.address = kHdmiTxTopTmdsClkPttn23, .value = 0x001f'001f, .write = true},
      {.address = kHdmiTxTopTmdsClkPttnCntl, .value = 0x01, .write = true},
      {.address = kHdmiTxTopTmdsClkPttnCntl, .value = 0x02, .write = true},
  }));

  static constexpr HdmiTransmitterControllerCall kExpectedCalls[] = {
      HdmiTransmitterControllerCall::kConfigHdmitx,
      HdmiTransmitterControllerCall::kSetupInterrupts,
      HdmiTransmitterControllerCall::kReset,
      HdmiTransmitterControllerCall::kSetFcScramblerCtrl,
      HdmiTransmitterControllerCall::kSetupScdc,
      HdmiTransmitterControllerCall::kResetFc,
  };
  mock_hdmitx_controller_->ExpectCalls(kExpectedCalls);

  zx::result<> result = dut_->ModeSet(display_timing, color_param);
  EXPECT_OK(result.status_value());
}

}  // namespace amlogic_display
