1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <assert.h> 8#include <ddk/protocol/display-controller.h> 9#include <ddk/protocol/intel-gpu-core.h> 10#include <hwreg/bitfields.h> 11#include <zircon/pixelformat.h> 12 13namespace registers { 14 15// Number of pipes that the hardware provides. 16static constexpr uint32_t kPipeCount = 3; 17 18enum Pipe { PIPE_A, PIPE_B, PIPE_C, PIPE_INVALID }; 19 20static const Pipe kPipes[kPipeCount] = { 21 PIPE_A, PIPE_B, PIPE_C, 22}; 23 24static constexpr uint32_t kImagePlaneCount = 3; 25static constexpr uint32_t kCursorPlane = 2; 26 27// PIPE_SRCSZ 28class PipeSourceSize : public hwreg::RegisterBase<PipeSourceSize, uint32_t> { 29public: 30 static constexpr uint32_t kBaseAddr = 0x6001c; 31 32 DEF_FIELD(28, 16, horizontal_source_size); 33 DEF_FIELD(11, 0, vertical_source_size); 34}; 35 36// PIPE_BOTTOM_COLOR 37class PipeBottomColor : public hwreg::RegisterBase<PipeBottomColor, uint32_t> { 38public: 39 static constexpr uint32_t kBaseAddr = 0x70034; 40 41 DEF_BIT(31, gamma_enable); 42 DEF_BIT(30, csc_enable); 43 DEF_FIELD(29, 20, r); 44 DEF_FIELD(19, 10, g); 45 DEF_FIELD(9, 0, b); 46}; 47 48 49// PLANE_SURF 50class PlaneSurface : public hwreg::RegisterBase<PlaneSurface, uint32_t> { 51public: 52 static constexpr uint32_t kBaseAddr = 0x7019c; 53 54 // This field omits the lower 12 bits of the address, so the address 55 // must be 4k-aligned. 56 static constexpr uint32_t kPageShift = 12; 57 DEF_FIELD(31, 12, surface_base_addr); 58 static constexpr uint32_t kRShiftCount = 12; 59 static constexpr uint32_t kLinearAlignment = 256 * 1024; 60 static constexpr uint32_t kXTilingAlignment = 256 * 1024; 61 static constexpr uint32_t kYTilingAlignment = 1024 * 1024; 62 63 DEF_BIT(3, ring_flip_source); 64}; 65 66// PLANE_SURFLIVE 67class PlaneSurfaceLive : public hwreg::RegisterBase<PlaneSurfaceLive, uint32_t> { 68public: 69 static constexpr uint32_t kBaseAddr = 0x701ac; 70 71 // This field omits the lower 12 bits of the address, so the address 72 // must be 4k-aligned. 73 static constexpr uint32_t kPageShift = 12; 74 DEF_FIELD(31, 12, surface_base_addr); 75}; 76 77// PLANE_STRIDE 78class PlaneSurfaceStride : public hwreg::RegisterBase<PlaneSurfaceStride, uint32_t> { 79public: 80 static constexpr uint32_t kBaseAddr = 0x70188; 81 82 DEF_FIELD(9, 0, stride); 83}; 84 85// PLANE_SIZE 86class PlaneSurfaceSize : public hwreg::RegisterBase<PlaneSurfaceSize, uint32_t> { 87public: 88 static constexpr uint32_t kBaseAddr = 0x70190; 89 90 DEF_FIELD(27, 16, height_minus_1); 91 DEF_FIELD(12, 0, width_minus_1); 92}; 93 94// PLANE_CTL 95class PlaneControl : public hwreg::RegisterBase<PlaneControl, uint32_t> { 96public: 97 static constexpr uint32_t kBaseAddr = 0x70180; 98 99 DEF_BIT(31, plane_enable); 100 DEF_BIT(30, pipe_gamma_enable); 101 DEF_BIT(29, remove_yuv_offset); 102 DEF_BIT(28, yuv_range_correction_disable); 103 104 DEF_FIELD(27, 24, source_pixel_format); 105 static constexpr uint32_t kFormatRgb8888 = 4; 106 107 DEF_BIT(23, pipe_csc_enable); 108 DEF_FIELD(22, 21, key_enable); 109 DEF_BIT(20, rgb_color_order); 110 DEF_BIT(19, plane_yuv_to_rgb_csc_dis); 111 DEF_BIT(18, plane_yuv_to_rgb_csc_format); 112 DEF_FIELD(17, 16, yuv_422_byte_order); 113 DEF_BIT(15, render_decompression); 114 DEF_BIT(14, trickle_feed_enable); 115 DEF_BIT(13, plane_gamma_disable); 116 117 DEF_FIELD(12, 10, tiled_surface); 118 static constexpr uint32_t kLinear = 0; 119 static constexpr uint32_t kTilingX = 1; 120 static constexpr uint32_t kTilingYLegacy = 4; 121 static constexpr uint32_t kTilingYF = 5; 122 123 DEF_BIT(9, async_address_update_enable); 124 DEF_FIELD(7, 6, stereo_surface_vblank_mask); 125 DEF_FIELD(5, 4, alpha_mode); 126 static constexpr uint32_t kAlphaDisable = 0; 127 static constexpr uint32_t kAlphaPreMultiply = 2; 128 static constexpr uint32_t kAlphaHwMultiply = 3; 129 130 131 DEF_BIT(3, allow_double_buffer_update_disable); 132 DEF_FIELD(1, 0, plane_rotation); 133 static constexpr uint32_t kIdentity = 0; 134 static constexpr uint32_t k90deg = 1; 135 static constexpr uint32_t k180deg = 2; 136 static constexpr uint32_t k270deg = 3; 137}; 138 139// PLANE_BUF_CFG 140class PlaneBufCfg : public hwreg::RegisterBase<PlaneBufCfg, uint32_t> { 141public: 142 static constexpr uint32_t kBaseAddr = 0x7017c; 143 static constexpr uint32_t kBufferCount = 892; 144 145 DEF_FIELD(25, 16, buffer_end); 146 DEF_FIELD(9, 0, buffer_start); 147}; 148 149// PLANE_WM 150class PlaneWm : public hwreg::RegisterBase<PlaneWm, uint32_t> { 151public: 152 static constexpr uint32_t kBaseAddr = 0x70140; 153 154 DEF_BIT(31, enable); 155 DEF_FIELD(18, 14, lines); 156 DEF_FIELD(9, 0, blocks); 157}; 158 159// PLANE_KEYMSK 160class PlaneKeyMask : public hwreg::RegisterBase<PlaneKeyMask, uint32_t> { 161public: 162 static constexpr uint32_t kBaseAddr = 0x70198; 163 164 DEF_BIT(31, plane_alpha_enable); 165}; 166 167// PLANE_KEYMAX 168class PlaneKeyMax : public hwreg::RegisterBase<PlaneKeyMax, uint32_t> { 169public: 170 static constexpr uint32_t kBaseAddr = 0x701a0; 171 172 DEF_FIELD(31, 24, plane_alpha_value); 173}; 174 175// PLANE_OFFSET 176class PlaneOffset : public hwreg::RegisterBase<PlaneOffset, uint32_t> { 177public: 178 static constexpr uint32_t kBaseAddr = 0x701a4; 179 180 DEF_FIELD(28, 16, start_y); 181 DEF_FIELD(12, 0, start_x); 182}; 183 184// PLANE_POS 185class PlanePosition : public hwreg::RegisterBase<PlanePosition, uint32_t> { 186public: 187 static constexpr uint32_t kBaseAddr = 0x7018c; 188 189 DEF_FIELD(28, 16, y_pos); 190 DEF_FIELD(12, 0, x_pos); 191}; 192 193// PS_CTRL 194class PipeScalerCtrl : public hwreg::RegisterBase<PipeScalerCtrl, uint32_t> { 195public: 196 static constexpr uint32_t kBaseAddr = 0x68180; 197 198 DEF_BIT(31, enable); 199 DEF_FIELD(29, 28, mode); 200 static constexpr uint32_t kDynamic = 0; 201 static constexpr uint32_t k7x5 = 1; 202 203 DEF_FIELD(27, 25, binding); 204 static constexpr uint32_t kPipeScaler = 0; 205 static constexpr uint32_t kPlane1 = 1; 206 static constexpr uint32_t kPlane2 = 2; 207 static constexpr uint32_t kPlane3 = 3; 208 209 DEF_FIELD(24, 23, filter_select); 210 static constexpr uint32_t kMedium = 0; 211 static constexpr uint32_t kEdgeEnhance = 2; 212 static constexpr uint32_t kBilienar = 3; 213 214 static constexpr uint32_t kMinSrcSizePx = 8; 215 static constexpr uint32_t kMaxSrcWidthPx = 4096; 216 static constexpr uint32_t kPipeABScalersAvailable = 2; 217 static constexpr uint32_t kPipeCScalersAvailable = 1; 218 static constexpr float k7x5MaxRatio = 2.99f; 219 static constexpr float kDynamicMaxRatio = 2.99f; 220 static constexpr float kDynamicMaxVerticalRatio2049 = 1.99f; 221}; 222 223// PS_WIN_POS 224class PipeScalerWinPosition : public hwreg::RegisterBase<PipeScalerWinPosition, uint32_t> { 225public: 226 static constexpr uint32_t kBaseAddr = 0x68170; 227 228 DEF_FIELD(28, 16, x_pos); 229 DEF_FIELD(11, 0, y_pos); 230}; 231 232// PS_WIN_SIZE 233class PipeScalerWinSize : public hwreg::RegisterBase<PipeScalerWinSize, uint32_t> { 234public: 235 static constexpr uint32_t kBaseAddr = 0x68174; 236 237 DEF_FIELD(28, 16, x_size); 238 DEF_FIELD(11, 0, y_size); 239}; 240 241// DE_PIPE_INTERRUPT 242class PipeDeInterrupt : public hwreg::RegisterBase<PipeDeInterrupt, uint32_t> { 243public: 244 DEF_BIT(1, vsync); 245}; 246 247// CUR_BASE 248class CursorBase : public hwreg::RegisterBase<CursorBase, uint32_t> { 249public: 250 static constexpr uint32_t kBaseAddr = 0x70084; 251 252 DEF_FIELD(31, 12, cursor_base); 253 // This field omits the lower 12 bits of the address, so the address 254 // must be 4k-aligned. 255 static constexpr uint32_t kPageShift = 12; 256}; 257 258// CUR_CTL 259class CursorCtrl : public hwreg::RegisterBase<CursorCtrl, uint32_t> { 260public: 261 static constexpr uint32_t kBaseAddr = 0x70080; 262 263 DEF_BIT(24, pipe_csc_enable); 264 DEF_FIELD(5, 0, mode_select); 265 static constexpr uint32_t kDisabled = 0; 266 static constexpr uint32_t kArgb128x128 = 34; 267 static constexpr uint32_t kArgb256x256 = 35; 268 static constexpr uint32_t kArgb64x64 = 39; 269}; 270 271// CUR_POS 272class CursorPos : public hwreg::RegisterBase<CursorPos, uint32_t> { 273public: 274 static constexpr uint32_t kBaseAddr = 0x70088; 275 276 DEF_BIT(31, y_sign); 277 DEF_FIELD(27, 16, y_pos); 278 DEF_BIT(15, x_sign); 279 DEF_FIELD(12, 0, x_pos); 280}; 281 282// CUR_SURFLIVE 283class CursorSurfaceLive : public hwreg::RegisterBase<CursorSurfaceLive, uint32_t> { 284public: 285 static constexpr uint32_t kBaseAddr = 0x700ac; 286 287 static constexpr uint32_t kPageShift = 12; 288 DEF_FIELD(31, 12, surface_base_addr); 289}; 290 291// CSC_COEFF 292class CscCoeff : public hwreg::RegisterBase<CscCoeff, uint32_t> { 293public: 294 static constexpr uint32_t kBaseAddr = 0x49010; 295 296 hwreg::BitfieldRef<uint32_t> coefficient(uint32_t i, uint32_t j) { 297 ZX_DEBUG_ASSERT(i < 3 && j < 3); 298 uint32_t bit = 16 - ((j % 2) * 16); 299 return hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), bit + 15, bit); 300 } 301}; 302 303class CscCoeffFormat : public hwreg::RegisterBase<CscCoeffFormat, uint16_t> { 304public: 305 DEF_BIT(15, sign); 306 DEF_FIELD(14, 12, exponent); 307 static constexpr uint16_t kExponent0125 = 3; 308 static constexpr uint16_t kExponent025 = 2; 309 static constexpr uint16_t kExponent05 = 1; 310 static constexpr uint16_t kExponent1 = 0; 311 static constexpr uint16_t kExponent2 = 7; 312 static constexpr uint16_t kExponent4 = 6; 313 DEF_FIELD(11, 3, mantissa); 314}; 315 316// CSC_MODE 317class CscMode : public hwreg::RegisterBase<CscMode, uint32_t> { 318public: 319 static constexpr uint32_t kBaseAddr = 0x49028; 320}; 321 322// CSC_POSTOFF / CSC_PREOFF 323class CscOffset : public hwreg::RegisterBase<CscOffset, uint32_t> { 324public: 325 static constexpr uint32_t kPostOffsetBaseAddr = 0x49040; 326 static constexpr uint32_t kPreOffsetBaseAddr = 0x49030; 327 328 DEF_BIT(12, sign); 329 DEF_FIELD(11, 0, magnitude); 330}; 331 332// An instance of PipeRegs represents the registers for a particular pipe. 333class PipeRegs { 334public: 335 static constexpr uint32_t kStatusReg = 0x44400; 336 static constexpr uint32_t kMaskReg = 0x44404; 337 static constexpr uint32_t kIdentityReg = 0x44408; 338 static constexpr uint32_t kEnableReg = 0x4440c; 339 340 PipeRegs(Pipe pipe) : pipe_(pipe) { } 341 342 hwreg::RegisterAddr<registers::PipeSourceSize> PipeSourceSize() { 343 return GetReg<registers::PipeSourceSize>(); 344 } 345 hwreg::RegisterAddr<registers::PipeBottomColor> PipeBottomColor() { 346 return GetReg<registers::PipeBottomColor>(); 347 } 348 349 hwreg::RegisterAddr<registers::PlaneSurface> PlaneSurface(int32_t plane_num) { 350 return GetPlaneReg<registers::PlaneSurface>(plane_num); 351 } 352 hwreg::RegisterAddr<registers::PlaneSurfaceLive> PlaneSurfaceLive(int32_t plane_num) { 353 return GetPlaneReg<registers::PlaneSurfaceLive>(plane_num); 354 } 355 hwreg::RegisterAddr<registers::PlaneSurfaceStride> PlaneSurfaceStride(int32_t plane_num) { 356 return GetPlaneReg<registers::PlaneSurfaceStride>(plane_num); 357 } 358 hwreg::RegisterAddr<registers::PlaneSurfaceSize> PlaneSurfaceSize(int32_t plane_num) { 359 return GetPlaneReg<registers::PlaneSurfaceSize>(plane_num); 360 } 361 hwreg::RegisterAddr<registers::PlaneControl> PlaneControl(int32_t plane_num) { 362 return GetPlaneReg<registers::PlaneControl>(plane_num); 363 } 364 hwreg::RegisterAddr<registers::PlaneOffset> PlaneOffset(int32_t plane_num) { 365 return GetPlaneReg<registers::PlaneOffset>(plane_num); 366 } 367 hwreg::RegisterAddr<registers::PlanePosition> PlanePosition(int32_t plane_num) { 368 return GetPlaneReg<registers::PlanePosition>(plane_num); 369 } 370 // 0 == cursor, 1-3 are regular planes 371 hwreg::RegisterAddr<registers::PlaneBufCfg> PlaneBufCfg(int plane) { 372 return hwreg::RegisterAddr<registers::PlaneBufCfg>( 373 PlaneBufCfg::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); 374 } 375 376 hwreg::RegisterAddr<registers::PlaneWm>PlaneWatermark(int plane, int wm_num) { 377 return hwreg::RegisterAddr<PlaneWm>( 378 PlaneWm::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane + 4 * wm_num); 379 } 380 381 hwreg::RegisterAddr<registers::PlaneKeyMask> PlaneKeyMask(int32_t plane_num) { 382 return GetPlaneReg<registers::PlaneKeyMask>(plane_num); 383 } 384 hwreg::RegisterAddr<registers::PlaneKeyMax> PlaneKeyMax(int32_t plane_num) { 385 return GetPlaneReg<registers::PlaneKeyMax>(plane_num); 386 } 387 388 hwreg::RegisterAddr<registers::PipeScalerCtrl> PipeScalerCtrl(int num) { 389 return hwreg::RegisterAddr<registers::PipeScalerCtrl>( 390 PipeScalerCtrl::kBaseAddr + 0x800 * pipe_ + num * 0x100); 391 } 392 393 hwreg::RegisterAddr<registers::PipeScalerWinPosition> PipeScalerWinPosition(int num) { 394 return hwreg::RegisterAddr<registers::PipeScalerWinPosition>( 395 PipeScalerWinPosition::kBaseAddr + 0x800 * pipe_ + num * 0x100); 396 } 397 398 hwreg::RegisterAddr<registers::PipeScalerWinSize> PipeScalerWinSize(int num) { 399 return hwreg::RegisterAddr<registers::PipeScalerWinSize>( 400 PipeScalerWinSize::kBaseAddr + 0x800 * pipe_ + num * 0x100); 401 } 402 403 hwreg::RegisterAddr<registers::PipeDeInterrupt> PipeDeInterrupt(uint32_t type) { 404 return hwreg::RegisterAddr<registers::PipeDeInterrupt>(type + 0x10 * pipe_); 405 } 406 407 hwreg::RegisterAddr<registers::CursorBase> CursorBase() { 408 return GetReg<registers::CursorBase>(); 409 } 410 411 hwreg::RegisterAddr<registers::CursorCtrl> CursorCtrl() { 412 return GetReg<registers::CursorCtrl>(); 413 } 414 415 hwreg::RegisterAddr<registers::CursorPos> CursorPos() { 416 return GetReg<registers::CursorPos>(); 417 } 418 419 hwreg::RegisterAddr<registers::CursorSurfaceLive> CursorSurfaceLive() { 420 return GetReg<registers::CursorSurfaceLive>(); 421 } 422 423 hwreg::RegisterAddr<registers::CscCoeff> CscCoeff(uint32_t i, uint32_t j) { 424 ZX_DEBUG_ASSERT(i < 3 && j < 3); 425 uint32_t base = registers::CscCoeff::kBaseAddr + 4 * ((i * 2) + (j == 2 ? 1 : 0)); 426 return GetCscReg<registers::CscCoeff>(base); 427 } 428 429 hwreg::RegisterAddr<registers::CscMode> CscMode() { 430 return GetCscReg<registers::CscMode>(registers::CscMode::kBaseAddr); 431 } 432 433 hwreg::RegisterAddr<registers::CscOffset> CscOffset(bool preoffset, uint32_t component_idx) { 434 uint32_t base = (4 * component_idx) + (preoffset ? 435 registers::CscOffset::kPreOffsetBaseAddr : registers::CscOffset::kPostOffsetBaseAddr); 436 return GetCscReg<registers::CscOffset>(base); 437 } 438 439private: 440 template <class RegType> hwreg::RegisterAddr<RegType> GetReg() { 441 return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_); 442 } 443 444 template <class RegType> hwreg::RegisterAddr<RegType> GetPlaneReg(int32_t plane) { 445 return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); 446 } 447 448 template <class RegType> hwreg::RegisterAddr<RegType> GetCscReg(uint32_t base) { 449 return hwreg::RegisterAddr<RegType>(base + 0x100 * pipe_); 450 } 451 452 Pipe pipe_; 453}; 454 455// Struct of registers which arm double buffered registers 456typedef struct pipe_arming_regs { 457 uint32_t csc_mode; 458 uint32_t pipe_bottom_color; 459 uint32_t cur_base; 460 uint32_t cur_pos; 461 uint32_t plane_surf[kImagePlaneCount]; 462 uint32_t ps_win_sz[2]; 463} pipe_arming_regs_t; 464 465} // namespace registers 466