blob: 8daf72d1a3dd4cc9744f9a0f692902bbc4c5d91d [file] [log] [blame]
// Copyright 2022 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.
#ifndef SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_PIPE_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_PIPE_H_
#include <fuchsia/hardware/display/controller/c/banjo.h>
#include <fuchsia/hardware/intelgpucore/c/banjo.h>
#include <zircon/assert.h>
#include <hwreg/bitfields.h>
#include "src/graphics/display/drivers/intel-i915/hardware-common.h"
#include "src/graphics/display/drivers/intel-i915/registers-pipe-scaler.h"
namespace registers {
static constexpr uint32_t kImagePlaneCount = 3;
static constexpr uint32_t kCursorPlane = 2;
// PIPE_SRCSZ (Pipe Image Source Size)
//
// All reserved bits are MBZ (must be zero), so this register can be written
// safely without reading it first.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 704-705
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 533-534
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 550-551
class PipeSourceSize : public hwreg::RegisterBase<PipeSourceSize, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x6001c;
DEF_RSVDZ_FIELD(31, 29);
// The horizontal size of the image created by the display planes.
//
// The value stored in this field is the horizontal size in pixels, minus one.
//
// On Kaby Lake and Skylake, when Frame Buffer Compression or Panel Fitting
// are in use, the maximum supported image size is 4096 pixels.
DEF_FIELD(28, 16, horizontal_source_size_minus_one);
DEF_RSVDZ_FIELD(15, 13);
// The vertical size of the image created by the display planes.
//
// The value stored in this field is the vertical size in pixels, minus one.
//
// On Tiger Lake, the maximum supported image size is 4320 pixels.
//
// On Kaby Lake and Skylake, the maximum supported image size is 4096 pixels.
// The field is documented as taking up bits 11:0, and bit 12 is reserved MBZ
// (Must Be Zero). Our field declaration will respect the MBZ constraint, as
// long as we obey the maximum vertical image size.
DEF_FIELD(12, 0, vertical_source_size_minus_one);
};
// 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 (Plane Stride)
//
// This register is double-buffered. Changes are reflected at the start of the
// next Vblank (vertical blank period) after the PLANE_SURF register is written.
//
// This register can be written safely without reading it first. On Tiger Lake,
// all reserved bits are explicitly documented as MBZ (must be zero). While this
// is not the case for the Kaby Lake and Skylake, experiments and the OpenBSD
// i915 driver suggest that writing zeros to the reserved bits is safe.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 832-836
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 603-606
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 598-600
class PlaneSurfaceStride : public hwreg::RegisterBase<PlaneSurfaceStride, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70188;
DEF_RSVDZ_FIELD(31, 11);
// The stride of the plane.
//
// Linear memory: the value is a cache line (64 bytes) count.
// X-Tiled and Y-tiled memory: the value is a number of tiles.
//
// The stride must not exceed the size of 8192 pixels.
//
// On Kaby Lake and Skylake, the stride size must not exceed 32KB. On Kaby
// Lake and Skylake, the stride field only takes up bits 9-0.
DEF_FIELD(10, 0, stride);
};
// PLANE_SIZE
class PlaneSurfaceSize : public hwreg::RegisterBase<PlaneSurfaceSize, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70190;
DEF_FIELD(28, 16, height_minus_1);
DEF_FIELD(12, 0, width_minus_1);
};
// Possible values for the `alpha_mode*` fields in plane control registers.
enum class PlaneControlAlphaMode {
kAlphaIgnored = 0,
kInvalid = 1,
kAlphaPreMultiplied = 2,
kAlphaHardwareMultiply = 3,
};
// PLANE_COLOR_CTL (Plane Color Control)
//
// This register is not documented on Kaby Lake or Skylake. On that hardware,
// some of the fields here are located in the PLANE_CTL register.
//
// All reserved bits are MBZ (must be zero), so this register can be written
// safely without reading it first.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 627-735
class PlaneColorControl : public hwreg::RegisterBase<PlaneColorControl, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x701CC;
DEF_RSVDZ_BIT(31);
// If true, pipe-level gamma correction is enabled for the plane's pixel data.
//
// This field is documented as deprecated in favor of the "Post CSC Gamma
// Enable" field in the Pipe-specific GAMMA_MODE register.
DEF_BIT(30, pipe_gamma_enabled_deprecated);
// If false, the plane removes UV offsets for YUV formats without YUV/RGB CSC.
//
// This field is used when the plane's source pixel format is a YUV format,
// and plane-level YUV to RGB CSC (Color Space Conversion) is disabled. If
// the field is true, 1/2 offsets on the U and V components are preserved.
// If the field is false, 1/2 offsets are removed.
DEF_BIT(29, yuv_offset_preserved);
// If true, plane-level YUV range correction logic is disabled.
//
// Range correction expands YUV components from compressed ranges to the full
// range of values. The 8-bit compressed ranges are +16 to +235 for the Y
// component, and -112 to +112 for the U and V components.
//
// This field is only effective when the plane has a YUV source pixel format.
// RGB pixel formats always bypass range correction.
DEF_BIT(28, yuv_range_correction_disabled);
DEF_RSVDZ_FIELD(27, 24);
// If true, pipe-level CSC (Color Space Conversion) and pre-CSC gamma
// correction are enabled for the plane's pixel data.
//
// This field is documented as deprecated in favor of the "Pre CSC Gamma
// Enable" field in the Pipe-specific GAMMA_MODE register, and the "Pipe CSC
// Enable" field in the CSC_MODE register.
DEF_BIT(23, pipe_csc_enabled_deprecated);
// If true, planel-level CSC (Color Space Conversion) logic is enabled.
//
// This field is only effective on planes 1-3.
DEF_BIT(21, csc_enabled);
// If true, planel-level input CSC (Color Space Conversion) logic is enabled.
//
// This field is only effective on planes 1-3.
DEF_BIT(20, plane_input_csc_enabled);
// Documented values for the `csc_mode` field.
enum class ColorSpaceConversion {
kBypass = 0,
kYuvToRgbBt601 = 1,
kYuvToRgbBt709 = 2,
kYuvtoRgbBt2020 = 3,
kRgbBt709toBt2020 = 4,
// TODO(https://fxbug.dev/42062082): Figure out modeling for invalid values 5-7.
};
// Specifies the plane-level CSC (Color Space Conversion) mode.
//
// This field is only effective on planes 4-7. The CSC logic in planes 1-3 is
// configured by PLANE_CSC_* registers.
DEF_ENUM_FIELD(ColorSpaceConversion, 19, 17, csc_mode);
DEF_RSVDZ_BIT(16);
// If true, plane-level post-CSC gamma multi-segment processing is enabled.
//
// This logic is intended to support HDR tone mapping.
DEF_BIT(15, post_csc_gamma_multi_segment_enabled);
// If true, plane-level pre-CSC gamma correction is enabled.
DEF_BIT(14, pre_csc_gamma_enabled);
// If true, plane-level post-CSC gamma correction is disabled.
DEF_BIT(13, post_csc_gamma_disabled);
// Possible values for the `gamma_mode` field.
enum class GammaMode {
// The table lookup is based on pixel R, G, B component values. The output
// is an interpolation of the values in the two nearest table entries.
kDirect = 0,
// The table lookup is based on a pseudo-luminance (L) for the pixel. An
// adjustment factor (F) is computed by interpolating the entries in the two
// nearest table entries. Each output component is the input component
// multiplied by the adjustment factor F.
// L = 0.25 * R + 0.625 * G + 0.125 * B.
//
// This mode is intended to support HDR tone mapping.
kMultiply = 1,
};
// The mode of operation of the plane's gamma correction logic.
//
// This field is ignored if plane-level gamma correction is disabled.
DEF_ENUM_FIELD(GammaMode, 12, 12, gamma_mode);
// Possible values for the `gamma_multiplier_format` field.
enum class GammaMultiplierFormat {
kU0_24 = 0,
kU8_16 = 1,
};
// Specifies how the gamma table entries are turned into multipliers.
//
// This field is ignored if plane-level gamma correction is not operating in
// multiplication mode.
DEF_ENUM_FIELD(GammaMultiplierFormat, 11, 11, gamma_multiplier_format);
DEF_RSVDZ_FIELD(10, 6);
// Selects the plane's alpha blending mode.
//
// The registers PLANE_KEYMSK and PLANE_KEYMAX specify constant plane alpha.
DEF_ENUM_FIELD(PlaneControlAlphaMode, 5, 4, alpha_mode);
DEF_RSVDZ_FIELD(3, 0);
};
// PLANE_CTL (Plane Control)
//
// This register is double-buffered. Changes are reflected at the start of the
// next Vblank (vertical blank period) after the PLANE_SURF register is written.
//
// All reserved bits are MBZ (must be zero), so this register can be written
// safely without reading it first.
//
// TODO(https://fxbug.dev/42062857): Split this register definitions into separate
// variants for Tiger Lake vs Kaby Lake / Skylake.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 745-753
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 562-569
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 559-566
class PlaneControl : public hwreg::RegisterBase<PlaneControl, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x70180;
// If true, the plane generates pixels for display.
//
// If false, the plane stops fetching surface memory, and outputs transparent
// pixels.
DEF_BIT(31, plane_enabled);
// If true, pipe-level gamma correction is enabled for the plane's pixel data.
//
// Pipe-level gamma correction is separate from plane-level gamma correction.
//
// This field only exists on Kaby Lake and Skylake. On Tiger Lake, this field
// was moved to the PlaneColorControl register, and the underlying bit here
// is used for another field.
DEF_BIT(30, pipe_gamma_enabled_kaby_lake);
// See `yuv_offset_preserved` in PlaneColorControl for details.
//
// This field only exists on Kaby Lake and Skylake. On Tiger Lake, this field
// was moved to the PlaneColorControl register, and the underlying bit here
// is used for another field.
DEF_BIT(29, yuv_offset_preserved_kaby_lake);
// See `yuv_range_correction_disabled` in PlaneColorControl for details.
//
// This field only exists on Kaby Lake and Skylake. On Tiger Lake, this field
// was moved to the PlaneColorControl register, and the underlying bit here
// is used for another field.
DEF_BIT(28, yuv_range_correction_disabled_kaby_lake);
// Number of slots allocated to this plane in pipe slice request arbitration.
//
// This field is not documented on Kaby Lake or Skylake. The underlying bits
// are used by different fields.
int pipe_slice_request_arbitration_slot_count_tiger_lake() const {
// The cast is lossless and the addition doesn't overflow (causing UB)
// because this is a 3-bit field.
return static_cast<int>(hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), 30, 28).get()) + 1;
}
// See `pipe_slice_request_arbitration_slot_count_tiger_lake()` for details.
PlaneControl& set_pipe_slice_request_arbitration_slot_count_tiger_lake(int slot_count) {
ZX_DEBUG_ASSERT(slot_count > 0);
ZX_DEBUG_ASSERT(slot_count <= 8);
// The cast is lossless and the addition doesn't overflow (causing UB)
// because this is a 3-bit field.
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 30, 28).set(slot_count - 1);
return *this;
}
// Documented values for the `source_pixel_format_kaby_lake` field.
//
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 page 564
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 561
enum class ColorFormatKabyLake {
kYuv422Packed = 0b0000,
kYuv420Planar8bpc = 0b0001, // NV12, not documented on Skylake
kRgb2_10_10_10 = 0b0010,
kRgb8888 = 0b0100,
kRgb16_16_16_16_float = 0b0110,
kYuv444Packed8bpc = 0b1000,
kRgb2_10_10_10XrBias = 0b1010, // Extended range bias
kIndexed8bit = 0b1100,
kRgb565 = 0b1110,
// TODO(https://fxbug.dev/42062082): Figure out modeling for invalid values, and add
// a getter for the field.
};
// Documented values for the `source_pixel_format_tiger_lake` field.
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 page 749
enum class ColorFormatTigerLake {
kYuv422Packed8bpc = 0b00000,
kYuv422Packed10bpc = 0b00001, // Y210
kYuv420Planar8bpc = 0b00010, // NV12
kYuv422Packed12bpc = 0b00011, // Y212
kRgb2_10_10_10 = 0b00100,
kYuv422Packed16bpc = 0b00101, // Y216
kYuv420Planar10bpc = 0b00110, // P010. Only supported on HDR planes.
kYuv444Packed10bpc = 0b00111, // Y410
kRgb8888 = 0b01000,
kYuv444Packed12bpc = 0b01001, // Y412
kYuv420Planar12bpc = 0b01010, // P012. Only supported on HDR planes.
kYuv444Packed16bpc = 0b01011, // Y416
kRgb16_16_16_16_float = 0b01100, // FP16. Only supported on HDR planes.
kYuv420Planar16bpc = 0b01110, // P016. Only supported on HDR planes.
kYuv444Packed8bpc = 0b10000,
kRgb2_10_10_10XrBias = 0b10100, // Extended range bias
kIndexed8bit = 0b11000,
kRgb565 = 0b11100,
// TODO(https://fxbug.dev/42062082): Figure out modeling for invalid values, and add
// a getter for the field.
};
// The source pixel format for the plane.
//
// The plane converts the source data to the pipe's pixel format, before the
// data enters the blending logic. Some formats are only supported by HDR
// planes.
//
// This setter uses the field and color format values documented for Tiger
// Lake.
PlaneControl& set_source_pixel_format_tiger_lake(ColorFormatTigerLake format) {
const uint32_t raw_format = static_cast<uint32_t>(format);
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 27, 23).set(raw_format);
return *this;
}
// The source pixel format for the plane.
//
// The plane converts the source data to the pipe's pixel format, before the
// data enters the blending logic.
//
// This setter uses the field and color format values documented for Kaby Lake
// and Skylake.
PlaneControl& set_source_pixel_format_kaby_lake(ColorFormatKabyLake format) {
const uint32_t raw_format = static_cast<uint32_t>(format);
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 27, 24).set(raw_format);
return *this;
}
// If true, pipe-level color space conversion is enabled for this plane.
//
// The pipe-level CSC (color space conversion) is separate from the
// plane-level CSC.
//
// This field only exists on Kaby Lake and Skylake. On Tiger Lake, this field
// was moved to the PlaneColorControl register, and the underlying bit here
// is used for another field.
DEF_BIT(23, pipe_csc_enabled_kaby_lake);
// Possible values for the `color_key` field.
enum class ColorKey : uint32_t {
kColorKeyDisabled = 0b00,
kColorKeySource = 0b01,
kColorKeyDestination = 0b01,
kColorKeySourceWindow = 0b01,
};
// Selects the plane's color keying functionality.
//
// Color keying has the following restrictions:
// * The pixel format must not be 8-bit indexed
// * If used, Source Key Window and Destination color keying must be enabled
// on a pair of adjacent planes on a pipe
// * Source and Source Window keying must not be used on the bottom active
// plane
// * Destination keying must not be used on the top active plane
DEF_ENUM_FIELD(ColorKey, 22, 21, color_key);
// Possible values for the `rgb_color_order` field.
enum class RgbColorOrder {
kBgrx = 0,
kRgbx = 1,
};
// Selects the color ordering for most RGB formats.
//
// This field is ignored for the following input formats:
// * XR_BIAS 10:10:10
// * BGRX 5:6:5
// * Non-RGB color formats, such as YUV and indexed
DEF_ENUM_FIELD(RgbColorOrder, 20, 20, rgb_color_order);
// If true, the plane performs no YUV-to-RGB color conversion.
//
// This field is ignored when the plane's source is an RGB format.
//
// This field is not documented on Tiger Lake. The underlying bit is used by a
// different field.
DEF_BIT(19, yuv_to_rgb_csc_disabled_kaby_lake);
// If true, this plane stores the Y component of planar YUV420 data.
//
// If false, this plane stores the U and V components of planar YUV420 data.
//
// This field is used when the source pixel format is a YUV420 planar format
// (NV12 or P0xx). This field must be set to false for all other formats.
//
// Only planes 1-5 can store the U and V components in planar YUV420 data.
// Only planes 6-7 can store the Y component in planar YUV420 data.
//
// This field is not documented on Kaby Lake or Skylake. The underlying bit is
// used by a different field.
bool has_y_component_in_planar_yuv420_tiger_lake() const {
return static_cast<bool>(hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), 19, 19).get());
}
// See `has_y_component_in_planar_yuv420_tiger_lake()` for details.
PlaneControl& set_has_y_component_in_planar_yuv420_tiger_lake(bool has_y_component) {
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 19, 19).set(has_y_component ? 1 : 0);
return *this;
}
// Possible values for the `yuv_to_rgb_csc_format_kaby_lake` field.
enum class YuvToRgbConversionKabyLake {
kBt601 = 0,
kBt709 = 1,
};
// Specifies the YUV format for the plane's YUV-to-RGB color space conversion.
//
// This field is ignored when the plane's source is not a YUV format.
//
// This field is not documented on Tiger Lake. The underlying bit is reserved
// MBZ (must be zero).
DEF_ENUM_FIELD(YuvToRgbConversionKabyLake, 18, 18, yuv_to_rgb_csc_format_kaby_lake);
// Possible values for the `yuv_422_byte_order` field.
enum class Yuv422ByteOrder {
kOrderYuyv = 0b00,
kOrderUyvy = 0b01,
kOrderYvyu = 0b10,
kOrderVyuy = 0b11,
};
// Selects the byte order for YUV 4:2:2 data formats.
//
// This field is ignored when the plane's source format is not YUV 4:2:2.
DEF_ENUM_FIELD(Yuv422ByteOrder, 17, 16, yuv_422_byte_order);
// If true, the display engine will decompress Render-compressed surfaces.
//
// Decompression has the following limitations:
// * Decompression must be left-right cache-line pair
// * The compressed surface must use Y (Legacy) or YF tiling
// * Plane rotation must not be set to 90 or 270 degrees
// * The surface format must be RGB8888, RGB1010102 (only on Tiger Lake), or
// FP16 (only on Tiger Lake)
// * On Kaby Lake and Skylake, decompression is only supported on planes 1-2
// of pipes A and B
DEF_BIT(15, decompress_render_compressed_surfaces);
// Bit 14 is documented as reserved MBZ (must be zero) on Tiger Lake.
//
// On Kaby Lake and Skylake, the documented semantics of bit 14 would warrant
// the name `trickle_feed_disabled`. However, the documentation states that
// this bit must not be programmed to 1, suggesting that the feature was
// probably backed out. For our purposes, it's simpler to just consider the
// bit MBZ everywhere.
DEF_RSVDZ_BIT(14);
// If true, plane-level gamma correction is disabled.
//
// This field is not documented on Tiger Lake. The underlying bit is used by a
// different field.
DEF_BIT(13, plane_gamma_disabled_kaby_lake);
// If true, clear color mode is disabled when display decompresses surfaces.
//
// This field is ignored if `decompress_render_compressed_surfaces` is false.
// If `decompress_render_compressed_surfaces` and this field is false (Color
// Clear is enabled), the color must be set in the PLANE_CC_VAL register
// before performing a flip via a PLANE_SURF register write.
//
// This field is not documented on Kaby Lake and Skylake. That hardware does
// not support Color Clear with decompression. The underlying bit is used by a
// different field.
bool render_decompression_clear_color_disabled_tiger_lake() const {
return static_cast<bool>(hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), 13, 13).get());
}
// See `render_decompression_clear_color_disabled_tiger_lake()` for details.
PlaneControl& set_render_decompression_clear_color_disabled_tiger_lake(bool disabled) {
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 13, 13).set(disabled ? 1 : 0);
return *this;
}
// Documented values for the `surface_tiling` field.
enum class SurfaceTiling {
kLinear = 0b000,
kTilingX = 0b001,
kTilingYLegacy = 0b100,
// YF tiling is not supported on Tiger Lake.
kTilingYFKabyLake = 0b101,
// TODO(https://fxbug.dev/42062082): Figure out modeling for invalid values 2-3, 6-7.
};
// Indicates the tiling used by the plane's surface data.
//
// Y tiling is not compatible with interlaced modes. YS tiling is not
// supported.
DEF_ENUM_FIELD(SurfaceTiling, 12, 10, surface_tiling);
// If true, surface MMIO address writes take effect as soon as possible.
//
// If false, MMIO writes that change the plane's surface address will take
// effect synchronously, during vertical blank start.
DEF_BIT(9, async_surface_address_update_enabled);
// If true, the plane performs a horizontal flip before any rotation.
//
// This field is not documented on Kaby Lake and Skylake. The underlying bit
// is reserved MBZ (must be zero), which is semantically equivalent to
// considering that horizontal flipping is not supported on Kaby Lake /
// Skylake, and must always be disabled.
DEF_BIT(8, horizontal_flip_tiger_lake);
// If true, right eye Vblank does not trigger plane surface double-buffering.
//
// This field is ignored outside stereo 3D mode. In stereo 3D mode, at least
// one eye Vblank must be unmasked.
DEF_BIT(7, stereo_surface_right_eye_vblank_masked);
// If true, left eye Vblank does not trigger plane surface double-buffering.
//
// This field is ignored outside stereo 3D mode. In stereo 3D mode, at least
// one eye Vblank must be unmasked.
DEF_BIT(6, stereo_surface_left_eye_vblank_masked);
// See `alpha_mode` in PlaneColorControl for details.
//
// This field only exists on Kaby Lake and Skylake. On Tiger Lake, this field
// was moved to the PlaneColorControl register, and the underlying bits here
// are used for other fields.
DEF_ENUM_FIELD(PlaneControlAlphaMode, 5, 4, alpha_mode_kaby_lake);
// If true, the display engine will decompress Media-compressed surfaces.
//
// This field must not be set to true for a plane where
// `decompress_render_compressed_surfaces` is true.
//
// Media decompression is supported for the following formats: YUV420 planar
// (NV12, P0xx), YUV422, YUV4444, RGB8888, RGB1010102 and FP16.
//
// This field is not documented on Kaby Lake and Skylake. The underlying bit
// is used by a different field.
bool decompress_media_compressed_surfaces_tiger_lake() const {
return static_cast<bool>(hwreg::BitfieldRef<const uint32_t>(reg_value_ptr(), 4, 4).get());
}
// See `decompress_media_compressed_surfaces_tiger_lake()` for details.
PlaneControl& set_decompress_media_compressed_surfaces_tiger_lake(bool decompress_media) {
hwreg::BitfieldRef<uint32_t>(reg_value_ptr(), 4, 4).set(decompress_media ? 1 : 0);
return *this;
}
// If true, double-buffer updates can be disabled for this plane.
//
// This field applies when the DOUBLE_BUFFER_CTL register is used to disable
// the double-buffering of for all the resources that allow disabling.
DEF_BIT(3, double_buffer_update_disabling_allowed);
DEF_RSVDZ_BIT(2);
// Possible values for the `rotation` field.
enum class Rotation : uint32_t {
kIdentity = 0,
k90degrees = 1,
k180degrees = 2,
k270degrees = 3,
};
// Selects the hardware rotation performed by the plane.
//
// 90 and 270 degree rotations have the following restrictions:
// * The surface must be Y-Tiled
// * Interlacing must be disabled
// * Render-Display compression must be disabled
DEF_ENUM_FIELD(Rotation, 1, 0, rotation);
};
// PLANE_BUF_CFG (Plane Buffer Config)
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-1.22-Rev2.0 Part 2 pages 720-724
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 2 pages 558-561
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 2 page 555-558
class PlaneBufferConfig : public hwreg::RegisterBase<PlaneBufferConfig, uint32_t> {
public:
static constexpr uint32_t kBaseAddr = 0x7017c;
DEF_RSVDZ_FIELD(31, 27);
// The buffer end position for this plane.
//
// On Kaby Lake and Skylake, bit 26 is reserved.
DEF_FIELD(26, 16, buffer_end);
DEF_RSVDZ_FIELD(15, 11);
// The buffer start position for this plane.
//
// On Kaby Lake and Skylake, bit 10 is reserved.
DEF_FIELD(10, 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(10, 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);
};
// DE_PIPE_INTERRUPT (Display Engine Pipe Interrupts)
//
// Tiger Lake: IHD-OS-TGL-Vol 2c-12.21 Part 1 pages 361-364
// Kaby Lake: IHD-OS-KBL-Vol 2c-1.17 Part 1 pages 448-450
// Skylake: IHD-OS-SKL-Vol 2c-05.16 Part 1 pages 444-446
class PipeInterrupt : public hwreg::RegisterBase<PipeInterrupt, uint32_t> {
public:
// The attached transcoder experienced an underrun.
DEF_BIT(31, underrun);
// Active high level while the attached transcoder is in vertical sync.
DEF_BIT(1, vsync);
// Active high level while the attached transcoder is in vertical blank.
//
// This is the VBlank (vertical blank) signal used by the pipe and planes.
// In particular, this causes the double-buffered pipe and plane registers to
// update.
//
// By default, the (unmodified) transcoder vertical blank always starts at the
// end of the vertical active. If the transcoder's vertical blank start is set
// to a value higher than vertical active, the pipe's vertical blank signal
// starts later than the (modified) transcoder vertical blank.
DEF_BIT(0, vblank);
};
// 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:
enum class InterruptRegister : uint32_t {
kStatus = 0x44400,
kMask = 0x44404,
kIdentity = 0x44408,
kEnable = 0x4440c,
};
explicit PipeRegs(i915::PipeId pipe_id) : pipe_id_(pipe_id) {}
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::PlaneColorControl> PlaneColorControlTigerLake(int32_t plane_num) {
return GetPlaneReg<registers::PlaneColorControl>(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::PlaneBufferConfig> PlaneBufCfg(int plane) {
return hwreg::RegisterAddr<registers::PlaneBufferConfig>(PlaneBufferConfig::kBaseAddr +
0x1000 * pipe_id_ + 0x100 * plane);
}
hwreg::RegisterAddr<registers::PlaneWm> PlaneWatermark(int plane, int wm_num) {
return hwreg::RegisterAddr<PlaneWm>(PlaneWm::kBaseAddr + 0x1000 * pipe_id_ + 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::PipeInterrupt> PipeInterrupt(InterruptRegister register_type) {
return hwreg::RegisterAddr<registers::PipeInterrupt>(static_cast<uint32_t>(register_type) +
0x10 * pipe_id_);
}
PipeScalerRegs PipeScalerRegs(int scaler_index) {
return registers::PipeScalerRegs(pipe_id_, scaler_index);
}
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_id_);
}
template <class RegType>
hwreg::RegisterAddr<RegType> GetPlaneReg(int32_t plane) {
return hwreg::RegisterAddr<RegType>(RegType::kBaseAddr + 0x1000 * pipe_id_ + 0x100 * plane);
}
template <class RegType>
hwreg::RegisterAddr<RegType> GetCscReg(uint32_t base) {
return hwreg::RegisterAddr<RegType>(base + 0x100 * pipe_id_);
}
i915::PipeId pipe_id_;
};
// 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
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_REGISTERS_PIPE_H_