// 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 #include #include #include #include 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 { 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 { 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 { 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 { 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 { public: static constexpr uint32_t kBaseAddr = 0x70188; DEF_FIELD(9, 0, stride); }; // PLANE_SIZE class PlaneSurfaceSize : public hwreg::RegisterBase { 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 { 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 { 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 { 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 { public: static constexpr uint32_t kBaseAddr = 0x70198; DEF_BIT(31, plane_alpha_enable); }; // PLANE_KEYMAX class PlaneKeyMax : public hwreg::RegisterBase { public: static constexpr uint32_t kBaseAddr = 0x701a0; DEF_FIELD(31, 24, plane_alpha_value); }; // PLANE_OFFSET class PlaneOffset : public hwreg::RegisterBase { 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 { 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 { 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 { 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 { 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 { public: DEF_BIT(1, vsync); }; // CUR_BASE class CursorBase : public hwreg::RegisterBase { 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 { 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 { 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 { 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 { public: static constexpr uint32_t kBaseAddr = 0x49010; hwreg::BitfieldRef coefficient(uint32_t i, uint32_t j) { ZX_DEBUG_ASSERT(i < 3 && j < 3); uint32_t bit = 16 - ((j % 2) * 16); return hwreg::BitfieldRef(reg_value_ptr(), bit + 15, bit); } }; class CscCoeffFormat : public hwreg::RegisterBase { 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 { public: static constexpr uint32_t kBaseAddr = 0x49028; }; // CSC_POSTOFF / CSC_PREOFF class CscOffset : public hwreg::RegisterBase { 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 PipeSourceSize() { return GetReg(); } hwreg::RegisterAddr PipeBottomColor() { return GetReg(); } hwreg::RegisterAddr PlaneSurface(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneSurfaceLive(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneSurfaceStride(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneSurfaceSize(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneControl(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneOffset(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlanePosition(int32_t plane_num) { return GetPlaneReg(plane_num); } // 0 == cursor, 1-3 are regular planes hwreg::RegisterAddr PlaneBufCfg(int plane) { return hwreg::RegisterAddr( PlaneBufCfg::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); } hwreg::RegisterAddrPlaneWatermark(int plane, int wm_num) { return hwreg::RegisterAddr( PlaneWm::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane + 4 * wm_num); } hwreg::RegisterAddr PlaneKeyMask(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PlaneKeyMax(int32_t plane_num) { return GetPlaneReg(plane_num); } hwreg::RegisterAddr PipeScalerCtrl(int num) { return hwreg::RegisterAddr( PipeScalerCtrl::kBaseAddr + 0x800 * pipe_ + num * 0x100); } hwreg::RegisterAddr PipeScalerWinPosition(int num) { return hwreg::RegisterAddr( PipeScalerWinPosition::kBaseAddr + 0x800 * pipe_ + num * 0x100); } hwreg::RegisterAddr PipeScalerWinSize(int num) { return hwreg::RegisterAddr( PipeScalerWinSize::kBaseAddr + 0x800 * pipe_ + num * 0x100); } hwreg::RegisterAddr PipeDeInterrupt(uint32_t type) { return hwreg::RegisterAddr(type + 0x10 * pipe_); } hwreg::RegisterAddr CursorBase() { return GetReg(); } hwreg::RegisterAddr CursorCtrl() { return GetReg(); } hwreg::RegisterAddr CursorPos() { return GetReg(); } hwreg::RegisterAddr CursorSurfaceLive() { return GetReg(); } hwreg::RegisterAddr 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(base); } hwreg::RegisterAddr CscMode() { return GetCscReg(registers::CscMode::kBaseAddr); } hwreg::RegisterAddr CscOffset(bool preoffset, uint32_t component_idx) { uint32_t base = (4 * component_idx) + (preoffset ? registers::CscOffset::kPreOffsetBaseAddr : registers::CscOffset::kPostOffsetBaseAddr); return GetCscReg(base); } private: template hwreg::RegisterAddr GetReg() { return hwreg::RegisterAddr(RegType::kBaseAddr + 0x1000 * pipe_); } template hwreg::RegisterAddr GetPlaneReg(int32_t plane) { return hwreg::RegisterAddr(RegType::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); } template hwreg::RegisterAddr GetCscReg(uint32_t base) { return hwreg::RegisterAddr(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