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/intelgpucore.h> 10 #include <hwreg/bitfields.h> 11 #include <zircon/pixelformat.h> 12 13 namespace registers { 14 15 // Number of pipes that the hardware provides. 16 static constexpr uint32_t kPipeCount = 3; 17 18 enum Pipe { PIPE_A, PIPE_B, PIPE_C, PIPE_INVALID }; 19 20 static const Pipe kPipes[kPipeCount] = { 21 PIPE_A, PIPE_B, PIPE_C, 22 }; 23 24 static constexpr uint32_t kImagePlaneCount = 3; 25 static constexpr uint32_t kCursorPlane = 2; 26 27 // PIPE_SRCSZ 28 class PipeSourceSize : public hwreg::RegisterBase<PipeSourceSize, uint32_t> { 29 public: 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 37 class PipeBottomColor : public hwreg::RegisterBase<PipeBottomColor, uint32_t> { 38 public: 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 50 class PlaneSurface : public hwreg::RegisterBase<PlaneSurface, uint32_t> { 51 public: 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 67 class PlaneSurfaceLive : public hwreg::RegisterBase<PlaneSurfaceLive, uint32_t> { 68 public: 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 78 class PlaneSurfaceStride : public hwreg::RegisterBase<PlaneSurfaceStride, uint32_t> { 79 public: 80 static constexpr uint32_t kBaseAddr = 0x70188; 81 82 DEF_FIELD(9, 0, stride); 83 }; 84 85 // PLANE_SIZE 86 class PlaneSurfaceSize : public hwreg::RegisterBase<PlaneSurfaceSize, uint32_t> { 87 public: 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 95 class PlaneControl : public hwreg::RegisterBase<PlaneControl, uint32_t> { 96 public: 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 140 class PlaneBufCfg : public hwreg::RegisterBase<PlaneBufCfg, uint32_t> { 141 public: 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 150 class PlaneWm : public hwreg::RegisterBase<PlaneWm, uint32_t> { 151 public: 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 160 class PlaneKeyMask : public hwreg::RegisterBase<PlaneKeyMask, uint32_t> { 161 public: 162 static constexpr uint32_t kBaseAddr = 0x70198; 163 164 DEF_BIT(31, plane_alpha_enable); 165 }; 166 167 // PLANE_KEYMAX 168 class PlaneKeyMax : public hwreg::RegisterBase<PlaneKeyMax, uint32_t> { 169 public: 170 static constexpr uint32_t kBaseAddr = 0x701a0; 171 172 DEF_FIELD(31, 24, plane_alpha_value); 173 }; 174 175 // PLANE_OFFSET 176 class PlaneOffset : public hwreg::RegisterBase<PlaneOffset, uint32_t> { 177 public: 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 185 class PlanePosition : public hwreg::RegisterBase<PlanePosition, uint32_t> { 186 public: 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 194 class PipeScalerCtrl : public hwreg::RegisterBase<PipeScalerCtrl, uint32_t> { 195 public: 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 224 class PipeScalerWinPosition : public hwreg::RegisterBase<PipeScalerWinPosition, uint32_t> { 225 public: 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 233 class PipeScalerWinSize : public hwreg::RegisterBase<PipeScalerWinSize, uint32_t> { 234 public: 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 242 class PipeDeInterrupt : public hwreg::RegisterBase<PipeDeInterrupt, uint32_t> { 243 public: 244 DEF_BIT(1, vsync); 245 }; 246 247 // CUR_BASE 248 class CursorBase : public hwreg::RegisterBase<CursorBase, uint32_t> { 249 public: 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 259 class CursorCtrl : public hwreg::RegisterBase<CursorCtrl, uint32_t> { 260 public: 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 272 class CursorPos : public hwreg::RegisterBase<CursorPos, uint32_t> { 273 public: 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 283 class CursorSurfaceLive : public hwreg::RegisterBase<CursorSurfaceLive, uint32_t> { 284 public: 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 292 class CscCoeff : public hwreg::RegisterBase<CscCoeff, uint32_t> { 293 public: 294 static constexpr uint32_t kBaseAddr = 0x49010; 295 coefficient(uint32_t i,uint32_t j)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 303 class CscCoeffFormat : public hwreg::RegisterBase<CscCoeffFormat, uint16_t> { 304 public: 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 317 class CscMode : public hwreg::RegisterBase<CscMode, uint32_t> { 318 public: 319 static constexpr uint32_t kBaseAddr = 0x49028; 320 }; 321 322 // CSC_POSTOFF / CSC_PREOFF 323 class CscOffset : public hwreg::RegisterBase<CscOffset, uint32_t> { 324 public: 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. 333 class PipeRegs { 334 public: 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 PipeRegs(Pipe pipe)340 PipeRegs(Pipe pipe) : pipe_(pipe) { } 341 PipeSourceSize()342 hwreg::RegisterAddr<registers::PipeSourceSize> PipeSourceSize() { 343 return GetReg<registers::PipeSourceSize>(); 344 } PipeBottomColor()345 hwreg::RegisterAddr<registers::PipeBottomColor> PipeBottomColor() { 346 return GetReg<registers::PipeBottomColor>(); 347 } 348 PlaneSurface(int32_t plane_num)349 hwreg::RegisterAddr<registers::PlaneSurface> PlaneSurface(int32_t plane_num) { 350 return GetPlaneReg<registers::PlaneSurface>(plane_num); 351 } PlaneSurfaceLive(int32_t plane_num)352 hwreg::RegisterAddr<registers::PlaneSurfaceLive> PlaneSurfaceLive(int32_t plane_num) { 353 return GetPlaneReg<registers::PlaneSurfaceLive>(plane_num); 354 } PlaneSurfaceStride(int32_t plane_num)355 hwreg::RegisterAddr<registers::PlaneSurfaceStride> PlaneSurfaceStride(int32_t plane_num) { 356 return GetPlaneReg<registers::PlaneSurfaceStride>(plane_num); 357 } PlaneSurfaceSize(int32_t plane_num)358 hwreg::RegisterAddr<registers::PlaneSurfaceSize> PlaneSurfaceSize(int32_t plane_num) { 359 return GetPlaneReg<registers::PlaneSurfaceSize>(plane_num); 360 } PlaneControl(int32_t plane_num)361 hwreg::RegisterAddr<registers::PlaneControl> PlaneControl(int32_t plane_num) { 362 return GetPlaneReg<registers::PlaneControl>(plane_num); 363 } PlaneOffset(int32_t plane_num)364 hwreg::RegisterAddr<registers::PlaneOffset> PlaneOffset(int32_t plane_num) { 365 return GetPlaneReg<registers::PlaneOffset>(plane_num); 366 } PlanePosition(int32_t plane_num)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 PlaneBufCfg(int plane)371 hwreg::RegisterAddr<registers::PlaneBufCfg> PlaneBufCfg(int plane) { 372 return hwreg::RegisterAddr<registers::PlaneBufCfg>( 373 PlaneBufCfg::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); 374 } 375 PlaneWatermark(int plane,int wm_num)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 PlaneKeyMask(int32_t plane_num)381 hwreg::RegisterAddr<registers::PlaneKeyMask> PlaneKeyMask(int32_t plane_num) { 382 return GetPlaneReg<registers::PlaneKeyMask>(plane_num); 383 } PlaneKeyMax(int32_t plane_num)384 hwreg::RegisterAddr<registers::PlaneKeyMax> PlaneKeyMax(int32_t plane_num) { 385 return GetPlaneReg<registers::PlaneKeyMax>(plane_num); 386 } 387 PipeScalerCtrl(int num)388 hwreg::RegisterAddr<registers::PipeScalerCtrl> PipeScalerCtrl(int num) { 389 return hwreg::RegisterAddr<registers::PipeScalerCtrl>( 390 PipeScalerCtrl::kBaseAddr + 0x800 * pipe_ + num * 0x100); 391 } 392 PipeScalerWinPosition(int num)393 hwreg::RegisterAddr<registers::PipeScalerWinPosition> PipeScalerWinPosition(int num) { 394 return hwreg::RegisterAddr<registers::PipeScalerWinPosition>( 395 PipeScalerWinPosition::kBaseAddr + 0x800 * pipe_ + num * 0x100); 396 } 397 PipeScalerWinSize(int num)398 hwreg::RegisterAddr<registers::PipeScalerWinSize> PipeScalerWinSize(int num) { 399 return hwreg::RegisterAddr<registers::PipeScalerWinSize>( 400 PipeScalerWinSize::kBaseAddr + 0x800 * pipe_ + num * 0x100); 401 } 402 PipeDeInterrupt(uint32_t type)403 hwreg::RegisterAddr<registers::PipeDeInterrupt> PipeDeInterrupt(uint32_t type) { 404 return hwreg::RegisterAddr<registers::PipeDeInterrupt>(type + 0x10 * pipe_); 405 } 406 CursorBase()407 hwreg::RegisterAddr<registers::CursorBase> CursorBase() { 408 return GetReg<registers::CursorBase>(); 409 } 410 CursorCtrl()411 hwreg::RegisterAddr<registers::CursorCtrl> CursorCtrl() { 412 return GetReg<registers::CursorCtrl>(); 413 } 414 CursorPos()415 hwreg::RegisterAddr<registers::CursorPos> CursorPos() { 416 return GetReg<registers::CursorPos>(); 417 } 418 CursorSurfaceLive()419 hwreg::RegisterAddr<registers::CursorSurfaceLive> CursorSurfaceLive() { 420 return GetReg<registers::CursorSurfaceLive>(); 421 } 422 CscCoeff(uint32_t i,uint32_t j)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 CscMode()429 hwreg::RegisterAddr<registers::CscMode> CscMode() { 430 return GetCscReg<registers::CscMode>(registers::CscMode::kBaseAddr); 431 } 432 CscOffset(bool preoffset,uint32_t component_idx)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 439 private: GetReg()440 template <class RegType> hwreg::RegisterAddr<RegType> GetReg() { 441 return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_); 442 } 443 GetPlaneReg(int32_t plane)444 template <class RegType> hwreg::RegisterAddr<RegType> GetPlaneReg(int32_t plane) { 445 return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_ + 0x100 * plane); 446 } 447 GetCscReg(uint32_t base)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 456 typedef 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