// 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_PIPE_MANAGER_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_PIPE_MANAGER_H_

#include <lib/mmio/mmio-buffer.h>

#include <iterator>
#include <list>
#include <type_traits>
#include <unordered_map>

#include "src/graphics/display/drivers/intel-i915/pipe.h"
#include "src/graphics/display/drivers/intel-i915/registers-pipe.h"
#include "src/graphics/display/drivers/intel-i915/registers-transcoder.h"

namespace i915 {

class Controller;

template <bool IsConst, template <class, class...> class Container = std::vector>
class PipeIteratorBase {
 public:
  // Implement `std::iterator_traits`.
  using difference_type = int64_t;
  using value_type = std::conditional_t<IsConst, const Pipe*, Pipe*>;
  using pointer = void;
  using reference = std::add_lvalue_reference_t<value_type>;
  using iterator_category = std::forward_iterator_tag;

  using container_t = Container<std::unique_ptr<Pipe>>;
  using container_iterator_t = std::conditional_t<IsConst, typename container_t::const_iterator,
                                                  typename container_t::iterator>;

  explicit PipeIteratorBase(container_iterator_t it) : it_(it) {}

  explicit operator value_type() { return it_->get(); }
  value_type operator*() { return it_->get(); }

  bool operator!=(const PipeIteratorBase<IsConst>& other) const { return it_ != other.it_; }
  bool operator==(const PipeIteratorBase<IsConst>& other) const { return it_ == other.it_; }
  PipeIteratorBase<IsConst>& operator++() {
    ++it_;
    return *this;
  }
  PipeIteratorBase<IsConst> operator++(int) { return PipeIteratorBase<IsConst>(it_++); }

 private:
  container_iterator_t it_;
};

// `PipeManager` manages state of all `Pipe`s on the display engine.
//
// The set of `Pipe`s is defined at creation and is fixed and static over the
// lifetime of `PipeManager`. Callers can borrow a Pipe instance when they need
// it for display devices, and must return it before `PipeManager` is destroyed.
class PipeManager {
 public:
  virtual ~PipeManager() = default;

  PipeManager(PipeManager&&) = delete;
  PipeManager(const PipeManager&) = delete;

  // Request an unused Pipe for a new display, and attach the Pipe to |display|.
  //
  // Returned Pipes are guaranteed to outlive the display; On display removal,
  // The Pipe must be recycled by calling |ReturnPipe()|.
  //
  // Returns |nullptr| if there is no Pipe available.
  //
  // TODO(https://fxbug.dev/42056163): This is error-prone because the caller has to call
  // `ReturnPipe()` to recycle used pipe manually. Instead we should add a
  // wrapper class (like `BorrowedPipeRef`) which could automatically return the
  // Pipe after use.
  Pipe* RequestPipe(DisplayDevice& display);

  // Request the Pipe that have been attached to |display| by other drivers
  // (i.e. BIOS / bootloader) by reading the pipe's hardware register state, and
  // then update the Pipe's state to note that it's attached to |display|.
  //
  // Returned Pipes are guaranteed to outlive the display; On display removal,
  // The Pipe must be recycled by calling |ReturnPipe()|.
  //
  // Returns |nullptr| if
  // - No Pipe has been ever attached to this |display|, or
  // - Error occurs when reading the hardware state.
  Pipe* RequestPipeFromHardwareState(DisplayDevice& display, fdf::MmioBuffer* mmio_space);

  // Reset pipe transcoders that are not actively in use, e.g. due to pipe being
  // inactive, or its corresponding pipe currently connects to another
  // transcoder.
  virtual void ResetInactiveTranscoders() = 0;

  // Return unused Pipe back to |PipeManager| when the display device is
  // removed; |pipe| must be a return value of previous |RequestPipe| or
  // |RequestPipeFromHardwareState| calls.
  void ReturnPipe(Pipe* pipe);

  // Returns whether there is any new Pipe allocated to displays, or unused
  // Pipe gets reset since last |PipeReallocated()| call.
  bool PipeReallocated();

  // Random accessor and forward iterator so that we can access the pipes
  // using <algorithms> methods and range-based for loop.
  //
  // TODO(https://fxbug.dev/42056164): This (and the pipe iterator class) adds some
  // unnecessary complexity to the PipeManager; we can just replace it with a
  // method which returns `std::span<Pipe*>` instead.
  Pipe* operator[](PipeId idx) const;
  Pipe* At(PipeId idx) const;

  using PipeIterator = PipeIteratorBase<false>;
  using PipeConstIterator = PipeIteratorBase<true>;
  PipeIterator begin();
  PipeIterator end();
  PipeConstIterator begin() const;
  PipeConstIterator end() const;

 protected:
  explicit PipeManager(std::vector<std::unique_ptr<Pipe>> pipes);

  // Platform specific functions to get a new available pipe for an arbitrary
  // display device. Return |nullptr| if such a pipe is not available.
  virtual Pipe* GetAvailablePipe() = 0;

  // Platform specific functions to get a pipe that has been bound to this
  // DDI (usually by bootloader) for a display device.
  // Return |nullptr| if there is no such a pipe or if there is any other
  // internal error when loading the hardware state.
  virtual Pipe* GetPipeFromHwState(DdiId ddi_id, fdf::MmioBuffer* mmio_space) = 0;

 private:
  bool pipes_reallocated_ = false;
  std::vector<std::unique_ptr<Pipe>> pipes_;
};

// Instantiation of PipeManager for gen9 devices (Skylake, Kaby Lake, etc.)
class PipeManagerSkylake : public PipeManager {
 public:
  explicit PipeManagerSkylake(Controller* controller);
  ~PipeManagerSkylake() override = default;

  void ResetInactiveTranscoders() override;

 private:
  static constexpr PipeId kPipeEnums[] = {PipeId::PIPE_A, PipeId::PIPE_B, PipeId::PIPE_C};

  Pipe* GetAvailablePipe() override;
  Pipe* GetPipeFromHwState(DdiId ddi_id, fdf::MmioBuffer* mmio_space) override;

  static std::vector<std::unique_ptr<Pipe>> GetPipes(fdf::MmioBuffer* mmio_space, Power* power);

  fdf::MmioBuffer* mmio_space_;
};

// Instantiation of PipeManager for Tiger Lake
class PipeManagerTigerLake : public PipeManager {
 public:
  explicit PipeManagerTigerLake(Controller* controller);
  ~PipeManagerTigerLake() override = default;

  void ResetInactiveTranscoders() override;

 private:
  Pipe* GetAvailablePipe() override;
  Pipe* GetPipeFromHwState(DdiId ddi_id, fdf::MmioBuffer* mmio_space) override;

  static std::vector<std::unique_ptr<Pipe>> GetPipes(fdf::MmioBuffer* mmio_space, Power* power);

  fdf::MmioBuffer* mmio_space_;
};

}  // namespace i915

#endif  // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_PIPE_MANAGER_H_
