blob: b59d8fc7efca28dd221f7e163db0bbb7e1bac438 [file] [log] [blame]
// Copyright 2017 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.
#pragma once
#include <assert.h>
#include <ddk/protocol/display/controller.h>
#include <ddk/protocol/intelgpucore.h>
#include <hwreg/bitfields.h>
#include <zircon/pixelformat.h>
namespace registers {
// Number of pipes that the hardware provides.
static constexpr uint32_t kPipeCount = 3;
enum Pipe { PIPE_A, PIPE_B, PIPE_C, PIPE_INVALID };
static const Pipe kPipes[kPipeCount] = {
PIPE_A, PIPE_B, PIPE_C,
};
static constexpr uint32_t kImagePlaneCount = 3;
static constexpr uint32_t kCursorPlane = 2;
// PIPE_SRCSZ
class PipeSourceSize : public hwreg::RegisterBase<PipeSourceSize, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x6001c;
DEF_FIELD(28, 16, horizontal_source_size);
DEF_FIELD(11, 0, vertical_source_size);
};
// PIPE_BOTTOM_COLOR
class PipeBottomColor : public hwreg::RegisterBase<PipeBottomColor, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70034;
DEF_BIT(31, gamma_enable);
DEF_BIT(30, csc_enable);
DEF_FIELD(29, 20, r);
DEF_FIELD(19, 10, g);
DEF_FIELD(9, 0, b);
};
// PLANE_SURF
class PlaneSurface : public hwreg::RegisterBase<PlaneSurface, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x7019c;
// This field omits the lower 12 bits of the address, so the address
// must be 4k-aligned.
static constexpr uint32_t kPageShift = 12;
DEF_FIELD(31, 12, surface_base_addr);
static constexpr uint32_t kRShiftCount = 12;
static constexpr uint32_t kLinearAlignment = 256 * 1024;
static constexpr uint32_t kXTilingAlignment = 256 * 1024;
static constexpr uint32_t kYTilingAlignment = 1024 * 1024;
DEF_BIT(3, ring_flip_source);
};
// PLANE_SURFLIVE
class PlaneSurfaceLive : public hwreg::RegisterBase<PlaneSurfaceLive, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x701ac;
// This field omits the lower 12 bits of the address, so the address
// must be 4k-aligned.
static constexpr uint32_t kPageShift = 12;
DEF_FIELD(31, 12, surface_base_addr);
};
// PLANE_STRIDE
class PlaneSurfaceStride : public hwreg::RegisterBase<PlaneSurfaceStride, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70188;
DEF_FIELD(9, 0, stride);
};
// PLANE_SIZE
class PlaneSurfaceSize : public hwreg::RegisterBase<PlaneSurfaceSize, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70190;
DEF_FIELD(27, 16, height_minus_1);
DEF_FIELD(12, 0, width_minus_1);
};
// PLANE_CTL
class PlaneControl : public hwreg::RegisterBase<PlaneControl, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70180;
DEF_BIT(31, plane_enable);
DEF_BIT(30, pipe_gamma_enable);
DEF_BIT(29, remove_yuv_offset);
DEF_BIT(28, yuv_range_correction_disable);
DEF_FIELD(27, 24, source_pixel_format);
static constexpr uint32_t kFormatRgb8888 = 4;
DEF_BIT(23, pipe_csc_enable);
DEF_FIELD(22, 21, key_enable);
DEF_BIT(20, rgb_color_order);
DEF_BIT(19, plane_yuv_to_rgb_csc_dis);
DEF_BIT(18, plane_yuv_to_rgb_csc_format);
DEF_FIELD(17, 16, yuv_422_byte_order);
DEF_BIT(15, render_decompression);
DEF_BIT(14, trickle_feed_enable);
DEF_BIT(13, plane_gamma_disable);
DEF_FIELD(12, 10, tiled_surface);
static constexpr uint32_t kLinear = 0;
static constexpr uint32_t kTilingX = 1;
static constexpr uint32_t kTilingYLegacy = 4;
static constexpr uint32_t kTilingYF = 5;
DEF_BIT(9, async_address_update_enable);
DEF_FIELD(7, 6, stereo_surface_vblank_mask);
DEF_FIELD(5, 4, alpha_mode);
static constexpr uint32_t kAlphaDisable = 0;
static constexpr uint32_t kAlphaPreMultiply = 2;
static constexpr uint32_t kAlphaHwMultiply = 3;
DEF_BIT(3, allow_double_buffer_update_disable);
DEF_FIELD(1, 0, plane_rotation);
static constexpr uint32_t kIdentity = 0;
static constexpr uint32_t k90deg = 1;
static constexpr uint32_t k180deg = 2;
static constexpr uint32_t k270deg = 3;
};
// PLANE_BUF_CFG
class PlaneBufCfg : public hwreg::RegisterBase<PlaneBufCfg, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x7017c;
static constexpr uint32_t kBufferCount = 892;
DEF_FIELD(25, 16, buffer_end);
DEF_FIELD(9, 0, buffer_start);
};
// PLANE_WM
class PlaneWm : public hwreg::RegisterBase<PlaneWm, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70140;
DEF_BIT(31, enable);
DEF_FIELD(18, 14, lines);
DEF_FIELD(9, 0, blocks);
};
// PLANE_KEYMSK
class PlaneKeyMask : public hwreg::RegisterBase<PlaneKeyMask, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70198;
DEF_BIT(31, plane_alpha_enable);
};
// PLANE_KEYMAX
class PlaneKeyMax : public hwreg::RegisterBase<PlaneKeyMax, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x701a0;
DEF_FIELD(31, 24, plane_alpha_value);
};
// PLANE_OFFSET
class PlaneOffset : public hwreg::RegisterBase<PlaneOffset, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x701a4;
DEF_FIELD(28, 16, start_y);
DEF_FIELD(12, 0, start_x);
};
// PLANE_POS
class PlanePosition : public hwreg::RegisterBase<PlanePosition, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x7018c;
DEF_FIELD(28, 16, y_pos);
DEF_FIELD(12, 0, x_pos);
};
// PS_CTRL
class PipeScalerCtrl : public hwreg::RegisterBase<PipeScalerCtrl, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x68180;
DEF_BIT(31, enable);
DEF_FIELD(29, 28, mode);
static constexpr uint32_t kDynamic = 0;
static constexpr uint32_t k7x5 = 1;
DEF_FIELD(27, 25, binding);
static constexpr uint32_t kPipeScaler = 0;
static constexpr uint32_t kPlane1 = 1;
static constexpr uint32_t kPlane2 = 2;
static constexpr uint32_t kPlane3 = 3;
DEF_FIELD(24, 23, filter_select);
static constexpr uint32_t kMedium = 0;
static constexpr uint32_t kEdgeEnhance = 2;
static constexpr uint32_t kBilienar = 3;
static constexpr uint32_t kMinSrcSizePx = 8;
static constexpr uint32_t kMaxSrcWidthPx = 4096;
static constexpr uint32_t kPipeABScalersAvailable = 2;
static constexpr uint32_t kPipeCScalersAvailable = 1;
static constexpr float k7x5MaxRatio = 2.99f;
static constexpr float kDynamicMaxRatio = 2.99f;
static constexpr float kDynamicMaxVerticalRatio2049 = 1.99f;
};
// PS_WIN_POS
class PipeScalerWinPosition : public hwreg::RegisterBase<PipeScalerWinPosition, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x68170;
DEF_FIELD(28, 16, x_pos);
DEF_FIELD(11, 0, y_pos);
};
// PS_WIN_SIZE
class PipeScalerWinSize : public hwreg::RegisterBase<PipeScalerWinSize, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x68174;
DEF_FIELD(28, 16, x_size);
DEF_FIELD(11, 0, y_size);
};
// DE_PIPE_INTERRUPT
class PipeDeInterrupt : public hwreg::RegisterBase<PipeDeInterrupt, uint32_t> {
public:
DEF_BIT(1, vsync);
};
// CUR_BASE
class CursorBase : public hwreg::RegisterBase<CursorBase, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70084;
DEF_FIELD(31, 12, cursor_base);
// This field omits the lower 12 bits of the address, so the address
// must be 4k-aligned.
static constexpr uint32_t kPageShift = 12;
};
// CUR_CTL
class CursorCtrl : public hwreg::RegisterBase<CursorCtrl, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70080;
DEF_BIT(24, pipe_csc_enable);
DEF_FIELD(5, 0, mode_select);
static constexpr uint32_t kDisabled = 0;
static constexpr uint32_t kArgb128x128 = 34;
static constexpr uint32_t kArgb256x256 = 35;
static constexpr uint32_t kArgb64x64 = 39;
};
// CUR_POS
class CursorPos : public hwreg::RegisterBase<CursorPos, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70088;
DEF_BIT(31, y_sign);
DEF_FIELD(27, 16, y_pos);
DEF_BIT(15, x_sign);
DEF_FIELD(12, 0, x_pos);
};
// CUR_SURFLIVE
class CursorSurfaceLive : public hwreg::RegisterBase<CursorSurfaceLive, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x700ac;
static constexpr uint32_t kPageShift = 12;
DEF_FIELD(31, 12, surface_base_addr);
};
// CSC_COEFF
class CscCoeff : public hwreg::RegisterBase<CscCoeff, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x49010;
hwreg::BitfieldRef<uint32_t> coefficient(uint32_t i, uint32_t j) {
ZX_DEBUG_ASSERT(i < 3 && j < 3);
uint32_t bit = 16 - ((j % 2) * 16);
return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 15, bit);
}
};
class CscCoeffFormat : public hwreg::RegisterBase<CscCoeffFormat, uint16_t> {
public:
DEF_BIT(15, sign);
DEF_FIELD(14, 12, exponent);
static constexpr uint16_t kExponent0125 = 3;
static constexpr uint16_t kExponent025 = 2;
static constexpr uint16_t kExponent05 = 1;
static constexpr uint16_t kExponent1 = 0;
static constexpr uint16_t kExponent2 = 7;
static constexpr uint16_t kExponent4 = 6;
DEF_FIELD(11, 3, mantissa);
};
// CSC_MODE
class CscMode : public hwreg::RegisterBase<CscMode, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x49028;
};
// CSC_POSTOFF / CSC_PREOFF
class CscOffset : public hwreg::RegisterBase<CscOffset, uint32_t> {
public:
static constexpr uint32_t kPostOffsetBaseAddr = 0x49040;
static constexpr uint32_t kPreOffsetBaseAddr = 0x49030;
DEF_BIT(12, sign);
DEF_FIELD(11, 0, magnitude);
};
// An instance of PipeRegs represents the registers for a particular pipe.
class PipeRegs {
public:
static constexpr uint32_t kStatusReg = 0x44400;
static constexpr uint32_t kMaskReg = 0x44404;
static constexpr uint32_t kIdentityReg = 0x44408;
static constexpr uint32_t kEnableReg = 0x4440c;
PipeRegs(Pipe pipe) : pipe_(pipe) { }
hwreg::RegisterAddr<registers::PipeSourceSize> PipeSourceSize() {
return GetReg<registers::PipeSourceSize>();
}
hwreg::RegisterAddr<registers::PipeBottomColor> PipeBottomColor() {
return GetReg<registers::PipeBottomColor>();
}
hwreg::RegisterAddr<registers::PlaneSurface> PlaneSurface(int32_t plane_num) {
return GetPlaneReg<registers::PlaneSurface>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneSurfaceLive> PlaneSurfaceLive(int32_t plane_num) {
return GetPlaneReg<registers::PlaneSurfaceLive>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneSurfaceStride> PlaneSurfaceStride(int32_t plane_num) {
return GetPlaneReg<registers::PlaneSurfaceStride>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneSurfaceSize> PlaneSurfaceSize(int32_t plane_num) {
return GetPlaneReg<registers::PlaneSurfaceSize>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneControl> PlaneControl(int32_t plane_num) {
return GetPlaneReg<registers::PlaneControl>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneOffset> PlaneOffset(int32_t plane_num) {
return GetPlaneReg<registers::PlaneOffset>(plane_num);
}
hwreg::RegisterAddr<registers::PlanePosition> PlanePosition(int32_t plane_num) {
return GetPlaneReg<registers::PlanePosition>(plane_num);
}
// 0 == cursor, 1-3 are regular planes
hwreg::RegisterAddr<registers::PlaneBufCfg> PlaneBufCfg(int plane) {
return hwreg::RegisterAddr<registers::PlaneBufCfg>(
PlaneBufCfg::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane);
}
hwreg::RegisterAddr<registers::PlaneWm>PlaneWatermark(int plane, int wm_num) {
return hwreg::RegisterAddr<PlaneWm>(
PlaneWm::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane + 4 * wm_num);
}
hwreg::RegisterAddr<registers::PlaneKeyMask> PlaneKeyMask(int32_t plane_num) {
return GetPlaneReg<registers::PlaneKeyMask>(plane_num);
}
hwreg::RegisterAddr<registers::PlaneKeyMax> PlaneKeyMax(int32_t plane_num) {
return GetPlaneReg<registers::PlaneKeyMax>(plane_num);
}
hwreg::RegisterAddr<registers::PipeScalerCtrl> PipeScalerCtrl(int num) {
return hwreg::RegisterAddr<registers::PipeScalerCtrl>(
PipeScalerCtrl::kBaseAddr + 0x800 * pipe_ + num * 0x100);
}
hwreg::RegisterAddr<registers::PipeScalerWinPosition> PipeScalerWinPosition(int num) {
return hwreg::RegisterAddr<registers::PipeScalerWinPosition>(
PipeScalerWinPosition::kBaseAddr + 0x800 * pipe_ + num * 0x100);
}
hwreg::RegisterAddr<registers::PipeScalerWinSize> PipeScalerWinSize(int num) {
return hwreg::RegisterAddr<registers::PipeScalerWinSize>(
PipeScalerWinSize::kBaseAddr + 0x800 * pipe_ + num * 0x100);
}
hwreg::RegisterAddr<registers::PipeDeInterrupt> PipeDeInterrupt(uint32_t type) {
return hwreg::RegisterAddr<registers::PipeDeInterrupt>(type + 0x10 * pipe_);
}
hwreg::RegisterAddr<registers::CursorBase> CursorBase() {
return GetReg<registers::CursorBase>();
}
hwreg::RegisterAddr<registers::CursorCtrl> CursorCtrl() {
return GetReg<registers::CursorCtrl>();
}
hwreg::RegisterAddr<registers::CursorPos> CursorPos() {
return GetReg<registers::CursorPos>();
}
hwreg::RegisterAddr<registers::CursorSurfaceLive> CursorSurfaceLive() {
return GetReg<registers::CursorSurfaceLive>();
}
hwreg::RegisterAddr<registers::CscCoeff> CscCoeff(uint32_t i, uint32_t j) {
ZX_DEBUG_ASSERT(i < 3 && j < 3);
uint32_t base = registers::CscCoeff::kBaseAddr + 4 * ((i * 2) + (j == 2 ? 1 : 0));
return GetCscReg<registers::CscCoeff>(base);
}
hwreg::RegisterAddr<registers::CscMode> CscMode() {
return GetCscReg<registers::CscMode>(registers::CscMode::kBaseAddr);
}
hwreg::RegisterAddr<registers::CscOffset> CscOffset(bool preoffset, uint32_t component_idx) {
uint32_t base = (4 * component_idx) + (preoffset ?
registers::CscOffset::kPreOffsetBaseAddr : registers::CscOffset::kPostOffsetBaseAddr);
return GetCscReg<registers::CscOffset>(base);
}
private:
template <class RegType> hwreg::RegisterAddr<RegType> GetReg() {
return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_);
}
template <class RegType> hwreg::RegisterAddr<RegType> GetPlaneReg(int32_t plane) {
return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane);
}
template <class RegType> hwreg::RegisterAddr<RegType> GetCscReg(uint32_t base) {
return hwreg::RegisterAddr<RegType>(base + 0x100 * pipe_);
}
Pipe pipe_;
};
// Struct of registers which arm double buffered registers
typedef struct pipe_arming_regs {
uint32_t csc_mode;
uint32_t pipe_bottom_color;
uint32_t cur_base;
uint32_t cur_pos;
uint32_t plane_surf[kImagePlaneCount];
uint32_t ps_win_sz[2];
} pipe_arming_regs_t;
} // namespace registers