blob: 044f04c8bbb6ffb253bcafc48059459be762aba6 [file] [log] [blame]
// Copyright 2018 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 <fuchsia/hardware/display/controller/c/banjo.h>
#include <lib/edid/edid.h>
#include <lib/fit/function.h>
#include <lib/mmio/mmio.h>
#include <lib/zx/vmo.h>
#include <cstdint>
#include <list>
#include <unordered_map>
#include <ddktl/device.h>
#include <region-alloc/region-alloc.h>
#include "gtt.h"
#include "power.h"
#include "registers-ddi.h"
#include "registers-pipe.h"
#include "registers-transcoder.h"
namespace i915 {
class Controller;
class DisplayDevice;
class Pipe {
Pipe(i915::Pipe&& other) : Pipe(other.mmio_space_, other.pipe_, std::move(other.pipe_power_)) {}
Pipe(fdf::MmioBuffer* mmio_space, registers::Pipe pipe, PowerWellRef pipe_power);
void AttachToDisplay(uint64_t display_id, bool is_edp);
void Detach();
void ApplyModeConfig(const display_mode_t& mode);
using SetupGttImageFunc = fit::function<uint64_t(const image_t* image, uint32_t rotation)>;
void ApplyConfiguration(const display_config_t* config, const config_stamp_t* config_stamp,
const SetupGttImageFunc& setup_gtt_image);
// The controller will reset pipe registers and pipe transcoder registers.
// TODO( Remove the circular dependency between Controller
// and Pipe.
void Reset(Controller* controller);
void LoadActiveMode(display_mode_t* mode);
registers::Pipe pipe() const { return pipe_; }
registers::Trans transcoder() const {
return attached_edp_ ? registers::TRANS_EDP : static_cast<registers::Trans>(pipe_);
uint64_t attached_display_id() const { return attached_display_; }
bool in_use() const { return attached_display_ != INVALID_DISPLAY_ID; }
// Display device registers only store image handles / addresses. We should
// convert the handles to corresponding config stamps using the existing
// mapping updated in |ApplyConfig()|.
std::optional<config_stamp_t> GetVsyncConfigStamp(const std::vector<uint64_t>& image_handles);
// Borrowed reference to Controller instance
fdf::MmioBuffer* mmio_space_ = nullptr;
void ConfigurePrimaryPlane(uint32_t plane_num, const primary_layer_t* primary, bool enable_csc,
bool* scaler_1_claimed, registers::pipe_arming_regs* regs,
uint64_t config_stamp_seqno, const SetupGttImageFunc& setup_gtt_image);
void ConfigureCursorPlane(const cursor_layer_t* cursor, bool enable_csc,
registers::pipe_arming_regs* regs, uint64_t config_stamp_seqno);
void SetColorConversionOffsets(bool preoffsets, const float vals[3]);
uint64_t attached_display_ = INVALID_DISPLAY_ID;
bool attached_edp_ = false;
registers::Pipe pipe_;
PowerWellRef pipe_power_;
// For any scaled planes, this contains the (1-based) index of the active scaler
uint32_t scaled_planes_[registers::kPipeCount][registers::kImagePlaneCount] = {};
// On each Vsync, the driver should return the stamp of the *oldest*
// configuration that has been fully applied to the device. We use the
// following way to keep track of images and config stamps:
// Config stamps can be of random values (per definition in display Controller
// banjo protocol), so while we keep all the stamps in a linked list sorted
// chronologically, we also keep a sequence number of the first config stamp
// in the list.
// Every time a config is applied, a new stamp will be added to the list. An
// config stamp is removed from the list when it is older than all the current
// config stamps used in the display layers. In this case, the front old
// stamps will be removed and |config_stamps_front_seqno_| will be updated
// accordingly.
// A linked list of configuration stamps in chronological order.
// Unused configuration stamps will be evicted from the list.
std::list<config_stamp_t> config_stamps_;
// Consecutive sequence numbers are assigned to each configuration applied to
// the device; this keeps track the seqno of the front (oldest configuration)
// that is still in the linked list |config_stamps_|.
// If no configuration has been applied to the device, it stores
// |std::nullopt|.
std::optional<uint64_t> config_stamps_front_seqno_;
// The pipe registers only store the handle (address) of the images that are
// being displayed. In order to get the config stamp for each layer and for
// each configuration, we need to keep a mapping from *image handle* to the
// *seqno of the configuration* so that we can know which layer has the oldest
// configuration.
std::unordered_map<uintptr_t, uint64_t> latest_config_seqno_of_image_;
} // namespace i915