// 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_I915_DISPLAY_DEVICE_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_DISPLAY_DEVICE_H_

#include <fidl/fuchsia.hardware.backlight/cpp/wire.h>
#include <fuchsia/hardware/display/controller/c/banjo.h>
#include <fuchsia/hardware/i2cimpl/cpp/banjo.h>
#include <lib/mmio/mmio.h>
#include <lib/zx/result.h>
#include <lib/zx/vmo.h>
#include <zircon/types.h>

#include <ddktl/device.h>
#include <region-alloc/region-alloc.h>

#include "src/graphics/display/drivers/intel-i915/ddi-physical-layer-manager.h"
#include "src/graphics/display/drivers/intel-i915/dpll.h"
#include "src/graphics/display/drivers/intel-i915/pipe.h"
#include "src/graphics/display/drivers/intel-i915/power.h"
#include "src/graphics/display/lib/api-types-cpp/config-stamp.h"
#include "src/graphics/display/lib/api-types-cpp/display-id.h"
#include "src/graphics/display/lib/api-types-cpp/display-timing.h"

namespace i915 {

class Controller;
class DisplayDevice;
namespace FidlBacklight = fuchsia_hardware_backlight;

// Thread safe weak-ref to the DisplayDevice, because the backlight device
// lifecycle is managed by devmgr but the DisplayDevice lifecycle is managed
// by the display controller class.
typedef struct display_ref {
  mtx_t mtx;
  DisplayDevice* display_device __TA_GUARDED(mtx);
} display_ref_t;

class DisplayDevice : public fidl::WireServer<FidlBacklight::Device> {
 public:
  enum class Type {
    kEdp,
    kDp,
    kHdmi,
    kDvi,
  };

  DisplayDevice(Controller* controller, display::DisplayId id, DdiId ddi_id,
                DdiReference ddi_reference, Type type);

  DisplayDevice(const DisplayDevice&) = delete;
  DisplayDevice(DisplayDevice&&) = delete;
  DisplayDevice& operator=(const DisplayDevice&) = delete;
  DisplayDevice& operator=(DisplayDevice&&) = delete;

  ~DisplayDevice() override;

  void ApplyConfiguration(const display_config_t* banjo_display_config,
                          display::ConfigStamp config_stamp);

  // TODO(https://fxbug.dev/42167004): Initialization-related interactions between the Controller class and
  // DisplayDevice can currently take different paths, with Init() being called conditionally in
  // some cases (e.g. if the display has already been configured and powered up by the bootloader),
  // which means a DisplayDevice can hold many states before being considered fully-initialized.
  // It would be good to simplify this by:
  // 1. Eliminating the "partially initialized" DisplayDevice state from the point of its owner.
  // 2. Having a single Init factory function with options, such as the current DPLL state, which is
  // always called to construct a DisplayDevice, possibly merging Query, Init,
  // InitWithDdiPllConfig, and InitBacklight, into a single routine.
  // 3. Perhaps what represents a DDI and a display attached to a DDI should be separate
  // abstractions?

  // Query whether or not there is a display attached to this ddi. Does not
  // actually do any initialization - that is done by Init.
  virtual bool Query() = 0;
  // Does display mode agnostic ddi initialization - subclasses implement InitDdi.
  bool Init();
  // Initialize the display based on existing hardware state. This method should be used instead of
  // Init() when a display PLL has already been powered up and configured (e.g. by the bootlader)
  // when the driver discovers the display. DDI initialization will not be performed in this case.
  virtual bool InitWithDdiPllConfig(const DdiPllConfig& pll_config);
  // Initializes the display backlight for an already initialized display.
  void InitBacklight();
  // Resumes the ddi after suspend.
  bool Resume();
  // Loads ddi state from the hardware at driver startup.
  void LoadActiveMode();
  // Method to allow the display device to handle hotplug events. Returns
  // true if the device can handle the event without disconnecting. Otherwise
  // the device will be removed.
  virtual bool HandleHotplug(bool long_pulse) { return false; }

  display::DisplayId id() const { return id_; }
  DdiId ddi_id() const { return ddi_id_; }
  Controller* controller() { return controller_; }
  const std::optional<DdiReference>& ddi_reference() const { return ddi_reference_; }

  virtual ddk::I2cImplProtocolClient i2c() = 0;

  void set_pipe(Pipe* pipe) { pipe_ = pipe; }
  Pipe* pipe() const { return pipe_; }

  Type type() const { return type_; }
  void set_type(Type type) { type_ = type; }

  virtual bool HasBacklight() { return false; }
  virtual zx::result<> SetBacklightState(bool power, double brightness) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }
  virtual zx::result<FidlBacklight::wire::State> GetBacklightState() {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  virtual bool CheckPixelRate(int64_t pixel_rate_hz) = 0;

  // FIDL calls
  void GetStateNormalized(GetStateNormalizedCompleter::Sync& completer) override;
  void SetStateNormalized(SetStateNormalizedRequestView request,
                          SetStateNormalizedCompleter::Sync& completer) override;
  void GetStateAbsolute(GetStateAbsoluteCompleter::Sync& completer) override;
  void SetStateAbsolute(SetStateAbsoluteRequestView request,
                        SetStateAbsoluteCompleter::Sync& completer) override;
  void GetMaxAbsoluteBrightness(GetMaxAbsoluteBrightnessCompleter::Sync& completer) override;
  void SetNormalizedBrightnessScale(
      SetNormalizedBrightnessScaleRequestView request,
      SetNormalizedBrightnessScaleCompleter::Sync& completer) override;
  void GetNormalizedBrightnessScale(
      GetNormalizedBrightnessScaleCompleter::Sync& completer) override;

 protected:
  // Attempts to initialize the ddi.
  virtual bool InitDdi() = 0;
  virtual bool InitBacklightHw() { return false; }

  // Configures the hardware to display content at the given resolution.
  virtual bool DdiModeset(const display::DisplayTiming& mode) = 0;

  // Returns an empty configuration if the desired pixel clock is unattainable.
  // Otherwise, the returned configuration is guaranteed to be valid.
  virtual DdiPllConfig ComputeDdiPllConfig(int32_t pixel_clock_khz) = 0;

  // Load the pixel rate from hardware if it's necessary when changing the
  // transcoder.
  //
  // The return value is in kHz.
  virtual int32_t LoadPixelRateForTranscoderKhz(TranscoderId transcoder_id) = 0;

  // Attaching a pipe to a display or configuring a pipe after display mode change has
  // 3 steps. The second step is generic pipe configuration, whereas PipeConfigPreamble
  // and PipeConfigEpilogue are responsible for display-type-specific configuration that
  // must be done before and after the generic configuration.
  virtual bool PipeConfigPreamble(const display::DisplayTiming& mode, PipeId pipe_id,
                                  TranscoderId transcoder_id) = 0;
  virtual bool PipeConfigEpilogue(const display::DisplayTiming& mode, PipeId pipe_id,
                                  TranscoderId transcoder_id) = 0;

  fdf::MmioBuffer* mmio_space() const;

 private:
  bool CheckNeedsModeset(const display::DisplayTiming& mode);

  // Borrowed reference to Controller instance
  Controller* controller_;

  display::DisplayId id_;
  DdiId ddi_id_;

  Pipe* pipe_ = nullptr;

  std::optional<DdiReference> ddi_reference_;

  PowerWellRef ddi_power_;
  PowerWellRef ddi_io_power_;

  bool inited_ = false;
  display::DisplayTiming info_ = {};

  Type type_;

  zx_device_t* backlight_device_ = nullptr;
  display_ref_t* display_ref_ = nullptr;
};

}  // namespace i915

#endif  // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_DISPLAY_DEVICE_H_
