edid: add display range limits type

This is a bit messy because the values depend on various misc flags
defined earlier in the spec, and the meaning changes between EDID 1.3
and 1.4. On top of that edid-decode prints something confusing in the
EDID 1.3 case.

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2022-06-17 12:58:17 +02:00
parent cf66667ac3
commit 4f4aa025cf
7 changed files with 119 additions and 22 deletions

View file

@ -212,12 +212,30 @@ display_desc_tag_name(enum di_edid_display_descriptor_tag tag)
abort();
}
static const char *
display_range_limits_type_name(enum di_edid_display_range_limits_type type)
{
switch (type) {
case DI_EDID_DISPLAY_RANGE_LIMITS_BARE:
return "Bare Limits";
case DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF:
return "GTF";
case DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF:
return "Secondary GTF";
case DI_EDID_DISPLAY_RANGE_LIMITS_CVT:
return "CVT";
}
abort();
}
static void
print_display_desc(const struct di_edid_display_descriptor *desc)
print_display_desc(const struct di_edid *edid,
const struct di_edid_display_descriptor *desc)
{
enum di_edid_display_descriptor_tag tag;
const char *tag_name, *str;
const struct di_edid_display_range_limits *range_limits;
enum di_edid_display_range_limits_type range_limits_type;
tag = di_edid_display_descriptor_get_tag(desc);
tag_name = display_desc_tag_name(tag);
@ -233,7 +251,17 @@ print_display_desc(const struct di_edid_display_descriptor *desc)
break;
case DI_EDID_DISPLAY_DESCRIPTOR_RANGE_LIMITS:
range_limits = di_edid_display_descriptor_get_range_limits(desc);
printf("\n Monitor ranges: %d-%d Hz V, %d-%d kHz H",
range_limits_type = range_limits->type;
if (di_edid_get_revision(edid) < 4
&& range_limits_type == DI_EDID_DISPLAY_RANGE_LIMITS_BARE) {
/* edid-decode always prints "GTF" for EDID 1.3 and
* earlier even if the display doesn't support it */
range_limits_type = DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF;
}
printf("\n Monitor ranges (%s): %d-%d Hz V, %d-%d kHz H",
display_range_limits_type_name(range_limits_type),
range_limits->min_vert_rate_hz,
range_limits->max_vert_rate_hz,
range_limits->min_horiz_rate_hz / 1000,
@ -622,7 +650,7 @@ main(int argc, char *argv[])
}
display_descs = di_edid_get_display_descriptors(edid);
for (i = 0; display_descs[i] != NULL; i++) {
print_display_desc(display_descs[i]);
print_display_desc(edid, display_descs[i]);
}
exts = di_edid_get_extensions(edid);

60
edid.c
View file

@ -429,6 +429,7 @@ parse_display_range_limits(struct di_edid *edid,
struct di_edid_display_range_limits *out)
{
uint8_t offset_flags, vert_offset_flags, horiz_offset_flags;
uint8_t support_flags;
int max_vert_offset = 0, min_vert_offset = 0;
int max_horiz_offset = 0, min_horiz_offset = 0;
@ -483,7 +484,64 @@ parse_display_range_limits(struct di_edid *edid,
add_failure(edid, "EDID 1.4 block does not set max dotclock.");
}
/* TODO: parse video timing support flags */
support_flags = data[10];
switch (support_flags) {
case 0x00:
/* For EDID 1.4 and later, always indicates support for default
* GTF. For EDID 1.3 and earlier, a misc features bit indicates
* support for default GTF. */
if (edid->revision >= 4 || edid->misc_features.default_gtf) {
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF;
} else {
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
}
break;
case 0x01:
if (edid->revision < 4) {
/* Reserved */
add_failure(edid, "'Bare Limits' is not allowed for EDID < 1.4.");
return false;
}
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
break;
case 0x02:
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF;
break;
case 0x04:
if (edid->revision < 4) {
/* Reserved */
add_failure(edid, "'CVT' is not allowed for EDID < 1.4.");
return false;
}
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_CVT;
break;
default:
/* Reserved */
if (edid->revision <= 4) {
add_failure(edid, "Unknown range class (0x%02x).", support_flags);
return false;
}
out->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
break;
}
/* Some types require the display to support continuous frequencies, but
* this flag is only set for EDID 1.4 and later */
if (edid->revision >= 4 && !edid->misc_features.continuous_freq) {
switch (out->type) {
case DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF:
case DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF:
add_failure(edid, "GTF can't be combined with non-continuous frequencies.");
return false;
case DI_EDID_DISPLAY_RANGE_LIMITS_CVT:
add_failure(edid, "CVT can't be combined with non-continuous frequencies.");
return false;
default:
break;
}
}
/* TODO: parse video timing data in bytes 11 to 17 */
return true;
}

View file

@ -373,6 +373,24 @@ di_edid_display_descriptor_get_tag(const struct di_edid_display_descriptor *desc
const char *
di_edid_display_descriptor_get_string(const struct di_edid_display_descriptor *desc);
/**
* EDID display range limits type.
*
* The values do not match the EDID specification.
*
* The CVT entry was introduced in EDID 1.4.
*/
enum di_edid_display_range_limits_type {
/* Range Limits Only - no additional timing information is provided */
DI_EDID_DISPLAY_RANGE_LIMITS_BARE,
/* Default GTF supported */
DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF,
/* Secondary GTF supported */
DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF,
/* CVT supported */
DI_EDID_DISPLAY_RANGE_LIMITS_CVT,
};
/**
* EDID display range limits, defined in section 3.10.3.3.1.
*/
@ -386,6 +404,8 @@ struct di_edid_display_range_limits {
/* Maximum pixel clock in Hz, zero if unset, rounded to the nearest
* multiple of 10 MHz */
int32_t max_pixel_clock_hz;
enum di_edid_display_range_limits_type type;
};
/**

View file

@ -1,6 +1,6 @@
--- ref
+++ di
@@ -19,25 +19,16 @@
@@ -19,23 +19,14 @@
Green: 0.1875, 0.7060
Blue : 0.1484, 0.0644
White: 0.3134, 0.3291
@ -29,6 +29,3 @@
Display Product Serial Number: 'G283H8BI21MS'
Display Product Name: 'DELL 2408WFP'
Display Range Limits:
- Monitor ranges (Bare Limits): 56-76 Hz V, 30-83 kHz H, max dotclock 170 MHz
+ Monitor ranges: 56-76 Hz V, 30-83 kHz H, max dotclock 170 MHz
Checksum: 0x92

View file

@ -1,6 +1,6 @@
--- ref
+++ di
@@ -17,26 +17,21 @@
@@ -17,24 +17,19 @@
Green: 0.2890, 0.6435
Blue : 0.1494, 0.0507
White: 0.3134, 0.3291
@ -33,11 +33,8 @@
+ Hfront 48 Hsync 32 Hback 80
+ Vfront 3 Vsync 5 Vback 33
Display Range Limits:
- Monitor ranges (GTF): 46-75 Hz V, 30-112 kHz H, max dotclock 310 MHz
+ Monitor ranges: 46-75 Hz V, 30-112 kHz H, max dotclock 310 MHz
Monitor ranges (GTF): 46-75 Hz V, 30-112 kHz H, max dotclock 310 MHz
Display Product Name: 'HP 27 QD'
Display Product Serial Number: 'CN49120J6N'
Extension blocks: 1
@@ -51,57 +46,7 @@
Supports YCbCr 4:2:2
Native detailed modes: 1

View file

@ -1,6 +1,6 @@
--- ref
+++ di
@@ -17,16 +17,15 @@
@@ -17,15 +17,14 @@
Green: 0.2949, 0.6083
Blue : 0.1533, 0.0605
White: 0.3134, 0.3291
@ -18,7 +18,5 @@
+ Hfront 88 Hsync 32 Hback 120
+ Vfront 28 Vsync 5 Vback 443
Display Range Limits:
- Monitor ranges (Bare Limits): 46-62 Hz V, 89-94 kHz H, max dotclock 260 MHz
+ Monitor ranges: 46-62 Hz V, 89-94 kHz H, max dotclock 260 MHz
Monitor ranges (Bare Limits): 46-62 Hz V, 89-94 kHz H, max dotclock 260 MHz
Alphanumeric Data String: 'VVX14T058J10'
Checksum: 0x09

View file

@ -1,6 +1,6 @@
--- ref
+++ di
@@ -18,17 +18,16 @@
@@ -18,17 +18,14 @@
Green: 0.2890, 0.6093
Blue : 0.1455, 0.0703
White: 0.3125, 0.3291
@ -15,15 +15,14 @@
DTD 2: 1920x1080 99.930409 Hz 16:9 113.221 kHz 235.500000 MHz (field sequential R/L, 598 mm x 336 mm)
- Hfront 48 Hsync 32 Hback 80 Hpol P
- Vfront 3 Vsync 5 Vback 45 Vpol N
- Display Range Limits:
- Monitor ranges (GTF): 24-120 Hz V, 26-140 kHz H, max dotclock 300 MHz
+ Hfront 48 Hsync 32 Hback 80
+ Vfront 3 Vsync 5 Vback 45
Display Range Limits:
- Monitor ranges (GTF): 24-120 Hz V, 26-140 kHz H, max dotclock 300 MHz
+ Monitor ranges: 24-120 Hz V, 26-140 kHz H, max dotclock 300 MHz
Display Product Name: 'S27A950D'
Extension blocks: 1
Checksum: 0x1b
@@ -41,10 +40,5 @@
@@ -41,10 +38,5 @@
Basic audio support
Native detailed modes: 0
Audio Data Block: