| // Copyright 2024 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_AMLOGIC_DISPLAY_ENCODER_REGS_H_ |
| #define SRC_GRAPHICS_DISPLAY_DRIVERS_AMLOGIC_DISPLAY_ENCODER_REGS_H_ |
| |
| #include <zircon/assert.h> |
| |
| #include <cstdint> |
| |
| #include <hwreg/bitfields.h> |
| |
| #include "src/graphics/display/lib/api-types/cpp/display-timing.h" |
| |
| namespace amlogic_display { |
| |
| // VENC_VIDEO_TST_EN |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 377. |
| class EncoderBuiltInSelfTestEnabled |
| : public hwreg::RegisterBase<EncoderBuiltInSelfTestEnabled, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<EncoderBuiltInSelfTestEnabled> Get() { |
| return {0x1b70 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 1); |
| |
| // If true, the encoder built-in self-test (BIST) mode is enabled, and the |
| // encoder outputs predefined patterns as specified in the |
| // EncoderBuiltInSelfTestModeSelection register. |
| DEF_BIT(0, enabled); |
| }; |
| |
| enum class EncoderBuiltInSelfTestMode : uint8_t { |
| // Outputs a fixed color specified by the following registers: |
| // - EncoderBuiltInSelfTestFixedColorLuminance |
| // - EncoderBuiltInSelfTestFixedColorChrominanceBlue |
| // - EncoderBuiltInSelfTestFixedColorChrominanceRed |
| kFixedColor = 0, |
| |
| // Outputs color bars with 100% and 75% luminance (intensity), also known as |
| // 100/75 color bars. |
| kColorBar = 1, |
| |
| // Outputs thin horizontal and vertical lines on the screen. |
| kThinLines = 2, |
| |
| // Outputs a grid of white dots on the display. |
| kDotGrid = 3, |
| }; |
| |
| // VENC_VIDEO_TST_MDSEL |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", pages 377-378. |
| class EncoderBuiltInSelfTestModeSelection |
| : public hwreg::RegisterBase<EncoderBuiltInSelfTestModeSelection, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<EncoderBuiltInSelfTestModeSelection> Get() { |
| return {0x1b71 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 8); |
| |
| DEF_ENUM_FIELD(EncoderBuiltInSelfTestMode, 7, 0, mode); |
| }; |
| |
| class EncoderBuiltInSelfTestFixedColorLuminance |
| : public hwreg::RegisterBase<EncoderBuiltInSelfTestFixedColorLuminance, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<EncoderBuiltInSelfTestFixedColorLuminance> Get() { |
| return {0x1b72 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 10); |
| |
| DEF_FIELD(9, 0, luminance); |
| }; |
| |
| // VENC_VIDEO_TST_CB |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", pages 378. |
| class EncoderBuiltInSelfTestFixedColorChrominanceBlue |
| : public hwreg::RegisterBase<EncoderBuiltInSelfTestFixedColorChrominanceBlue, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<EncoderBuiltInSelfTestFixedColorChrominanceBlue> Get() { |
| return {0x1b73 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 10); |
| |
| DEF_FIELD(9, 0, chrominance_blue); |
| }; |
| |
| // VENC_VIDEO_TST_CR |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", pages 378. |
| class EncoderBuiltInSelfTestFixedColorChrominanceRed |
| : public hwreg::RegisterBase<EncoderBuiltInSelfTestFixedColorChrominanceRed, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<EncoderBuiltInSelfTestFixedColorChrominanceRed> Get() { |
| return {0x1b74 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 10); |
| |
| DEF_FIELD(9, 0, chrominance_red); |
| }; |
| |
| // The code references the S912 datasheet for the encoder control registers. |
| // |
| // These registers are not documented in the datasheets of the newer SoCs |
| // (S905D2, A311D / T931 and S905D3). Experiments on Astro (using S905D2), |
| // Sherlock (using T931), Nelson (using S905D3) and Khadas VIM3 (using A311D) |
| // boards show that these registers have the same definition and register |
| // addresses as S912. |
| |
| // # Amlogic Display Encoders |
| // |
| // An encoder converts the image data processed by the Video Input Unit to |
| // video and timing signals. |
| // |
| // The following encoders are available on an Amlogic SoC: |
| // |
| // * ENCP (HDMI / DVI encoder) |
| // |
| // Encodes the image data for digital output over HDMI / DVI. |
| // |
| // While the name ENCP stands for "Progressive encoder", it actually supports |
| // both progressive and interlaced (1080i) display timings. |
| // |
| // * ENCI (Standard-definition interlaced HDMI / DVI encoder) |
| // |
| // Encodes the image data to 480i / 576i (standard definition) for digital |
| // output over HDMI / DVI. |
| // |
| // * ENCL (LCD panel encoder) |
| // |
| // Encodes the image data for MIPI-DSI host controller and / or LCD timing |
| // controllers (TCON). |
| // |
| // * ENCT (TV panel encoder) |
| // |
| // Encodes the image data for composite video baseband signal (CVBS) output. |
| |
| // ENCI_VIDEO_EN (Interlace Video Enable) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 372. |
| class InterlacedHdmiEncoderEnabled |
| : public hwreg::RegisterBase<InterlacedHdmiEncoderEnabled, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<InterlacedHdmiEncoderEnabled> Get() { |
| return {0x1b57 * sizeof(uint32_t)}; |
| } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 1); |
| |
| DEF_BIT(0, enabled); |
| }; |
| |
| // ## ENCP (HDMI / DVI encoder) |
| // |
| // The HDMI / DVI encoder takes its input from the VIU FIFO (VFIFO) and the |
| // HDMI Pixel Clock (from the clock tree), and generates the following signals |
| // for the HDMI / DVI transmitter: |
| // |
| // - Video signal, a parallel 24-bit wide RGB / YUV color signal (for non-HDR |
| // displays). |
| // - Display Enabled (DE) signal |
| // - Horizontal Sync (HSYNC) signal |
| // - Vertical Sync (VSYNC) signal |
| // |
| // All the signals are synchronized to the Pixel Clock. |
| // |
| // The HDMI / DVI encoder consists of two parts: |
| // - The video signal encoder, converting the VFIFO bytes to the video signal. |
| // - The timing signal producer, producing DE, HSYNC and VSYNC signals. |
| |
| // ENCP_VIDEO_EN (Progressive Video Enable) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 379. |
| class HdmiEncoderEnabled : public hwreg::RegisterBase<HdmiEncoderEnabled, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderEnabled> Get() { return {0x1b80 * sizeof(uint32_t)}; } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 1); |
| |
| DEF_BIT(0, enabled); |
| }; |
| |
| // ENCP_VIDEO_MODE |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", pages 380-381. |
| class HdmiEncoderModeConfig : public hwreg::RegisterBase<HdmiEncoderModeConfig, uint32_t> { |
| public: |
| enum class DisplayEnabledSignalPolarity : uint8_t { |
| kActiveLow = 0, |
| kActiveHigh = 1, |
| }; |
| |
| static hwreg::RegisterAddr<HdmiEncoderModeConfig> Get() { return {0x1b8d * sizeof(uint32_t)}; } |
| |
| // These bits are undocumented on Amlogic datasheets. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 16); |
| |
| // If true, the ENCP encoder debug counter registers are enabled. |
| // |
| // Documented as "pixel count and line count shadow enable" in the S912 |
| // datasheet. |
| DEF_BIT(15, debug_counter_enabled); |
| |
| DEF_ENUM_FIELD(DisplayEnabledSignalPolarity, 14, 14, display_enabled_signal_polarity); |
| |
| // If true, the encoder increases the value of the horizontal period (maximum |
| // pixel counter) register by one internally. |
| DEF_BIT(13, horizontal_period_increases_by_one); |
| |
| // Bits 12-0 configure the timing signals for the interlaced output. |
| // |
| // Rather than directly manipulating these bits, it's preferred to use the |
| // helper methods: ConfigureFor1080i(), ConfigureForHighDefinitionProgressive() |
| // and ConfigureForStandardDefinitionProgressive(). |
| |
| DEF_BIT(12, is_output_interlaced); |
| |
| // True iff the Vertical Sync Offset for odd field registers are enabled to |
| // produce vertical sync signals for odd fields. |
| DEF_BIT(11, vertical_sync_offset_for_odd_field_enabled); |
| |
| // True iff the Vertical Active On for odd field registers are enabled to |
| // produce video signals for odd fields. |
| DEF_BIT(10, vertical_active_on_for_odd_field_enabled); |
| |
| // Equalizing pulses are narrow pulses added before (pre-equalizing) and |
| // after (post-equalizing) the vertical sync pulses (also known as "broad |
| // pulses" in Analog TV) to indicate the start of a field. |
| // |
| // This avoids premature vertical-deflections when the vertical and |
| // horizontal syncs are combined into a single sync signal, which is common |
| // in Analog TV [1]. The equalizing pulse is also used to indicate the |
| // start of a field in 525/59.94 (NTSC) TV system [2]. |
| // |
| // Digital signals don't require equalizing pulses. |
| // |
| // [1] Raster Graphics Handbook, Chapter 8 "The Monitor Interface", |
| // Conrac Corporation, 1985, pages 8-9 and 8-10. |
| // [2] A Technical Introduction to Digital Video, Chapter 1 "Basic |
| // Principles", Charles Poynton, 1996, page 12. |
| |
| // True iff the equalizing pulse generator is enabled to produce analog |
| // equalizing pulse signals for odd fields in interlaced outputs. |
| DEF_BIT(9, analog_equalizing_pulse_for_odd_field_enabled); |
| |
| // True iff the equalizing pulse generator is enabled to produce analog |
| // equalizing pulse signals for even fields in interlaced outputs, or for |
| // progressive outputs. |
| DEF_BIT(8, analog_equalizing_pulse_enabled); |
| |
| // Undocumented in the S912 datasheet. |
| // |
| // The S912 datasheet requires this bit set to 1 for 1080i output, and |
| // requires this bit set to 0 for 720p, 480p and 540p output. |
| DEF_BIT(7, bit7_undocumented); |
| |
| // Documented as "Enable Hsync and equalization pulse switch in center" in |
| // the S912 datasheet. The function of this bit is unclear; it seems it |
| // only works for the analog signal output. |
| DEF_BIT(6, analog_hsync_and_equalizing_pulse_switch_in_center); |
| |
| // True iff the Analog vertical sync signal generator is enabled to produce |
| // analog Vsync signals for odd fields. |
| DEF_BIT(5, analog_vertical_sync_for_odd_field_enabled); |
| |
| // Documented as "Enable 2nd vertical pulse in a line (1080i)" in the |
| // S912 datasheet. The function of this bit is unclear. |
| DEF_BIT(4, second_vertical_sync_in_a_line_enabled); |
| |
| // Bits 3-0 configures the analog signal generator to handle the timings with |
| // non-integral values. |
| // |
| // The SMPTE 274M-2008 Standard requires that, for the 1080i output with |
| // a total of 1125 lines per picture, the digital interface may output 563 |
| // and 562 lines in even and odd fields respectively, while the analog |
| // interface must remain equally spaced (562 1/2 lines) for each field and |
| // must align to the half of a line. |
| // |
| // Section 7 "Raster Structure", SMPTE Standard 274M-2008: For Television -- |
| // 1920 x 1080 Image Sample Structure, Digital Representation and Digital |
| // Timing Reference Sequences for Multiple Picture Rates, The Society of |
| // Motion Picture and Television Engineers, Jan 2008, page 6. |
| |
| // True iff the end of the vertical sync is aligned to the half of a line |
| // for odd fields. |
| DEF_BIT(3, analog_vertical_sync_end_for_odd_field_aligned_to_half_line); |
| |
| // True iff the start of the vertical sync is aligned to the half of a line |
| // for odd fields. |
| DEF_BIT(2, analog_vertical_sync_start_for_odd_field_aligned_to_half_line); |
| |
| // True iff the end of the vertical sync is aligned to the half of a line |
| // for even fields. |
| DEF_BIT(1, analog_vertical_sync_end_for_even_field_aligned_to_half_line); |
| |
| // True iff the start of the vertical sync is aligned to the half of a line |
| // for even fields. |
| DEF_BIT(0, analog_vertical_sync_start_for_even_field_aligned_to_half_line); |
| |
| // The following register field configuration matches the preferred register |
| // value provided in the S912 datasheet. |
| HdmiEncoderModeConfig& ConfigureFor1080i() { |
| return set_is_output_interlaced(true) |
| .set_vertical_sync_offset_for_odd_field_enabled(true) |
| .set_vertical_active_on_for_odd_field_enabled(true) |
| .set_analog_equalizing_pulse_for_odd_field_enabled(true) |
| .set_analog_equalizing_pulse_enabled(true) |
| .set_bit7_undocumented(true) |
| .set_analog_hsync_and_equalizing_pulse_switch_in_center(true) |
| .set_analog_vertical_sync_for_odd_field_enabled(true) |
| .set_second_vertical_sync_in_a_line_enabled(true) |
| .set_analog_vertical_sync_end_for_odd_field_aligned_to_half_line(true) |
| .set_analog_vertical_sync_start_for_odd_field_aligned_to_half_line(true) |
| .set_analog_vertical_sync_end_for_even_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_start_for_even_field_aligned_to_half_line(false); |
| } |
| |
| // The following register field configuration matches the preferred register |
| // value provided in the Amlogic-provided code (except for the DE signal |
| // polarity, which the drivers should set by themselves for consistency with |
| // the transmitter configuration). |
| // |
| // The datasheets and the Amlogic-provided code deviate in some register field |
| // configurations: The S912 datasheet mentions that the register should be |
| // set to 0x140 for 720p, while the Amlogic-provided code use 0x4040 for all |
| // progressive outputs. |
| HdmiEncoderModeConfig& ConfigureForHighDefinitionProgressive() { |
| return set_is_output_interlaced(false) |
| .set_vertical_sync_offset_for_odd_field_enabled(false) |
| .set_vertical_active_on_for_odd_field_enabled(false) |
| .set_analog_equalizing_pulse_for_odd_field_enabled(false) |
| .set_analog_equalizing_pulse_enabled(false) |
| .set_bit7_undocumented(false) |
| .set_analog_hsync_and_equalizing_pulse_switch_in_center(true) |
| .set_analog_vertical_sync_for_odd_field_enabled(false) |
| .set_second_vertical_sync_in_a_line_enabled(false) |
| .set_analog_vertical_sync_end_for_odd_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_start_for_odd_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_end_for_even_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_start_for_even_field_aligned_to_half_line(false); |
| } |
| |
| // The following register field configuration matches the preferred register |
| // value provided in the S912 datasheet for 480p or 576p. |
| HdmiEncoderModeConfig& ConfigureForStandardDefinitionProgressive() { |
| return set_is_output_interlaced(false) |
| .set_vertical_sync_offset_for_odd_field_enabled(false) |
| .set_vertical_active_on_for_odd_field_enabled(false) |
| .set_analog_equalizing_pulse_for_odd_field_enabled(false) |
| .set_analog_equalizing_pulse_enabled(false) |
| .set_bit7_undocumented(false) |
| .set_analog_hsync_and_equalizing_pulse_switch_in_center(false) |
| .set_analog_vertical_sync_for_odd_field_enabled(false) |
| .set_second_vertical_sync_in_a_line_enabled(false) |
| .set_analog_vertical_sync_end_for_odd_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_start_for_odd_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_end_for_even_field_aligned_to_half_line(false) |
| .set_analog_vertical_sync_start_for_even_field_aligned_to_half_line(false); |
| } |
| }; |
| |
| // ENCP_VIDEO_MODE_ADV |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 382. |
| class HdmiEncoderAdvancedModeConfig |
| : public hwreg::RegisterBase<HdmiEncoderAdvancedModeConfig, uint32_t> { |
| public: |
| // Selection of the downsampling multiplier (reciprocal of the downsampling |
| // ratio) from the VIU to the VIU FIFO (VFIFO). |
| // |
| // A downsampling multiplier of N means that the VIU FIFO only takes one of |
| // every N pixels from the VIU's output. |
| enum class ViuFifoDownsamplingMultiplierSelection : uint8_t { |
| k1 = 0, |
| k2 = 1, |
| k4 = 2, |
| k8 = 3, |
| }; |
| static hwreg::RegisterAddr<HdmiEncoderAdvancedModeConfig> Get() { |
| return {0x1b8e * sizeof(uint32_t)}; |
| } |
| |
| // This field is undocumented on Amlogic datasheets. |
| // Amlogic-provided code directly writes 0 to this field regardless of its |
| // original value, so we can believe that zero is a safe setting for this |
| // field. |
| DEF_RSVDZ_FIELD(31, 16); |
| |
| DEF_FIELD(15, 14, sp_timing_control); |
| |
| DEF_BIT(13, cr_bypasses_limiter); |
| DEF_BIT(12, cb_bypasses_limiter); |
| DEF_BIT(11, y_bypasses_limiter); |
| DEF_BIT(10, gamma_rgb_input_selection); |
| |
| // This field is undocumented on Amlogic datasheets. |
| // Amlogic-provided code directly writes 0 to this field regardless of its |
| // original value, so we can believe that zero is a safe setting for this |
| // field. |
| DEF_RSVDZ_FIELD(9, 8); |
| |
| // True iff the hue adjustment matrix (controlled by ENCP_VIDEO_MATRIX_CB |
| // and ENCP_VIDEO_MATRIX_CR) is enabled. |
| DEF_BIT(7, hue_matrix_enabled); |
| |
| // Bits 6-4 are related to YPbPr (analog output) which seem to be unused |
| // for the HDMI encoder. |
| DEF_BIT(6, pb_pr_swapped); |
| DEF_BIT(5, pb_pr_hsync_enabled); |
| DEF_BIT(4, ypbpr_gain_as_hdtv_type); |
| |
| // True iff the VIU FIFO (VFIFO) which samples the VIU output pixels is |
| // enabled. |
| DEF_BIT(3, viu_fifo_enabled); |
| |
| // It's preferred to use the `viu_fifo_downsampling_multiplier()` and |
| // `set_viu_fifo_downsampling_multiplier()` helper methods. |
| DEF_ENUM_FIELD(ViuFifoDownsamplingMultiplierSelection, 2, 0, |
| viu_fifo_downsampling_multiplier_selection); |
| |
| int viu_fifo_downsampling_multiplier() const { |
| switch (viu_fifo_downsampling_multiplier_selection()) { |
| case ViuFifoDownsamplingMultiplierSelection::k1: |
| return 1; |
| case ViuFifoDownsamplingMultiplierSelection::k2: |
| return 2; |
| case ViuFifoDownsamplingMultiplierSelection::k4: |
| return 4; |
| case ViuFifoDownsamplingMultiplierSelection::k8: |
| return 8; |
| } |
| } |
| |
| // `multiplier` must be 1, 2, 4 or 8. |
| HdmiEncoderAdvancedModeConfig& set_viu_fifo_downsampling_multiplier(int multiplier) { |
| switch (multiplier) { |
| case 1: |
| return set_viu_fifo_downsampling_multiplier_selection( |
| ViuFifoDownsamplingMultiplierSelection::k1); |
| case 2: |
| return set_viu_fifo_downsampling_multiplier_selection( |
| ViuFifoDownsamplingMultiplierSelection::k2); |
| case 4: |
| return set_viu_fifo_downsampling_multiplier_selection( |
| ViuFifoDownsamplingMultiplierSelection::k4); |
| case 8: |
| return set_viu_fifo_downsampling_multiplier_selection( |
| ViuFifoDownsamplingMultiplierSelection::k8); |
| } |
| ZX_DEBUG_ASSERT_MSG(false, "Invalid downsampling multiplier: %d", multiplier); |
| return *this; |
| } |
| }; |
| |
| // ENCP_VIDEO_MAX_PXCNT (Max pixel counter) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 382. |
| class HdmiEncoderHorizontalTotal |
| : public hwreg::RegisterBase<HdmiEncoderHorizontalTotal, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderHorizontalTotal> Get() { |
| return {0x1b97 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // The horizontal period is `pixels_minus_one + 1` pixels. |
| // |
| // ENCP horizontal pixel registers must be set to values within the range |
| // [0..pixels_minus_one]. |
| // |
| // For a horizontal range of pixels [start..end]: |
| // - If start <= end, the pixels are within the same line. |
| // - If start > end, the pixels [start..pixels_minus_one] are |
| // on one line, while pixels [0..end] are rolled over to the next line. |
| // |
| // It's preferred to use `pixels()` and `set_pixels()` helper methods. |
| DEF_FIELD(12, 0, pixels_minus_one); |
| |
| int pixels() const { return static_cast<int>(pixels_minus_one()) + 1; } |
| |
| // `pixels` must be within [1, 2^13]. |
| HdmiEncoderHorizontalTotal& set_pixels(int pixels) { |
| ZX_DEBUG_ASSERT(pixels >= 1); |
| ZX_DEBUG_ASSERT(pixels <= (1 << 13)); |
| return set_pixels_minus_one(pixels - 1); |
| } |
| }; |
| |
| // The duration of the horizontal active (pixels) part of the video signal for |
| // each line. |
| // |
| // This register only configures the timing of the video signal output; |
| // the DE (data enabled) signal produced for the HDMI transmitter is |
| // controlled by the `HdmiEncoderDataEnableHorizontalActiveStart` and |
| // `HdmiEncoderDataEnableHorizontalActiveEnd` register pair. |
| |
| // ENCP_VIDEO_HAVON_BEGIN (Horizontal active video start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoHorizontalActiveStart |
| : public hwreg::RegisterBase<HdmiEncoderVideoHorizontalActiveStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoHorizontalActiveStart> Get() { |
| return {0x1ba4 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point (inclusive) of active video signals for each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_VIDEO_HAVON_END (Horizontal active video end point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoHorizontalActiveEnd |
| : public hwreg::RegisterBase<HdmiEncoderVideoHorizontalActiveEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoHorizontalActiveEnd> Get() { |
| return {0x1ba3 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // End point (inclusive) of active video signals for each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // The duration of the horizontal sync (blank) part of the video signal for |
| // each line. |
| // |
| // This register only configures the timing of the video signal output; |
| // the actual HSYNC signal produced for the HDMI transmitter is controlled by |
| // the `HdmiEncoderHorizontalSyncStart` and `HdmiEncoderHorizontalSyncEnd` |
| // register pair. |
| |
| // ENCP_VIDEO_HSO_BEGIN (Digital Hsync out start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoHorizontalSyncStart |
| : public hwreg::RegisterBase<HdmiEncoderVideoHorizontalSyncStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoHorizontalSyncStart> Get() { |
| return {0x1ba7 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point (inclusive) of the horizontal sync part of the video signal |
| // for each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_VIDEO_HSO_END (Digital Hsync out end point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoHorizontalSyncEnd |
| : public hwreg::RegisterBase<HdmiEncoderVideoHorizontalSyncEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoHorizontalSyncEnd> Get() { |
| return {0x1ba8 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // One (1) plus the end point (inclusive) of the horizontal sync part of the |
| // video signal for each line, in pixels. |
| // |
| // The register is originally named "hsync out end point", and the end point |
| // is exclusive from the range. For consistency with other register pairs, we |
| // rename the field to its current name. |
| // |
| // It's preferred to use `pixels()` and `set_pixels()` helper methods to |
| // get / set its value. |
| DEF_FIELD(12, 0, pixels_plus_one); |
| |
| int pixels() const { return static_cast<int>(pixels_plus_one()) - 1; } |
| |
| // `pixels` must be within [0, 2^13 - 1]. |
| HdmiEncoderVideoHorizontalSyncEnd& set_pixels(int pixels) { |
| ZX_DEBUG_ASSERT(pixels >= 0); |
| ZX_DEBUG_ASSERT(pixels <= (1 << 13) - 1); |
| return set_pixels_plus_one(pixels + 1); |
| } |
| }; |
| |
| // ENCP_VIDEO_MAX_LNCNT (Max line counter) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", pages 383-384. |
| class HdmiEncoderVerticalTotal : public hwreg::RegisterBase<HdmiEncoderVerticalTotal, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalTotal> Get() { return {0x1bae * sizeof(uint32_t)}; } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // In the S912 datasheet, only bits 10-0 are used. |
| // |
| // Given that the S912 SoC (and other SoCs that use the same encoder design, |
| // including S905D2, S905D3 and A311D) supports 3840 x 2160 output, bit 11 |
| // should also be supported as well. |
| // |
| // Experiments on A311D shows that the bit 11 is also supported, thus we use |
| // bits 11-0 for the field. |
| |
| // The vertical period is set to `lines_minus_one + 1` lines. |
| // |
| // ENCP vertical line registers must be set to values within the range |
| // [0..lines_minus_one]. |
| // |
| // For a vertical range of lines [start..end]: |
| // - If start <= end, the lines are within the same frame. |
| // - If start > end, the lines [start..pixels_minus_one] are |
| // on one frame, while lines [0..end] are rolled over to the next frame. |
| // |
| // It's preferred to use `lines()` and `set_lines()` methods to get / set |
| // its value. |
| DEF_FIELD(11, 0, lines_minus_one); |
| |
| int pixels() const { return static_cast<int>(lines_minus_one()) + 1; } |
| |
| // `lines` must be within [1, 2^12]. |
| HdmiEncoderVerticalTotal& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 1); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12)); |
| return set_lines_minus_one(lines - 1); |
| } |
| }; |
| |
| // The duration of the vertical active part of the video signal for each frame |
| // (for progressive output), or for each even field (for interlaced output). |
| // |
| // This register only configures the timing of the video signal output; |
| // the DE (display enabled) signal produced for the HDMI transmitter is |
| // controlled by the `HdmiEncoderDataEnableVerticalActiveStart` and |
| // `HdmiEncoderDataEnableVerticalActiveEnd` register pair. |
| |
| // ENCP_VIDEO_VAVON_BLINE (Vertical active video start line) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalActiveStart |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalActiveStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalActiveStart> Get() { |
| return {0x1ba6 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // On the S912 datasheet, only bits 10-0 are used. |
| // |
| // Given that the S912 SoC (and other SoCs that use the same encoder design, |
| // including S905D2, S905D3 and A311D) supports 3840 x 2160 output, the bit |
| // 11 should also be supported as well. |
| // |
| // Experiments on A311D shows that the bit 11 is also supported, thus we use |
| // bits 11-0 for the field. |
| |
| // Start line (inclusive) of active video signals for each field, in lines. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_VIDEO_VAVON_ELINE (Vertical active video end line) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalActiveEnd |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalActiveEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalActiveEnd> Get() { |
| return {0x1baf * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // On the S912 datasheet, only bits 10-0 are used. |
| // |
| // Given that the S912 SoC (and other SoCs that use the same encoder design, |
| // including S905D2, S905D3 and A311D) supports 3840 x 2160 output, the bit |
| // 11 should also be supported as well. |
| // |
| // Experiments on A311D shows that the bit 11 is also supported, thus we use |
| // bits 11-0 for the field. |
| |
| // End line (inclusive) of active video signals for each field, in lines. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // The duration of the vertical sync pulse in the video signal for each frame. |
| // |
| // This register only configures the timing of the video signal output; |
| // the actual VSYNC signal produced for the HDMI transmitter is controlled by |
| // the `HdmiEncoderVerticalSyncStart` and `HdmiEncoderVerticalSyncEnd` |
| // register pair. |
| |
| // ENCP_VIDEO_VSO_BLINE (Digital Vsync out start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalSyncStart |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalSyncStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalSyncStart> Get() { |
| return {0x1bab * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // Start line (inclusive) of the Vertical sync part of the video signal |
| // for each field, in lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_VIDEO_VSO_ELINE (Digital Vsync out end line) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalSyncEnd |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalSyncEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalSyncEnd> Get() { |
| return {0x1bac * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // One (1) plus the end line (inclusive) of the Vertical sync part of the |
| // video signal for each line, in pixels. |
| // |
| // The register is originally named "hsync out end point", and the end point |
| // is exclusive from the range. For consistency with other register pairs, we |
| // rename the field to its current name. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| // |
| // It's preferred to use `lines()` and `set_lines()` |
| // helper methods to get / set its value. |
| DEF_FIELD(11, 0, lines_plus_one); |
| |
| int lines() const { return static_cast<int>(lines_plus_one()) - 1; } |
| |
| // `lines` must be within [0, 2^12 - 1]. |
| HdmiEncoderVideoVerticalSyncEnd& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 0); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12) - 1); |
| return set_lines_plus_one(lines + 1); |
| } |
| }; |
| |
| // The horizontal start and end points for Vertical sync parts of the video |
| // signal for each line. |
| // |
| // The actual function of this register is unclear. Theoretically, it |
| // should not affect the output video signal, because during Vsync there should |
| // be no video signal at all regardless of the start/end horizontal points. |
| // |
| // Amlogic-provided code has multiple different configurations on this register |
| // and its corresponding `End` register. Experiment shows that start == 0 and |
| // end == 0 is a valid pair on Khadas VIM3 (using Amlogic A311D). |
| |
| // ENCP_VIDEO_VSO_BEGIN (Digital Vsync out start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalSyncHorizontalStart |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalSyncHorizontalStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalSyncHorizontalStart> Get() { |
| return {0x1ba9 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point of the horizontal part of the video signal |
| // for each Vertical sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_VIDEO_VSO_END (Digital Vsync out end point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 383. |
| class HdmiEncoderVideoVerticalSyncHorizontalEnd |
| : public hwreg::RegisterBase<HdmiEncoderVideoVerticalSyncHorizontalEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalSyncHorizontalEnd> Get() { |
| return {0x1baa * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // End point of the horizontal sync part of the video signal for each |
| // Vertical sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // The duration of the horizontal active part of the DE (data enabled) timing |
| // signal for each line. |
| // |
| // This register only configures the DE timing signal produced for the |
| // HDMI transmitter; the timing of the video signal output is controlled by the |
| // `HdmiEncoderVideoHorizontalActiveStart` and `HdmiEncoderVideoHorizontalActiveEnd` |
| // register pair. |
| |
| // ENCP_DE_H_BEGIN (DVI/HDMI horizontal active video start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableHorizontalActiveStart |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableHorizontalActiveStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableHorizontalActiveStart> Get() { |
| return {0x1c3a * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point (inclusive) of horizontal active signals for each line, in |
| // pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_DE_H_END (DVI/HDMI horizontal active video end point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableHorizontalActiveEnd |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableHorizontalActiveEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableHorizontalActiveEnd> Get() { |
| return {0x1c3b * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // One (1) plus the end point (inclusive) of horizontal active signals for |
| // each line, in pixels. |
| // |
| // It's preferred to use `pixels()` and `set_pixels()` helper methods to |
| // get / set its value. |
| DEF_FIELD(12, 0, pixels_plus_one); |
| |
| int pixels() const { return static_cast<int>(pixels_plus_one()) - 1; } |
| |
| // `pixels` must be within [0, 2^13 - 1]. |
| HdmiEncoderDataEnableHorizontalActiveEnd& set_pixels(int pixels) { |
| ZX_DEBUG_ASSERT(pixels >= 0); |
| ZX_DEBUG_ASSERT(pixels <= (1 << 13) - 1); |
| return set_pixels_plus_one(pixels + 1); |
| } |
| }; |
| |
| // The duration of the horizontal sync part of the HSYNC timing signal for each |
| // line. |
| // |
| // This register only configures the HSYNC timing signal produced for the |
| // HDMI transmitter; the timing of the video signal output is controlled by the |
| // `HdmiEncoderVideoHorizontalSyncStart` and `HdmiEncoderVideoHorizontalSyncEnd` |
| // register pair. |
| |
| // ENCP_DVI_HSO_BEGIN (DVI/HDMI Hsync out start point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 391. |
| class HdmiEncoderHorizontalSyncStart |
| : public hwreg::RegisterBase<HdmiEncoderHorizontalSyncStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderHorizontalSyncStart> Get() { |
| return {0x1c30 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point (inclusive) of the horizontal sync signal for each line, in |
| // pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_VIDEO_HSO_END (Digital Hsync out end point) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 391. |
| class HdmiEncoderHorizontalSyncEnd |
| : public hwreg::RegisterBase<HdmiEncoderHorizontalSyncEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderHorizontalSyncEnd> Get() { |
| return {0x1c31 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // One (1) plus the end point (inclusive) of the horizontal sync signal for |
| // each line, in pixels. |
| // |
| // It's preferred to use `pixels()` and `set_pixels()` helper methods to |
| // get / set its value. |
| DEF_FIELD(12, 0, pixels_plus_one); |
| |
| int pixels() const { return static_cast<int>(pixels_plus_one()) - 1; } |
| |
| // `pixels` must be within [0, 2^13 - 1]. |
| HdmiEncoderHorizontalSyncEnd& set_pixels(int pixels) { |
| ZX_DEBUG_ASSERT(pixels >= 0); |
| ZX_DEBUG_ASSERT(pixels <= (1 << 13) - 1); |
| return set_pixels_plus_one(pixels + 1); |
| } |
| }; |
| |
| // The duration of the vertical active part of the DE (data enabled) timing |
| // signal for each field (progressive) or for each even field (interlaced). |
| // |
| // This register only configures the DE timing signal produced for the |
| // HDMI transmitter; the timing of the video signal output is controlled by the |
| // `HdmiEncoderVideoVerticalActiveStart` and `HdmiEncoderVideoVerticalActiveEnd` |
| // register pair. |
| |
| // ENCP_DE_V_BEGIN_EVEN (DVI/HDMI vertical active video start line for even |
| // field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableVerticalActiveStart |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableVerticalActiveStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableVerticalActiveStart> Get() { |
| return {0x1c3c * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // Start line (inclusive) of vertical active signals for each field, in |
| // lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_DE_V_END_EVEN (DVI/HDMI vertical active video end line for even field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableVerticalActiveEnd |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableVerticalActiveEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableVerticalActiveEnd> Get() { |
| return {0x1c3d * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // One (1) plus the end line (inclusive) of vertical active signals for each |
| // field, in lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| // |
| // It's preferred to use `lines()` and `set_lines()` helper methods to |
| // get / set its value. |
| DEF_FIELD(11, 0, lines_plus_one); |
| |
| int lines() const { return static_cast<int>(lines_plus_one()) - 1; } |
| |
| // `vertical_active_end_line` must be within [0, 2^12 - 1]. |
| HdmiEncoderDataEnableVerticalActiveEnd& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 0); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12) - 1); |
| return set_lines_plus_one(lines + 1); |
| } |
| }; |
| |
| // The duration of the vertical active (pixels) part of the DE (data enabled) |
| // timing signal for each odd field. Used for interlaced output only. |
| |
| // ENCP_DE_V_BEGIN_ODD (DVI/HDMI vertical active video start line for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableVerticalActiveStartOddFields |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableVerticalActiveStartOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableVerticalActiveStartOddFields> Get() { |
| return {0x1c3e * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // Start line (inclusive) of vertical active signals for each field, in |
| // lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_DE_V_END_ODD (DVI/HDMI vertical active video end line for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderDataEnableVerticalActiveEndOddFields |
| : public hwreg::RegisterBase<HdmiEncoderDataEnableVerticalActiveEndOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderDataEnableVerticalActiveEndOddFields> Get() { |
| return {0x1c3f * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // One (1) plus the end line (inclusive) of vertical active signals for each |
| // field, in lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| // |
| // It's preferred to use `lines()` and `set_lines()` helper methods to |
| // get / set its value. |
| DEF_FIELD(11, 0, lines_plus_one); |
| |
| int lines() const { return static_cast<int>(lines_plus_one()) - 1; } |
| |
| // `lines` must be within [0, 2^12 - 1]. |
| HdmiEncoderDataEnableVerticalActiveEndOddFields& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 0); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12) - 1); |
| return set_lines_plus_one(lines + 1); |
| } |
| }; |
| |
| // The duration of the vertical sync part of the VSYNC timing signal for each |
| // field (progressive) or each even field (interlaced). |
| // |
| // This register only configures the VSYNC timing signal produced for the |
| // HDMI transmitter; the timing of the video signal output is controlled by the |
| // `HdmiEncoderVideoVerticalSyncStart` and `HdmiEncoderVideoVerticalSyncEnd` |
| // register pair. |
| |
| // ENCP_DVI_VSO_BLINE_EVEN (DVI/HDMI Vsync out start line for even field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 391. |
| class HdmiEncoderVerticalSyncStart |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncStart> Get() { |
| return {0x1c32 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // Start line (inclusive) of the vertical sync signal for each field, in |
| // lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_VIDEO_VSO_ELINE_EVEN (Digital Vsync out end line for even field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderVerticalSyncEnd |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncEnd> Get() { |
| return {0x1c34 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // One (1) plus the end line (inclusive) of the vertical sync signal for each |
| // field, in lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| // |
| // It's preferred to use `lines()` and `set_lines()` helper methods to |
| // get / set its value. |
| DEF_FIELD(11, 0, lines_plus_one); |
| |
| int lines() const { return static_cast<int>(lines_plus_one()) - 1; } |
| |
| // `lines` must be within [0, 2^12 - 1]. |
| HdmiEncoderVerticalSyncEnd& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 0); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12) - 1); |
| return set_lines_plus_one(lines + 1); |
| } |
| }; |
| |
| // The duration of the vertical sync part of the VSYNC timing signal for each |
| // odd field. Used for interlaced output only. |
| |
| // ENCP_DVI_VSO_BLINE_ODD (DVI/HDMI Vsync out start line for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderVerticalSyncStartOddFields |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncStartOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncStartOddFields> Get() { |
| return {0x1c33 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // Start line (inclusive) of the vertical sync signal for each field, in |
| // lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| DEF_FIELD(11, 0, lines); |
| }; |
| |
| // ENCP_VIDEO_VSO_ELINE_ODD (Digital Vsync out end line for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 392. |
| class HdmiEncoderVerticalSyncEndOddFields |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncEndOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncEndOddFields> Get() { |
| return {0x1c35 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-12 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 12); |
| |
| // One (1) plus the end line (inclusive) of the vertical sync signal for each |
| // field, in lines. |
| // |
| // S912 datasheet only specifies bits 10-0 are used for this field. However, |
| // experiments confirm that bit 11 is functional on S912 and SoCs with similar |
| // encoder designs (S905D2, S905D3, A311D) due to their support for the |
| // 3840x2160 resolution. Therefore, this code utilizes bits 11-0 for the |
| // field. |
| // |
| // It's preferred to use `lines()` and `set_lines()` helper methods to |
| // get / set its value. |
| DEF_FIELD(11, 0, lines_plus_one); |
| |
| int lines() const { return static_cast<int>(lines_plus_one()) - 1; } |
| |
| // `lines` must be within [0, 2^12 - 1]. |
| HdmiEncoderVerticalSyncEndOddFields& set_lines(int lines) { |
| ZX_DEBUG_ASSERT(lines >= 0); |
| ZX_DEBUG_ASSERT(lines <= (1 << 12) - 1); |
| return set_lines_plus_one(lines + 1); |
| } |
| }; |
| |
| // The horizontal duration (start and end points) for Vertical sync parts of |
| // the VSYNC signal on each line, for each field (progressive) or for each even |
| // field (interlaced). |
| // |
| // The actual function of this register is unclear. Theoretically, it |
| // should not affect the output VSYNC signal, because during Vsync the vsync |
| // signal should be high throughout the line. |
| // |
| // Amlogic-provided code always set both start and end points to the Hsync |
| // offset. Experiments on Khadas VIM3 (Amlogic A311D) show that this |
| // configuration works. |
| |
| // ENCP_DVI_VSO_BEGIN_EVN (DVI/HDMI Interface VSO start position for even field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 389. |
| class HdmiEncoderVerticalSyncHorizontalStart |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncHorizontalStart, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncHorizontalStart> Get() { |
| return {0x1c36 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point of the horizontal part of the VSYNC signal for each Vertical |
| // sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_DVI_VSO_END_EVN (DVI/HDMI Interface VSO end position for even field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 389. |
| class HdmiEncoderVerticalSyncHorizontalEnd |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncHorizontalEnd, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVideoVerticalSyncHorizontalEnd> Get() { |
| return {0x1c38 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // End point of the horizontal sync part of the VSYNC signal for each |
| // Vertical sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // The horizontal start and end points for Vertical sync parts of the VSYNC |
| // signal on each line for each odd field. Used for interlaced output only. |
| // |
| // The actual function of this register is unclear. Theoretically, it |
| // should not affect the output VSYNC signal, because during Vsync the vsync |
| // signal should be high throughout the line. |
| // |
| // Amlogic-provided code always set both start and end points to the Hsync |
| // offset. |
| |
| // ENCP_DVI_VSO_BEGIN_ODD (DVI/HDMI Interface VSO start position for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 389. |
| class HdmiEncoderVerticalSyncHorizontalStartOddFields |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncHorizontalStartOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncHorizontalStartOddFields> Get() { |
| return {0x1c07 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // Start point of the horizontal part of the VSYNC signal for each Vertical |
| // sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // ENCP_DVI_VSO_END_ODD (DVI/HDMI Interface VSO end position for odd field) |
| // |
| // S912 Datasheet, Section 27.5 "CVBS and LCD", page 389. |
| class HdmiEncoderVerticalSyncHorizontalEndOddFields |
| : public hwreg::RegisterBase<HdmiEncoderVerticalSyncHorizontalEndOddFields, uint32_t> { |
| public: |
| static hwreg::RegisterAddr<HdmiEncoderVerticalSyncHorizontalEndOddFields> Get() { |
| return {0x1c09 * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-13 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 13); |
| |
| // End point of the horizontal sync part of the VSYNC signal for each |
| // Vertical sync pulse on each line, in pixels. |
| DEF_FIELD(12, 0, pixels); |
| }; |
| |
| // VPU_HDMI_SETTING |
| // |
| // S905D2 Datasheet, Section 7.2.3.1 "VPU Registers", pages 313-314. |
| // A311D Datasheet, Section 10.2.3.1 "VPU Registers", pages 668-669. |
| // S905D3 Datasheet, Section 9.2.3.1 "VPU Registers", pages 260-261. |
| class HdmiEncoderTransmitterBridgeSetting |
| : public hwreg::RegisterBase<HdmiEncoderTransmitterBridgeSetting, uint32_t> { |
| public: |
| enum class SourceEncoderSelection : uint8_t { |
| // No encoder is selected. The bridge is disabled. |
| kNone = 0b00, |
| // ENCI (Interlaced encoder) |
| kInterlaced = 0b01, |
| // ENCP (Progressive encoder) |
| kProgressive = 0b10, |
| }; |
| |
| // The reordered color components for output, assuming the input color |
| // components are in the (component0, component1, component2) order. |
| enum class ColorComponentMappingFrom012 : uint8_t { |
| // Outputs (component0, component1, component2). |
| kTo012 = 0, |
| // Outputs (component1, component2, component0). |
| kTo120 = 1, |
| // Outputs (component1, component0, component2). |
| kTo102 = 2, |
| // Outputs (component2, component0, component1). |
| kTo201 = 3, |
| // Outputs (component2, component1, component0). |
| kTo210 = 4, |
| // Outputs (component0, component2, component1). |
| kTo021 = 5, |
| }; |
| |
| static hwreg::RegisterAddr<HdmiEncoderTransmitterBridgeSetting> Get() { |
| return {0x271b * sizeof(uint32_t)}; |
| } |
| |
| // Bits 31-16 are not documented in the datasheet. |
| // We model these bits as reserved must be zero because Amlogic-provided code |
| // unconditionally sets them to zero. |
| DEF_RSVDZ_FIELD(31, 16); |
| |
| // While setting the FIFO read / write downsampling multipliers, drivers |
| // must guarantee that the FIFO read sample rate equals to the FIFO write |
| // sample rate, i.e. |
| // (Encoder pixel rate) / fifo_read_downsampling_multiplier() |
| // = (Transmitter pixel rate) / fifo_write_downsampling_multiplier() |
| |
| // Downsampling multiplier (reciprocal of the downsampling ratio) of the |
| // Encoder-Transmitter FIFO reading pixel data from the encoder, minus one. |
| // |
| // A downsampling multiplier of N means that the FIFO performs a read |
| // operation once every N cycles of the "read clock" (rd_clk), which is |
| // possibly the encoder clock. |
| // |
| // It's preferred to use the `fifo_read_downsampling_multiplier()` and |
| // `set_fifo_read_downsampling_multiplier()` helper methods to get / set its |
| // value. |
| DEF_FIELD(15, 12, fifo_read_downsampling_multiplier_minus_one); |
| |
| // Downsampling multiplier (reciprocal of the downsampling ratio) of the |
| // Encoder-Transmitter FIFO writing pixel data to the transmitter, minus one. |
| // |
| // A downsampling multiplier of N means that the FIFO performs a write |
| // operation once every N cycles of the "write clock" (wr_clk), which is |
| // possibly the HDMI transmitter pixel clock. |
| // |
| // It's preferred to use the `fifo_write_downsampling_multiplier()` and |
| // `set_fifo_write_downsampling_multiplier()` helper methods to get / set its |
| // value. |
| DEF_FIELD(11, 8, fifo_write_downsampling_multiplier_minus_one); |
| |
| // Sets the ordering of color components reordered by the encoder-transmitter |
| // bridge for the transmitter to read. |
| DEF_ENUM_FIELD(ColorComponentMappingFrom012, 7, 5, color_component_mapping); |
| |
| // If true, the polarity of the clock output to the external DVI interface |
| // (not the internal HDMI interface) is positive (active high). |
| // |
| // None of the Amlogic SoCs we use (S905D2, A311D and S905D3) support |
| // external DVI interfaces. Amlogic-provided code always sets this bit to 0. |
| // |
| // It's preferred to use `dvi_clock_polarity()` and `set_dvi_clock_polarity()` |
| // helper methods to get / set its value. |
| DEF_BIT(4, is_dvi_clock_polarity_positive); |
| |
| // If true, the polarity of the VSYNC signal the bridge outputs is positive |
| // (active high). |
| // |
| // It's preferred to use `vsync_polarity()` and `set_vsync_polarity()` helper |
| // methods to get / set its value. |
| DEF_BIT(3, is_vsync_polarity_positive); |
| |
| // If true, the polarity of the HSYNC signal the bridge outputs is positive |
| // (active high). |
| // |
| // It's preferred to use `hsync_polarity()` and `set_hsync_polarity()` helper |
| // methods to get / set its value. |
| DEF_BIT(2, is_hsync_polarity_positive); |
| |
| DEF_ENUM_FIELD(SourceEncoderSelection, 1, 0, source_encoder_selection); |
| |
| int fifo_read_downsampling_multiplier() const { |
| return static_cast<int>(fifo_read_downsampling_multiplier_minus_one()) + 1; |
| } |
| |
| // `multiplier` must be a valid integer in [1, 16]. |
| HdmiEncoderTransmitterBridgeSetting& set_fifo_read_downsampling_multiplier(int multiplier) { |
| ZX_DEBUG_ASSERT(multiplier >= 1); |
| ZX_DEBUG_ASSERT(multiplier <= 16); |
| return set_fifo_read_downsampling_multiplier_minus_one(multiplier - 1); |
| } |
| |
| int fifo_write_downsampling_multiplier() const { |
| return static_cast<int>(fifo_write_downsampling_multiplier_minus_one()) + 1; |
| } |
| |
| // `multiplier` must be a valid integer in [1, 16]. |
| HdmiEncoderTransmitterBridgeSetting& set_fifo_write_downsampling_multiplier(int multiplier) { |
| ZX_DEBUG_ASSERT(multiplier >= 1); |
| ZX_DEBUG_ASSERT(multiplier <= 16); |
| return set_fifo_write_downsampling_multiplier_minus_one(multiplier - 1); |
| } |
| |
| display::SyncPolarity dvi_clock_polarity() const { |
| return is_dvi_clock_polarity_positive() ? display::SyncPolarity::kPositive |
| : display::SyncPolarity::kNegative; |
| } |
| |
| HdmiEncoderTransmitterBridgeSetting& set_dvi_clock_polarity(display::SyncPolarity polarity) { |
| return set_is_dvi_clock_polarity_positive(polarity == display::SyncPolarity::kPositive); |
| } |
| |
| display::SyncPolarity vsync_polarity() const { |
| return is_vsync_polarity_positive() ? display::SyncPolarity::kPositive |
| : display::SyncPolarity::kNegative; |
| } |
| |
| HdmiEncoderTransmitterBridgeSetting& set_vsync_polarity(display::SyncPolarity polarity) { |
| return set_is_vsync_polarity_positive(polarity == display::SyncPolarity::kPositive); |
| } |
| |
| display::SyncPolarity hsync_polarity() const { |
| return is_hsync_polarity_positive() ? display::SyncPolarity::kPositive |
| : display::SyncPolarity::kNegative; |
| } |
| |
| HdmiEncoderTransmitterBridgeSetting& set_hsync_polarity(display::SyncPolarity polarity) { |
| return set_is_hsync_polarity_positive(polarity == display::SyncPolarity::kPositive); |
| } |
| }; |
| |
| // VPU_HDMI_DITH_CNTL (10-bit to 8-bit dither control register) |
| // |
| // S905D2 Datasheet, Section 7.2.3.1 "VPU Registers", page 335. |
| // A311D Datasheet, Section 10.2.3.1 "VPU Registers", pages 687-688. |
| // S905D3 Datasheet, Section 9.2.3.1 "VPU Registers", page 280. |
| class HdmiEncoderTransmitterBridge10BitTo8BitDitheringControl |
| : public hwreg::RegisterBase<HdmiEncoderTransmitterBridge10BitTo8BitDitheringControl, |
| uint32_t> { |
| public: |
| static auto Get() { |
| return hwreg::RegisterAddr<HdmiEncoderTransmitterBridge10BitTo8BitDitheringControl>( |
| 0x27fc * sizeof(uint32_t)); |
| } |
| |
| // Bits 21-5 and Bit 0 are documented in the Amlogic datasheets; these bits |
| // are not documented in this driver yet because the current driver |
| // implementation does not support dithering. |
| // TODO(https://fxbug.dev/319165154): Document the configuration bits and |
| // related registers. |
| |
| // If true, the 10-bit to 8-bit dithering is enabled. |
| DEF_BIT(4, enabled); |
| |
| // If true, the polarity of the VSYNC signal the dithering module outputs is |
| // inverted from the encoder's output. |
| DEF_BIT(3, vsync_polarity_inverted); |
| |
| // If true, the polarity of the VSYNC signal the dithering module outputs is |
| // inverted from the encoder's output. |
| DEF_BIT(2, hsync_polarity_inverted); |
| }; |
| |
| // VPU_HDMI_FMT_CTRL (12-bit to 10-bit dither control register) |
| // |
| // S905D2 Datasheet, Section 7.2.3.1 "VPU Registers", pages 318-319. |
| // A311D Datasheet, Section 10.2.3.1 "VPU Registers", pages 673-674. |
| // S905D3 Datasheet, Section 9.2.3.1 "VPU Registers", pages 265-266. |
| class HdmiEncoderTransmitterBridge12BitTo10BitDitheringControl |
| : public hwreg::RegisterBase<HdmiEncoderTransmitterBridge12BitTo10BitDitheringControl, |
| uint32_t> { |
| public: |
| static auto Get() { |
| return hwreg::RegisterAddr<HdmiEncoderTransmitterBridge12BitTo10BitDitheringControl>( |
| 0x2743 * sizeof(uint32_t)); |
| } |
| |
| // Bits 21-11, bits 9-5 and bits 3-0 are documented in the Amlogic datasheets; |
| // These bits are not documented in this driver yet because the current |
| // driver implementation doesn't support dithering. |
| // TODO(https://fxbug.dev/319165154): Document the configuration bits and |
| // related registers. |
| |
| // If true, the 12-bit colors are rounded down to 10-bit colors. |
| // |
| // `rounding_enabled` and `dithering_enabled` must not be both true. |
| DEF_BIT(10, rounding_enabled); |
| |
| // If true, the 12-bit to 10-bit dithering is enabled. |
| // |
| // `rounding_enabled` and `dithering_enabled` must not be both true. |
| // |
| // This bit is documented as "dither 10-b to 8-b enable" in Amlogic |
| // datasheets, which is a typo per the Amlogic-provided code. |
| DEF_BIT(4, dithering_enabled); |
| }; |
| |
| } // namespace amlogic_display |
| |
| #endif // SRC_GRAPHICS_DISPLAY_DRIVERS_AMLOGIC_DISPLAY_ENCODER_REGS_H_ |