diff --git a/di-edid-decode.c b/di-edid-decode.c index feaf292..cc1db3d 100644 --- a/di-edid-decode.c +++ b/di-edid-decode.c @@ -341,6 +341,24 @@ display_range_limits_type_name(enum di_edid_display_range_limits_type type) abort(); } +static const char * +cvt_aspect_ratio_name(enum di_edid_cvt_aspect_ratio aspect_ratio) +{ + switch (aspect_ratio) { + case DI_EDID_CVT_ASPECT_RATIO_4_3: + return "4:3"; + case DI_EDID_CVT_ASPECT_RATIO_16_9: + return "16:9"; + case DI_EDID_CVT_ASPECT_RATIO_16_10: + return "16:10"; + case DI_EDID_CVT_ASPECT_RATIO_5_4: + return "5:4"; + case DI_EDID_CVT_ASPECT_RATIO_15_9: + return "15:9"; + } + abort(); +} + static void print_display_desc(const struct di_edid *edid, const struct di_edid_display_descriptor *desc) @@ -397,6 +415,51 @@ print_display_desc(const struct di_edid *edid, printf(" K: %u\n", (int) range_limits->secondary_gtf->k); printf(" J: %.1f%%\n", range_limits->secondary_gtf->j); break; + case DI_EDID_DISPLAY_RANGE_LIMITS_CVT: + printf(" CVT version %d.%d\n", + range_limits->cvt->version, + range_limits->cvt->revision); + + if (range_limits->cvt->max_horiz_px != 0) + printf(" Max active pixels per line: %d\n", + range_limits->cvt->max_horiz_px); + + printf(" Supported aspect ratios:"); + if (range_limits->cvt->supported_aspect_ratio & DI_EDID_CVT_ASPECT_RATIO_4_3) + printf(" 4:3"); + if (range_limits->cvt->supported_aspect_ratio & DI_EDID_CVT_ASPECT_RATIO_16_9) + printf(" 16:9"); + if (range_limits->cvt->supported_aspect_ratio & DI_EDID_CVT_ASPECT_RATIO_16_10) + printf(" 16:10"); + if (range_limits->cvt->supported_aspect_ratio & DI_EDID_CVT_ASPECT_RATIO_5_4) + printf(" 5:4"); + if (range_limits->cvt->supported_aspect_ratio & DI_EDID_CVT_ASPECT_RATIO_15_9) + printf(" 15:9"); + printf("\n"); + + printf(" Preferred aspect ratio: %s\n", + cvt_aspect_ratio_name(range_limits->cvt->preferred_aspect_ratio)); + + if (range_limits->cvt->standard_blanking) + printf(" Supports CVT standard blanking\n"); + if (range_limits->cvt->reduced_blanking) + printf(" Supports CVT reduced blanking\n"); + + if (range_limits->cvt->supported_scaling != 0) { + printf(" Supported display scaling:\n"); + if (range_limits->cvt->supported_scaling & DI_EDID_CVT_SCALING_HORIZ_SHRINK) + printf(" Horizontal shrink\n"); + if (range_limits->cvt->supported_scaling & DI_EDID_CVT_SCALING_HORIZ_STRETCH) + printf(" Horizontal stretch\n"); + if (range_limits->cvt->supported_scaling & DI_EDID_CVT_SCALING_VERT_SHRINK) + printf(" Vertical shrink\n"); + if (range_limits->cvt->supported_scaling & DI_EDID_CVT_SCALING_VERT_STRETCH) + printf(" Vertical stretch\n"); + } + + printf(" Preferred vertical refresh: %d Hz\n", + range_limits->cvt->preferred_vert_refresh_hz); + break; default: break; } diff --git a/edid.c b/edid.c index b45f4e8..95121b6 100644 --- a/edid.c +++ b/edid.c @@ -496,12 +496,13 @@ parse_display_range_limits(struct di_edid *edid, struct di_edid_display_range_limits_priv *priv) { uint8_t offset_flags, vert_offset_flags, horiz_offset_flags; - uint8_t support_flags; + uint8_t support_flags, preferred_aspect_ratio; int max_vert_offset = 0, min_vert_offset = 0; int max_horiz_offset = 0, min_horiz_offset = 0; size_t i; struct di_edid_display_range_limits *base; struct di_edid_display_range_limits_secondary_gtf *secondary_gtf; + struct di_edid_display_range_limits_cvt *cvt; base = &priv->base; @@ -633,7 +634,64 @@ parse_display_range_limits(struct di_edid *edid, base->secondary_gtf = secondary_gtf; break; case DI_EDID_DISPLAY_RANGE_LIMITS_CVT: - /* TODO: parse video timing data in bytes 11 to 17 */ + cvt = &priv->cvt; + + cvt->version = get_bit_range(data[11], 7, 4); + cvt->revision = get_bit_range(data[11], 3, 0); + + base->max_pixel_clock_hz -= get_bit_range(data[12], 7, 2) * 250 * 1000; + cvt->max_horiz_px = 8 * ((get_bit_range(data[12], 1, 0) << 8) | data[13]); + + cvt->supported_aspect_ratio = data[14]; + if (get_bit_range(data[14], 2, 0) != 0) + add_failure_until(edid, 4, + "Display Range Limits: Reserved bits of byte 14 are non-zero."); + + preferred_aspect_ratio = get_bit_range(data[15], 7, 5); + switch (preferred_aspect_ratio) { + case 0: + cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_4_3; + break; + case 1: + cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_16_9; + break; + case 2: + cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_16_10; + break; + case 3: + cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_5_4; + break; + case 4: + cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_15_9; + break; + default: + /* Reserved */ + add_failure_until(edid, 4, + "Display Range Limits: Invalid preferred aspect ratio 0x%02x.", + preferred_aspect_ratio); + return false; + } + + cvt->standard_blanking = has_bit(data[15], 3); + cvt->reduced_blanking = has_bit(data[15], 4); + + if (get_bit_range(data[15], 2, 0) != 0) + add_failure_until(edid, 4, + "Display Range Limits: Reserved bits of byte 15 are non-zero."); + + cvt->supported_scaling = data[16]; + if (get_bit_range(data[16], 3, 0) != 0) + add_failure_until(edid, 4, + "Display Range Limits: Reserved bits of byte 16 are non-zero."); + + cvt->preferred_vert_refresh_hz = data[17]; + if (cvt->preferred_vert_refresh_hz == 0) { + add_failure_until(edid, 4, + "Display Range Limits: Preferred vertical refresh rate must be specified."); + return false; + } + + base->cvt = cvt; break; case DI_EDID_DISPLAY_RANGE_LIMITS_BARE: case DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF: diff --git a/include/edid.h b/include/edid.h index b70dcb9..230e3b6 100644 --- a/include/edid.h +++ b/include/edid.h @@ -84,6 +84,7 @@ struct di_edid { struct di_edid_display_range_limits_priv { struct di_edid_display_range_limits base; struct di_edid_display_range_limits_secondary_gtf secondary_gtf; + struct di_edid_display_range_limits_cvt cvt; }; struct di_edid_display_descriptor { diff --git a/include/libdisplay-info/edid.h b/include/libdisplay-info/edid.h index 81ace07..87b12d0 100644 --- a/include/libdisplay-info/edid.h +++ b/include/libdisplay-info/edid.h @@ -558,6 +558,40 @@ struct di_edid_display_range_limits_secondary_gtf { float c, m, k, j; }; +enum di_edid_cvt_aspect_ratio { + DI_EDID_CVT_ASPECT_RATIO_4_3 = 1 << 7, + DI_EDID_CVT_ASPECT_RATIO_16_9 = 1 << 6, + DI_EDID_CVT_ASPECT_RATIO_16_10 = 1 << 5, + DI_EDID_CVT_ASPECT_RATIO_5_4 = 1 << 4, + DI_EDID_CVT_ASPECT_RATIO_15_9 = 1 << 3, +}; + +enum di_edid_cvt_scaling { + DI_EDID_CVT_SCALING_HORIZ_SHRINK = 1 << 7, + DI_EDID_CVT_SCALING_HORIZ_STRETCH = 1 << 6, + DI_EDID_CVT_SCALING_VERT_SHRINK = 1 << 5, + DI_EDID_CVT_SCALING_VERT_STRETCH = 1 << 4, +}; + +struct di_edid_display_range_limits_cvt { + int32_t version, revision; + /* Maximum active pixels per line, zero for no limit */ + int32_t max_horiz_px; + /* Supported aspect ratio, bitfield of enum di_edid_cvt_aspect_ratio */ + uint32_t supported_aspect_ratio; + /* Preferred aspect ratio */ + enum di_edid_cvt_aspect_ratio preferred_aspect_ratio; + /* Whether standard CVT blanking is supported */ + bool standard_blanking; + /* Whether reduced CVT blanking is supported */ + bool reduced_blanking; + /* Supported types of display scaling, bitfield of + * enum di_edid_cvt_scaling */ + uint32_t supported_scaling; + /* Preferred vertical refresh rate, in Hz */ + int32_t preferred_vert_refresh_hz; +}; + /** * EDID display range limits, defined in section 3.10.3.3.1. */ @@ -569,13 +603,16 @@ struct di_edid_display_range_limits { int32_t min_horiz_rate_hz, max_horiz_rate_hz; /* Maximum pixel clock in Hz, zero if unset, rounded to the nearest - * multiple of 10 MHz */ + * multiple of 0.25 MHz if CVT, otherwise to the nearest multiple of + * 10 MHz */ int32_t max_pixel_clock_hz; enum di_edid_display_range_limits_type type; /* For SECONDARY_GTF limits, NULL otherwise */ const struct di_edid_display_range_limits_secondary_gtf *secondary_gtf; + /* For CVT limits, NULL otherwise */ + const struct di_edid_display_range_limits_cvt *cvt; }; /** diff --git a/test/data/viewsonic-vp2768-dp.diff b/test/data/viewsonic-vp2768-dp.diff index c845260..cee7ed9 100644 --- a/test/data/viewsonic-vp2768-dp.diff +++ b/test/data/viewsonic-vp2768-dp.diff @@ -23,26 +23,7 @@ Detailed Timing Descriptors: DTD 1: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (597 mm x 336 mm) Hfront 48 Hsync 32 Hback 80 Hpol P -@@ -53,18 +53,6 @@ - Display Product Serial Number: 'UY5171500307' - Display Range Limits: - Monitor ranges (CVT): 50-75 Hz V, 24-90 kHz H, max dotclock 250 MHz -- CVT version 1.1 -- Max active pixels per line: 6400 -- Supported aspect ratios: 4:3 16:9 -- Preferred aspect ratio: 16:9 -- Supports CVT standard blanking -- Supports CVT reduced blanking -- Supported display scaling: -- Horizontal shrink -- Horizontal stretch -- Vertical shrink -- Vertical stretch -- Preferred vertical refresh: 60 Hz - Display Product Name: 'VP2768 Series' - Extension blocks: 1 - Checksum: 0xa0 -@@ -79,35 +67,29 @@ +@@ -79,35 +79,29 @@ Supports YCbCr 4:2:2 Native detailed modes: 1 Video Data Block: @@ -94,7 +75,7 @@ DTD 4: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz (597 mm x 336 mm) Hfront 110 Hsync 40 Hback 220 Hpol P Vfront 5 Vsync 5 Vback 20 Vpol P -@@ -117,28 +99,8 @@ +@@ -117,28 +111,14 @@ DTD 6: 1920x1080 50.000000 Hz 16:9 56.250 kHz 148.500000 MHz (597 mm x 336 mm) Hfront 528 Hsync 44 Hback 148 Hpol P Vfront 4 Vsync 5 Vback 36 Vpol P @@ -111,17 +92,16 @@ - Base EDID: Some timings are out of range of the Monitor Ranges: - Vertical Freq: 24.000 - 75.062 Hz (Monitor: 50.000 - 75.000 Hz) - --Failures: -- --Block 0, Base EDID: + Failures: + + Block 0, Base EDID: - Basic Display Parameters & Features: sRGB is signaled, but the chromaticities do not match. -- Display Range Limits: Reserved bits of byte 14 are non-zero. -- Display Range Limits: Reserved bits of byte 15 are non-zero. -- Display Range Limits: Reserved bits of byte 16 are non-zero. + Display Range Limits: Reserved bits of byte 14 are non-zero. + Display Range Limits: Reserved bits of byte 15 are non-zero. + Display Range Limits: Reserved bits of byte 16 are non-zero. -Block 1, CTA-861 Extension Block: - Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues. -EDID: - CTA-861: Native progressive timings are a mix of several resolutions. - --EDID conformity: FAIL -+EDID conformity: PASS + EDID conformity: FAIL