// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/graphics/display/drivers/intel-i915/power.h"

#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/time.h>
#include <zircon/assert.h>

#include <unordered_set>

#include "src/graphics/display/drivers/intel-i915/hardware-common.h"
#include "src/graphics/display/drivers/intel-i915/pci-ids.h"
#include "src/graphics/display/drivers/intel-i915/poll-until.h"
#include "src/graphics/display/drivers/intel-i915/registers.h"
namespace i915 {

namespace {

bool SetPowerWellImpl(const PowerWellInfo& power_well_info, bool enable,
                      const fdf::MmioBuffer* mmio_space, int32_t timeout_for_pwr_well_ctl_state_us,
                      int32_t timeout_for_fuse_state_us) {
  if (power_well_info.always_on) {
    return true;
  }

  // Sequences from IHD-OS-TGL-Vol 12-12.21 "Sequences for Power Wells".
  // "Enable sequence" on page 220, "Disable sequence" on page 221.

  auto power_well_reg = registers::PowerWellControl::Get().ReadFrom(mmio_space);

  power_well_reg.power_request(power_well_info.request_bit_index).set(enable);
  power_well_reg.WriteTo(mmio_space);

  if (enable) {
    power_well_reg.ReadFrom(mmio_space);

    if (!PollUntil(
            [&] {
              return registers::PowerWellControl::Get()
                  .ReadFrom(mmio_space)
                  .power_state(power_well_info.state_bit_index)
                  .get();
            },
            zx::usec(1), timeout_for_pwr_well_ctl_state_us)) {
      zxlogf(ERROR, "Failed to enable power well (%s)", power_well_info.name);
      return false;
    }

    if (!PollUntil(
            [&] {
              ZX_DEBUG_ASSERT_MSG(
                  power_well_info.fuse_dist_bit_index <= std::numeric_limits<uint32_t>::max(),
                  "%zu overflows uint32_t", power_well_info.fuse_dist_bit_index);
              return registers::FuseStatus::Get()
                  .ReadFrom(mmio_space)
                  .dist_status(static_cast<uint32_t>(power_well_info.fuse_dist_bit_index));
            },
            zx::usec(1), timeout_for_fuse_state_us)) {
      zxlogf(ERROR, "Power well (%s) distribution failed", power_well_info.name);
      return false;
    }
  }

  return true;
}

const std::unordered_map<PowerWellId, PowerWellInfo> kPowerWellInfoTestDevice = {
    {PowerWellId::PG1,
     {
         .name = "Power Well 1",
         .always_on = true,
         .state_bit_index = 0,
         .request_bit_index = 1,
         .fuse_dist_bit_index = 2,
         .parent = PowerWellId::PG1,
     }},
};

// A fake power well implementation used only for integration tests.
class TestPowerWell : public Power {
 public:
  explicit TestPowerWell(fdf::MmioBuffer* mmio_space)
      : Power(mmio_space, &kPowerWellInfoTestDevice) {}
  void Resume() override {}

  PowerWellRef GetCdClockPowerWellRef() override { return PowerWellRef(this, PowerWellId::PG1); }
  PowerWellRef GetPipePowerWellRef(PipeId pipe_id) override {
    return PowerWellRef(this, PowerWellId::PG1);
  }
  PowerWellRef GetDdiPowerWellRef(DdiId ddi_id) override {
    return PowerWellRef(this, PowerWellId::PG1);
  }

  bool GetDdiIoPowerState(DdiId ddi_id) override {
    if (ddi_state_.find(ddi_id) == ddi_state_.end()) {
      ddi_state_[ddi_id] = false;
    }
    return ddi_state_[ddi_id];
  }

  void SetDdiIoPowerState(DdiId ddi_id, bool enable) override { ddi_state_[ddi_id] = enable; }

  bool GetAuxIoPowerState(DdiId ddi_id) override {
    if (aux_state_.find(ddi_id) == aux_state_.end()) {
      aux_state_[ddi_id] = false;
    }
    return aux_state_[ddi_id] = true;
  }

  void SetAuxIoPowerState(DdiId ddi_id, bool enable) override { aux_state_[ddi_id] = enable; }

 private:
  void SetPowerWell(PowerWellId power_well, bool enable) override {}

  std::unordered_map<DdiId, bool> ddi_state_;
  std::unordered_map<DdiId, bool> aux_state_;
};

const std::unordered_map<PowerWellId, PowerWellInfo> kPowerWellInfoSkylake = {
    {PowerWellId::PG1,
     {
         .name = "Power Well 1",
         .always_on = true,
         .state_bit_index = 28,
         .request_bit_index = 29,
         .fuse_dist_bit_index = 26,
         .parent = PowerWellId::PG1,
     }},
    {
        PowerWellId::PG2,
        {
            .name = "Power Well 2",
            .state_bit_index = 30,
            .request_bit_index = 31,
            .fuse_dist_bit_index = 25,
            .parent = PowerWellId::PG1,
        },
    },
};

// Power implementation for Sky lake and Kaby lake platforms.
class PowerSkylake : public Power {
 public:
  explicit PowerSkylake(fdf::MmioBuffer* mmio_space) : Power(mmio_space, &kPowerWellInfoSkylake) {}
  void Resume() override {
    if (ref_count().find(PowerWellId::PG2) != ref_count().end()) {
      SetPowerWell(PowerWellId::PG2, /* enable */ true);
    }
  }

  PowerWellRef GetCdClockPowerWellRef() override { return PowerWellRef(this, PowerWellId::PG1); }
  PowerWellRef GetPipePowerWellRef(PipeId pipe_id) override {
    return PowerWellRef(this, pipe_id == PipeId::PIPE_A ? PowerWellId::PG1 : PowerWellId::PG2);
  }
  PowerWellRef GetDdiPowerWellRef(DdiId ddi_id) override {
    return PowerWellRef(this, ddi_id == DdiId::DDI_A ? PowerWellId::PG1 : PowerWellId::PG2);
  }

  bool GetDdiIoPowerState(DdiId ddi_id) override {
    auto power_well = registers::PowerWellControl::Get().ReadFrom(mmio_space());
    return power_well.ddi_io_power_state_skylake(ddi_id).get();
  }

  void SetDdiIoPowerState(DdiId ddi_id, bool enable) override {
    auto power_well = registers::PowerWellControl::Get().ReadFrom(mmio_space());
    power_well.ddi_io_power_request_skylake(ddi_id).set(1);
    power_well.WriteTo(mmio_space());
  }

  bool GetAuxIoPowerState(DdiId ddi_id) override {
    // Per https://patchwork.freedesktop.org/series/453/, toggling hardware
    // resources that is controlled by DMC (display microcontroller) firmware
    // is redundant and could interfere with firmware's functionality.
    // Misc IO is controlled by DMC and it should be kept always on.
    return true;
  }

  void SetAuxIoPowerState(DdiId ddi_id, bool enable) override {
    // See comments above at GetAuxIoPowerState(). This method will not enable /
    // disable Misc IO power on-demand.
  }

 private:
  void SetPowerWell(PowerWellId power_well, bool enable) override {
    const auto& power_well_info = power_well_info_map()->at(power_well);

    constexpr int32_t kWaitForPwrWellCtlStateUs = 20;
    constexpr int32_t kWaitForFuseStatusDistUs = 1;
    auto ok = SetPowerWellImpl(power_well_info, enable, mmio_space(), kWaitForPwrWellCtlStateUs,
                               kWaitForFuseStatusDistUs);

    ZX_DEBUG_ASSERT(ok);
  }

  std::unordered_set<DdiId> aux_io_enabled_ddis_;
};

// Dependencies between power wells from IHD-OS-TGL-Vol 12-12.21
// "Enable Sequence", pages 220-221.
//
// FUSE_STATUS bits from IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 990-991.
// PWR_WELL_CTL bits from IHD-OS-TGL-Vol 2c-12.21 Part 2 pages 1063-1065.
const std::unordered_map<PowerWellId, PowerWellInfo> kPowerWellInfoTigerLake = {
    // PG0 not tracked because it's managed by the CPU power controller.
    {PowerWellId::PG1,
     {
         .name = "Power Well 1",
         .always_on = true,
         .state_bit_index = 0,
         .request_bit_index = 1,
         .fuse_dist_bit_index = 26,
         .parent = PowerWellId::PG1,
     }},
    {PowerWellId::PG2,
     {
         .name = "Power Well 2",
         .state_bit_index = 2,
         .request_bit_index = 3,
         .fuse_dist_bit_index = 25,
         .parent = PowerWellId::PG1,
     }},
    {PowerWellId::PG3,
     {
         .name = "Power Well 3",
         .state_bit_index = 4,
         .request_bit_index = 5,
         .fuse_dist_bit_index = 24,
         .parent = PowerWellId::PG2,
     }},
    {PowerWellId::PG4,
     {
         .name = "Power Well 4",
         .state_bit_index = 6,
         .request_bit_index = 7,
         .fuse_dist_bit_index = 23,
         .parent = PowerWellId::PG3,
     }},
    {PowerWellId::PG5,
     {
         .name = "Power Well 5",
         .state_bit_index = 8,
         .request_bit_index = 9,
         .fuse_dist_bit_index = 22,
         .parent = PowerWellId::PG4,
     }},
};

// Power well implementation for Tiger lake platforms.
class PowerTigerLake : public Power {
 public:
  explicit PowerTigerLake(fdf::MmioBuffer* mmio_space)
      : Power(mmio_space, &kPowerWellInfoTigerLake) {}
  void Resume() override {
    constexpr PowerWellId kPowerWellEnableSeq[] = {
        PowerWellId::PG2,
        PowerWellId::PG3,
        PowerWellId::PG4,
        PowerWellId::PG5,
    };
    for (const auto power_well : kPowerWellEnableSeq) {
      if (ref_count().find(power_well) != ref_count().end()) {
        SetPowerWell(power_well, /* enable */ true);
      }
    }
  }

  PowerWellRef GetCdClockPowerWellRef() override { return PowerWellRef(this, PowerWellId::PG1); }
  PowerWellRef GetPipePowerWellRef(PipeId pipe_id) override {
    // Power well assignments from IHD-OS-TGL-Vol 12-12.21
    // "Functions Within Each Well", pages 219-220.

    // TODO(https://fxbug.dev/42177916): Add all pipes supported by gen12.
    switch (pipe_id) {
      case PipeId::PIPE_A:
        return PowerWellRef(this, PowerWellId::PG1);
      case PipeId::PIPE_B:
        return PowerWellRef(this, PowerWellId::PG2);
      case PipeId::PIPE_C:
        return PowerWellRef(this, PowerWellId::PG3);
      case PipeId::PIPE_INVALID:
        ZX_ASSERT(false);
    }
  }

  PowerWellRef GetDdiPowerWellRef(DdiId ddi_id) override {
    // Power well assignments from IHD-OS-TGL-Vol 12-12.21
    // "Functions Within Each Well", pages 219-220.

    switch (ddi_id) {
      case DdiId::DDI_A:
      case DdiId::DDI_B:
      case DdiId::DDI_C:
        return PowerWellRef(this, PowerWellId::PG1);
      case DdiId::DDI_TC_1:
      case DdiId::DDI_TC_2:
      case DdiId::DDI_TC_3:
      case DdiId::DDI_TC_4:
      case DdiId::DDI_TC_5:
      case DdiId::DDI_TC_6:
        return PowerWellRef(this, PowerWellId::PG3);
    }
  }

  bool GetDdiIoPowerState(DdiId ddi_id) override {
    auto power_well = registers::PowerWellControlDdi2::Get().ReadFrom(mmio_space());
    return power_well.ddi_io_power_state_tiger_lake(ddi_id).get();
  }

  void SetDdiIoPowerState(DdiId ddi_id, bool enable) override {
    auto power_well = registers::PowerWellControlDdi2::Get().ReadFrom(mmio_space());
    power_well.ddi_io_power_request_tiger_lake(ddi_id).set(enable);
    power_well.WriteTo(mmio_space());
  }

  bool GetAuxIoPowerState(DdiId ddi_id) override {
    auto power_well = registers::PowerWellControlAux::Get().ReadFrom(mmio_space());
    return power_well.powered_on_combo_or_usb_c(ddi_id);
  }

  void SetAuxIoPowerState(DdiId ddi_id, bool enable) override {
    auto power_well = registers::PowerWellControlAux::Get().ReadFrom(mmio_space());
    power_well.set_power_on_request_combo_or_usb_c(ddi_id, enable);
    power_well.WriteTo(mmio_space());
  }

 private:
  void SetPowerWell(PowerWellId power_well, bool enable) override {
    const auto& power_well_info = power_well_info_map()->at(power_well);

    constexpr int32_t kWaitForPwrWellCtlStateUs = 20;
    constexpr int32_t kWaitForFuseStatusDistUs = 20;
    auto ok = SetPowerWellImpl(power_well_info, enable, mmio_space(), kWaitForPwrWellCtlStateUs,
                               kWaitForFuseStatusDistUs);

    ZX_DEBUG_ASSERT(ok);
  }
};

}  // namespace

PowerWellRef::PowerWellRef() {}

PowerWellRef::PowerWellRef(Power* power, PowerWellId power_well)
    : power_(power), power_well_(power_well) {
  power_->IncRefCount(power_well);
}

PowerWellRef::PowerWellRef(PowerWellRef&& o) : power_(o.power_), power_well_(o.power_well_) {
  o.power_ = nullptr;
}

PowerWellRef& PowerWellRef::operator=(PowerWellRef&& o) {
  if (power_) {
    power_->DecRefCount(power_well_);
  }
  power_ = o.power_;
  power_well_ = o.power_well_;
  o.power_ = nullptr;
  return *this;
}

PowerWellRef::~PowerWellRef() {
  if (power_) {
    power_->DecRefCount(power_well_);
  }
}

Power::Power(fdf::MmioBuffer* mmio_space, const PowerWellInfoMap* power_well_info)
    : mmio_space_(mmio_space), power_well_info_map_(power_well_info) {}

void Power::IncRefCount(PowerWellId power_well) {
  ZX_DEBUG_ASSERT(power_well_info_map_ &&
                  power_well_info_map_->find(power_well) != power_well_info_map_->end());

  auto power_well_info = power_well_info_map_->at(power_well);
  auto parent = power_well_info.parent;
  if (parent != power_well) {
    IncRefCount(parent);
  }

  if (ref_count_.find(power_well) == ref_count_.end()) {
    if (!power_well_info.always_on) {
      SetPowerWell(power_well, /* enable */ true);
    }
    ref_count_[power_well] = 1;
  } else {
    ++ref_count_[power_well];
  }
}

void Power::DecRefCount(PowerWellId power_well) {
  ZX_DEBUG_ASSERT(power_well_info_map_ &&
                  power_well_info_map_->find(power_well) != power_well_info_map_->end());
  ZX_DEBUG_ASSERT(ref_count_.find(power_well) != ref_count_.end() && ref_count_.at(power_well) > 0);

  auto power_well_info = power_well_info_map_->at(power_well);
  if (ref_count_.at(power_well) == 1) {
    if (!power_well_info.always_on) {
      SetPowerWell(power_well, /* enable */ false);
    }
    ref_count_.erase(power_well);
  } else {
    --ref_count_[power_well];
  }

  auto parent = power_well_info.parent;
  if (parent != power_well) {
    DecRefCount(parent);
  }
}

// static
std::unique_ptr<Power> Power::New(fdf::MmioBuffer* mmio_space, uint16_t device_id) {
  if (is_skl(device_id) || is_kbl(device_id)) {
    return std::make_unique<PowerSkylake>(mmio_space);
  }
  if (is_tgl(device_id)) {
    return std::make_unique<PowerTigerLake>(mmio_space);
  }
  if (is_test_device(device_id)) {
    return std::make_unique<TestPowerWell>(mmio_space);
  }
  ZX_DEBUG_ASSERT_MSG(false, "Device id %04x is not supported", device_id);
  return nullptr;
}

}  // namespace i915
