This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: edid-decode: add more details to the AMD VSDB Author: Julian Orth <[email protected]> Date: Thu Nov 20 16:17:44 2025 +0100 These values have been determined through reverse engineering and might be inaccurate. Signed-off-by: Julian Orth <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> utils/edid-decode/parse-cta-block.cpp | 183 +++++++++++++++++++++++++--------- 1 file changed, 137 insertions(+), 46 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=07632801b9d39d4fdb41a3346e74f88b16519fa2 diff --git a/utils/edid-decode/parse-cta-block.cpp b/utils/edid-decode/parse-cta-block.cpp index 3783a32e9e7e..ecf32b9fbe48 100644 --- a/utils/edid-decode/parse-cta-block.cpp +++ b/utils/edid-decode/parse-cta-block.cpp @@ -1576,60 +1576,151 @@ static void cta_hf_sbtmdb(const unsigned char *x, unsigned length) static void cta_amd(const unsigned char *x, unsigned length) { - // These Freesync values are reversed engineered by looking - // at existing EDIDs. - printf(" Version: %u\n", x[0]); + // x[00] - major version + // x[01] & 0x01 - unknown, set in almost all EDIDs + // x[01] & 0x02 - set if x[05..=09] are valid + // x[01] & 0x04 - global backlight control support + // x[01] & 0x08 - local dimming support + // x[01] & 0x10 - FreeSync Panel Replay/PSR switch support + // x[01] & 0x20 - called the SPRS bit by AMD, related to Replay + // x[01] & 0x40 - FreeSync Panel Replay support + // x[01] & 0x80 - set if x[12..=14] are valid + // x[02] - min refresh rate + // x[03] - max refresh rate in versions < 3 + // x[04] - MCCS flags + // -- start of version 2 fields + // x[05] & 0x01 - unknown + // x[05] & 0x02 - unknown + // x[05] & 0x04 - PQ EOTF support + // x[05] & 0x08 - unknown + // x[05] & 0x10 - PQ-Interim EOTF support (unknown what that is but enumerated in ADL) + // x[05] & 0x20 - unknown but see the calculation of supported_tf below + // x[05] & 0xc0 - set to 1 if the display is Mini LED + // set to 2 if the display is OLED + // x[06] - max luminance + // x[07] - min luminance + // x[08] - if x[01] & 0x08 or display is OLED: max luminance without local dimming + // else if x[01] & 0x04 : max luminance at min backlight + // x[09] - if x[01] & 0x08 or display is OLED: min luminance without local dimming + // else if x[01] & 0x04 : min luminance at min backlight + // -- start of version 3 fields + // x[10] - max refresh rate lower 8 bits in version >= 3 + // x[11] & 0x03 - max refresh rate upper 2 bits in version >= 3 + // x[11] & 0xfc - unused + // -- end of version 3 mandatory fields, fields below will be parsed only if the VSDB + // block is large enough + // x[12] - unknown + // x[13] - unknown + // x[14] - unknown + // x[15] & 0x80 - x[15] & 0x7f is valid + // x[15] & 0x7f - unknown + // x[16] & 0x80 - x[16] & 0x7f is valid + // x[16] & 0x7f - DPCD (DisplayPort configuration data) register offset for + // proprietary AMD settings + + if (length < 5) { + printf(" Data block is truncated (length = %d)\n", length); + return; + } + + unsigned version = x[0]; + printf(" Version: %u\n", version); - // Obtained from: - // https://github.com/torvalds/linux/commit/ec8e59cb4e0c1a52d5a541fff9dcec398b48f7b4 printf(" Feature Caps: 0x%02x\n", x[1]); - if (x[1] & 0x40) - printf(" Replay Supported\n"); - + bool hdr_fields_valid = false; + bool supports_local_dimming = false; + bool has_global_backlight_control = false; + if (version > 1) { + hdr_fields_valid = x[1] & 0x02; + has_global_backlight_control = x[1] & 0x04; + supports_local_dimming = x[1] & 0x08; + if (has_global_backlight_control) + printf(" Global Backlight Control Supported\n"); + if (supports_local_dimming) + printf(" Local Dimming Supported\n"); + if (version > 2) { + // Obtained from: + // https://github.com/torvalds/linux/commit/ec8e59cb4e0c1a52d5a541fff9dcec398b48f7b4 + if (x[1] & 0x40) + printf(" FreeSync Panel Replay Supported\n"); + } + } + + unsigned short max_refresh_rate; + if (version > 2 && length > 0xb) { + max_refresh_rate = (x[0xb] & 3) << 8 | x[0xa]; + } else { + max_refresh_rate = x[3]; + } printf(" Minimum Refresh Rate: %u Hz\n", x[2]); - printf(" Maximum Refresh Rate: %u Hz\n", x[3]); + printf(" Maximum Refresh Rate: %u Hz\n", max_refresh_rate); // Freesync 1.x flags // One or more of the 0xe6 bits signal that the VESA MCCS // protocol is used to switch the Freesync range printf(" Flags 1.x: 0x%02x%s\n", x[4], (x[4] & 0xe6) ? " (MCCS)" : ""); - if (length >= 10) { - // Freesync 2.x flags - // Bit 2 no doubt indicates if the monitor supports Local Dimming - // There are probably also bits to signal support of the - // FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes. - // I suspect bits 0 and 1. - printf(" Flags 2.x: 0x%02x\n", x[5]); - // The AMD tone mapping tutorial referred to in the URL below - // mentions that the Freesync HDR info reports max/min - // luminance of the monitor with and without local dimming. - // - // https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/ - // - // So I assume that the first two luminance values are - // the max/min luminance of the display and the next two - // luminance values are the max/min luminance values when - // local dimming is disabled. The values I get seem to - // support that. - printf(" Maximum luminance: %u (%.3f cd/m^2)\n", - x[6], 50.0 * pow(2, x[6] / 32.0)); - printf(" Minimum luminance: %u (%.3f cd/m^2)\n", - x[7], (50.0 * pow(2, x[6] / 32.0)) * pow(x[7] / 255.0, 2) / 100.0); - if (x[5] & 4) { - // One or both bytes can be 0. The meaning of that - // is unknown. - printf(" Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n", - x[8], 50.0 * pow(2, x[8] / 32.0)); - printf(" Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n", - x[9], (50.0 * pow(2, x[8] / 32.0)) * pow(x[9] / 255.0, 2) / 100.0); - } else { - // These bytes are always 0x08 0x2f. If these values - // represent max/min luminance as well, then these - // would map to 59.460 and 0.020 cd/m^2 respectively. - // I wonder if this somehow relates to SDR. - printf(" Unknown: 0x%02x 0x%02x\n", x[8], x[9]); - } - } + + if (version < 2) + return; + if (length < 10) { + printf(" Data block is truncated (length = %d)\n", length); + return; + } + + printf(" Flags 2.x: 0x%02x\n", x[5]); + + if (!hdr_fields_valid) + return; + + const unsigned TF_PQ2084 = 0x0004; + const unsigned TF_LINEAR_0_125 = 0x0020; + const unsigned TF_GAMMA_22 = 0x0080; + + const unsigned CS_BT2020 = 0x0008; + + // the calculation of supported_tf is a bit weird because it doesn't correspond to + // the description in the comment at the start of the function. but this is what ADL + // (AMD Display Library) reports + unsigned supported_tf = 0; + unsigned supported_cs = 0; + bool supports_hdr10 = x[5] & 0x34; + if (supports_hdr10) { + supported_tf |= TF_LINEAR_0_125 | TF_PQ2084; + supported_cs |= CS_BT2020; + } + if (x[5] & 0x04) + supported_tf |= TF_GAMMA_22; + + if (supported_tf & TF_PQ2084) + printf(" ST 2084 (PQ) EOTF Supported\n"); + if (supported_tf & TF_LINEAR_0_125) + printf(" Linear EOTF (Windows scRGB, 0.0 - 125.0) Supported\n"); + if (supported_tf & TF_GAMMA_22) + printf(" Gamma 2.2 EOTF Supported\n"); + + if (supported_cs & CS_BT2020) + printf(" BT.2020 Gamut Supported\n"); + + bool is_mini_led = x[5] >> 5 == 1; + bool is_oled = x[5] >> 5 == 2; + if (is_mini_led) + printf(" Display is Mini LED\n"); + if (is_oled) + printf(" Display is OLED\n"); + + printf(" Maximum luminance: %u (%.3f cd/m^2)\n", + x[6], 50.0 * pow(2, x[6] / 32.0)); + printf(" Minimum luminance: %u (%.3f cd/m^2)\n", + x[7], (50.0 * pow(2, x[6] / 32.0)) * pow(x[7] / 255.0, 2) / 100.0); + if (supports_local_dimming || is_oled || has_global_backlight_control) { + const char *type = "minimum backlight"; + if (supports_local_dimming || is_oled) + type = "without local dimming"; + printf(" Maximum luminance (%s): %u (%.3f cd/m^2)\n", + type, x[8], 50.0 * pow(2, x[8] / 32.0)); + printf(" Minimum luminance (%s): %u (%.3f cd/m^2)\n", + type, x[9], (50.0 * pow(2, x[8] / 32.0)) * pow(x[9] / 255.0, 2) / 100.0); + } } static std::string display_use_case(unsigned char x) _______________________________________________ linuxtv-commits mailing list -- [email protected] To unsubscribe send an email to [email protected]
