// 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.

#ifndef SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_DISPLAY_IGD_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_DISPLAY_IGD_H_

#include <lib/device-protocol/pci.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <zircon/assert.h>
#include <zircon/types.h>

#include <cinttypes>
#include <cstddef>
#include <cstring>
#include <unordered_map>

#include <hwreg/bitfields.h>

#include "src/graphics/display/drivers/intel-display/acpi-memory-region.h"
#include "src/graphics/display/drivers/intel-display/hardware-common.h"

namespace intel_display {
// Various definitions from IGD OpRegion/Software SCI documentation.

// Length of the igd opregion
constexpr uint32_t kIgdOpRegionLen = 0x2000;

constexpr uint32_t kMaxVbtSize = 6144;

typedef struct igd_opregion {
  uint8_t signature[16];
  uint32_t kb_size;
  uint32_t version;
  uint8_t system_bios_build_version[32];
  uint8_t video_bios_build_version[16];
  uint8_t graphics_bios_build_version[16];
  uint32_t supported_mailboxes;
  uint32_t driver_model;
  uint32_t pcon;
  uint8_t gop_version[32];
  uint8_t rsvd[124];

  uint8_t mailbox1[256];
  uint8_t mailbox2[256];
  uint8_t mailbox3[256];
  uint8_t mailbox4[kMaxVbtSize];
  uint8_t mailbox5[1024];

  uint8_t major_version() const { return version >> 24; }
  uint8_t minor_version() const { return (version >> 16) & 0xff; }

  bool asle_supported() const { return supported_mailboxes & (1 << 2); }

  struct vbt_region_t {
    uint64_t rvda;
    uint32_t rvds;
  } __attribute__((__packed__));

  vbt_region_t vbt_region() {
    vbt_region_t region;
    // According to the IGD OpRegion spec v0.5, this offset is the beginning
    // of a reserved region.  It would be good to confirm this offset with a
    // newer version of the spec.
    std::memcpy(&region, &mailbox3[186], sizeof(vbt_region_t));
    return region;
  }

  bool validate() {
    const char* sig = "IntelGraphicsMem";
    return !memcmp(signature, reinterpret_cast<const void*>(sig), 16) &&
           kb_size >= (sizeof(struct igd_opregion) >> 10);
  }
} igd_opregion_t;

static_assert(sizeof(igd_opregion_t) == 0x2000, "Bad igd opregion len");
static_assert(offsetof(igd_opregion_t, mailbox4) == 1024, "Bad mailbox4 offset");

typedef struct sci_interface {
  uint32_t entry_and_exit_params;
  uint32_t additional_params;
  uint32_t driver_sleep_timeout;
  uint8_t rsvd[240];
} sci_interface_protocol_t;

static_assert(sizeof(sci_interface_protocol_t) == 252, "Bad sci_interface_protocol_t size");

// Header for each bios data block.
typedef struct block_header {
  uint8_t type;
  // Size of the block, not including the header
  uint8_t size_low;
  uint8_t size_high;
} block_header_t;
static_assert(sizeof(block_header_t) == 3, "Bad block_header size");

typedef struct bios_data_blocks_header {
  uint8_t signature[16];
  uint16_t version;
  // Size of the header by itself
  uint16_t header_size;
  // Size of the header + all the blocks
  uint16_t bios_data_blocks_size;

  bool validate() {
    const char* sig = "BIOS_DATA_BLOCK";
    return !memcmp(signature, sig, 15) && bios_data_blocks_size >= sizeof(block_header_t);
  }
} bios_data_blocks_header_t;
static_assert(sizeof(bios_data_blocks_header_t) == 22, "Bad bios_data_blocks_header size");

typedef struct vbt_header {
  uint8_t signature[20];
  uint16_t version;
  uint16_t header_size;
  uint16_t vbt_size;
  uint8_t checksum;
  uint8_t rsvd;
  uint32_t bios_data_blocks_offset;
  uint32_t aim_offset[4];

  bool validate() {
    const char* sig_prefix = "$VBT";
    return !memcmp(signature, sig_prefix, 4) && sizeof(bios_data_blocks_header_t) < vbt_size &&
           bios_data_blocks_offset < vbt_size - sizeof(bios_data_blocks_header_t);
  }
} vbt_header_t;
static_assert(sizeof(vbt_header_t) == 48, "Bad vbt_header size");

typedef struct general_definitions {
  static constexpr uint32_t kBlockType = 2;

  uint8_t unused[4];
  // Contains the length of each entry in ddis.
  uint8_t ddi_config_size;
  // Array of ddi_config structures.
  uint8_t ddis[0];
} general_definitions_t;

// Bitfield for ddi_config's ddi_flags register
class DdiFlags : public hwreg::RegisterBase<DdiFlags, uint16_t> {
 public:
  DEF_BIT(12, internal);
  DEF_BIT(11, not_hdmi);
  DEF_BIT(4, tmds);
  DEF_BIT(2, dp);

  static auto Get() { return hwreg::RegisterAddr<DdiFlags>(0); }
};

typedef struct __attribute__((packed)) ddi_config {
  uint8_t unused1[2];
  // See DdiFlags class
  uint16_t ddi_flags;
  uint8_t unused2[3];

  uint8_t hdmi_cfg;
  // Index into the recommended buffer translation table to use when
  // configuring DDI_BUF_TRANS[9] for HDMI/DVI.
  DEF_SUBFIELD(hdmi_cfg, 3, 0, ddi_buf_trans_idx);

  uint8_t unused3[8];
  // Specifies the DDI this config this corresponds to as well as type of DDI.
  uint8_t port_type;
  uint8_t unused4[6];

  uint8_t flags;
  // Flag that indicates that there is an iboost override. An override enables
  // iboost for all DDI_BUF_TRANS values and overrides the recommended iboost.
  DEF_SUBBIT(flags, 3, has_iboost_override);

  uint8_t unused5[9];

  uint8_t type_c_config;
  DEF_SUBBIT(type_c_config, 0, is_usb_type_c);
  DEF_SUBBIT(type_c_config, 1, is_thunderbolt);

  uint8_t unused6[3];

  uint8_t iboost_levels;
  // The iboost override level, if has_iboost_override is set.
  DEF_SUBFIELD(iboost_levels, 7, 4, hdmi_iboost_override);
  DEF_SUBFIELD(iboost_levels, 3, 0, dp_iboost_override);
} ddi_config_t;
static_assert(offsetof(ddi_config_t, ddi_flags) == 2, "Bad ddi_flags offset");
static_assert(offsetof(ddi_config_t, hdmi_cfg) == 7, "Bad hdmi_cfg offset");
static_assert(offsetof(ddi_config_t, port_type) == 16, "Bad port_type offset");
static_assert(offsetof(ddi_config_t, flags) == 23, "Bad flags offset");
static_assert(offsetof(ddi_config_t, iboost_levels) == 37, "Bad iboost_levels offset");
static_assert(sizeof(ddi_config_t) == 38, "Bad ddi_config_t size");

typedef struct edp_config {
  static constexpr uint32_t kBlockType = 27;

  uint8_t unused[204];
  // Contains 16 nibbles, one for each panel type 0x0-0xf. If the value
  // is 0, then the panel is a low voltage panel.
  uint8_t vswing_preemphasis[8];
  // A bunch of other unused stuff
} edp_config_t;
static_assert(offsetof(edp_config_t, vswing_preemphasis) == 204, "Bad vswing_preemphasis offset");

typedef struct lvds_config {
  static constexpr uint32_t kBlockType = 40;

  // The default panel type for the hardware. Can be overridden by the IGD
  // SCI panel details function.
  uint8_t panel_type;
  // A bunch of other unused stuff
} lvds_config_t;

typedef struct lfp_backlight_entry {
  uint8_t flags;
  uint8_t pwm_freq_hz_low;
  uint8_t pwm_freq_hz_high;
  uint8_t min_brightness;
  uint8_t unused[2];
} lfp_backlight_entry_t;
static_assert(sizeof(lfp_backlight_entry_t) == 6, "Bad struct size");

typedef struct lfp_backlight {
  static constexpr uint32_t kBlockType = 43;

  uint8_t entry_size;
  lfp_backlight_entry_t entries[16];
  uint8_t level[16];
} lfp_backlight_t;
static_assert(sizeof(lfp_backlight_t) == 113, "Bad struct size");

class IgdOpRegion {
 public:
  IgdOpRegion() = default;
  ~IgdOpRegion();

  // `mmio_resource` must be of kind `ZX_RSRC_KIND_MMIO` and must have access
  // to all valid physical memory address ranges.
  //
  // Returns ZX_ERR_NOT_SUPPORTED if the boot firmware doesn't support the
  // OpRegion protocol. The firmware might be completely missing OpRegion
  // support, or may have a broken implementation that reports invalid data.
  zx_status_t Init(zx::unowned_resource mmio_resource, ddk::Pci& pci);

  bool HasDdi(DdiId ddi_id) const { return ddi_features_.find(ddi_id) != ddi_features_.end(); }
  bool SupportsHdmi(DdiId ddi_id) const {
    return HasDdi(ddi_id) && ddi_features_.at(ddi_id).supports_hdmi;
  }
  bool SupportsDvi(DdiId ddi_id) const {
    return HasDdi(ddi_id) && ddi_features_.at(ddi_id).supports_dvi;
  }
  bool SupportsDp(DdiId ddi_id) const {
    return HasDdi(ddi_id) && ddi_features_.at(ddi_id).supports_dp;
  }
  bool IsTypeC(DdiId ddi_id) const { return HasDdi(ddi_id) && ddi_features_.at(ddi_id).is_type_c; }
  bool IsEdp(DdiId ddi_id) const { return HasDdi(ddi_id) && ddi_features_.at(ddi_id).is_edp; }

  bool IsLowVoltageEdp(DdiId ddi_id) const {
    // TODO(stevensd): Support the case where more than one type of edp panel is present.
    return HasDdi(ddi_id) && ddi_features_.at(ddi_id).is_edp && edp_is_low_voltage_;
  }

  uint8_t GetIBoost(DdiId ddi_id, bool is_dp) const {
    return is_dp ? HasDdi(ddi_id) && ddi_features_.at(ddi_id).iboosts.dp_iboost
                 : HasDdi(ddi_id) && ddi_features_.at(ddi_id).iboosts.hdmi_iboost;
  }

  static constexpr uint8_t kUseDefaultIdx = 0xff;
  uint8_t GetHdmiBufferTranslationIndex(DdiId ddi_id) const {
    ZX_DEBUG_ASSERT(SupportsHdmi(ddi_id) || SupportsDvi(ddi_id));
    return ddi_features_.at(ddi_id).hdmi_buffer_translation_idx;
  }

  double GetMinBacklightBrightness() const { return min_backlight_brightness_; }

  // TODO(https://fxbug.dev/42063424): Instead of adding the helper functions, these DDI
  // features should be exported as a data-only struct that can be easily
  // injected by tests.
  void SetIsEdpForTesting(DdiId ddi_id, bool is_edp) { ddi_features_[ddi_id].is_edp = is_edp; }
  void SetSupportsDpForTesting(DdiId ddi_id, bool value) {
    ddi_features_[ddi_id].supports_dp = value;
  }
  void SetIsTypeCForTesting(DdiId ddi_id, bool value) { ddi_features_[ddi_id].is_type_c = value; }

 private:
  template <typename T>
  T* GetSection(uint16_t* size);
  uint8_t* GetSection(uint8_t tag, uint16_t* size);
  bool ProcessDdiConfigs();
  bool CheckForLowVoltageEdp(ddk::Pci& pci);
  bool GetPanelType(ddk::Pci& pci, uint8_t* type);
  bool Swsci(ddk::Pci& pci, uint16_t function, uint16_t subfunction, uint32_t additional_param,
             uint16_t* exit_param, uint32_t* additional_res);
  void ProcessBacklightData();

  AcpiMemoryRegion memory_op_region_;

  // Empty if the VBT fits in the Memory OpRegion's Mailbox 4.
  AcpiMemoryRegion extended_vbt_region_;

  igd_opregion_t* igd_opregion_;
  bios_data_blocks_header_t* bdb_;

  struct DdiFeatures {
    bool supports_hdmi;
    bool supports_dvi;
    bool supports_dp;
    bool is_edp;
    bool is_type_c;
    bool is_thunderbolt;

    struct Iboost {
      uint8_t hdmi_iboost = 0;
      uint8_t dp_iboost = 0;
    };
    Iboost iboosts;
    uint8_t hdmi_buffer_translation_idx;
  };
  std::unordered_map<DdiId, DdiFeatures> ddi_features_;

  bool edp_is_low_voltage_ = false;
  uint8_t panel_type_;
  double min_backlight_brightness_;
};

}  // namespace intel_display

#endif  // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_DISPLAY_IGD_H_
