linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] edid-decode: bug fixes, additions, changes
@ 2019-11-23 16:45 joevt
  2019-11-23 16:45 ` [PATCH 01/10] edid-decode: change horizontal refresh rates to kHz joevt
                   ` (10 more replies)
  0 siblings, 11 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

This patchset is a set of bug-fixes, additions, and changes I've made while examining various EDIDs I have encountered.

joevt (10):
  edid-decode: change horizontal refresh rates to kHz
  edid-decode: correct horizontal range in Monitor Ranges
  edid-decode: correct calculation of DisplayID type 1 timings
  edid-decode: add front porch, pulse width, and back porch
  edid-decode: output timings for YCbCr 4:2:0 cmdb
  edid-decode: Dump hex of unknown CTA Vendor-Specific blocks
  edid-decode: cleanup printf format string compiler warnings
  edid-decode: Dump hex of non-decoded extension blocks
  edid-decode: DisplayID additions
  edid-decode: add example EDIDs

 data/acer-xv273k-dp1                          | Bin 0 -> 384 bytes
 data/acer-xv273k-dp1-tile0                    | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2                          | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2-tile1                    | Bin 0 -> 384 bytes
 data/dell-p2415q-dp-mdp                       | Bin 0 -> 256 bytes
 data/dell-p2415q-hdmi1.4                      | Bin 0 -> 256 bytes
 data/dell-p2415q-hdmi2.0                      | Bin 0 -> 256 bytes
 data/dell-up2715k-dp1-tile1                   | Bin 0 -> 384 bytes
 data/dell-up2715k-dp2-tile0                   | Bin 0 -> 256 bytes
 data/dell-up2715k-mdp                         | Bin 0 -> 256 bytes
 data/dell-up2715k-mdp-switchresx              | Bin 0 -> 384 bytes
 data/kogan-kaled24144f-dp                     | Bin 0 -> 256 bytes
 data/kogan-kaled24144f-hdmi                   | Bin 0 -> 256 bytes
 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 | Bin 0 -> 384 bytes
 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 | Bin 0 -> 256 bytes
 edid-decode.c                                 | 758 ++++++++++++++++--
 16 files changed, 671 insertions(+), 87 deletions(-)
 create mode 100644 data/acer-xv273k-dp1
 create mode 100644 data/acer-xv273k-dp1-tile0
 create mode 100644 data/acer-xv273k-dp2
 create mode 100644 data/acer-xv273k-dp2-tile1
 create mode 100644 data/dell-p2415q-dp-mdp
 create mode 100644 data/dell-p2415q-hdmi1.4
 create mode 100644 data/dell-p2415q-hdmi2.0
 create mode 100644 data/dell-up2715k-dp1-tile1
 create mode 100644 data/dell-up2715k-dp2-tile0
 create mode 100644 data/dell-up2715k-mdp
 create mode 100644 data/dell-up2715k-mdp-switchresx
 create mode 100644 data/kogan-kaled24144f-dp
 create mode 100644 data/kogan-kaled24144f-hdmi
 create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
 create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1

-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/10] edid-decode: change horizontal refresh rates to kHz
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
@ 2019-11-23 16:45 ` joevt
  2019-11-23 16:45 ` [PATCH 02/10] edid-decode: correct horizontal range in Monitor Ranges joevt
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

- Timings that show horizontal refresh rate should use kHz to distinguish them from vertical refresh rate (Hz) and pixel clock rate (MHz). Matches representation in Monitor ranges descriptor.
- Make vertical refresh rate floating point instead of integer in detailed timings descriptors. For example, NTSC modes use 59.94 Hz and should not be rounded to 60 Hz.
- Remove double space when "(native)" is not output for CTA VIC timings.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index 932dd20..4ba0808 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -489,7 +489,7 @@ static int detailed_cvt_descriptor(const unsigned char *x, int first)
 			edid_cvt_mode(width, height, 60, 1,
 				      &min_hfreq, &max_hfreq, &max_clock);
 
-		printf("    %ux%u @ ( %s%s%s%s%s) Hz %s (%s%s preferred) HorFreq: %u-%u Hz MaxClock: %.3f MHz\n",
+		printf("    %ux%u @ ( %s%s%s%s%s) Hz %s (%s%s preferred) HorFreq: %.3f-%.3f kHz MaxClock: %.3f MHz\n",
 		       width, height,
 		       fifty ? "50 " : "",
 		       sixty ? "60 " : "",
@@ -499,7 +499,7 @@ static int detailed_cvt_descriptor(const unsigned char *x, int first)
 		       ratio,
 		       names[(x[2] & 0x60) >> 5],
 		       (((x[2] & 0x60) == 0x20) && reduced) ? "RB" : "",
-		       min_hfreq, max_hfreq, max_clock / 1000000.0);
+		       min_hfreq / 1000.0, max_hfreq / 1000.0, max_clock / 1000000.0);
 	}
 
 	return valid;
@@ -709,9 +709,9 @@ static void print_standard_timing(uint8_t b1, uint8_t b2)
 		min_hor_freq_hz = min(min_hor_freq_hz, hor_freq_hz);
 		max_hor_freq_hz = max(max_hor_freq_hz, hor_freq_hz);
 		max_pixclk_khz = max(max_pixclk_khz, pixclk_khz);
-		printf("  %ux%u@%uHz %u:%u HorFreq: %u Hz Clock: %.3f MHz\n",
+		printf("  %ux%u@%uHz %u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
 		       x, y, refresh, ratio_w, ratio_h,
-		       hor_freq_hz, pixclk_khz / 1000.0);
+		       hor_freq_hz / 1000.0, pixclk_khz / 1000.0);
 	} else {
 		printf("  %ux%u@%uHz %u:%u\n",
 		       x, y, refresh, ratio_w, ratio_h);
@@ -723,7 +723,8 @@ static int detailed_block(const unsigned char *x, int in_extension)
 {
 	unsigned ha, hbl, hso, hspw, hborder, va, vbl, vso, vspw, vborder;
 	unsigned hor_mm, vert_mm;
-	unsigned refresh, pixclk_khz;
+	unsigned pixclk_khz;
+	float refresh;
 	unsigned i;
 	char phsync, pvsync, *syncmethod, *stereo;
 
@@ -769,12 +770,12 @@ static int detailed_block(const unsigned char *x, int in_extension)
 			printf("Established timings III:\n");
 			for (i = 0; i < 44; i++) {
 				if (x[6 + i / 8] & (1 << (7 - i % 8))) {
-					printf("  %dx%d@%dHz %s%u:%u HorFreq: %d Hz Clock: %.3f MHz\n",
+					printf("  %dx%d@%dHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
 					       established_timings3[i].x,
 					       established_timings3[i].y, established_timings3[i].refresh,
 					       established_timings3[i].rb ? "RB " : "",
 					       established_timings3[i].ratio_w, established_timings3[i].ratio_h,
-					       established_timings3[i].hor_freq_hz,
+					       established_timings3[i].hor_freq_hz / 1000.0,
 					       established_timings3[i].pixclk_khz / 1000.0);
 					min_vert_freq_hz = min(min_vert_freq_hz, established_timings3[i].refresh);
 					max_vert_freq_hz = max(max_vert_freq_hz, established_timings3[i].refresh);
@@ -1078,20 +1079,20 @@ static int detailed_block(const unsigned char *x, int in_extension)
 	}
 
 	pixclk_khz = (x[0] + (x[1] << 8)) * 10;
-	refresh = (pixclk_khz * 1000) / ((ha + hbl) * (va + vbl));
+	refresh = (pixclk_khz * 1000.0) / ((ha + hbl) * (va + vbl));
 	hor_mm = x[12] + ((x[14] & 0xf0) << 4);
 	vert_mm = x[13] + ((x[14] & 0x0f) << 8);
 	printf("Detailed mode: Clock %.3f MHz, %u mm x %u mm\n"
 	       "               %4u %4u %4u %4u hborder %u\n"
 	       "               %4u %4u %4u %4u vborder %u\n"
 	       "               %chsync %cvsync%s%s %s\n"
-	       "               VertFreq: %u Hz, HorFreq: %u Hz\n",
+	       "               VertFreq: %.3f Hz, HorFreq: %.3f kHz\n",
 	       pixclk_khz / 1000.0,
 	       hor_mm, vert_mm,
 	       ha, ha + hso, ha + hso + hspw, ha + hbl, hborder,
 	       va, va + vso, va + vso + vspw, va + vbl, vborder,
-	       phsync, pvsync, syncmethod, x[17] & 0x80 ? " interlaced" : "",
-	       stereo, refresh, (pixclk_khz * 1000) / (ha + hbl)
+	       phsync, pvsync, syncmethod, x[17] & 0x80 ? " interlaced" : "", stereo,
+	       refresh, (float)pixclk_khz / (ha + hbl)
 	      );
 	if ((!max_display_width_mm && hor_mm) ||
 	    (!max_display_height_mm && vert_mm)) {
@@ -1505,8 +1506,8 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
 			mode = "Unknown mode";
 		}
 
-		printf("    VIC %3u %s %s HorFreq: %u Hz Clock: %.3f MHz\n",
-		       vic, mode, native ? "(native)" : "", hfreq, clock_khz / 1000.0);
+		printf("VIC %3u %s%sHorFreq: %.3f kHz Clock: %.3f MHz",
+		       vic, mode, native ? " (native) " : " ", hfreq / 1000.0, clock_khz / 1000.0);
 		if (vic == 1)
 			has_cta861_vic_1 = 1;
 	}
@@ -1690,8 +1691,8 @@ static void cta_hdmi_block(const unsigned char *x, unsigned length)
 				mode = "Unknown mode";
 			}
 
-			printf("      HDMI VIC %u %s HorFreq: %u Hz Clock: %.3f MHz\n",
-			       vic, mode, hfreq, clock_khz / 1000.0);
+			printf("      HDMI VIC %u %s HorFreq: %.3f kHz Clock: %.3f MHz\n",
+			       vic, mode, hfreq / 1000.0, clock_khz / 1000.0);
 		}
 
 		b += len_vic;
@@ -2706,14 +2707,14 @@ static int parse_displayid(const unsigned char *x)
 			printf("Type 1 VESA DMT Timings Block\n");
 			for (i = 0; i < min(len, 10) * 8; i++) {
 				if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
-					printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %u Hz Clock: %.3f MHz\n",
+					printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
 					       displayid_vesa_dmt[i].x,
 					       displayid_vesa_dmt[i].y,
 					       displayid_vesa_dmt[i].interlaced ? "i" : "",
 					       displayid_vesa_dmt[i].refresh,
 					       displayid_vesa_dmt[i].rb ? "RB " : "",
 					       displayid_vesa_dmt[i].ratio_w, displayid_vesa_dmt[i].ratio_h,
-					       displayid_vesa_dmt[i].hor_freq_hz,
+					       displayid_vesa_dmt[i].hor_freq_hz / 1000.0,
 					       displayid_vesa_dmt[i].pixclk_khz / 1000.0);
 					min_vert_freq_hz = min(min_vert_freq_hz, displayid_vesa_dmt[i].refresh);
 					max_vert_freq_hz = max(max_vert_freq_hz, displayid_vesa_dmt[i].refresh);
@@ -3455,12 +3456,12 @@ static int edid_from_file(const char *from_file, const char *to_file,
 			min_hor_freq_hz = min(min_hor_freq_hz, established_timings[i].hor_freq_hz);
 			max_hor_freq_hz = max(max_hor_freq_hz, established_timings[i].hor_freq_hz);
 			max_pixclk_khz = max(max_pixclk_khz, established_timings[i].pixclk_khz);
-			printf("  %ux%u%s@%uHz %u:%u HorFreq: %d Hz Clock: %.3f MHz\n",
+			printf("  %ux%u%s@%uHz %u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
 			       established_timings[i].x, established_timings[i].y,
 			       established_timings[i].interlaced ? "i" : "",
 			       established_timings[i].refresh,
 			       established_timings[i].ratio_w, established_timings[i].ratio_h,
-			       established_timings[i].hor_freq_hz,
+			       established_timings[i].hor_freq_hz / 1000.0,
 			       established_timings[i].pixclk_khz / 1000.0);
 		}
 	}
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/10] edid-decode: correct horizontal range in Monitor Ranges
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
  2019-11-23 16:45 ` [PATCH 01/10] edid-decode: change horizontal refresh rates to kHz joevt
@ 2019-11-23 16:45 ` joevt
  2019-11-23 16:45 ` [PATCH 03/10] edid-decode: correct calculation of DisplayID type 1 timings joevt
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

Broken since commit 1508f040.
The max and min horizontal frequency in the "Monitor ranges" descriptor is to be offset by 255 when bit 3 and bit 2 are set, respectively.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index 4ba0808..b2e57a3 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -863,9 +863,9 @@ static int detailed_block(const unsigned char *x, int in_extension)
 						v_min_offset = 255;
 					}
 				}
-				if (x[4] & 0x04) {
+				if (x[4] & 0x08) {
 					h_max_offset = 255;
-					if (x[4] & 0x03) {
+					if (x[4] & 0x04) {
 						h_min_offset = 255;
 					}
 				}
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/10] edid-decode: correct calculation of DisplayID type 1 timings
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
  2019-11-23 16:45 ` [PATCH 01/10] edid-decode: change horizontal refresh rates to kHz joevt
  2019-11-23 16:45 ` [PATCH 02/10] edid-decode: correct horizontal range in Monitor Ranges joevt
@ 2019-11-23 16:45 ` joevt
  2019-11-23 16:45 ` [PATCH 04/10] edid-decode: add front porch, pulse width, and back porch joevt
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

Fix DisplayID type 1 timing calculations which is missing the +1 increment for pix_clock,ha,hbl,hso,hspw,va,vbl,vso,vspw.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/edid-decode.c b/edid-decode.c
index b2e57a3..e1386ce 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -2550,6 +2550,18 @@ static void parse_displayid_detailed_timing(const unsigned char *x)
 	vspw = x[18] | (x[19] << 8);
 	pvsync = ((x[17] >> 7) & 0x1 ) ? '+' : '-';
 
+	pix_clock++;
+
+	ha++;
+	hbl++;
+	hso++;
+	hspw++;
+	
+	va++;
+	vbl++;
+	vso++;
+	vspw++;
+	
 	printf("  Detailed mode: Clock %.3f MHz, %u mm x %u mm\n"
 	       "                 %4u %4u %4u %4u\n"
 	       "                 %4u %4u %4u %4u\n"
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/10] edid-decode: add front porch, pulse width, and back porch
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (2 preceding siblings ...)
  2019-11-23 16:45 ` [PATCH 03/10] edid-decode: correct calculation of DisplayID type 1 timings joevt
@ 2019-11-23 16:45 ` joevt
  2019-11-23 16:45 ` [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb joevt
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

For detailed timings, add front porch, pulse width, and back porch numbers in parenthesis (smaller integers are easier to comprehend, useful when comparing or editing timings in SwitchResX or other custom timing editors, negative values will be more apparent - this can happen for back porch when offset and width exceed total blanking).
Also, add missing VertFreq and HorFreq values to DisplayID type 1 timings.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index e1386ce..b833178 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -1083,14 +1083,14 @@ static int detailed_block(const unsigned char *x, int in_extension)
 	hor_mm = x[12] + ((x[14] & 0xf0) << 4);
 	vert_mm = x[13] + ((x[14] & 0x0f) << 8);
 	printf("Detailed mode: Clock %.3f MHz, %u mm x %u mm\n"
-	       "               %4u %4u %4u %4u hborder %u\n"
-	       "               %4u %4u %4u %4u vborder %u\n"
+	       "               %4u %4u %4u %4u (%3u %3u %3d) hborder %u\n"
+	       "               %4u %4u %4u %4u (%3u %3u %3d) vborder %u\n"
 	       "               %chsync %cvsync%s%s %s\n"
 	       "               VertFreq: %.3f Hz, HorFreq: %.3f kHz\n",
 	       pixclk_khz / 1000.0,
 	       hor_mm, vert_mm,
-	       ha, ha + hso, ha + hso + hspw, ha + hbl, hborder,
-	       va, va + vso, va + vso + vspw, va + vbl, vborder,
+	       ha, ha + hso, ha + hso + hspw, ha + hbl, hso, hspw, hbl - hso - hspw, hborder,
+	       va, va + vso, va + vso + vspw, va + vbl, vso, vspw, vbl - vso - vspw, vborder,
 	       phsync, pvsync, syncmethod, x[17] & 0x80 ? " interlaced" : "", stereo,
 	       refresh, (float)pixclk_khz / (ha + hbl)
 	      );
@@ -2563,13 +2563,15 @@ static void parse_displayid_detailed_timing(const unsigned char *x)
 	vspw++;
 	
 	printf("  Detailed mode: Clock %.3f MHz, %u mm x %u mm\n"
-	       "                 %4u %4u %4u %4u\n"
-	       "                 %4u %4u %4u %4u\n"
-	       "                 %chsync %cvsync\n",
+	       "                 %4u %4u %4u %4u (%3u %3u %3d)\n"
+	       "                 %4u %4u %4u %4u (%3u %3u %3d)\n"
+	       "                 %chsync %cvsync\n"
+	       "                 VertFreq: %.3f Hz, HorFreq: %.3f kHz\n",
 	       (float)pix_clock/100.0, 0, 0,
-	       ha, ha + hso, ha + hso + hspw, ha + hbl,
-	       va, va + vso, va + vso + vspw, va + vbl,
-	       phsync, pvsync
+	       ha, ha + hso, ha + hso + hspw, ha + hbl, hso, hspw, hbl - hso - hspw,
+	       va, va + vso, va + vso + vspw, va + vbl, vso, vspw, vbl - vso - vspw,
+	       phsync, pvsync,
+	       ((float)pix_clock * 10000.0) / ((ha + hbl) * (va + vbl)), ((float)pix_clock * 10.0) / (ha + hbl)
 	      );
 }
 
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (3 preceding siblings ...)
  2019-11-23 16:45 ` [PATCH 04/10] edid-decode: add front porch, pulse width, and back porch joevt
@ 2019-11-23 16:45 ` joevt
  2019-11-24 10:26   ` Hans Verkuil
  2019-11-23 16:46 ` [PATCH 06/10] edid-decode: Dump hex of unknown CTA Vendor-Specific blocks joevt
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: joevt @ 2019-11-23 16:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

- "YCbCr 4:2:0 capability map data block" now outputs the modes that support YCbCr 4:2:0 instead of just indexes of the modes. Indexes refer to timings in "Video Data Block".
- Warnings are included in the output if "Video Data Block" doesn't appear before "YCbCr 4:2:0 Capability Map Data Block" or if the index is outside the range defined in the "Video Data Block".
- Moved inner loop of cta_svd into a new function cta_svd_one so that it can be reused by cta_y420cmdb.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index b833178..4d6fe29 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -1454,13 +1454,10 @@ static const struct edid_cta_mode *vic_to_mode(unsigned char vic)
 	return NULL;
 }
 
-static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
+static void cta_svd_one(const unsigned char *x, int for_ycbcr420)
 {
-	unsigned i;
-
-	for (i = 0; i < n; i++)  {
 		const struct edid_cta_mode *vicmode = NULL;
-		unsigned char svd = x[i];
+		unsigned char svd = x[0];
 		unsigned char native;
 		unsigned char vic;
 		const char *mode;
@@ -1468,7 +1465,7 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
 		unsigned clock_khz = 0;
 
 		if ((svd & 0x7f) == 0)
-			continue;
+			return;
 
 		if ((svd - 1) & 0x40) {
 			vic = svd;
@@ -1511,10 +1508,23 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
 		if (vic == 1)
 			has_cta861_vic_1 = 1;
 	}
+
+static void cta_svd(const unsigned char *x, int n, int for_ycbcr420)
+{
+	for (unsigned i = 0; i < n; i++)  {
+		printf("    ");
+		cta_svd_one(x+i, for_ycbcr420);
+		printf("\n");
+	}
 }
 
+unsigned const char *last_cta_video_block_start = NULL;
+unsigned last_cta_video_block_length = 0;
+
 static void cta_video_block(const unsigned char *x, unsigned length)
 {
+	last_cta_video_block_start = x;
+	last_cta_video_block_length = length;
 	cta_svd(x, length, 0);
 }
 
@@ -1531,9 +1541,25 @@ static void cta_y420cmdb(const unsigned char *x, unsigned length)
 		uint8_t v = x[0 + i];
 		unsigned j;
 
-		for (j = 0; j < 8; j++)
-			if (v & (1 << j))
-				printf("    VSD Index %u\n", i * 8 + j);
+		for (j = 0; j < 8; j++) {
+			if (v & (1 << j)) {
+				unsigned k = i * 8 + j;
+				printf("    VSD Index %u", k + 1);
+				if (k >= last_cta_video_block_length) {
+					if (last_cta_video_block_start) {
+						printf(" (out of range)");
+					} else {
+						printf(" (missing CTA video block)");
+					}
+				}
+				else
+				{
+					printf(" ");
+					cta_svd_one(last_cta_video_block_start+k, 0);
+				}
+				printf("\n");
+			}
+		}
 	}
 }
 
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/10] edid-decode: Dump hex of unknown CTA Vendor-Specific blocks
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (4 preceding siblings ...)
  2019-11-23 16:45 ` [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb joevt
@ 2019-11-23 16:46 ` joevt
  2019-11-23 16:46 ` [PATCH 07/10] edid-decode: cleanup printf format string compiler warnings joevt
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

- Unknown CTA Vendor-Specific blocks will output as hex. With this, two EDIDs with different data will not be considered equal.
- Added hex_block to output hex for blocks of data that are not decoded.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index 4d6fe29..ce404cd 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -1934,6 +1934,18 @@ static void cta_hdr10plus(const unsigned char *x, unsigned length)
 	printf("    Application Version: %u\n", x[0]);
 }
 
+static void hex_block(const unsigned char *x, unsigned int length)
+{
+	if (length) {
+		for (int i = 0; i < length; i++)
+			printf("%02x", x[i]);
+		printf("  ");
+		for (int i = 0; i < length; i++)
+			printf("%c", x[i] >= ' ' && x[i] <= '~' ? x[i] : '.');
+		printf("\n");
+	}
+}
+
 DEFINE_FIELD("YCbCr quantization", YCbCr_quantization, 7, 7,
 	     { 0, "No Data" },
 	     { 1, "Selectable (via AVI YQ)" });
@@ -2321,7 +2333,9 @@ static void cta_block(const unsigned char *x)
 			cta_hf_scdb(x + 4, length - 3);
 			have_hf_vsdb = 1;
 		} else {
-			printf("\n");
+			printf(" (unknown)\n");
+			printf("    ");
+			hex_block(x + 4, length - 3);
 		}
 		break;
 	case 0x04:
@@ -2348,7 +2362,9 @@ static void cta_block(const unsigned char *x)
 				printf(" (HDR10+)\n");
 				cta_hdr10plus(x + 5, length - 4);
 			} else {
-				printf("\n");
+				printf(" (unknown)\n");
+				printf("    ");
+				hex_block(x + 5, length - 4);
 			}
 			break;
 		case 0x02:
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/10] edid-decode: cleanup printf format string compiler warnings
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (5 preceding siblings ...)
  2019-11-23 16:46 ` [PATCH 06/10] edid-decode: Dump hex of unknown CTA Vendor-Specific blocks joevt
@ 2019-11-23 16:46 ` joevt
  2019-11-23 16:46 ` [PATCH 08/10] edid-decode: Dump hex of non-decoded extension blocks joevt
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

In current versions of macOS, $(CC) in Makefile is gcc but gcc points to clang. clang complains when h is used for char or int (h is usually for short).

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index ce404cd..a40ee96 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -1127,13 +1127,13 @@ static int do_checksum(const unsigned char *x, size_t len)
 	unsigned char sum = 0;
 	unsigned i;
 
-	printf("Checksum: 0x%hx", check);
+	printf("Checksum: 0x%hhx", check);
 
 	for (i = 0; i < len-1; i++)
 		sum += x[i];
 
 	if ((unsigned char)(check + sum) != 0) {
-		printf(" (should be 0x%hx)\n", -sum & 0xff);
+		printf(" (should be 0x%x)\n", -sum & 0xff);
 		return 0;
 	}
 
@@ -3286,7 +3286,7 @@ static int edid_from_file(const char *from_file, const char *to_file,
 	}
 
 	cur_block = "EDID Structure Version & Revision";
-	printf("EDID version: %hd.%hd\n", edid[0x12], edid[0x13]);
+	printf("EDID version: %hhu.%hhu\n", edid[0x12], edid[0x13]);
 	if (edid[0x12] == 1) {
 		if (edid[0x13] > 4) {
 			printf("Claims > 1.4, assuming 1.4 conformance\n");
@@ -3321,12 +3321,12 @@ static int edid_from_file(const char *from_file, const char *to_file,
 		if (edid[0x11] <= 0x0f) {
 			fail("bad year of manufacture\n");
 		} else if (edid[0x10] == 0xff) {
-			printf("Model year %hu\n", edid[0x11] + 1990);
+			printf("Model year %u\n", edid[0x11] + 1990);
 		} else if (edid[0x11] + 90 <= ptm->tm_year + 1) {
 			if (edid[0x10])
-				printf("Made in week %hu of %hu\n", edid[0x10], edid[0x11] + 1990);
+				printf("Made in week %hhu of %u\n", edid[0x10], edid[0x11] + 1990);
 			else
-				printf("Made in year %hu\n", edid[0x11] + 1990);
+				printf("Made in year %u\n", edid[0x11] + 1990);
 		} else {
 			fail("bad year of manufacture\n");
 		}
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/10] edid-decode: Dump hex of non-decoded extension blocks
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (6 preceding siblings ...)
  2019-11-23 16:46 ` [PATCH 07/10] edid-decode: cleanup printf format string compiler warnings joevt
@ 2019-11-23 16:46 ` joevt
  2019-11-23 16:46 ` [PATCH 09/10] edid-decode: DisplayID additions joevt
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: joevt @ 2019-11-23 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

- Extension blocks that are not decoded will at least have their contents output as hex. With this, two EDIDs with different data in an undecoded extension block will not be considered equal.
- For unknown extension blocks, include the Extension Block tag number.
- Renamed conformant_extension to nonconformant_extension in parse_extension because boolean value of 1 = nonconformant according to return result of parse_cta and parse_displayid; matches interpretation in edid_from_file.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 80 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 62 insertions(+), 18 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index a40ee96..2f2f1c5 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -2474,7 +2474,7 @@ static void cta_block(const unsigned char *x)
 
 static int parse_cta(const unsigned char *x)
 {
-	int ret = 0;
+	int ret = 0; // 0 = conformant
 	unsigned version = x[1];
 	unsigned offset = x[2];
 	const unsigned char *detailed;
@@ -2483,7 +2483,7 @@ static int parse_cta(const unsigned char *x)
 
 	if (version >= 1) do {
 		if (version == 1 && x[3] != 0)
-			ret = 1;
+			ret = 1; // 1 = nonconformant
 
 		if (offset < 4)
 			break;
@@ -2866,28 +2866,72 @@ static void extension_version(const unsigned char *x)
 
 static int parse_extension(const unsigned char *x)
 {
-	int conformant_extension = 0;
+	int nonconformant_extension = 0;
 
 	printf("\n");
 
 	switch (x[0]) {
-	case 0x02: printf("CTA Extension Block\n");
-		   extension_version(x);
-		   conformant_extension = parse_cta(x);
-		   break;
-	case 0x10: printf("VTB Extension Block\n"); break;
-	case 0x40: printf("DI Extension Block\n"); break;
-	case 0x50: printf("LS Extension Block\n"); break;
-	case 0x60: printf("DPVL Extension Block\n"); break;
-	case 0x70: printf("DisplayID Extension Block\n");
-		   conformant_extension = parse_displayid(x);
-		   break;
-	case 0xf0: printf("Block map\n"); break;
-	case 0xff: printf("Manufacturer-specific Extension Block\n"); break;
-	default:   printf("Unknown Extension Block\n"); break;
+	case 0x02:
+		printf("CTA Extension Block\n");
+		extension_version(x);
+		nonconformant_extension = parse_cta(x);
+		break;
+	case 0x10:
+		printf("VTB Extension Block\n");
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0x40:
+		printf("DI Extension Block\n");
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0x50:
+		printf("LS Extension Block\n");
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0x60:
+		printf("DPVL Extension Block\n");
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0x70:
+		printf("DisplayID Extension Block\n");
+		nonconformant_extension = parse_displayid(x);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0xf0:
+		printf("Block map\n");
+		printf("  ");
+		hex_block(x + 1, 126);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	case 0xff:
+		printf("Manufacturer-specific Extension Block\n");
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
+	default:
+		printf("Unknown Extension Block (%02Xh)\n", x[0]);
+		extension_version(x);
+		printf("  ");
+		hex_block(x + 2, 125);
+		do_checksum(x, EDID_PAGE_SIZE);
+		break;
 	}
 
-	return conformant_extension;
+	return nonconformant_extension;
 }
 
 static int edid_lines = 0;
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/10] edid-decode: DisplayID additions
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (7 preceding siblings ...)
  2019-11-23 16:46 ` [PATCH 08/10] edid-decode: Dump hex of non-decoded extension blocks joevt
@ 2019-11-23 16:46 ` joevt
  2019-11-24 10:03   ` Hans Verkuil
  2019-11-23 16:46 ` [PATCH 10/10] edid-decode: add example EDIDs joevt
  2019-11-24 11:12 ` [PATCH 00/10] edid-decode: bug fixes, additions, changes Hans Verkuil
  10 siblings, 1 reply; 19+ messages in thread
From: joevt @ 2019-11-23 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

- Decode "Display Parameters Block". Example in lg-ultrafine-5k*
- Decode "CTA Timings Block". Similar to "Type 1 VESA DMT Timings Block".
- Decode "GP ASCII String Block". Example in dell-up2715k-mdp-switchresx

- Added DisplayID 2.0 tags:
    - Decode "Display Interface Features Data Block". Example in acer-xv273k* but it appears to be missing the "additional combinations count" byte.
    - Decode "ContainerID Data Block". Example in lg-ultrafine-5k*
    - Unknown DisplayID blocks are dumped as hex.

- Show DisplayID tag hex byte to make it possible to distinguish between DisplayID 1.3 and 2.0 spec blocks of the same name.
- Show DisplayID product type.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 504 insertions(+), 21 deletions(-)

diff --git a/edid-decode.c b/edid-decode.c
index 2f2f1c5..29f8f88 100644
--- a/edid-decode.c
+++ b/edid-decode.c
@@ -55,6 +55,7 @@ static int did_detailed_timing = 0;
 static int has_name_descriptor = 0;
 static int has_serial_string = 0;
 static int has_ascii_string = 0;
+static int has_GP_ascii_string = 0;
 static int has_range_descriptor = 0;
 static int has_preferred_timing = 0;
 static int has_valid_checksum = 1;
@@ -64,6 +65,7 @@ static int has_valid_cvt = 1;
 static int has_valid_serial_number = 0;
 static int has_valid_serial_string = 0;
 static int has_valid_ascii_string = 0;
+static int has_valid_GP_ascii_string = 0;
 static int has_valid_name_descriptor = 0;
 static int has_valid_detailed_blocks = 0;
 static int has_valid_descriptor_ordering = 1;
@@ -2528,6 +2530,53 @@ static int parse_cta(const unsigned char *x)
 	return ret;
 }
 
+
+static const char *feature_support_flags[] = {
+	"De-interlacing",
+	"Support ACP, ISRC1, or ISRC2packets",
+	"Fixed pixel format",
+	"Fixed timing",
+	"Power management (DPM)",
+	"Audio input override",
+	"Separate audio inputs provided",
+	"Audio support on video interface"
+};
+
+static void print_flag_lines(const char *indent, const char *label, unsigned char flag_byte, const char **flags) {
+	if (flag_byte) {
+		printf("%s\n", label);
+		for (int i = 0; i < 8; i++) {
+			if (flag_byte & (1<<i)) {
+				printf("%s%s\n", indent, flags[i]);
+			}
+		}
+	}
+}
+
+static void parse_displayid_parameters(const unsigned char *x) {
+	int revisionflags=x[1];
+	int len=x[2];
+	if (revisionflags) {
+		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
+	}
+	if (len != 12) {
+		printf("  Length is different than expected (%d != 12)\n", len);
+		printf("  ");
+		hex_block(x + 3, len);
+	} else {
+		printf("  Image size: %.1f mm x %.1f mm\n", ((x[4]<<8) + x[3]) / 10.0, ((x[6]<<8) + x[5]) / 10.0);
+		printf("  Pixels: %d x %d\n", (x[8]<<8) + x[7], (x[10]<<8) + x[9]);
+		print_flag_lines("    ", "  Feature support flags:", x[11], feature_support_flags);
+
+		if (x[12] != 0xff) {
+			printf("  Gamma: %.2f\n", ((x[12] + 100.0) / 100.0));
+		}
+		printf("  Aspect ratio: %.2f\n", ((x[13] + 100.0) / 100.0));
+		printf("  Dynamic bpc native: %d\n", (x[14] & 0xf) + 1);
+		printf("  Dynamic bpc overall: %d\n", ((x[14] >> 4) & 0xf) + 1);
+	} // else
+}
+
 static void parse_displayid_detailed_timing(const unsigned char *x)
 {
 	unsigned ha, hbl, hso, hspw;
@@ -2713,18 +2762,343 @@ static const struct {
 	{2560, 1600, 120, 16, 10, 203217, 552750, 1},
 };
 
+const char *displayid_vesa_dmt_timings[] = {
+	"640x350@85Hz",
+	"640x400@85Hz",
+	"720x400@85Hz",
+	"640x480@60Hz",
+	"640x480@72Hz",
+	"640x480@75Hz",
+	"640x480@85Hz",
+	"800x600@56Hz",
+	"800x600@60Hz",
+	"800x600@72Hz",
+	"800x600@75Hz",
+	"800x600@85Hz",
+	"800x600@120Hz (RB)",
+	"848x480@60Hz",
+	"1024x768@43Hz (INT)",
+	"1024x768@60Hz",
+	"1024x768@70Hz",
+	"1024x768@75Hz",
+	"1024x768@85Hz",
+	"1024x768@120Hz (RB)",
+	"1152x864@75Hz",
+	"1280x768@60Hz (RB)",
+	"1280x768@60Hz",
+	"1280x768@75Hz",
+	"1280x768@85Hz",
+	"1280x768@120Hz (RB)",
+	"1280x800@60Hz (RB)",
+	"1280x800@60Hz",
+	"1280x800@75Hz",
+	"1280x800@85Hz",
+	"1280x800@120Hz (RB)",
+	"1280x960@60Hz",
+	"1280x960@85Hz",
+	"1280x960@120Hz (RB)",
+	"1280x1024@60Hz",
+	"1280x1024@75Hz",
+	"1280x1024@85Hz",
+	"1280x1024@120Hz (RB)",
+	"1360x768@60Hz",
+	"1360x768@120Hz (RB)",
+	"1400x1050@60Hz (RB)",
+	"1400x1050@60Hz",
+	"1400x1050@75Hz",
+	"1400x1050@85Hz",
+	"1400x1050@120Hz (RB)",
+	"1440x900@60Hz (RB)",
+	"1440x900@60Hz",
+	"1440x900@75Hz",
+	"1440x900@85Hz",
+	"1440x900@120Hz (RB)",
+	"1600x1200@60Hz",
+	"1600x1200@65Hz",
+	"1600x1200@70Hz",
+	"1600x1200@75Hz",
+	"1600x1200@85Hz",
+	"1600x1200@120Hz (RB)",
+	"1680x1050@60Hz (RB)",
+	"1680x1050@60Hz",
+	"1680x1050@75Hz",
+	"1680x1050@85Hz",
+	"1680x1050@120Hz (RB)",
+	"1792x1344@60Hz",
+	"1792x1344@75Hz",
+	"1792x1344@120Hz (RB)",
+	"1856x1392@60Hz",
+	"1856x1392@75Hz",
+	"1856x1392@120Hz (RB)",
+	"1920x1200@60Hz (RB)",
+	"1920x1200@60Hz",
+	"1920x1200@75Hz",
+	"1920x1200@85Hz",
+	"1920x1200@120Hz (RB)",
+	"1920x1440@60Hz",
+	"1920x1440@75Hz",
+	"1920x1440@120Hz (RB)",
+	"2560x1600@60Hz (RB)",
+	"2560x1600@60Hz",
+	"2560x1600@75Hz",
+	"2560x1600@85Hz",
+	"2560x1600@120Hz (RB)",
+};
+
+const char *displayid_cta_timings[] = {
+	"640x480p@59.94/60Hz 4:3",
+	"720x480p@59.94/60Hz 4:3",
+	"720x480p@59.94/60Hz 16:9",
+	"1280x720p@59.94/60Hz 16:9",
+	"1920x1080i@59.94/60Hz 16:9",
+	"720(1440)x480i@59.94/60Hz 4:3",
+	"720(1440)x480i@59.94/60Hz 16:9",
+	"720(1440)x240p@59.94/60Hz 4:3",
+	"720(1440)x240p@59.94/60Hz 16:9",
+	"2880x480i@59.94/60Hz 4:3",
+	"2880x480i@59.94/60Hz 16:9",
+	"2880x240p@59.94/60Hz 4:3",
+	"2880x240p@59.94/60Hz 16:9",
+	"1440x480p@59.94/60Hz 4:3",
+	"1440x480p@59.94/60Hz 16:9",
+	"1920x1080p@59.94/60Hz 16:9",
+	"720x576p@50Hz 4:3",
+	"720x576p@50Hz 16:9",
+	"1280x720p@50Hz 16:9",
+	"1920x1080i@50Hz 16:9",
+	"720(1440)x576i@50Hz 4:3",
+	"720(1440)x576i@50Hz 16:9",
+	"720(1440)x288p@50Hz 4:3",
+	"720(1440)x288p@50Hz 16:9",
+	"2880x576i@50Hz 4:3",
+	"2880x576i@50Hz 16:9",
+	"2880x288p@50Hz 4:3",
+	"2880x288p@50Hz 16:9",
+	"1440x576p@50Hz 4:3",
+	"1440x576p@50Hz 16:9",
+	"1920x1080p@50Hz 16:9",
+	"1920x1080p@23.97/24Hz 16:9",
+	"1920x1080p@25Hz 16:9",
+	"1920x1080p@29.97/30Hz 16:9",
+	"2880x480p@59.94/60Hz 4:3",
+	"2880x480p@59.94/60Hz 16:9",
+	"2880x576p@50Hz 4:3",
+	"2880x576p@50Hz 16:9",
+	"1920x1080i@50Hz 16:9",
+	"1920x1080i@100Hz 16:9",
+	"1280x720p@100Hz 16:9",
+	"720x576p@100Hz 4:3",
+	"720x576p@100Hz 16:9",
+	"720(1440)x576i@100Hz 4:3",
+	"720(1440)x576i@100Hz 16:9",
+	"1920x1080i@119.88/120Hz 16:9",
+	"1280x720p@119.88/120Hz 16:9",
+	"720x480p@119.88/120Hz 4:3",
+	"720x480p@119.88/120Hz 16:9",
+	"720(1440)x480i@119.88/120Hz 4:3",
+	"720(1440)x480i@119.88/120Hz 16:9",
+	"720x576p@200Hz 4:3",
+	"720x576p@200Hz 16:9",
+	"720(1440)x576i@200Hz 4:3",
+	"720(1440)x576i@200Hz 16:9",
+	"720x480p@239.76/240Hz 4:3",
+	"720x480p@239.76/240Hz 16:9",
+	"720(1440)x480i@239.76/240Hz 4:3",
+	"720(1440)x480i@239.76/240Hz 16:9",
+	"1280x720p@23.97/24Hz 16:9",
+	"1280x720p@25Hz 16:9",
+	"1280x720p@29.97/30Hz 16:9",
+	"1920x1080p@120Hz 16:9",
+	"1920x1080p@100Hz 16:9",
+};
+
+static void parse_displayid_timing(const unsigned char *x, int expectedlen, const char** list)
+{
+	int revisionflags=x[1];
+	int len=x[2];
+	if (revisionflags) {
+		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
+	}
+	if (len > expectedlen) {
+		printf("  Length is greater than expected (%d > %d)\n", len, expectedlen);
+	} else if (len < expectedlen) {
+		printf("  Length is less than expected (%d < %d)\n", len, expectedlen);
+	}
+	x += 3;
+	for (int i = 0; i < len * 8; i++) {
+		if (x[i>>3] & (1<<(i&7))) {
+			if ((i>>3) < expectedlen) {
+				printf("  %s\n", list[i]);
+			} else {
+				printf("  #%d\n", i+1);
+			}
+		}
+	}
+}
+
+static void parse_displayid_gp_string(const unsigned char *x)
+{
+	int revisionflags=x[1];
+	if (revisionflags) {
+		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
+	}
+}
+
+static const char *bpc444[] = {"6", "8", "10", "12", "14", "16", NULL, NULL};
+static const char *bpc4xx[] = {"8", "10", "12", "14", "16", NULL, NULL, NULL};
+static const char *audiorates[] = {"32", "44.1", "48", NULL, NULL, NULL, NULL, NULL};
+
+static const char *colorspace_eotf_combinations[] = {
+	"sRGB",
+	"BT.601",
+	"BT.709/BT.1886",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"BT.2020/SMPTE ST 2084"
+};
+
+static const char *colorspace_eotf_reserved[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+static const char *colorspaces[] = {
+	"Undefined",
+	"sRGB",
+	"BT.601",
+	"BT.709",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"Custom"
+};
+
+static const char *eotfs[] = {
+	"Undefined",
+	"sRGB",
+	"BT.601",
+	"BT.1886",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"Gamma function",
+	"SMPTE ST 2084",
+	"Hybrid Log",
+	"Custom"
+};
+
+static void print_flags(const char *label, unsigned char flag_byte, const char **flags, int reverse)
+{
+	if (flag_byte) {
+		printf("%s: ", label);
+		int countflags = 0;
+		for (int i = 0; i < 8; i++) {
+			if (flag_byte & (1<<(reverse?7-i:i))) {
+				if (countflags)
+					printf(", ");
+				if (flags[i])
+					printf("%s", flags[i]);
+				else
+					printf("Undefined(%d)", i);
+				countflags++;
+			}
+		}
+		printf("\n");
+	}
+}
+
+static void parse_displayid_interface_features(const unsigned char *x)
+{
+	int revisionflags=x[1];
+	int len=x[2];
+	if (revisionflags) {
+		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
+	}
+	if (len < 9) {
+		printf("  Length is less than expected (%d < 9)\n", len);
+		printf("  ");
+		hex_block(x + 3, len);
+	} else {
+		print_flags("  Supported bpc for RGB encoding", x[3], bpc444, 0);
+		print_flags("  Supported bpc for YCbCr 4:4:4 encoding", x[4], bpc444, 0);
+		print_flags("  Supported bpc for YCbCr 4:2:2 encoding", x[5], bpc4xx, 0);
+		print_flags("  Supported bpc for YCbCr 4:2:0 encoding", x[6], bpc4xx, 0);
+		if (x[7])
+			printf("  Minimum pixel rate at which YCbCr 4:2:0 encoding is supported: %.3f MHz\n", 74.25 * x[7]);
+		print_flags("  Supported audio capability and features (kHz)", x[8], audiorates, 1);
+		print_flags("  Supported color space and EOTF standard combination 1", x[9], colorspace_eotf_combinations, 0);
+		print_flags("  Supported color space and EOTF standard combination 2", x[10], colorspace_eotf_reserved, 0);
+		int i = 0;
+		if (len >= 9 && x[11] > 0) {
+			printf("  Supported color space and EOTF additional combinations:");
+			for (i = 1; i <= x[11]; i++) {
+				if (i > 7) {
+					printf("\n  Number of additional color space and EOTF combinations (%d) is greater than allowed (7).", x[11]);
+					break;
+				} else if (9 + i > len) {
+					printf("\n  Number of additional color space and EOTF combinations (%d) is too many to fit in block (%d).", x[11], len - 9);
+					break;
+				}
+
+				const char *colorspace = "Out of range";
+				const char *eotf = "Out of range";
+				int colorspace_index = (x[11 + i] >> 4) & 0xf;
+				int eotf_index = x[11 + i] & 0xf;
+				if (colorspace_index < sizeof(colorspaces) / sizeof(colorspaces[0])) {
+					colorspace = colorspaces[colorspace_index];
+				}
+				if (eotf_index < sizeof(eotfs) / sizeof(eotfs[0])) {
+					eotf = eotfs[eotf_index];
+				}
+
+				if (i > 1)
+					printf(", ");
+				if (!strcmp(colorspace, eotf)) {
+					printf("%s", colorspace);
+				} else {
+					printf("%s/%s", colorspace, eotf);
+				}
+			} // for
+			printf("\n");
+		} // x[11]
+		if (len > 9 + i) {
+			printf("  Length is greater than expected (%d > %d)\n", len, 9 + i);
+			printf("  ");
+			hex_block(x + 11 + i, len - 9 - i);
+		} else if (len != 9 + i)  {
+			printf("  Length is unexpected (%d != %d)\n", len, 9 + i);
+		}
+	}
+}
+
+static void parse_displayid_ContainerID(const unsigned char *x)
+{
+	int revisionflags=x[1];
+	int len=x[2];
+	if (revisionflags) {
+		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
+	}
+	x += 3;
+	if (len != 16) {
+		printf("  Length is unexpected (%d != 16)\n", len);
+		printf("  ");
+		hex_block(x, len);
+	} else {
+		printf("  %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]);
+	}
+}
+
 static int parse_displayid(const unsigned char *x)
 {
 	const unsigned char *orig = x;
 	unsigned version = x[1];
 	unsigned length = x[2];
+	unsigned producttype = x[3];
 	unsigned ext_count = x[4];
 	unsigned i;
 
 	cur_block = "DisplayID";
 
-	printf("Length %u, version %u.%u, extension count %u\n",
-	       length, version >> 4, version & 0xf, ext_count);
+	printf("Length %u, version %u.%u, type %u, extension count %u\n",
+	       length, version >> 4, version & 0xf, producttype, ext_count);
 
 	unsigned offset = 5;
 	while (length > 0) {
@@ -2734,33 +3108,49 @@ static int parse_displayid(const unsigned char *x)
 		if (len == 0)
 			break;
 		switch (tag) {
+		
+		// DisplayID 1.3:
 		case 0:
-			printf("Product ID Block\n");
+			printf("Product ID Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 1:
-			printf("Display Parameters Block\n");
+			printf("Display Parameters Block (%02Xh):\n", tag);
+			parse_displayid_parameters(x + offset);
 			break;
 		case 2:
-			printf("Color Characteristics Block\n");
+			printf("Color Characteristics Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 3: {
-			printf("Type 1 Detailed Timings Block\n");
+			printf("Type 1 Detailed Timings Block (%02Xh)\n", tag);
 			for (i = 0; i < len / 20; i++) {
 				parse_displayid_detailed_timing(&x[offset + 3 + (i * 20)]);
 			}
 			break;
 		}
 		case 4:
-			printf("Type 2 Detailed Timings Block\n");
+			printf("Type 2 Detailed Timings Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 5:
-			printf("Type 3 Short Timings Block\n");
+			printf("Type 3 Short Timings Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 6:
-			printf("Type 4 DMT Timings Block\n");
+			printf("Type 4 DMT Timings Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 7:
-			printf("Type 1 VESA DMT Timings Block\n");
+			printf("Type 1 VESA DMT Timings Block (%02Xh)\n", tag);
+			#if 0
+			parse_displayid_timing(x + offset, 10, displayid_vesa_dmt_timings);
+			#else
 			for (i = 0; i < min(len, 10) * 8; i++) {
 				if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
 					printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
@@ -2779,33 +3169,51 @@ static int parse_displayid(const unsigned char *x)
 					max_pixclk_khz = max(max_pixclk_khz, displayid_vesa_dmt[i].pixclk_khz);
 				}
 			}
+			#endif
 			break;
 		case 8:
-			printf("CTA Timings Block\n");
+			printf("CTA Timings Block (%02Xh):\n", tag);
+			parse_displayid_timing(x + offset, 8, displayid_cta_timings);
 			break;
 		case 9:
-			printf("Video Timing Range Block\n");
+			printf("Video Timing Range Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0xa:
-			printf("Product Serial Number Block\n");
+			printf("Product Serial Number Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0xb:
-			printf("GP ASCII String Block\n");
+			printf("GP ASCII String Block (%02Xh): %s\n", tag, extract_string("GP ASCII String", x + offset + 3, &has_valid_GP_ascii_string, len));
+			has_GP_ascii_string = 1;
+			parse_displayid_gp_string(x + offset);
 			break;
 		case 0xc:
-			printf("Display Device Data Block\n");
+			printf("Display Device Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0xd:
-			printf("Interface Power Sequencing Block\n");
+			printf("Interface Power Sequencing Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0xe:
-			printf("Transfer Characteristics Block\n");
+			printf("Transfer Characteristics Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0xf:
-			printf("Display Interface Block\n");
+			printf("Display Interface Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0x10:
-			printf("Stereo Display Interface Block\n");
+			printf("Stereo Display Interface Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		case 0x12: {
 			unsigned capabilities = x[offset + 3];
@@ -2817,7 +3225,7 @@ static int parse_displayid(const unsigned char *x)
 			unsigned tile_height = x[offset + 9] | (x[offset + 10] << 8);
 			unsigned pix_mult = x[offset + 11];
 
-			printf("Tiled Display Topology Block\n");
+			printf("Tiled Display Topology Block (%02Xh)\n", tag);
 			printf("  Capabilities: 0x%08x\n", capabilities);
 			printf("  Num horizontal tiles: %u Num vertical tiles: %u\n", num_h_tile + 1, num_v_tile + 1);
 			printf("  Tile location: %u, %u\n", tile_h_location, tile_v_location);
@@ -2841,8 +3249,80 @@ static int parse_displayid(const unsigned char *x)
 			}
 			break;
 		}
+
+		// DisplayID 2.0
+		case 0x20:
+			printf("Product ID Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x21:
+			printf("Display Parameters Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x22:
+			printf("Type 7 Timing - Detailed Timing Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x23:
+			printf("Type 8 Timing - Enumerated Timing Code Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x24:
+			printf("Type 9 Timing - Formula-based Timing Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x25:
+			printf("Dynamic Video Timing Range Limits Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x26:
+			printf("Display Interface Features Data Block (%02Xh):\n", tag);
+			parse_displayid_interface_features(x + offset);
+			break;
+		case 0x27:
+			printf("Stereo Display Interface Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x28:
+			printf("Tiled Display Topology Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+		case 0x29:
+			printf("ContainerID Data Block (%02Xh):\n", tag);
+			parse_displayid_ContainerID(x + offset);
+			break;
+
+		// 2Ah .. 7Dh RESERVED for Additional VESA-defined Data Blocks
+
+		case 0x7e: // DisplayID 2.0
+		case 0x7f: // DisplayID 1.3
+			printf("Vendor-specific Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+
+		// 7Fh .. 80h RESERVED
+
+		case 0x81:
+			printf("CTA DisplayID Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
+			break;
+
+		// 82h .. FFh RESERVED
+		
 		default:
-			printf("Unknown DisplayID Data Block 0x%x\n", tag);
+			printf("Unknown DisplayID Data Block (%02Xh)\n", tag);
+			printf("  ");
+			hex_block(x + offset + 3, len);
 			break;
 		}
 		length -= len + 3;
@@ -3687,6 +4167,7 @@ static int edid_from_file(const char *from_file, const char *to_file,
 	    !has_valid_range_descriptor ||
 	    (has_name_descriptor && !has_valid_name_descriptor) ||
 	    (has_serial_string && !has_valid_serial_string) ||
+		(has_GP_ascii_string && !has_valid_GP_ascii_string) ||
 	    (has_ascii_string && !has_valid_ascii_string)) {
 		conformant = 0;
 		printf("EDID block does not conform:\n");
@@ -3709,6 +4190,8 @@ static int edid_from_file(const char *from_file, const char *to_file,
 			printf("\tInvalid Monitor Name descriptor\n");
 		if (has_ascii_string && !has_valid_ascii_string)
 			printf("\tInvalid ASCII string\n");
+		if (has_GP_ascii_string && !has_valid_GP_ascii_string)
+			printf("\tInvalid GP ASCII string\n");
 		if (has_serial_string && !has_valid_serial_string)
 			printf("\tInvalid serial string\n");
 	}
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/10] edid-decode: add example EDIDs
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (8 preceding siblings ...)
  2019-11-23 16:46 ` [PATCH 09/10] edid-decode: DisplayID additions joevt
@ 2019-11-23 16:46 ` joevt
  2019-11-24 11:10   ` Hans Verkuil
  2019-11-24 11:12 ` [PATCH 00/10] edid-decode: bug fixes, additions, changes Hans Verkuil
  10 siblings, 1 reply; 19+ messages in thread
From: joevt @ 2019-11-23 16:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, joevt

acer-xv273k*
- contains a broken example of "Display Interface Features Data Block" (appears to be missing the "additional combinations count" byte)
- contains an unknown "Vendor-Specific Data Block"

dell-p2415q-hdmi2.0
- contains an example of "YCbCr 4:2:0 Capability Map Data Block". They have specified that the last two "Video Data Block" resolutions 4K50Hz and 4K60Hz support "YCbCr 4:2:0", while lower refresh rates do not support "YCbCr 4:2:0". For example, HDMI 2.0 has bandwidth for 4K60 8bpc RGB and 4:4:4, but there is not enough bandwidth for 10bpc at 60Hz so 4:2:0 is allowed for that refresh rate.

dell-up2715k-dp1-tile1
- contains an example of "Type 1 VESA DMT Timings Block"

lg-ultrafine-5k*
- contains an example of "Display Parameters Block"
- contains an example of "ContainerID Data Block"

kogan-kaled24144f-hdmi
- contains a type 1 timing with a negative horizontal back porch.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 data/acer-xv273k-dp1                          | Bin 0 -> 384 bytes
 data/acer-xv273k-dp1-tile0                    | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2                          | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2-tile1                    | Bin 0 -> 384 bytes
 data/dell-p2415q-dp-mdp                       | Bin 0 -> 256 bytes
 data/dell-p2415q-hdmi1.4                      | Bin 0 -> 256 bytes
 data/dell-p2415q-hdmi2.0                      | Bin 0 -> 256 bytes
 data/dell-up2715k-dp1-tile1                   | Bin 0 -> 384 bytes
 data/dell-up2715k-dp2-tile0                   | Bin 0 -> 256 bytes
 data/dell-up2715k-mdp                         | Bin 0 -> 256 bytes
 data/dell-up2715k-mdp-switchresx              | Bin 0 -> 384 bytes
 data/kogan-kaled24144f-dp                     | Bin 0 -> 256 bytes
 data/kogan-kaled24144f-hdmi                   | Bin 0 -> 256 bytes
 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 | Bin 0 -> 384 bytes
 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 | Bin 0 -> 256 bytes
 15 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 data/acer-xv273k-dp1
 create mode 100644 data/acer-xv273k-dp1-tile0
 create mode 100644 data/acer-xv273k-dp2
 create mode 100644 data/acer-xv273k-dp2-tile1
 create mode 100644 data/dell-p2415q-dp-mdp
 create mode 100644 data/dell-p2415q-hdmi1.4
 create mode 100644 data/dell-p2415q-hdmi2.0
 create mode 100644 data/dell-up2715k-dp1-tile1
 create mode 100644 data/dell-up2715k-dp2-tile0
 create mode 100644 data/dell-up2715k-mdp
 create mode 100644 data/dell-up2715k-mdp-switchresx
 create mode 100644 data/kogan-kaled24144f-dp
 create mode 100644 data/kogan-kaled24144f-hdmi
 create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
 create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1

diff --git a/data/acer-xv273k-dp1 b/data/acer-xv273k-dp1
new file mode 100644
index 0000000000000000000000000000000000000000..47c1528f315725450aa703e369c8709d5d607a5a
GIT binary patch
literal 384
zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VRL%|Nm@8E(I_Eiu_@S
z2s1J__J)cuDKas8d<<k{W)Tu*6_KC7&J-ILpO9#;%*oE)%*ep-h~YpkGY^9RgGGe`
zLjofcbA}WH10$os1ct|~j~SovGaO)e#>UQ=7$(Es)DTi&;p@Pm@Pj7|>>`Kf3|R{n
zWCd_2%z(Nm{}9811q(t0;I5WqI8Y!|$-uzOs4;5+W6OWO1q}KPiVXQ2b_~o6tPBsn
jF|gFLM*_v<fnt&jj6hK}1`c+1X66U=K+jMPrc3|;_Ayfd

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-dp1-tile0 b/data/acer-xv273k-dp1-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..d93c5d21f10d90f86eb8af00b205537d5b6323ca
GIT binary patch
literal 384
zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VSXS|9>_kmjW07MgA~E
zgc+F|dqYK-ESZ=+J_a%}vj_>ZipWo3XNrxBPe`;^=45AYW@KP^#Bd;&nTJ7u!J<Ne
zA%T&JIYWwpfsxUmg5fdiW5y@^3<nsVv9U8IhRHBlHAoa%=sHB`xI$bc$0*BC6nH^S
zAx|R|Dw2PQVZnk0p#gAL%P|BN2vssLFf(dA_{Pvu&mPI3-yqMB&mqac$iU1nYXKw6
zf4&7kF-4%59Z-aoL5+cfot>HaK|KS55QA8k00Tokdp-xyXABIE&Osa5z$~H(j|l*}
CM^ga+

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-dp2 b/data/acer-xv273k-dp2
new file mode 100644
index 0000000000000000000000000000000000000000..08ac45b3a3a5013c3adef432c6eacfe3b3c65f51
GIT binary patch
literal 384
zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VRL%|Nm@8E(I_Eiu_@S
z2s1J__J)cuDKas8d<<k{W)Tu*6_KC7&J-ILpO9#;%*oE)%*ep-h~YpkGY^9TgGGe`
zLjofcbA}WH10$os1ct|~j~SovGaO)e#>UQ=7$(Es)DTi&;p@Pm@Pj7|>>`Kf3|R{n
zWCd_2%z(Nm{}9811q(t0;I5Wq*iax;$-uzOs4;5+W6OWO1q}KPiVXQ2b_~o6tPBsn
jF|gFLM*_v<fnt&jj6hK}1`c+1X66U=K+jMPrc3|;`_WSY

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-dp2-tile1 b/data/acer-xv273k-dp2-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..8e41faf6cd086876bda4519bc823815ee655013b
GIT binary patch
literal 384
zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VSXS|9>_kmjW07MgA~E
zgc+F|dqYK-ESZ=+J_a%}vj_>ZipWo3XNrxBPe`;^=45AYW@KP^#Bd;&nTJ7v!J<Ne
zA%T&JIYWwpfsxUmg5fdiW5y@^3?~?#v9U8IhRHBlHAoa%=sHB`xI$bc$0*BC6nH^S
zAx|R|Dw2PQVZnk0p#gAL%Q09M2vssLFf(dA_{Pvu&mPI3-yqMB&mqac$iU1nYXKw6
zf4&7kF-4%59Z-aoL5+cfot>HaK|KS55QA8kfB-{1dp-xyXABIE&Osa5z$~H(iwOY5
C$5R0S

literal 0
HcmV?d00001

diff --git a/data/dell-p2415q-dp-mdp b/data/dell-p2415q-dp-mdp
new file mode 100644
index 0000000000000000000000000000000000000000..ffc77f0cbc914500564f7df3b08bddf27e315416
GIT binary patch
literal 256
zcmZSh4+abZYxXU0^6@cHmSSXCYARP@^~iNasPAGm?tqY`-VBBQjSVXgtaP||;330B
z21Z8T3k(ZB6xcP`8JIHgYbY`>NHH)l{AX}Cb}@G|v+y_Y@p0k;iu_@4arN<02rx1+
zG!5iZ0E+x&koA%4F=OCT00YLSOw6($0|ew1SVdTbg#?+I#6;QI7?nBY*_#;|7{cNh
z7A#nx8DO9Qvxdp4L88z?*C9ej6=Ja*qbx&F-~~B_JdIGO$l^4R<K!C<x_}nr0IvZ|
CY&!t}

literal 0
HcmV?d00001

diff --git a/data/dell-p2415q-hdmi1.4 b/data/dell-p2415q-hdmi1.4
new file mode 100644
index 0000000000000000000000000000000000000000..ada8d54fa0dd28c18763f41632502207bda56392
GIT binary patch
literal 256
zcmZSh4+abZYYr@M^6@cHmSSXXFqNx#^~iNasPAGm?tqY`-VBBQjSVXgtaP||;2{Ge
z5G+n(Sn#1hzQI7jl!0GEk%2*qfq~&agS)Ydxtp1Vzk!dB6BkhA4}*)VkB>rtk%^&c
zAeRDA<S&D)k6e!&1D66AFivD**83Pdft7`cU5rsgUPxG7K~agBO;A*sQ=Yw<k%1wX
znTG+W(MEwGftiVs$*Mu3&_dTCLPr&1uN<Q+P((&d0WLC+rG&xYQ$bY2hKMexny@&A
R1q&8v2B5eW=olcV0swnGJOKaz

literal 0
HcmV?d00001

diff --git a/data/dell-p2415q-hdmi2.0 b/data/dell-p2415q-hdmi2.0
new file mode 100644
index 0000000000000000000000000000000000000000..d9f3eca07a46223ae750a025b5bdc77242cd7b62
GIT binary patch
literal 256
zcmZSh4+abZYmP2(^6@cHmSSXXFqNx#^~iNasPAGm?tqY`-VBBQjSVXgtaP||;2{Ge
z5OBO;F!)pu)vzI=i-BK5k%2*qfq~&agS)Ydxtp1Vzk!dB6BkhA4}*)VkB>rtk%^&c
zAeRDA<S&D)k6e!p1D66AFs@}{cK8?}z{<kJF2*P#FC?t4ps2*mCMX&k7oV7*%qh>_
z%*eoy%gn<7)Lo&#kig8un0_Pn2xG+o_9y%d3<nrx8zc&4#1tZQR3R>z$5MjkHo34k
Vh6M{2Xa*Q4m?B&YbPNzQ0RUN@K>+{&

literal 0
HcmV?d00001

diff --git a/data/dell-up2715k-dp1-tile1 b/data/dell-up2715k-dp1-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..424394df2b31b89aae15440c7f11be1d1e3ef86b
GIT binary patch
literal 384
zcmZSh4+abZYqmKATUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
zL0BBaf&~jS0}K>Q8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
zdV@s%GRS(%Z!u%!QUC*{wM@)BAC)=T*_#;|7<?}<Ecj4h*ASqP$^$l40;@ehW2gp9
z3WO>d7=#$angj$G{&U)MgG~my8WI}J3^qO&7+U`G&1cYWkY~u}uw`IkU||r5WnlTw
l2@$jB)&PoeG91~1EEWhBV`t#vXk_4EVPIhr!0P0a69Bq!MF9W+

literal 0
HcmV?d00001

diff --git a/data/dell-up2715k-dp2-tile0 b/data/dell-up2715k-dp2-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..c95095fecc3962145d89efe0ae7caf7c6c1cb6cd
GIT binary patch
literal 256
zcmZSh4+abZYqmKATUr<hNiwo*wNa|DDpFk&V7y(8J0OICfq@YX%;yeRVDNxXz(B#2
zAv8ddfk6tW=s$y-p_j9-sY$4Tg=H`oP~;DTi>r^1LTG@IxuK~yNaQbrthf9YGe#~2
zFkqZeAXLe~AjBZnAOJLg)1Dish5@7t;u>ZK4S`q&mj9gd8T1?E8SJ?=7?>D18IJ5h
P77GN6fi;p!)K35az+)`|

literal 0
HcmV?d00001

diff --git a/data/dell-up2715k-mdp b/data/dell-up2715k-mdp
new file mode 100644
index 0000000000000000000000000000000000000000..835aaa5e87fd431a73579319724a97f4c136db27
GIT binary patch
literal 256
zcmZSh4+abZYj!vUTUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
zf$s%|1s@9R8VnRn8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
zdV@s%GRS(%Z!u%!QUC+SdrZtiA6+M~Ff%bKbF#BHGcqtRSv5!$TIf1N=%_->mJ5qx
tSg>G$W&pxAMp=fUzzcE;c^aWmH9cGxx)dJh3JBOugNR4~Z6geh0swE*IRO9w

literal 0
HcmV?d00001

diff --git a/data/dell-up2715k-mdp-switchresx b/data/dell-up2715k-mdp-switchresx
new file mode 100644
index 0000000000000000000000000000000000000000..d0d425a8d4db26170d21a92ee9e469eb7f9fc318
GIT binary patch
literal 384
zcmZSh4+abZYj!vUTUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
zf$s%|1s@9R8VnRn8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
zdV@s%GRS(%Z!u%!QUC*{yG+bNA6+M~Ff%bKbF#BHGcqtRSv5!$TIf1N=%_->mJ5qx
zSg>G$W&pxAMp=fUzzcE;c^aWmH9cGxx)dJh3JBOugNR4~Z6geh76_^^GcYrVG~_Wd
p{1=|jpx+?RV9y=Mz{J49z|FuFT%K8yoDq~-95IuyVPvS7007E9LjeE)

literal 0
HcmV?d00001

diff --git a/data/kogan-kaled24144f-dp b/data/kogan-kaled24144f-dp
new file mode 100644
index 0000000000000000000000000000000000000000..ce340a6c2fd85e6b459b33d966ad896a2bed6c60
GIT binary patch
literal 256
zcmZSh4+ac6?-*1VfIvoyk!7igLWObr(<Na6^VE0)Le`&V*vv4Mp|PRyK%xK21KkH0
z8JMgZBnmBb9U^pG8Se53GBC&iwf<$$n6P{~7bBMf7yw27FnBxqxVjjb7@C;4aVY>r
z1b`R`Fdk)M<~gX$$<E%)$iSf0)DTc$;p@Pm@Po%}6;P>ESAN5S0t*KR0|iqC2Ny-4
K2$E)MFj)XpaxDP>

literal 0
HcmV?d00001

diff --git a/data/kogan-kaled24144f-hdmi b/data/kogan-kaled24144f-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..f3d4a0f0700493d72de0e2cc8fb91214f2fbf1d6
GIT binary patch
literal 256
zcmZSh4+ac6?-*1VfIvoyk!6vILWN#pz_PG_1!}wjA?r^wY-X6s(Ady;pwNHif$js0
z3`|xH5``AJ4iP%840m}185kshTK_P3JNme~7?~KFn7DB%07d>XXiQkJK#_q<0Stg5
z0zixe7@L@wwLb<-U}a%uViXh-7GYx-6_Zy`=45AYW@KPUzY%+cvEl$jDl-p*0>iBO
zhKd3U1+b-I0g6CNyYd?r6j(So7$}%BIJf{s<TTAdBJxNgOp*)>0xpOufYdbH0NM|7
IDjbLd0L{=k0RR91

literal 0
HcmV?d00001

diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 b/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..13ab607a1763bf26fc8219904f7548963e9fd851
GIT binary patch
literal 384
zcmZSh4+ac!xh2tutyvk^WEoku+9*{t@K0P9<h((RKOjVbfq@YXsGea6_)uWiz@Z?)
z5D}utz#z3anjv7p0?hz~2m=Gde+EkfGrth$C`Thpb4xCu$R7qDcZJZLlA=Vn%)C@C
zrh5fKmCOu`3_Nz?V!R9@4%`71els;01hzbm>%YIiIbm0bRqnr6Ojns1G*r$owEXAu
zXJBuTXUONU1scZA5ZA}RQqKbsV`n!8ivbCuLB#~H{Xz_4O#(pYa@uo)wYmrUmPCWR
e%*-HiVGjexf6n<}YwfuMf%5D`8&6Q7&;$T`UqAr>

literal 0
HcmV?d00001

diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 b/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..abc93a47301db232ea159a68f1e5df5d64db4c27
GIT binary patch
literal 256
zcmZSh4+ac!xh2tutyvk^WEoku+9*{t@K0P9<h((RKOlsGfq@YX0EGmA7!_cO{AaK<
zF!Kv>j&d}zG`HjeD*waa<E{{zQ&N=ZmYJ8z#W=Y@sFIn1k%7lfT#T1N#DP1Y!f&P~
zgTR)@asBrfI4A51vC94Tis`BlgII%r0K<Pydv36$?!mq#(I7`LGl*Q+!@%*Mb3Oxm
TgFJ&hcOX!n9o1pDd2$l~Q#URF

literal 0
HcmV?d00001

-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 09/10] edid-decode: DisplayID additions
  2019-11-23 16:46 ` [PATCH 09/10] edid-decode: DisplayID additions joevt
@ 2019-11-24 10:03   ` Hans Verkuil
  2019-11-25  6:30     ` Joe van Tunen
  0 siblings, 1 reply; 19+ messages in thread
From: Hans Verkuil @ 2019-11-24 10:03 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

Hi Joe,

I have a few comments about this patch. See below:

On 11/23/19 5:46 PM, joevt wrote:
> - Decode "Display Parameters Block". Example in lg-ultrafine-5k*
> - Decode "CTA Timings Block". Similar to "Type 1 VESA DMT Timings Block".
> - Decode "GP ASCII String Block". Example in dell-up2715k-mdp-switchresx
> 
> - Added DisplayID 2.0 tags:
>     - Decode "Display Interface Features Data Block". Example in acer-xv273k* but it appears to be missing the "additional combinations count" byte.
>     - Decode "ContainerID Data Block". Example in lg-ultrafine-5k*
>     - Unknown DisplayID blocks are dumped as hex.
> 
> - Show DisplayID tag hex byte to make it possible to distinguish between DisplayID 1.3 and 2.0 spec blocks of the same name.
> - Show DisplayID product type.
> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  edid-decode.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 504 insertions(+), 21 deletions(-)
> 
> diff --git a/edid-decode.c b/edid-decode.c
> index 2f2f1c5..29f8f88 100644
> --- a/edid-decode.c
> +++ b/edid-decode.c
> @@ -55,6 +55,7 @@ static int did_detailed_timing = 0;
>  static int has_name_descriptor = 0;
>  static int has_serial_string = 0;
>  static int has_ascii_string = 0;
> +static int has_GP_ascii_string = 0;
>  static int has_range_descriptor = 0;
>  static int has_preferred_timing = 0;
>  static int has_valid_checksum = 1;
> @@ -64,6 +65,7 @@ static int has_valid_cvt = 1;
>  static int has_valid_serial_number = 0;
>  static int has_valid_serial_string = 0;
>  static int has_valid_ascii_string = 0;
> +static int has_valid_GP_ascii_string = 0;
>  static int has_valid_name_descriptor = 0;
>  static int has_valid_detailed_blocks = 0;
>  static int has_valid_descriptor_ordering = 1;
> @@ -2528,6 +2530,53 @@ static int parse_cta(const unsigned char *x)
>  	return ret;
>  }
>  
> +
> +static const char *feature_support_flags[] = {
> +	"De-interlacing",
> +	"Support ACP, ISRC1, or ISRC2packets",
> +	"Fixed pixel format",
> +	"Fixed timing",
> +	"Power management (DPM)",
> +	"Audio input override",
> +	"Separate audio inputs provided",
> +	"Audio support on video interface"
> +};
> +
> +static void print_flag_lines(const char *indent, const char *label, unsigned char flag_byte, const char **flags) {
> +	if (flag_byte) {
> +		printf("%s\n", label);
> +		for (int i = 0; i < 8; i++) {
> +			if (flag_byte & (1<<i)) {
> +				printf("%s%s\n", indent, flags[i]);
> +			}
> +		}
> +	}
> +}
> +
> +static void parse_displayid_parameters(const unsigned char *x) {
> +	int revisionflags=x[1];
> +	int len=x[2];
> +	if (revisionflags) {
> +		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
> +	}
> +	if (len != 12) {
> +		printf("  Length is different than expected (%d != 12)\n", len);
> +		printf("  ");
> +		hex_block(x + 3, len);
> +	} else {
> +		printf("  Image size: %.1f mm x %.1f mm\n", ((x[4]<<8) + x[3]) / 10.0, ((x[6]<<8) + x[5]) / 10.0);
> +		printf("  Pixels: %d x %d\n", (x[8]<<8) + x[7], (x[10]<<8) + x[9]);
> +		print_flag_lines("    ", "  Feature support flags:", x[11], feature_support_flags);
> +
> +		if (x[12] != 0xff) {
> +			printf("  Gamma: %.2f\n", ((x[12] + 100.0) / 100.0));
> +		}
> +		printf("  Aspect ratio: %.2f\n", ((x[13] + 100.0) / 100.0));
> +		printf("  Dynamic bpc native: %d\n", (x[14] & 0xf) + 1);
> +		printf("  Dynamic bpc overall: %d\n", ((x[14] >> 4) & 0xf) + 1);
> +	} // else
> +}
> +
>  static void parse_displayid_detailed_timing(const unsigned char *x)
>  {
>  	unsigned ha, hbl, hso, hspw;
> @@ -2713,18 +2762,343 @@ static const struct {
>  	{2560, 1600, 120, 16, 10, 203217, 552750, 1},
>  };
>  
> +const char *displayid_vesa_dmt_timings[] = {
> +	"640x350@85Hz",
> +	"640x400@85Hz",
> +	"720x400@85Hz",
> +	"640x480@60Hz",
> +	"640x480@72Hz",
> +	"640x480@75Hz",
> +	"640x480@85Hz",
> +	"800x600@56Hz",
> +	"800x600@60Hz",
> +	"800x600@72Hz",
> +	"800x600@75Hz",
> +	"800x600@85Hz",
> +	"800x600@120Hz (RB)",
> +	"848x480@60Hz",
> +	"1024x768@43Hz (INT)",
> +	"1024x768@60Hz",
> +	"1024x768@70Hz",
> +	"1024x768@75Hz",
> +	"1024x768@85Hz",
> +	"1024x768@120Hz (RB)",
> +	"1152x864@75Hz",
> +	"1280x768@60Hz (RB)",
> +	"1280x768@60Hz",
> +	"1280x768@75Hz",
> +	"1280x768@85Hz",
> +	"1280x768@120Hz (RB)",
> +	"1280x800@60Hz (RB)",
> +	"1280x800@60Hz",
> +	"1280x800@75Hz",
> +	"1280x800@85Hz",
> +	"1280x800@120Hz (RB)",
> +	"1280x960@60Hz",
> +	"1280x960@85Hz",
> +	"1280x960@120Hz (RB)",
> +	"1280x1024@60Hz",
> +	"1280x1024@75Hz",
> +	"1280x1024@85Hz",
> +	"1280x1024@120Hz (RB)",
> +	"1360x768@60Hz",
> +	"1360x768@120Hz (RB)",
> +	"1400x1050@60Hz (RB)",
> +	"1400x1050@60Hz",
> +	"1400x1050@75Hz",
> +	"1400x1050@85Hz",
> +	"1400x1050@120Hz (RB)",
> +	"1440x900@60Hz (RB)",
> +	"1440x900@60Hz",
> +	"1440x900@75Hz",
> +	"1440x900@85Hz",
> +	"1440x900@120Hz (RB)",
> +	"1600x1200@60Hz",
> +	"1600x1200@65Hz",
> +	"1600x1200@70Hz",
> +	"1600x1200@75Hz",
> +	"1600x1200@85Hz",
> +	"1600x1200@120Hz (RB)",
> +	"1680x1050@60Hz (RB)",
> +	"1680x1050@60Hz",
> +	"1680x1050@75Hz",
> +	"1680x1050@85Hz",
> +	"1680x1050@120Hz (RB)",
> +	"1792x1344@60Hz",
> +	"1792x1344@75Hz",
> +	"1792x1344@120Hz (RB)",
> +	"1856x1392@60Hz",
> +	"1856x1392@75Hz",
> +	"1856x1392@120Hz (RB)",
> +	"1920x1200@60Hz (RB)",
> +	"1920x1200@60Hz",
> +	"1920x1200@75Hz",
> +	"1920x1200@85Hz",
> +	"1920x1200@120Hz (RB)",
> +	"1920x1440@60Hz",
> +	"1920x1440@75Hz",
> +	"1920x1440@120Hz (RB)",
> +	"2560x1600@60Hz (RB)",
> +	"2560x1600@60Hz",
> +	"2560x1600@75Hz",
> +	"2560x1600@85Hz",
> +	"2560x1600@120Hz (RB)",
> +};

Isn't this effectively the same as the displayid_vesa_dmt array?

> +
> +const char *displayid_cta_timings[] = {
> +	"640x480p@59.94/60Hz 4:3",
> +	"720x480p@59.94/60Hz 4:3",
> +	"720x480p@59.94/60Hz 16:9",
> +	"1280x720p@59.94/60Hz 16:9",
> +	"1920x1080i@59.94/60Hz 16:9",
> +	"720(1440)x480i@59.94/60Hz 4:3",
> +	"720(1440)x480i@59.94/60Hz 16:9",
> +	"720(1440)x240p@59.94/60Hz 4:3",
> +	"720(1440)x240p@59.94/60Hz 16:9",
> +	"2880x480i@59.94/60Hz 4:3",
> +	"2880x480i@59.94/60Hz 16:9",
> +	"2880x240p@59.94/60Hz 4:3",
> +	"2880x240p@59.94/60Hz 16:9",
> +	"1440x480p@59.94/60Hz 4:3",
> +	"1440x480p@59.94/60Hz 16:9",
> +	"1920x1080p@59.94/60Hz 16:9",
> +	"720x576p@50Hz 4:3",
> +	"720x576p@50Hz 16:9",
> +	"1280x720p@50Hz 16:9",
> +	"1920x1080i@50Hz 16:9",
> +	"720(1440)x576i@50Hz 4:3",
> +	"720(1440)x576i@50Hz 16:9",
> +	"720(1440)x288p@50Hz 4:3",
> +	"720(1440)x288p@50Hz 16:9",
> +	"2880x576i@50Hz 4:3",
> +	"2880x576i@50Hz 16:9",
> +	"2880x288p@50Hz 4:3",
> +	"2880x288p@50Hz 16:9",
> +	"1440x576p@50Hz 4:3",
> +	"1440x576p@50Hz 16:9",
> +	"1920x1080p@50Hz 16:9",
> +	"1920x1080p@23.97/24Hz 16:9",
> +	"1920x1080p@25Hz 16:9",
> +	"1920x1080p@29.97/30Hz 16:9",
> +	"2880x480p@59.94/60Hz 4:3",
> +	"2880x480p@59.94/60Hz 16:9",
> +	"2880x576p@50Hz 4:3",
> +	"2880x576p@50Hz 16:9",
> +	"1920x1080i@50Hz 16:9",
> +	"1920x1080i@100Hz 16:9",
> +	"1280x720p@100Hz 16:9",
> +	"720x576p@100Hz 4:3",
> +	"720x576p@100Hz 16:9",
> +	"720(1440)x576i@100Hz 4:3",
> +	"720(1440)x576i@100Hz 16:9",
> +	"1920x1080i@119.88/120Hz 16:9",
> +	"1280x720p@119.88/120Hz 16:9",
> +	"720x480p@119.88/120Hz 4:3",
> +	"720x480p@119.88/120Hz 16:9",
> +	"720(1440)x480i@119.88/120Hz 4:3",
> +	"720(1440)x480i@119.88/120Hz 16:9",
> +	"720x576p@200Hz 4:3",
> +	"720x576p@200Hz 16:9",
> +	"720(1440)x576i@200Hz 4:3",
> +	"720(1440)x576i@200Hz 16:9",
> +	"720x480p@239.76/240Hz 4:3",
> +	"720x480p@239.76/240Hz 16:9",
> +	"720(1440)x480i@239.76/240Hz 4:3",
> +	"720(1440)x480i@239.76/240Hz 16:9",
> +	"1280x720p@23.97/24Hz 16:9",
> +	"1280x720p@25Hz 16:9",
> +	"1280x720p@29.97/30Hz 16:9",
> +	"1920x1080p@120Hz 16:9",
> +	"1920x1080p@100Hz 16:9",
> +};

And this is the same as edid_cta_modes1[].

> +
> +static void parse_displayid_timing(const unsigned char *x, int expectedlen, const char** list)
> +{
> +	int revisionflags=x[1];
> +	int len=x[2];
> +	if (revisionflags) {
> +		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
> +	}
> +	if (len > expectedlen) {
> +		printf("  Length is greater than expected (%d > %d)\n", len, expectedlen);
> +	} else if (len < expectedlen) {
> +		printf("  Length is less than expected (%d < %d)\n", len, expectedlen);
> +	}
> +	x += 3;
> +	for (int i = 0; i < len * 8; i++) {
> +		if (x[i>>3] & (1<<(i&7))) {
> +			if ((i>>3) < expectedlen) {
> +				printf("  %s\n", list[i]);
> +			} else {
> +				printf("  #%d\n", i+1);
> +			}
> +		}
> +	}
> +}
> +
> +static void parse_displayid_gp_string(const unsigned char *x)
> +{
> +	int revisionflags=x[1];
> +	if (revisionflags) {
> +		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
> +	}
> +}
> +
> +static const char *bpc444[] = {"6", "8", "10", "12", "14", "16", NULL, NULL};
> +static const char *bpc4xx[] = {"8", "10", "12", "14", "16", NULL, NULL, NULL};
> +static const char *audiorates[] = {"32", "44.1", "48", NULL, NULL, NULL, NULL, NULL};
> +
> +static const char *colorspace_eotf_combinations[] = {
> +	"sRGB",
> +	"BT.601",
> +	"BT.709/BT.1886",
> +	"Adobe RGB",
> +	"DCI-P3",
> +	"BT.2020",
> +	"BT.2020/SMPTE ST 2084"
> +};
> +
> +static const char *colorspace_eotf_reserved[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
> +
> +static const char *colorspaces[] = {
> +	"Undefined",
> +	"sRGB",
> +	"BT.601",
> +	"BT.709",
> +	"Adobe RGB",
> +	"DCI-P3",
> +	"BT.2020",
> +	"Custom"
> +};
> +
> +static const char *eotfs[] = {
> +	"Undefined",
> +	"sRGB",
> +	"BT.601",
> +	"BT.1886",
> +	"Adobe RGB",
> +	"DCI-P3",
> +	"BT.2020",
> +	"Gamma function",
> +	"SMPTE ST 2084",
> +	"Hybrid Log",
> +	"Custom"
> +};
> +
> +static void print_flags(const char *label, unsigned char flag_byte, const char **flags, int reverse)
> +{
> +	if (flag_byte) {
> +		printf("%s: ", label);
> +		int countflags = 0;
> +		for (int i = 0; i < 8; i++) {
> +			if (flag_byte & (1<<(reverse?7-i:i))) {
> +				if (countflags)
> +					printf(", ");
> +				if (flags[i])
> +					printf("%s", flags[i]);
> +				else
> +					printf("Undefined(%d)", i);
> +				countflags++;
> +			}
> +		}
> +		printf("\n");
> +	}
> +}
> +
> +static void parse_displayid_interface_features(const unsigned char *x)
> +{
> +	int revisionflags=x[1];
> +	int len=x[2];
> +	if (revisionflags) {
> +		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
> +	}
> +	if (len < 9) {
> +		printf("  Length is less than expected (%d < 9)\n", len);
> +		printf("  ");
> +		hex_block(x + 3, len);
> +	} else {
> +		print_flags("  Supported bpc for RGB encoding", x[3], bpc444, 0);
> +		print_flags("  Supported bpc for YCbCr 4:4:4 encoding", x[4], bpc444, 0);
> +		print_flags("  Supported bpc for YCbCr 4:2:2 encoding", x[5], bpc4xx, 0);
> +		print_flags("  Supported bpc for YCbCr 4:2:0 encoding", x[6], bpc4xx, 0);
> +		if (x[7])
> +			printf("  Minimum pixel rate at which YCbCr 4:2:0 encoding is supported: %.3f MHz\n", 74.25 * x[7]);
> +		print_flags("  Supported audio capability and features (kHz)", x[8], audiorates, 1);
> +		print_flags("  Supported color space and EOTF standard combination 1", x[9], colorspace_eotf_combinations, 0);
> +		print_flags("  Supported color space and EOTF standard combination 2", x[10], colorspace_eotf_reserved, 0);
> +		int i = 0;
> +		if (len >= 9 && x[11] > 0) {
> +			printf("  Supported color space and EOTF additional combinations:");
> +			for (i = 1; i <= x[11]; i++) {
> +				if (i > 7) {
> +					printf("\n  Number of additional color space and EOTF combinations (%d) is greater than allowed (7).", x[11]);
> +					break;
> +				} else if (9 + i > len) {
> +					printf("\n  Number of additional color space and EOTF combinations (%d) is too many to fit in block (%d).", x[11], len - 9);
> +					break;
> +				}
> +
> +				const char *colorspace = "Out of range";
> +				const char *eotf = "Out of range";
> +				int colorspace_index = (x[11 + i] >> 4) & 0xf;
> +				int eotf_index = x[11 + i] & 0xf;
> +				if (colorspace_index < sizeof(colorspaces) / sizeof(colorspaces[0])) {
> +					colorspace = colorspaces[colorspace_index];
> +				}
> +				if (eotf_index < sizeof(eotfs) / sizeof(eotfs[0])) {
> +					eotf = eotfs[eotf_index];
> +				}
> +
> +				if (i > 1)
> +					printf(", ");
> +				if (!strcmp(colorspace, eotf)) {
> +					printf("%s", colorspace);
> +				} else {
> +					printf("%s/%s", colorspace, eotf);
> +				}
> +			} // for
> +			printf("\n");
> +		} // x[11]
> +		if (len > 9 + i) {
> +			printf("  Length is greater than expected (%d > %d)\n", len, 9 + i);
> +			printf("  ");
> +			hex_block(x + 11 + i, len - 9 - i);
> +		} else if (len != 9 + i)  {
> +			printf("  Length is unexpected (%d != %d)\n", len, 9 + i);
> +		}
> +	}
> +}
> +
> +static void parse_displayid_ContainerID(const unsigned char *x)
> +{
> +	int revisionflags=x[1];
> +	int len=x[2];
> +	if (revisionflags) {
> +		printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
> +	}
> +	x += 3;
> +	if (len != 16) {
> +		printf("  Length is unexpected (%d != 16)\n", len);
> +		printf("  ");
> +		hex_block(x, len);
> +	} else {
> +		printf("  %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]);
> +	}
> +}
> +
>  static int parse_displayid(const unsigned char *x)
>  {
>  	const unsigned char *orig = x;
>  	unsigned version = x[1];
>  	unsigned length = x[2];
> +	unsigned producttype = x[3];
>  	unsigned ext_count = x[4];
>  	unsigned i;
>  
>  	cur_block = "DisplayID";
>  
> -	printf("Length %u, version %u.%u, extension count %u\n",
> -	       length, version >> 4, version & 0xf, ext_count);
> +	printf("Length %u, version %u.%u, type %u, extension count %u\n",
> +	       length, version >> 4, version & 0xf, producttype, ext_count);
>  
>  	unsigned offset = 5;
>  	while (length > 0) {
> @@ -2734,33 +3108,49 @@ static int parse_displayid(const unsigned char *x)
>  		if (len == 0)
>  			break;
>  		switch (tag) {
> +		
> +		// DisplayID 1.3:
>  		case 0:
> -			printf("Product ID Block\n");
> +			printf("Product ID Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 1:
> -			printf("Display Parameters Block\n");
> +			printf("Display Parameters Block (%02Xh):\n", tag);
> +			parse_displayid_parameters(x + offset);
>  			break;
>  		case 2:
> -			printf("Color Characteristics Block\n");
> +			printf("Color Characteristics Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 3: {
> -			printf("Type 1 Detailed Timings Block\n");
> +			printf("Type 1 Detailed Timings Block (%02Xh)\n", tag);
>  			for (i = 0; i < len / 20; i++) {
>  				parse_displayid_detailed_timing(&x[offset + 3 + (i * 20)]);
>  			}
>  			break;
>  		}
>  		case 4:
> -			printf("Type 2 Detailed Timings Block\n");
> +			printf("Type 2 Detailed Timings Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 5:
> -			printf("Type 3 Short Timings Block\n");
> +			printf("Type 3 Short Timings Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 6:
> -			printf("Type 4 DMT Timings Block\n");
> +			printf("Type 4 DMT Timings Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 7:
> -			printf("Type 1 VESA DMT Timings Block\n");
> +			printf("Type 1 VESA DMT Timings Block (%02Xh)\n", tag);
> +			#if 0
> +			parse_displayid_timing(x + offset, 10, displayid_vesa_dmt_timings);

What is the reason for the #if 0?

I now get a warning that displayid_vesa_dmt_timings is unused.

> +			#else
>  			for (i = 0; i < min(len, 10) * 8; i++) {
>  				if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
>  					printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
> @@ -2779,33 +3169,51 @@ static int parse_displayid(const unsigned char *x)
>  					max_pixclk_khz = max(max_pixclk_khz, displayid_vesa_dmt[i].pixclk_khz);
>  				}
>  			}
> +			#endif
>  			break;
>  		case 8:
> -			printf("CTA Timings Block\n");
> +			printf("CTA Timings Block (%02Xh):\n", tag);
> +			parse_displayid_timing(x + offset, 8, displayid_cta_timings);
>  			break;
>  		case 9:
> -			printf("Video Timing Range Block\n");
> +			printf("Video Timing Range Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0xa:
> -			printf("Product Serial Number Block\n");
> +			printf("Product Serial Number Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0xb:
> -			printf("GP ASCII String Block\n");
> +			printf("GP ASCII String Block (%02Xh): %s\n", tag, extract_string("GP ASCII String", x + offset + 3, &has_valid_GP_ascii_string, len));
> +			has_GP_ascii_string = 1;
> +			parse_displayid_gp_string(x + offset);
>  			break;
>  		case 0xc:
> -			printf("Display Device Data Block\n");
> +			printf("Display Device Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0xd:
> -			printf("Interface Power Sequencing Block\n");
> +			printf("Interface Power Sequencing Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0xe:
> -			printf("Transfer Characteristics Block\n");
> +			printf("Transfer Characteristics Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0xf:
> -			printf("Display Interface Block\n");
> +			printf("Display Interface Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0x10:
> -			printf("Stereo Display Interface Block\n");
> +			printf("Stereo Display Interface Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		case 0x12: {
>  			unsigned capabilities = x[offset + 3];
> @@ -2817,7 +3225,7 @@ static int parse_displayid(const unsigned char *x)
>  			unsigned tile_height = x[offset + 9] | (x[offset + 10] << 8);
>  			unsigned pix_mult = x[offset + 11];
>  
> -			printf("Tiled Display Topology Block\n");
> +			printf("Tiled Display Topology Block (%02Xh)\n", tag);
>  			printf("  Capabilities: 0x%08x\n", capabilities);
>  			printf("  Num horizontal tiles: %u Num vertical tiles: %u\n", num_h_tile + 1, num_v_tile + 1);
>  			printf("  Tile location: %u, %u\n", tile_h_location, tile_v_location);
> @@ -2841,8 +3249,80 @@ static int parse_displayid(const unsigned char *x)
>  			}
>  			break;
>  		}
> +
> +		// DisplayID 2.0
> +		case 0x20:
> +			printf("Product ID Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x21:
> +			printf("Display Parameters Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x22:
> +			printf("Type 7 Timing - Detailed Timing Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x23:
> +			printf("Type 8 Timing - Enumerated Timing Code Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x24:
> +			printf("Type 9 Timing - Formula-based Timing Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x25:
> +			printf("Dynamic Video Timing Range Limits Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x26:
> +			printf("Display Interface Features Data Block (%02Xh):\n", tag);
> +			parse_displayid_interface_features(x + offset);
> +			break;
> +		case 0x27:
> +			printf("Stereo Display Interface Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x28:
> +			printf("Tiled Display Topology Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +		case 0x29:
> +			printf("ContainerID Data Block (%02Xh):\n", tag);
> +			parse_displayid_ContainerID(x + offset);
> +			break;
> +
> +		// 2Ah .. 7Dh RESERVED for Additional VESA-defined Data Blocks
> +
> +		case 0x7e: // DisplayID 2.0
> +		case 0x7f: // DisplayID 1.3
> +			printf("Vendor-specific Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +
> +		// 7Fh .. 80h RESERVED
> +
> +		case 0x81:
> +			printf("CTA DisplayID Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
> +			break;
> +
> +		// 82h .. FFh RESERVED
> +		
>  		default:
> -			printf("Unknown DisplayID Data Block 0x%x\n", tag);
> +			printf("Unknown DisplayID Data Block (%02Xh)\n", tag);
> +			printf("  ");
> +			hex_block(x + offset + 3, len);
>  			break;
>  		}
>  		length -= len + 3;
> @@ -3687,6 +4167,7 @@ static int edid_from_file(const char *from_file, const char *to_file,
>  	    !has_valid_range_descriptor ||
>  	    (has_name_descriptor && !has_valid_name_descriptor) ||
>  	    (has_serial_string && !has_valid_serial_string) ||
> +		(has_GP_ascii_string && !has_valid_GP_ascii_string) ||
>  	    (has_ascii_string && !has_valid_ascii_string)) {
>  		conformant = 0;
>  		printf("EDID block does not conform:\n");
> @@ -3709,6 +4190,8 @@ static int edid_from_file(const char *from_file, const char *to_file,
>  			printf("\tInvalid Monitor Name descriptor\n");
>  		if (has_ascii_string && !has_valid_ascii_string)
>  			printf("\tInvalid ASCII string\n");
> +		if (has_GP_ascii_string && !has_valid_GP_ascii_string)
> +			printf("\tInvalid GP ASCII string\n");
>  		if (has_serial_string && !has_valid_serial_string)
>  			printf("\tInvalid serial string\n");
>  	}
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb
  2019-11-23 16:45 ` [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb joevt
@ 2019-11-24 10:26   ` Hans Verkuil
  2019-11-25  6:32     ` Joe van Tunen
  0 siblings, 1 reply; 19+ messages in thread
From: Hans Verkuil @ 2019-11-24 10:26 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 11/23/19 5:45 PM, joevt wrote:
> - "YCbCr 4:2:0 capability map data block" now outputs the modes that support YCbCr 4:2:0 instead of just indexes of the modes. Indexes refer to timings in "Video Data Block".
> - Warnings are included in the output if "Video Data Block" doesn't appear before "YCbCr 4:2:0 Capability Map Data Block" or if the index is outside the range defined in the "Video Data Block".
> - Moved inner loop of cta_svd into a new function cta_svd_one so that it can be reused by cta_y420cmdb.

This isn't sufficient. There may be multiple SVD blocks in the EDID, and that's not taken
into account.

Also, I can't find any requirement in the CTA-861 spec that the YCbCr 4:2:0 Capability
Map Data Block has to appear after all SVD blocks. So the final check if the Y420CMDB
block references invalid SVDs should be postponed to the end of the CTA block.

I also found a pre-existing bug: if length == 0 in cta_y420cmdb() then that means that
all SVDs support 4:2:0. That should be added to cta_y420cmdb().

Regards,

	Hans

> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  edid-decode.c | 44 +++++++++++++++++++++++++++++++++++---------
>  1 file changed, 35 insertions(+), 9 deletions(-)
> 
> diff --git a/edid-decode.c b/edid-decode.c
> index b833178..4d6fe29 100644
> --- a/edid-decode.c
> +++ b/edid-decode.c
> @@ -1454,13 +1454,10 @@ static const struct edid_cta_mode *vic_to_mode(unsigned char vic)
>  	return NULL;
>  }
>  
> -static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
> +static void cta_svd_one(const unsigned char *x, int for_ycbcr420)
>  {
> -	unsigned i;
> -
> -	for (i = 0; i < n; i++)  {
>  		const struct edid_cta_mode *vicmode = NULL;
> -		unsigned char svd = x[i];
> +		unsigned char svd = x[0];
>  		unsigned char native;
>  		unsigned char vic;
>  		const char *mode;
> @@ -1468,7 +1465,7 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
>  		unsigned clock_khz = 0;
>  
>  		if ((svd & 0x7f) == 0)
> -			continue;
> +			return;
>  
>  		if ((svd - 1) & 0x40) {
>  			vic = svd;
> @@ -1511,10 +1508,23 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
>  		if (vic == 1)
>  			has_cta861_vic_1 = 1;
>  	}
> +
> +static void cta_svd(const unsigned char *x, int n, int for_ycbcr420)
> +{
> +	for (unsigned i = 0; i < n; i++)  {
> +		printf("    ");
> +		cta_svd_one(x+i, for_ycbcr420);
> +		printf("\n");
> +	}
>  }
>  
> +unsigned const char *last_cta_video_block_start = NULL;
> +unsigned last_cta_video_block_length = 0;
> +
>  static void cta_video_block(const unsigned char *x, unsigned length)
>  {
> +	last_cta_video_block_start = x;
> +	last_cta_video_block_length = length;
>  	cta_svd(x, length, 0);
>  }
>  
> @@ -1531,9 +1541,25 @@ static void cta_y420cmdb(const unsigned char *x, unsigned length)
>  		uint8_t v = x[0 + i];
>  		unsigned j;
>  
> -		for (j = 0; j < 8; j++)
> -			if (v & (1 << j))
> -				printf("    VSD Index %u\n", i * 8 + j);
> +		for (j = 0; j < 8; j++) {
> +			if (v & (1 << j)) {
> +				unsigned k = i * 8 + j;
> +				printf("    VSD Index %u", k + 1);
> +				if (k >= last_cta_video_block_length) {
> +					if (last_cta_video_block_start) {
> +						printf(" (out of range)");
> +					} else {
> +						printf(" (missing CTA video block)");
> +					}
> +				}
> +				else
> +				{
> +					printf(" ");
> +					cta_svd_one(last_cta_video_block_start+k, 0);
> +				}
> +				printf("\n");
> +			}
> +		}
>  	}
>  }
>  
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 10/10] edid-decode: add example EDIDs
  2019-11-23 16:46 ` [PATCH 10/10] edid-decode: add example EDIDs joevt
@ 2019-11-24 11:10   ` Hans Verkuil
  0 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2019-11-24 11:10 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 11/23/19 5:46 PM, joevt wrote:
> acer-xv273k*
> - contains a broken example of "Display Interface Features Data Block" (appears to be missing the "additional combinations count" byte)
> - contains an unknown "Vendor-Specific Data Block"

Drop data/acer-xv273k-dp2 since it does not add anything. And rename
data/acer-xv273k-dp1 to data/acer-xv273k-dp

> 
> dell-p2415q-hdmi2.0
> - contains an example of "YCbCr 4:2:0 Capability Map Data Block". They have specified that the last two "Video Data Block" resolutions 4K50Hz and 4K60Hz support "YCbCr 4:2:0", while lower refresh rates do not support "YCbCr 4:2:0". For example, HDMI 2.0 has bandwidth for 4K60 8bpc RGB and 4:4:4, but there is not enough bandwidth for 10bpc at 60Hz so 4:2:0 is allowed for that refresh rate.
> 
> dell-up2715k-dp1-tile1
> - contains an example of "Type 1 VESA DMT Timings Block"
> 
> lg-ultrafine-5k*
> - contains an example of "Display Parameters Block"
> - contains an example of "ContainerID Data Block"
> 
> kogan-kaled24144f-hdmi
> - contains a type 1 timing with a negative horizontal back porch.
> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  data/acer-xv273k-dp1                          | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp1-tile0                    | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp2                          | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp2-tile1                    | Bin 0 -> 384 bytes
>  data/dell-p2415q-dp-mdp                       | Bin 0 -> 256 bytes

Just to confirm: mdp stands for mini-DisplayPort?

I prefer to drop the mdp bit and just call it -dp since it's still a
DisplayPort, just a smaller connector.

>  data/dell-p2415q-hdmi1.4                      | Bin 0 -> 256 bytes
>  data/dell-p2415q-hdmi2.0                      | Bin 0 -> 256 bytes
>  data/dell-up2715k-dp1-tile1                   | Bin 0 -> 384 bytes
>  data/dell-up2715k-dp2-tile0                   | Bin 0 -> 256 bytes
>  data/dell-up2715k-mdp                         | Bin 0 -> 256 bytes
>  data/dell-up2715k-mdp-switchresx              | Bin 0 -> 384 bytes

Same here, rename mdp to dp.

Regards,

	Hans

>  data/kogan-kaled24144f-dp                     | Bin 0 -> 256 bytes
>  data/kogan-kaled24144f-hdmi                   | Bin 0 -> 256 bytes
>  data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 | Bin 0 -> 384 bytes
>  data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 | Bin 0 -> 256 bytes
>  15 files changed, 0 insertions(+), 0 deletions(-)
>  create mode 100644 data/acer-xv273k-dp1
>  create mode 100644 data/acer-xv273k-dp1-tile0
>  create mode 100644 data/acer-xv273k-dp2
>  create mode 100644 data/acer-xv273k-dp2-tile1
>  create mode 100644 data/dell-p2415q-dp-mdp
>  create mode 100644 data/dell-p2415q-hdmi1.4
>  create mode 100644 data/dell-p2415q-hdmi2.0
>  create mode 100644 data/dell-up2715k-dp1-tile1
>  create mode 100644 data/dell-up2715k-dp2-tile0
>  create mode 100644 data/dell-up2715k-mdp
>  create mode 100644 data/dell-up2715k-mdp-switchresx
>  create mode 100644 data/kogan-kaled24144f-dp
>  create mode 100644 data/kogan-kaled24144f-hdmi
>  create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
>  create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
> 
> diff --git a/data/acer-xv273k-dp1 b/data/acer-xv273k-dp1
> new file mode 100644
> index 0000000000000000000000000000000000000000..47c1528f315725450aa703e369c8709d5d607a5a
> GIT binary patch
> literal 384
> zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
> z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VRL%|Nm@8E(I_Eiu_@S
> z2s1J__J)cuDKas8d<<k{W)Tu*6_KC7&J-ILpO9#;%*oE)%*ep-h~YpkGY^9RgGGe`
> zLjofcbA}WH10$os1ct|~j~SovGaO)e#>UQ=7$(Es)DTi&;p@Pm@Pj7|>>`Kf3|R{n
> zWCd_2%z(Nm{}9811q(t0;I5WqI8Y!|$-uzOs4;5+W6OWO1q}KPiVXQ2b_~o6tPBsn
> jF|gFLM*_v<fnt&jj6hK}1`c+1X66U=K+jMPrc3|;_Ayfd
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/acer-xv273k-dp1-tile0 b/data/acer-xv273k-dp1-tile0
> new file mode 100644
> index 0000000000000000000000000000000000000000..d93c5d21f10d90f86eb8af00b205537d5b6323ca
> GIT binary patch
> literal 384
> zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
> z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VSXS|9>_kmjW07MgA~E
> zgc+F|dqYK-ESZ=+J_a%}vj_>ZipWo3XNrxBPe`;^=45AYW@KP^#Bd;&nTJ7u!J<Ne
> zA%T&JIYWwpfsxUmg5fdiW5y@^3<nsVv9U8IhRHBlHAoa%=sHB`xI$bc$0*BC6nH^S
> zAx|R|Dw2PQVZnk0p#gAL%P|BN2vssLFf(dA_{Pvu&mPI3-yqMB&mqac$iU1nYXKw6
> zf4&7kF-4%59Z-aoL5+cfot>HaK|KS55QA8k00Tokdp-xyXABIE&Osa5z$~H(j|l*}
> CM^ga+
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/acer-xv273k-dp2 b/data/acer-xv273k-dp2
> new file mode 100644
> index 0000000000000000000000000000000000000000..08ac45b3a3a5013c3adef432c6eacfe3b3c65f51
> GIT binary patch
> literal 384
> zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
> z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VRL%|Nm@8E(I_Eiu_@S
> z2s1J__J)cuDKas8d<<k{W)Tu*6_KC7&J-ILpO9#;%*oE)%*ep-h~YpkGY^9TgGGe`
> zLjofcbA}WH10$os1ct|~j~SovGaO)e#>UQ=7$(Es)DTi&;p@Pm@Pj7|>>`Kf3|R{n
> zWCd_2%z(Nm{}9811q(t0;I5Wq*iax;$-uzOs4;5+W6OWO1q}KPiVXQ2b_~o6tPBsn
> jF|gFLM*_v<fnt&jj6hK}1`c+1X66U=K+jMPrc3|;`_WSY
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/acer-xv273k-dp2-tile1 b/data/acer-xv273k-dp2-tile1
> new file mode 100644
> index 0000000000000000000000000000000000000000..8e41faf6cd086876bda4519bc823815ee655013b
> GIT binary patch
> literal 384
> zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
> z7#V#pFf8~`VAo)vV9F30pvb@=wIvNCBHzHFAi)9=VPIhR%VSXS|9>_kmjW07MgA~E
> zgc+F|dqYK-ESZ=+J_a%}vj_>ZipWo3XNrxBPe`;^=45AYW@KP^#Bd;&nTJ7v!J<Ne
> zA%T&JIYWwpfsxUmg5fdiW5y@^3?~?#v9U8IhRHBlHAoa%=sHB`xI$bc$0*BC6nH^S
> zAx|R|Dw2PQVZnk0p#gAL%Q09M2vssLFf(dA_{Pvu&mPI3-yqMB&mqac$iU1nYXKw6
> zf4&7kF-4%59Z-aoL5+cfot>HaK|KS55QA8kfB-{1dp-xyXABIE&Osa5z$~H(iwOY5
> C$5R0S
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-p2415q-dp-mdp b/data/dell-p2415q-dp-mdp
> new file mode 100644
> index 0000000000000000000000000000000000000000..ffc77f0cbc914500564f7df3b08bddf27e315416
> GIT binary patch
> literal 256
> zcmZSh4+abZYxXU0^6@cHmSSXCYARP@^~iNasPAGm?tqY`-VBBQjSVXgtaP||;330B
> z21Z8T3k(ZB6xcP`8JIHgYbY`>NHH)l{AX}Cb}@G|v+y_Y@p0k;iu_@4arN<02rx1+
> zG!5iZ0E+x&koA%4F=OCT00YLSOw6($0|ew1SVdTbg#?+I#6;QI7?nBY*_#;|7{cNh
> z7A#nx8DO9Qvxdp4L88z?*C9ej6=Ja*qbx&F-~~B_JdIGO$l^4R<K!C<x_}nr0IvZ|
> CY&!t}
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-p2415q-hdmi1.4 b/data/dell-p2415q-hdmi1.4
> new file mode 100644
> index 0000000000000000000000000000000000000000..ada8d54fa0dd28c18763f41632502207bda56392
> GIT binary patch
> literal 256
> zcmZSh4+abZYYr@M^6@cHmSSXXFqNx#^~iNasPAGm?tqY`-VBBQjSVXgtaP||;2{Ge
> z5G+n(Sn#1hzQI7jl!0GEk%2*qfq~&agS)Ydxtp1Vzk!dB6BkhA4}*)VkB>rtk%^&c
> zAeRDA<S&D)k6e!&1D66AFivD**83Pdft7`cU5rsgUPxG7K~agBO;A*sQ=Yw<k%1wX
> znTG+W(MEwGftiVs$*Mu3&_dTCLPr&1uN<Q+P((&d0WLC+rG&xYQ$bY2hKMexny@&A
> R1q&8v2B5eW=olcV0swnGJOKaz
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-p2415q-hdmi2.0 b/data/dell-p2415q-hdmi2.0
> new file mode 100644
> index 0000000000000000000000000000000000000000..d9f3eca07a46223ae750a025b5bdc77242cd7b62
> GIT binary patch
> literal 256
> zcmZSh4+abZYmP2(^6@cHmSSXXFqNx#^~iNasPAGm?tqY`-VBBQjSVXgtaP||;2{Ge
> z5OBO;F!)pu)vzI=i-BK5k%2*qfq~&agS)Ydxtp1Vzk!dB6BkhA4}*)VkB>rtk%^&c
> zAeRDA<S&D)k6e!p1D66AFs@}{cK8?}z{<kJF2*P#FC?t4ps2*mCMX&k7oV7*%qh>_
> z%*eoy%gn<7)Lo&#kig8un0_Pn2xG+o_9y%d3<nrx8zc&4#1tZQR3R>z$5MjkHo34k
> Vh6M{2Xa*Q4m?B&YbPNzQ0RUN@K>+{&
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-up2715k-dp1-tile1 b/data/dell-up2715k-dp1-tile1
> new file mode 100644
> index 0000000000000000000000000000000000000000..424394df2b31b89aae15440c7f11be1d1e3ef86b
> GIT binary patch
> literal 384
> zcmZSh4+abZYqmKATUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
> zL0BBaf&~jS0}K>Q8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
> zdV@s%GRS(%Z!u%!QUC*{wM@)BAC)=T*_#;|7<?}<Ecj4h*ASqP$^$l40;@ehW2gp9
> z3WO>d7=#$angj$G{&U)MgG~my8WI}J3^qO&7+U`G&1cYWkY~u}uw`IkU||r5WnlTw
> l2@$jB)&PoeG91~1EEWhBV`t#vXk_4EVPIhr!0P0a69Bq!MF9W+
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-up2715k-dp2-tile0 b/data/dell-up2715k-dp2-tile0
> new file mode 100644
> index 0000000000000000000000000000000000000000..c95095fecc3962145d89efe0ae7caf7c6c1cb6cd
> GIT binary patch
> literal 256
> zcmZSh4+abZYqmKATUr<hNiwo*wNa|DDpFk&V7y(8J0OICfq@YX%;yeRVDNxXz(B#2
> zAv8ddfk6tW=s$y-p_j9-sY$4Tg=H`oP~;DTi>r^1LTG@IxuK~yNaQbrthf9YGe#~2
> zFkqZeAXLe~AjBZnAOJLg)1Dish5@7t;u>ZK4S`q&mj9gd8T1?E8SJ?=7?>D18IJ5h
> P77GN6fi;p!)K35az+)`|
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-up2715k-mdp b/data/dell-up2715k-mdp
> new file mode 100644
> index 0000000000000000000000000000000000000000..835aaa5e87fd431a73579319724a97f4c136db27
> GIT binary patch
> literal 256
> zcmZSh4+abZYj!vUTUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
> zf$s%|1s@9R8VnRn8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
> zdV@s%GRS(%Z!u%!QUC+SdrZtiA6+M~Ff%bKbF#BHGcqtRSv5!$TIf1N=%_->mJ5qx
> tSg>G$W&pxAMp=fUzzcE;c^aWmH9cGxx)dJh3JBOugNR4~Z6geh0swE*IRO9w
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/dell-up2715k-mdp-switchresx b/data/dell-up2715k-mdp-switchresx
> new file mode 100644
> index 0000000000000000000000000000000000000000..d0d425a8d4db26170d21a92ee9e469eb7f9fc318
> GIT binary patch
> literal 384
> zcmZSh4+abZYj!vUTUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
> zf$s%|1s@9R8VnRn8A1aT85pD(7#RLDxEXpm`<j}B8dz8ca{)#EFu1t-_$Y)17?~TI
> zdV@s%GRS(%Z!u%!QUC*{yG+bNA6+M~Ff%bKbF#BHGcqtRSv5!$TIf1N=%_->mJ5qx
> zSg>G$W&pxAMp=fUzzcE;c^aWmH9cGxx)dJh3JBOugNR4~Z6geh76_^^GcYrVG~_Wd
> p{1=|jpx+?RV9y=Mz{J49z|FuFT%K8yoDq~-95IuyVPvS7007E9LjeE)
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/kogan-kaled24144f-dp b/data/kogan-kaled24144f-dp
> new file mode 100644
> index 0000000000000000000000000000000000000000..ce340a6c2fd85e6b459b33d966ad896a2bed6c60
> GIT binary patch
> literal 256
> zcmZSh4+ac6?-*1VfIvoyk!7igLWObr(<Na6^VE0)Le`&V*vv4Mp|PRyK%xK21KkH0
> z8JMgZBnmBb9U^pG8Se53GBC&iwf<$$n6P{~7bBMf7yw27FnBxqxVjjb7@C;4aVY>r
> z1b`R`Fdk)M<~gX$$<E%)$iSf0)DTc$;p@Pm@Po%}6;P>ESAN5S0t*KR0|iqC2Ny-4
> K2$E)MFj)XpaxDP>
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/kogan-kaled24144f-hdmi b/data/kogan-kaled24144f-hdmi
> new file mode 100644
> index 0000000000000000000000000000000000000000..f3d4a0f0700493d72de0e2cc8fb91214f2fbf1d6
> GIT binary patch
> literal 256
> zcmZSh4+ac6?-*1VfIvoyk!6vILWN#pz_PG_1!}wjA?r^wY-X6s(Ady;pwNHif$js0
> z3`|xH5``AJ4iP%840m}185kshTK_P3JNme~7?~KFn7DB%07d>XXiQkJK#_q<0Stg5
> z0zixe7@L@wwLb<-U}a%uViXh-7GYx-6_Zy`=45AYW@KPUzY%+cvEl$jDl-p*0>iBO
> zhKd3U1+b-I0g6CNyYd?r6j(So7$}%BIJf{s<TTAdBJxNgOp*)>0xpOufYdbH0NM|7
> IDjbLd0L{=k0RR91
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 b/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
> new file mode 100644
> index 0000000000000000000000000000000000000000..13ab607a1763bf26fc8219904f7548963e9fd851
> GIT binary patch
> literal 384
> zcmZSh4+ac!xh2tutyvk^WEoku+9*{t@K0P9<h((RKOjVbfq@YXsGea6_)uWiz@Z?)
> z5D}utz#z3anjv7p0?hz~2m=Gde+EkfGrth$C`Thpb4xCu$R7qDcZJZLlA=Vn%)C@C
> zrh5fKmCOu`3_Nz?V!R9@4%`71els;01hzbm>%YIiIbm0bRqnr6Ojns1G*r$owEXAu
> zXJBuTXUONU1scZA5ZA}RQqKbsV`n!8ivbCuLB#~H{Xz_4O#(pYa@uo)wYmrUmPCWR
> e%*-HiVGjexf6n<}YwfuMf%5D`8&6Q7&;$T`UqAr>
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 b/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
> new file mode 100644
> index 0000000000000000000000000000000000000000..abc93a47301db232ea159a68f1e5df5d64db4c27
> GIT binary patch
> literal 256
> zcmZSh4+ac!xh2tutyvk^WEoku+9*{t@K0P9<h((RKOlsGfq@YX0EGmA7!_cO{AaK<
> zF!Kv>j&d}zG`HjeD*waa<E{{zQ&N=ZmYJ8z#W=Y@sFIn1k%7lfT#T1N#DP1Y!f&P~
> zgTR)@asBrfI4A51vC94Tis`BlgII%r0K<Pydv36$?!mq#(I7`LGl*Q+!@%*Mb3Oxm
> TgFJ&hcOX!n9o1pDd2$l~Q#URF
> 
> literal 0
> HcmV?d00001
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 00/10] edid-decode: bug fixes, additions, changes
  2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
                   ` (9 preceding siblings ...)
  2019-11-23 16:46 ` [PATCH 10/10] edid-decode: add example EDIDs joevt
@ 2019-11-24 11:12 ` Hans Verkuil
  10 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2019-11-24 11:12 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

Hi Joe,

On 11/23/19 5:45 PM, joevt wrote:
> This patchset is a set of bug-fixes, additions, and changes I've made while examining various EDIDs I have encountered.
> 
> joevt (10):
>   edid-decode: change horizontal refresh rates to kHz
>   edid-decode: correct horizontal range in Monitor Ranges
>   edid-decode: correct calculation of DisplayID type 1 timings
>   edid-decode: add front porch, pulse width, and back porch
>   edid-decode: output timings for YCbCr 4:2:0 cmdb
>   edid-decode: Dump hex of unknown CTA Vendor-Specific blocks
>   edid-decode: cleanup printf format string compiler warnings
>   edid-decode: Dump hex of non-decoded extension blocks
>   edid-decode: DisplayID additions
>   edid-decode: add example EDIDs

I merged patches 1-4, and 6-8.

The others need a bit more work.

Note that I made some slight changes to some of the patches for stylistic
reasons. It's noted in the commit log.

Regards,

	Hans

> 
>  data/acer-xv273k-dp1                          | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp1-tile0                    | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp2                          | Bin 0 -> 384 bytes
>  data/acer-xv273k-dp2-tile1                    | Bin 0 -> 384 bytes
>  data/dell-p2415q-dp-mdp                       | Bin 0 -> 256 bytes
>  data/dell-p2415q-hdmi1.4                      | Bin 0 -> 256 bytes
>  data/dell-p2415q-hdmi2.0                      | Bin 0 -> 256 bytes
>  data/dell-up2715k-dp1-tile1                   | Bin 0 -> 384 bytes
>  data/dell-up2715k-dp2-tile0                   | Bin 0 -> 256 bytes
>  data/dell-up2715k-mdp                         | Bin 0 -> 256 bytes
>  data/dell-up2715k-mdp-switchresx              | Bin 0 -> 384 bytes
>  data/kogan-kaled24144f-dp                     | Bin 0 -> 256 bytes
>  data/kogan-kaled24144f-hdmi                   | Bin 0 -> 256 bytes
>  data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 | Bin 0 -> 384 bytes
>  data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 | Bin 0 -> 256 bytes
>  edid-decode.c                                 | 758 ++++++++++++++++--
>  16 files changed, 671 insertions(+), 87 deletions(-)
>  create mode 100644 data/acer-xv273k-dp1
>  create mode 100644 data/acer-xv273k-dp1-tile0
>  create mode 100644 data/acer-xv273k-dp2
>  create mode 100644 data/acer-xv273k-dp2-tile1
>  create mode 100644 data/dell-p2415q-dp-mdp
>  create mode 100644 data/dell-p2415q-hdmi1.4
>  create mode 100644 data/dell-p2415q-hdmi2.0
>  create mode 100644 data/dell-up2715k-dp1-tile1
>  create mode 100644 data/dell-up2715k-dp2-tile0
>  create mode 100644 data/dell-up2715k-mdp
>  create mode 100644 data/dell-up2715k-mdp-switchresx
>  create mode 100644 data/kogan-kaled24144f-dp
>  create mode 100644 data/kogan-kaled24144f-hdmi
>  create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
>  create mode 100644 data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 09/10] edid-decode: DisplayID additions
  2019-11-24 10:03   ` Hans Verkuil
@ 2019-11-25  6:30     ` Joe van Tunen
  2019-11-25  9:15       ` Hans Verkuil
  0 siblings, 1 reply; 19+ messages in thread
From: Joe van Tunen @ 2019-11-25  6:30 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

1)
Yes, my displayid_vesa_dmt_timings contains the same info as displayid_vesa_dmt.

displayid_vesa_dmt was added after I had created parse_displayid_timing which uses displayid_vesa_dmt_timings and displayid_cta_timings for " Type 1 VESA DMT Timings Block" and " CTA Timings Block".

Three options:
a) remove displayid_vesa_dmt_timings
b) keep parse_displayid_timing, displayid_vesa_dmt_timings, and displayid_cta_timings; remove displayid_vesa_dmt.
c) replace displayid_cta_timings with a displayid_cta array containing elements of the same type as displayid_vesa_dmt; rewrite parse_displayid_timing to use displayid_vesa_dmt  (like "Type 1 VESA DMT Timings Block" does), and displayid_cta : only problem here is that cta has floats for refresh rate.

1a is probably the best choice as suggested by the answer to your next question:

2)
Yes, displayid_cta_timings is identical to edid_cta_modes1 (only the first 64 VICs are used). I don't think I noticed that before. My displayid_cta_timings contains extra info about refresh rates that are not integer (23.97/24Hz, 59.94/60Hz, 29.97/30Hz, 119.88/120Hz, 239.76/240Hz). It also shows the 1440 wide timings are double clocked from 720. It has the correct interlaced flag for VIC 44 and 45. Perhaps that info could be placed into edid_cta_modes1 and edid_cta_modes2 (we could also add info about the H and V blanking front porch, width, and back porch). Then displayid_cta_timings can be removed. Then we do 1a above and rewrite parse_displayid_timing to use edid_cta_modes1 (with the modifications from displayid_cta_timings)

3)
See #1 above. The "#if 0" is there to show how I used parse_displayid_timing with displayid_vesa_dmt_timings before displayid_vesa_dmt was created. The changes suggested in #2 will remove that.


On 2019-11-24, 2:03 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    Hi Joe,
    
    I have a few comments about this patch. See below:
    
    On 11/23/19 5:46 PM, joevt wrote:
    > - Decode "Display Parameters Block". Example in lg-ultrafine-5k*
    > - Decode "CTA Timings Block". Similar to "Type 1 VESA DMT Timings Block".
    > - Decode "GP ASCII String Block". Example in dell-up2715k-mdp-switchresx
    > 
    > - Added DisplayID 2.0 tags:
    >     - Decode "Display Interface Features Data Block". Example in acer-xv273k* but it appears to be missing the "additional combinations count" byte.
    >     - Decode "ContainerID Data Block". Example in lg-ultrafine-5k*
    >     - Unknown DisplayID blocks are dumped as hex.
    > 
    > - Show DisplayID tag hex byte to make it possible to distinguish between DisplayID 1.3 and 2.0 spec blocks of the same name.
    > - Show DisplayID product type.
    > 
    > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    > ---
    >  edid-decode.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++--
    >  1 file changed, 504 insertions(+), 21 deletions(-)
    > 
    > diff --git a/edid-decode.c b/edid-decode.c
    > index 2f2f1c5..29f8f88 100644
    > --- a/edid-decode.c
    > +++ b/edid-decode.c
    > @@ -55,6 +55,7 @@ static int did_detailed_timing = 0;
    >  static int has_name_descriptor = 0;
    >  static int has_serial_string = 0;
    >  static int has_ascii_string = 0;
    > +static int has_GP_ascii_string = 0;
    >  static int has_range_descriptor = 0;
    >  static int has_preferred_timing = 0;
    >  static int has_valid_checksum = 1;
    > @@ -64,6 +65,7 @@ static int has_valid_cvt = 1;
    >  static int has_valid_serial_number = 0;
    >  static int has_valid_serial_string = 0;
    >  static int has_valid_ascii_string = 0;
    > +static int has_valid_GP_ascii_string = 0;
    >  static int has_valid_name_descriptor = 0;
    >  static int has_valid_detailed_blocks = 0;
    >  static int has_valid_descriptor_ordering = 1;
    > @@ -2528,6 +2530,53 @@ static int parse_cta(const unsigned char *x)
    >         return ret;
    >  }
    >  
    > +
    > +static const char *feature_support_flags[] = {
    > +      "De-interlacing",
    > +      "Support ACP, ISRC1, or ISRC2packets",
    > +      "Fixed pixel format",
    > +      "Fixed timing",
    > +      "Power management (DPM)",
    > +      "Audio input override",
    > +      "Separate audio inputs provided",
    > +      "Audio support on video interface"
    > +};
    > +
    > +static void print_flag_lines(const char *indent, const char *label, unsigned char flag_byte, const char **flags) {
    > +      if (flag_byte) {
    > +                      printf("%s\n", label);
    > +                      for (int i = 0; i < 8; i++) {
    > +                                      if (flag_byte & (1<<i)) {
    > +                                                      printf("%s%s\n", indent, flags[i]);
    > +                                      }
    > +                      }
    > +      }
    > +}
    > +
    > +static void parse_displayid_parameters(const unsigned char *x) {
    > +      int revisionflags=x[1];
    > +      int len=x[2];
    > +      if (revisionflags) {
    > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
    > +      }
    > +      if (len != 12) {
    > +                      printf("  Length is different than expected (%d != 12)\n", len);
    > +                      printf("  ");
    > +                      hex_block(x + 3, len);
    > +      } else {
    > +                      printf("  Image size: %.1f mm x %.1f mm\n", ((x[4]<<8) + x[3]) / 10.0, ((x[6]<<8) + x[5]) / 10.0);
    > +                      printf("  Pixels: %d x %d\n", (x[8]<<8) + x[7], (x[10]<<8) + x[9]);
    > +                      print_flag_lines("    ", "  Feature support flags:", x[11], feature_support_flags);
    > +
    > +                      if (x[12] != 0xff) {
    > +                                      printf("  Gamma: %.2f\n", ((x[12] + 100.0) / 100.0));
    > +                      }
    > +                      printf("  Aspect ratio: %.2f\n", ((x[13] + 100.0) / 100.0));
    > +                      printf("  Dynamic bpc native: %d\n", (x[14] & 0xf) + 1);
    > +                      printf("  Dynamic bpc overall: %d\n", ((x[14] >> 4) & 0xf) + 1);
    > +      } // else
    > +}
    > +
    >  static void parse_displayid_detailed_timing(const unsigned char *x)
    >  {
    >         unsigned ha, hbl, hso, hspw;
    > @@ -2713,18 +2762,343 @@ static const struct {
    >         {2560, 1600, 120, 16, 10, 203217, 552750, 1},
    >  };
    >  
    > +const char *displayid_vesa_dmt_timings[] = {
    > +      "640x350@85Hz",
    > +      "640x400@85Hz",
    > +      "720x400@85Hz",
    > +      "640x480@60Hz",
    > +      "640x480@72Hz",
    > +      "640x480@75Hz",
    > +      "640x480@85Hz",
    > +      "800x600@56Hz",
    > +      "800x600@60Hz",
    > +      "800x600@72Hz",
    > +      "800x600@75Hz",
    > +      "800x600@85Hz",
    > +      "800x600@120Hz (RB)",
    > +      "848x480@60Hz",
    > +      "1024x768@43Hz (INT)",
    > +      "1024x768@60Hz",
    > +      "1024x768@70Hz",
    > +      "1024x768@75Hz",
    > +      "1024x768@85Hz",
    > +      "1024x768@120Hz (RB)",
    > +      "1152x864@75Hz",
    > +      "1280x768@60Hz (RB)",
    > +      "1280x768@60Hz",
    > +      "1280x768@75Hz",
    > +      "1280x768@85Hz",
    > +      "1280x768@120Hz (RB)",
    > +      "1280x800@60Hz (RB)",
    > +      "1280x800@60Hz",
    > +      "1280x800@75Hz",
    > +      "1280x800@85Hz",
    > +      "1280x800@120Hz (RB)",
    > +      "1280x960@60Hz",
    > +      "1280x960@85Hz",
    > +      "1280x960@120Hz (RB)",
    > +      "1280x1024@60Hz",
    > +      "1280x1024@75Hz",
    > +      "1280x1024@85Hz",
    > +      "1280x1024@120Hz (RB)",
    > +      "1360x768@60Hz",
    > +      "1360x768@120Hz (RB)",
    > +      "1400x1050@60Hz (RB)",
    > +      "1400x1050@60Hz",
    > +      "1400x1050@75Hz",
    > +      "1400x1050@85Hz",
    > +      "1400x1050@120Hz (RB)",
    > +      "1440x900@60Hz (RB)",
    > +      "1440x900@60Hz",
    > +      "1440x900@75Hz",
    > +      "1440x900@85Hz",
    > +      "1440x900@120Hz (RB)",
    > +      "1600x1200@60Hz",
    > +      "1600x1200@65Hz",
    > +      "1600x1200@70Hz",
    > +      "1600x1200@75Hz",
    > +      "1600x1200@85Hz",
    > +      "1600x1200@120Hz (RB)",
    > +      "1680x1050@60Hz (RB)",
    > +      "1680x1050@60Hz",
    > +      "1680x1050@75Hz",
    > +      "1680x1050@85Hz",
    > +      "1680x1050@120Hz (RB)",
    > +      "1792x1344@60Hz",
    > +      "1792x1344@75Hz",
    > +      "1792x1344@120Hz (RB)",
    > +      "1856x1392@60Hz",
    > +      "1856x1392@75Hz",
    > +      "1856x1392@120Hz (RB)",
    > +      "1920x1200@60Hz (RB)",
    > +      "1920x1200@60Hz",
    > +      "1920x1200@75Hz",
    > +      "1920x1200@85Hz",
    > +      "1920x1200@120Hz (RB)",
    > +      "1920x1440@60Hz",
    > +      "1920x1440@75Hz",
    > +      "1920x1440@120Hz (RB)",
    > +      "2560x1600@60Hz (RB)",
    > +      "2560x1600@60Hz",
    > +      "2560x1600@75Hz",
    > +      "2560x1600@85Hz",
    > +      "2560x1600@120Hz (RB)",
    > +};
    
    Isn't this effectively the same as the displayid_vesa_dmt array?
    
    > +
    > +const char *displayid_cta_timings[] = {
    > +      "640x480p@59.94/60Hz 4:3",
    > +      "720x480p@59.94/60Hz 4:3",
    > +      "720x480p@59.94/60Hz 16:9",
    > +      "1280x720p@59.94/60Hz 16:9",
    > +      "1920x1080i@59.94/60Hz 16:9",
    > +      "720(1440)x480i@59.94/60Hz 4:3",
    > +      "720(1440)x480i@59.94/60Hz 16:9",
    > +      "720(1440)x240p@59.94/60Hz 4:3",
    > +      "720(1440)x240p@59.94/60Hz 16:9",
    > +      "2880x480i@59.94/60Hz 4:3",
    > +      "2880x480i@59.94/60Hz 16:9",
    > +      "2880x240p@59.94/60Hz 4:3",
    > +      "2880x240p@59.94/60Hz 16:9",
    > +      "1440x480p@59.94/60Hz 4:3",
    > +      "1440x480p@59.94/60Hz 16:9",
    > +      "1920x1080p@59.94/60Hz 16:9",
    > +      "720x576p@50Hz 4:3",
    > +      "720x576p@50Hz 16:9",
    > +      "1280x720p@50Hz 16:9",
    > +      "1920x1080i@50Hz 16:9",
    > +      "720(1440)x576i@50Hz 4:3",
    > +      "720(1440)x576i@50Hz 16:9",
    > +      "720(1440)x288p@50Hz 4:3",
    > +      "720(1440)x288p@50Hz 16:9",
    > +      "2880x576i@50Hz 4:3",
    > +      "2880x576i@50Hz 16:9",
    > +      "2880x288p@50Hz 4:3",
    > +      "2880x288p@50Hz 16:9",
    > +      "1440x576p@50Hz 4:3",
    > +      "1440x576p@50Hz 16:9",
    > +      "1920x1080p@50Hz 16:9",
    > +      "1920x1080p@23.97/24Hz 16:9",
    > +      "1920x1080p@25Hz 16:9",
    > +      "1920x1080p@29.97/30Hz 16:9",
    > +      "2880x480p@59.94/60Hz 4:3",
    > +      "2880x480p@59.94/60Hz 16:9",
    > +      "2880x576p@50Hz 4:3",
    > +      "2880x576p@50Hz 16:9",
    > +      "1920x1080i@50Hz 16:9",
    > +      "1920x1080i@100Hz 16:9",
    > +      "1280x720p@100Hz 16:9",
    > +      "720x576p@100Hz 4:3",
    > +      "720x576p@100Hz 16:9",
    > +      "720(1440)x576i@100Hz 4:3",
    > +      "720(1440)x576i@100Hz 16:9",
    > +      "1920x1080i@119.88/120Hz 16:9",
    > +      "1280x720p@119.88/120Hz 16:9",
    > +      "720x480p@119.88/120Hz 4:3",
    > +      "720x480p@119.88/120Hz 16:9",
    > +      "720(1440)x480i@119.88/120Hz 4:3",
    > +      "720(1440)x480i@119.88/120Hz 16:9",
    > +      "720x576p@200Hz 4:3",
    > +      "720x576p@200Hz 16:9",
    > +      "720(1440)x576i@200Hz 4:3",
    > +      "720(1440)x576i@200Hz 16:9",
    > +      "720x480p@239.76/240Hz 4:3",
    > +      "720x480p@239.76/240Hz 16:9",
    > +      "720(1440)x480i@239.76/240Hz 4:3",
    > +      "720(1440)x480i@239.76/240Hz 16:9",
    > +      "1280x720p@23.97/24Hz 16:9",
    > +      "1280x720p@25Hz 16:9",
    > +      "1280x720p@29.97/30Hz 16:9",
    > +      "1920x1080p@120Hz 16:9",
    > +      "1920x1080p@100Hz 16:9",
    > +};
    
    And this is the same as edid_cta_modes1[].
    
    > +
    > +static void parse_displayid_timing(const unsigned char *x, int expectedlen, const char** list)
    > +{
    > +      int revisionflags=x[1];
    > +      int len=x[2];
    > +      if (revisionflags) {
    > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
    > +      }
    > +      if (len > expectedlen) {
    > +                      printf("  Length is greater than expected (%d > %d)\n", len, expectedlen);
    > +      } else if (len < expectedlen) {
    > +                      printf("  Length is less than expected (%d < %d)\n", len, expectedlen);
    > +      }
    > +      x += 3;
    > +      for (int i = 0; i < len * 8; i++) {
    > +                      if (x[i>>3] & (1<<(i&7))) {
    > +                                      if ((i>>3) < expectedlen) {
    > +                                                      printf("  %s\n", list[i]);
    > +                                      } else {
    > +                                                      printf("  #%d\n", i+1);
    > +                                      }
    > +                      }
    > +      }
    > +}
    > +
    > +static void parse_displayid_gp_string(const unsigned char *x)
    > +{
    > +      int revisionflags=x[1];
    > +      if (revisionflags) {
    > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
    > +      }
    > +}
    > +
    > +static const char *bpc444[] = {"6", "8", "10", "12", "14", "16", NULL, NULL};
    > +static const char *bpc4xx[] = {"8", "10", "12", "14", "16", NULL, NULL, NULL};
    > +static const char *audiorates[] = {"32", "44.1", "48", NULL, NULL, NULL, NULL, NULL};
    > +
    > +static const char *colorspace_eotf_combinations[] = {
    > +      "sRGB",
    > +      "BT.601",
    > +      "BT.709/BT.1886",
    > +      "Adobe RGB",
    > +      "DCI-P3",
    > +      "BT.2020",
    > +      "BT.2020/SMPTE ST 2084"
    > +};
    > +
    > +static const char *colorspace_eotf_reserved[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    > +
    > +static const char *colorspaces[] = {
    > +      "Undefined",
    > +      "sRGB",
    > +      "BT.601",
    > +      "BT.709",
    > +      "Adobe RGB",
    > +      "DCI-P3",
    > +      "BT.2020",
    > +      "Custom"
    > +};
    > +
    > +static const char *eotfs[] = {
    > +      "Undefined",
    > +      "sRGB",
    > +      "BT.601",
    > +      "BT.1886",
    > +      "Adobe RGB",
    > +      "DCI-P3",
    > +      "BT.2020",
    > +      "Gamma function",
    > +      "SMPTE ST 2084",
    > +      "Hybrid Log",
    > +      "Custom"
    > +};
    > +
    > +static void print_flags(const char *label, unsigned char flag_byte, const char **flags, int reverse)
    > +{
    > +      if (flag_byte) {
    > +                      printf("%s: ", label);
    > +                      int countflags = 0;
    > +                      for (int i = 0; i < 8; i++) {
    > +                                      if (flag_byte & (1<<(reverse?7-i:i))) {
    > +                                                      if (countflags)
    > +                                                                      printf(", ");
    > +                                                      if (flags[i])
    > +                                                                      printf("%s", flags[i]);
    > +                                                      else
    > +                                                                      printf("Undefined(%d)", i);
    > +                                                      countflags++;
    > +                                      }
    > +                      }
    > +                      printf("\n");
    > +      }
    > +}
    > +
    > +static void parse_displayid_interface_features(const unsigned char *x)
    > +{
    > +      int revisionflags=x[1];
    > +      int len=x[2];
    > +      if (revisionflags) {
    > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
    > +      }
    > +      if (len < 9) {
    > +                      printf("  Length is less than expected (%d < 9)\n", len);
    > +                      printf("  ");
    > +                      hex_block(x + 3, len);
    > +      } else {
   > +                      print_flags("  Supported bpc for RGB encoding", x[3], bpc444, 0);
    > +                      print_flags("  Supported bpc for YCbCr 4:4:4 encoding", x[4], bpc444, 0);
    > +                      print_flags("  Supported bpc for YCbCr 4:2:2 encoding", x[5], bpc4xx, 0);
    > +                      print_flags("  Supported bpc for YCbCr 4:2:0 encoding", x[6], bpc4xx, 0);
    > +                      if (x[7])
    > +                                      printf("  Minimum pixel rate at which YCbCr 4:2:0 encoding is supported: %.3f MHz\n", 74.25 * x[7]);
    > +                      print_flags("  Supported audio capability and features (kHz)", x[8], audiorates, 1);
    > +                      print_flags("  Supported color space and EOTF standard combination 1", x[9], colorspace_eotf_combinations, 0);
    > +                      print_flags("  Supported color space and EOTF standard combination 2", x[10], colorspace_eotf_reserved, 0);
    > +                      int i = 0;
    > +                      if (len >= 9 && x[11] > 0) {
    > +                                      printf("  Supported color space and EOTF additional combinations:");
    > +                                      for (i = 1; i <= x[11]; i++) {
    > +                                                      if (i > 7) {
    > +                                                                      printf("\n  Number of additional color space and EOTF combinations (%d) is greater than allowed (7).", x[11]);
    > +                                                                      break;
    > +                                                      } else if (9 + i > len) {
    > +                                                                      printf("\n  Number of additional color space and EOTF combinations (%d) is too many to fit in block (%d).", x[11], len - 9);
    > +                                                                      break;
    > +                                                      }
    > +
    > +                                                      const char *colorspace = "Out of range";
    > +                                                      const char *eotf = "Out of range";
    > +                                                      int colorspace_index = (x[11 + i] >> 4) & 0xf;
    > +                                                      int eotf_index = x[11 + i] & 0xf;
    > +                                                      if (colorspace_index < sizeof(colorspaces) / sizeof(colorspaces[0])) {
    > +                                                                      colorspace = colorspaces[colorspace_index];
    > +                                                      }
    > +                                                      if (eotf_index < sizeof(eotfs) / sizeof(eotfs[0])) {
    > +                                                                      eotf = eotfs[eotf_index];
    > +                                                      }
    > +
    > +                                                      if (i > 1)
    > +                                                                      printf(", ");
    > +                                                      if (!strcmp(colorspace, eotf)) {
    > +                                                                      printf("%s", colorspace);
    > +                                                      } else {
    > +                                                                      printf("%s/%s", colorspace, eotf);
    > +                                                      }
    > +                                      } // for
    > +                                      printf("\n");
    > +                      } // x[11]
    > +                      if (len > 9 + i) {
    > +                                      printf("  Length is greater than expected (%d > %d)\n", len, 9 + i);
    > +                                      printf("  ");
    > +                                      hex_block(x + 11 + i, len - 9 - i);
    > +                      } else if (len != 9 + i)  {
    > +                                      printf("  Length is unexpected (%d != %d)\n", len, 9 + i);
    > +                      }
    > +      }
    > +}
    > +
    > +static void parse_displayid_ContainerID(const unsigned char *x)
    > +{
    > +      int revisionflags=x[1];
    > +      int len=x[2];
    > +      if (revisionflags) {
    > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
    > +      }
    > +      x += 3;
    > +      if (len != 16) {
    > +                      printf("  Length is unexpected (%d != 16)\n", len);
    > +                      printf("  ");
    > +                      hex_block(x, len);
    > +      } else {
    > +                      printf("  %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]);
    > +      }
    > +}
    > +
    >  static int parse_displayid(const unsigned char *x)
    >  {
    >         const unsigned char *orig = x;
    >         unsigned version = x[1];
    >         unsigned length = x[2];
    > +      unsigned producttype = x[3];
    >         unsigned ext_count = x[4];
    >         unsigned i;
    >  
    >         cur_block = "DisplayID";
    >  
    > -       printf("Length %u, version %u.%u, extension count %u\n",
    > -              length, version >> 4, version & 0xf, ext_count);
    > +      printf("Length %u, version %u.%u, type %u, extension count %u\n",
    > +             length, version >> 4, version & 0xf, producttype, ext_count);
    >  
    >         unsigned offset = 5;
    >         while (length > 0) {
    > @@ -2734,33 +3108,49 @@ static int parse_displayid(const unsigned char *x)
    >                         if (len == 0)
    >                                         break;
    >                         switch (tag) {
    > +                      
    > +                      // DisplayID 1.3:
    >                         case 0:
    > -                                       printf("Product ID Block\n");
    > +                                      printf("Product ID Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 1:
    > -                                       printf("Display Parameters Block\n");
    > +                                      printf("Display Parameters Block (%02Xh):\n", tag);
    > +                                      parse_displayid_parameters(x + offset);
    >                                         break;
    >                         case 2:
    > -                                       printf("Color Characteristics Block\n");
    > +                                      printf("Color Characteristics Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 3: {
    > -                                       printf("Type 1 Detailed Timings Block\n");
    > +                                      printf("Type 1 Detailed Timings Block (%02Xh)\n", tag);
    >                                         for (i = 0; i < len / 20; i++) {
    >                                                         parse_displayid_detailed_timing(&x[offset + 3 + (i * 20)]);
    >                                         }
    >                                         break;
    >                         }
    >                         case 4:
    > -                                       printf("Type 2 Detailed Timings Block\n");
    > +                                      printf("Type 2 Detailed Timings Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 5:
    > -                                       printf("Type 3 Short Timings Block\n");
    > +                                      printf("Type 3 Short Timings Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 6:
    > -                                       printf("Type 4 DMT Timings Block\n");
    > +                                      printf("Type 4 DMT Timings Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 7:
    > -                                       printf("Type 1 VESA DMT Timings Block\n");
    > +                                      printf("Type 1 VESA DMT Timings Block (%02Xh)\n", tag);
    > +                                      #if 0
    > +                                      parse_displayid_timing(x + offset, 10, displayid_vesa_dmt_timings);
    
    What is the reason for the #if 0?
    
    I now get a warning that displayid_vesa_dmt_timings is unused.
    
    > +                                      #else
    >                                         for (i = 0; i < min(len, 10) * 8; i++) {
    >                                                         if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
    >                                                                         printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
    > @@ -2779,33 +3169,51 @@ static int parse_displayid(const unsigned char *x)
    >                                                                         max_pixclk_khz = max(max_pixclk_khz, displayid_vesa_dmt[i].pixclk_khz);
    >                                                         }
    >                                         }
    > +                                      #endif
    >                                         break;
    >                         case 8:
    > -                                       printf("CTA Timings Block\n");
    > +                                      printf("CTA Timings Block (%02Xh):\n", tag);
    > +                                      parse_displayid_timing(x + offset, 8, displayid_cta_timings);
    >                                         break;
    >                         case 9:
    > -                                       printf("Video Timing Range Block\n");
    > +                                      printf("Video Timing Range Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0xa:
    > -                                       printf("Product Serial Number Block\n");
    > +                                      printf("Product Serial Number Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0xb:
    > -                                       printf("GP ASCII String Block\n");
    > +                                      printf("GP ASCII String Block (%02Xh): %s\n", tag, extract_string("GP ASCII String", x + offset + 3, &has_valid_GP_ascii_string, len));
    > +                                      has_GP_ascii_string = 1;
    > +                                      parse_displayid_gp_string(x + offset);
    >                                         break;
    >                         case 0xc:
    > -                                       printf("Display Device Data Block\n");
    > +                                      printf("Display Device Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0xd:
    > -                                       printf("Interface Power Sequencing Block\n");
    > +                                      printf("Interface Power Sequencing Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0xe:
    > -                                       printf("Transfer Characteristics Block\n");
    > +                                      printf("Transfer Characteristics Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0xf:
    > -                                       printf("Display Interface Block\n");
    > +                                      printf("Display Interface Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0x10:
    > -                                       printf("Stereo Display Interface Block\n");
    > +                                      printf("Stereo Display Interface Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         case 0x12: {
    >                                         unsigned capabilities = x[offset + 3];
    > @@ -2817,7 +3225,7 @@ static int parse_displayid(const unsigned char *x)
    >                                         unsigned tile_height = x[offset + 9] | (x[offset + 10] << 8);
    >                                         unsigned pix_mult = x[offset + 11];
    >  
    > -                                       printf("Tiled Display Topology Block\n");
    > +                                      printf("Tiled Display Topology Block (%02Xh)\n", tag);
    >                                         printf("  Capabilities: 0x%08x\n", capabilities);
    >                                         printf("  Num horizontal tiles: %u Num vertical tiles: %u\n", num_h_tile + 1, num_v_tile + 1);
    >                                         printf("  Tile location: %u, %u\n", tile_h_location, tile_v_location);
    > @@ -2841,8 +3249,80 @@ static int parse_displayid(const unsigned char *x)
    >                                         }
    >                                         break;
    >                         }
    > +
    > +                      // DisplayID 2.0
    > +                      case 0x20:
    > +                                      printf("Product ID Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x21:
    > +                                      printf("Display Parameters Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x22:
    > +                                      printf("Type 7 Timing - Detailed Timing Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x23:
    > +                                      printf("Type 8 Timing - Enumerated Timing Code Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x24:
    > +                                      printf("Type 9 Timing - Formula-based Timing Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x25:
    > +                                      printf("Dynamic Video Timing Range Limits Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x26:
    > +                                      printf("Display Interface Features Data Block (%02Xh):\n", tag);
    > +                                      parse_displayid_interface_features(x + offset);
    > +                                      break;
    > +                      case 0x27:
    > +                                      printf("Stereo Display Interface Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x28:
    > +                                      printf("Tiled Display Topology Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +                      case 0x29:
    > +                                      printf("ContainerID Data Block (%02Xh):\n", tag);
    > +                                      parse_displayid_ContainerID(x + offset);
    > +                                      break;
    > +
    > +                      // 2Ah .. 7Dh RESERVED for Additional VESA-defined Data Blocks
    > +
    > +                      case 0x7e: // DisplayID 2.0
    > +                      case 0x7f: // DisplayID 1.3
    > +                                      printf("Vendor-specific Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +
    > +                      // 7Fh .. 80h RESERVED
    > +
    > +                      case 0x81:
    > +                                      printf("CTA DisplayID Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    > +                                      break;
    > +
    > +                      // 82h .. FFh RESERVED
    > +                      
    >                         default:
    > -                                       printf("Unknown DisplayID Data Block 0x%x\n", tag);
    > +                                      printf("Unknown DisplayID Data Block (%02Xh)\n", tag);
    > +                                      printf("  ");
    > +                                      hex_block(x + offset + 3, len);
    >                                         break;
    >                         }
    >                         length -= len + 3;
    > @@ -3687,6 +4167,7 @@ static int edid_from_file(const char *from_file, const char *to_file,
    >             !has_valid_range_descriptor ||
    >             (has_name_descriptor && !has_valid_name_descriptor) ||
    >             (has_serial_string && !has_valid_serial_string) ||
    > +                      (has_GP_ascii_string && !has_valid_GP_ascii_string) ||
    >             (has_ascii_string && !has_valid_ascii_string)) {
    >                         conformant = 0;
    >                         printf("EDID block does not conform:\n");
    > @@ -3709,6 +4190,8 @@ static int edid_from_file(const char *from_file, const char *to_file,
    >                                         printf("\tInvalid Monitor Name descriptor\n");
    >                         if (has_ascii_string && !has_valid_ascii_string)
    >                                         printf("\tInvalid ASCII string\n");
    > +                      if (has_GP_ascii_string && !has_valid_GP_ascii_string)
    > +                                      printf("\tInvalid GP ASCII string\n");
    >                         if (has_serial_string && !has_valid_serial_string)
    >                                         printf("\tInvalid serial string\n");
    >         }
    > 
    
    Regards,
    
                Hans
    



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb
  2019-11-24 10:26   ` Hans Verkuil
@ 2019-11-25  6:32     ` Joe van Tunen
  2019-11-25  8:20       ` Hans Verkuil
  0 siblings, 1 reply; 19+ messages in thread
From: Joe van Tunen @ 2019-11-25  6:32 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Right. The code will have to iterate EDID extension blocks, find CTA extension blocks, then find VDB blocks.
In the case where Y420CMDB length = 0, I would maybe output "All VDB SVDs"?
Also, shouldn't "VSD Index" be "SVD Index" to match the abbreviations in the spec (or "VDB SVD Index" since it doesn't include SVDs from other sources such as Y420VDB)?
 
Can we assume that an EDID can't use more than one Y420CMDB to get beyond VDB SVD Index 240? Each Y420CMDB will use the same set of SVDs (starting at VDB SVD index 1). The spec explicitly says that bit 0 is the first SVD of the VDBs.
 
On 2019-11-24, 2:26 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    On 11/23/19 5:45 PM, joevt wrote:
    > - "YCbCr 4:2:0 capability map data block" now outputs the modes that support YCbCr 4:2:0 instead of just indexes of the modes. Indexes refer to timings in "Video Data Block".
    > - Warnings are included in the output if "Video Data Block" doesn't appear before "YCbCr 4:2:0 Capability Map Data Block" or if the index is outside the range defined in the "Video Data Block".
    > - Moved inner loop of cta_svd into a new function cta_svd_one so that it can be reused by cta_y420cmdb.
    
    This isn't sufficient. There may be multiple SVD blocks in the EDID, and that's not taken
    into account.
    
    Also, I can't find any requirement in the CTA-861 spec that the YCbCr 4:2:0 Capability
    Map Data Block has to appear after all SVD blocks. So the final check if the Y420CMDB
    block references invalid SVDs should be postponed to the end of the CTA block.
    
    I also found a pre-existing bug: if length == 0 in cta_y420cmdb() then that means that
    all SVDs support 4:2:0. That should be added to cta_y420cmdb().
    
    Regards,
    
                Hans
    
    > 
    > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    > ---
    >  edid-decode.c | 44 +++++++++++++++++++++++++++++++++++---------
    >  1 file changed, 35 insertions(+), 9 deletions(-)
    > 
    > diff --git a/edid-decode.c b/edid-decode.c
    > index b833178..4d6fe29 100644
    > --- a/edid-decode.c
    > +++ b/edid-decode.c
    > @@ -1454,13 +1454,10 @@ static const struct edid_cta_mode *vic_to_mode(unsigned char vic)
    >         return NULL;
    >  }
    >  
    > -static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
    > +static void cta_svd_one(const unsigned char *x, int for_ycbcr420)
    >  {
    > -       unsigned i;
    > -
    > -       for (i = 0; i < n; i++)  {
    >                         const struct edid_cta_mode *vicmode = NULL;
    > -                       unsigned char svd = x[i];
    > +                      unsigned char svd = x[0];
    >                         unsigned char native;
    >                         unsigned char vic;
    >                         const char *mode;
    > @@ -1468,7 +1465,7 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
    >                         unsigned clock_khz = 0;
    >  
    >                         if ((svd & 0x7f) == 0)
    > -                                       continue;
    > +                                      return;
    >  
    >                         if ((svd - 1) & 0x40) {
    >                                         vic = svd;
    > @@ -1511,10 +1508,23 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
    >                         if (vic == 1)
    >                                         has_cta861_vic_1 = 1;
    >         }
    > +
    > +static void cta_svd(const unsigned char *x, int n, int for_ycbcr420)
    > +{
    > +      for (unsigned i = 0; i < n; i++)  {
    > +                      printf("    ");
    > +                      cta_svd_one(x+i, for_ycbcr420);
    > +                      printf("\n");
    > +      }
    >  }
    >  
    > +unsigned const char *last_cta_video_block_start = NULL;
    > +unsigned last_cta_video_block_length = 0;
    > +
    >  static void cta_video_block(const unsigned char *x, unsigned length)
    >  {
    > +      last_cta_video_block_start = x;
    > +      last_cta_video_block_length = length;
    >         cta_svd(x, length, 0);
    >  }
    >  
    > @@ -1531,9 +1541,25 @@ static void cta_y420cmdb(const unsigned char *x, unsigned length)
    >                         uint8_t v = x[0 + i];
    >                         unsigned j;
    >  
    > -                       for (j = 0; j < 8; j++)
    > -                                       if (v & (1 << j))
    > -                                                       printf("    VSD Index %u\n", i * 8 + j);
    > +                      for (j = 0; j < 8; j++) {
    > +                                      if (v & (1 << j)) {
    > +                                                      unsigned k = i * 8 + j;
    > +                                                      printf("    VSD Index %u", k + 1);
    > +                                                      if (k >= last_cta_video_block_length) {
    > +                                                                      if (last_cta_video_block_start) {
    > +                                                                                      printf(" (out of range)");
    > +                                                                      } else {
    > +                                                                                      printf(" (missing CTA video block)");
   > +                                                                      }
    > +                                                      }
    > +                                                      else
    > +                                                      {
    > +                                                                      printf(" ");
    > +                                                                      cta_svd_one(last_cta_video_block_start+k, 0);
    > +                                                      }
    > +                                                      printf("\n");
    > +                                      }
    > +                      }
    >         }
    >  }
    >  
    > 
    
    



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb
  2019-11-25  6:32     ` Joe van Tunen
@ 2019-11-25  8:20       ` Hans Verkuil
  0 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2019-11-25  8:20 UTC (permalink / raw)
  To: Joe van Tunen; +Cc: linux-media

On 11/25/19 7:32 AM, Joe van Tunen wrote:
> Right. The code will have to iterate EDID extension blocks, find CTA extension blocks, then find VDB blocks.
> In the case where Y420CMDB length = 0, I would maybe output "All VDB SVDs"?

Yes,

> Also, shouldn't "VSD Index" be "SVD Index" to match the abbreviations in the spec (or "VDB SVD Index" since it doesn't include SVDs from other sources such as Y420VDB)?

I think 'VBD SVDs' is correct.

>  
> Can we assume that an EDID can't use more than one Y420CMDB to get beyond VDB SVD Index 240? Each Y420CMDB will use the same set of SVDs (starting at VDB SVD index 1). The spec explicitly says that bit 0 is the first SVD of the VDBs.

I agree with that assumption.

Regards,

	Hans

>  
> On 2019-11-24, 2:26 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:
> 
>     On 11/23/19 5:45 PM, joevt wrote:
>     > - "YCbCr 4:2:0 capability map data block" now outputs the modes that support YCbCr 4:2:0 instead of just indexes of the modes. Indexes refer to timings in "Video Data Block".
>     > - Warnings are included in the output if "Video Data Block" doesn't appear before "YCbCr 4:2:0 Capability Map Data Block" or if the index is outside the range defined in the "Video Data Block".
>     > - Moved inner loop of cta_svd into a new function cta_svd_one so that it can be reused by cta_y420cmdb.
>     
>     This isn't sufficient. There may be multiple SVD blocks in the EDID, and that's not taken
>     into account.
>     
>     Also, I can't find any requirement in the CTA-861 spec that the YCbCr 4:2:0 Capability
>     Map Data Block has to appear after all SVD blocks. So the final check if the Y420CMDB
>     block references invalid SVDs should be postponed to the end of the CTA block.
>     
>     I also found a pre-existing bug: if length == 0 in cta_y420cmdb() then that means that
>     all SVDs support 4:2:0. That should be added to cta_y420cmdb().
>     
>     Regards,
>     
>                 Hans
>     
>     > 
>     > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
>     > ---
>     >  edid-decode.c | 44 +++++++++++++++++++++++++++++++++++---------
>     >  1 file changed, 35 insertions(+), 9 deletions(-)
>     > 
>     > diff --git a/edid-decode.c b/edid-decode.c
>     > index b833178..4d6fe29 100644
>     > --- a/edid-decode.c
>     > +++ b/edid-decode.c
>     > @@ -1454,13 +1454,10 @@ static const struct edid_cta_mode *vic_to_mode(unsigned char vic)
>     >         return NULL;
>     >  }
>     >  
>     > -static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
>     > +static void cta_svd_one(const unsigned char *x, int for_ycbcr420)
>     >  {
>     > -       unsigned i;
>     > -
>     > -       for (i = 0; i < n; i++)  {
>     >                         const struct edid_cta_mode *vicmode = NULL;
>     > -                       unsigned char svd = x[i];
>     > +                      unsigned char svd = x[0];
>     >                         unsigned char native;
>     >                         unsigned char vic;
>     >                         const char *mode;
>     > @@ -1468,7 +1465,7 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
>     >                         unsigned clock_khz = 0;
>     >  
>     >                         if ((svd & 0x7f) == 0)
>     > -                                       continue;
>     > +                                      return;
>     >  
>     >                         if ((svd - 1) & 0x40) {
>     >                                         vic = svd;
>     > @@ -1511,10 +1508,23 @@ static void cta_svd(const unsigned char *x, unsigned n, int for_ycbcr420)
>     >                         if (vic == 1)
>     >                                         has_cta861_vic_1 = 1;
>     >         }
>     > +
>     > +static void cta_svd(const unsigned char *x, int n, int for_ycbcr420)
>     > +{
>     > +      for (unsigned i = 0; i < n; i++)  {
>     > +                      printf("    ");
>     > +                      cta_svd_one(x+i, for_ycbcr420);
>     > +                      printf("\n");
>     > +      }
>     >  }
>     >  
>     > +unsigned const char *last_cta_video_block_start = NULL;
>     > +unsigned last_cta_video_block_length = 0;
>     > +
>     >  static void cta_video_block(const unsigned char *x, unsigned length)
>     >  {
>     > +      last_cta_video_block_start = x;
>     > +      last_cta_video_block_length = length;
>     >         cta_svd(x, length, 0);
>     >  }
>     >  
>     > @@ -1531,9 +1541,25 @@ static void cta_y420cmdb(const unsigned char *x, unsigned length)
>     >                         uint8_t v = x[0 + i];
>     >                         unsigned j;
>     >  
>     > -                       for (j = 0; j < 8; j++)
>     > -                                       if (v & (1 << j))
>     > -                                                       printf("    VSD Index %u\n", i * 8 + j);
>     > +                      for (j = 0; j < 8; j++) {
>     > +                                      if (v & (1 << j)) {
>     > +                                                      unsigned k = i * 8 + j;
>     > +                                                      printf("    VSD Index %u", k + 1);
>     > +                                                      if (k >= last_cta_video_block_length) {
>     > +                                                                      if (last_cta_video_block_start) {
>     > +                                                                                      printf(" (out of range)");
>     > +                                                                      } else {
>     > +                                                                                      printf(" (missing CTA video block)");
>    > +                                                                      }
>     > +                                                      }
>     > +                                                      else
>     > +                                                      {
>     > +                                                                      printf(" ");
>     > +                                                                      cta_svd_one(last_cta_video_block_start+k, 0);
>     > +                                                      }
>     > +                                                      printf("\n");
>     > +                                      }
>     > +                      }
>     >         }
>     >  }
>     >  
>     > 
>     
>     
> 
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 09/10] edid-decode: DisplayID additions
  2019-11-25  6:30     ` Joe van Tunen
@ 2019-11-25  9:15       ` Hans Verkuil
  0 siblings, 0 replies; 19+ messages in thread
From: Hans Verkuil @ 2019-11-25  9:15 UTC (permalink / raw)
  To: Joe van Tunen; +Cc: linux-media

On 11/25/19 7:30 AM, Joe van Tunen wrote:
> 1)
> Yes, my displayid_vesa_dmt_timings contains the same info as displayid_vesa_dmt.
> 
> displayid_vesa_dmt was added after I had created parse_displayid_timing which uses displayid_vesa_dmt_timings and displayid_cta_timings for " Type 1 VESA DMT Timings Block" and " CTA Timings Block".
> 
> Three options:
> a) remove displayid_vesa_dmt_timings
> b) keep parse_displayid_timing, displayid_vesa_dmt_timings, and displayid_cta_timings; remove displayid_vesa_dmt.
> c) replace displayid_cta_timings with a displayid_cta array containing elements of the same type as displayid_vesa_dmt; rewrite parse_displayid_timing to use displayid_vesa_dmt  (like "Type 1 VESA DMT Timings Block" does), and displayid_cta : only problem here is that cta has floats for refresh rate.
> 
> 1a is probably the best choice as suggested by the answer to your next question:
> 
> 2)
> Yes, displayid_cta_timings is identical to edid_cta_modes1 (only the first 64 VICs are used). I don't think I noticed that before. My displayid_cta_timings contains extra info about refresh rates that are not integer (23.97/24Hz, 59.94/60Hz, 29.97/30Hz, 119.88/120Hz, 239.76/240Hz). 

Those 59.94/60 timings are implied in the CTA standard. Any frame rate that can be divided by 6 can
also be multiplied by 1000/1001 to get an alternate reduced frame rate.

I fixed the VIC 44/45: I missed that those are interlaced timings, it's now corrected in the table.

It also shows the 1440 wide timings are double clocked from 720. It has the correct interlaced flag for VIC 44 and 45. Perhaps that info
could be placed into edid_cta_modes1 and edid_cta_modes2 (we could also add info about the H and V blanking front porch, width, and back
porch). Then displayid_cta_timings can be removed. Then we do 1a above and rewrite parse_displayid_timing to use edid_cta_modes1 (with the
modifications from displayid_cta_timings)

edid-decode really needs a single struct that is used to represent a timings in these timing tables.
You can start by using the same struct for displayid_vesa_dmt and edid_cta_modes1/2. The string in
edid_cta_modes1/2 can be dropped since it can be regenerated from the data in the struct.

So do an initial patch converting the three tables to the same struct, then
a second patch for these DisplayID additions.

Regards,

	Hans

> 
> 3)
> See #1 above. The "#if 0" is there to show how I used parse_displayid_timing with displayid_vesa_dmt_timings before displayid_vesa_dmt was created. The changes suggested in #2 will remove that.
> 
> 
> On 2019-11-24, 2:03 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:
> 
>     Hi Joe,
>     
>     I have a few comments about this patch. See below:
>     
>     On 11/23/19 5:46 PM, joevt wrote:
>     > - Decode "Display Parameters Block". Example in lg-ultrafine-5k*
>     > - Decode "CTA Timings Block". Similar to "Type 1 VESA DMT Timings Block".
>     > - Decode "GP ASCII String Block". Example in dell-up2715k-mdp-switchresx
>     > 
>     > - Added DisplayID 2.0 tags:
>     >     - Decode "Display Interface Features Data Block". Example in acer-xv273k* but it appears to be missing the "additional combinations count" byte.
>     >     - Decode "ContainerID Data Block". Example in lg-ultrafine-5k*
>     >     - Unknown DisplayID blocks are dumped as hex.
>     > 
>     > - Show DisplayID tag hex byte to make it possible to distinguish between DisplayID 1.3 and 2.0 spec blocks of the same name.
>     > - Show DisplayID product type.
>     > 
>     > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
>     > ---
>     >  edid-decode.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++--
>     >  1 file changed, 504 insertions(+), 21 deletions(-)
>     > 
>     > diff --git a/edid-decode.c b/edid-decode.c
>     > index 2f2f1c5..29f8f88 100644
>     > --- a/edid-decode.c
>     > +++ b/edid-decode.c
>     > @@ -55,6 +55,7 @@ static int did_detailed_timing = 0;
>     >  static int has_name_descriptor = 0;
>     >  static int has_serial_string = 0;
>     >  static int has_ascii_string = 0;
>     > +static int has_GP_ascii_string = 0;
>     >  static int has_range_descriptor = 0;
>     >  static int has_preferred_timing = 0;
>     >  static int has_valid_checksum = 1;
>     > @@ -64,6 +65,7 @@ static int has_valid_cvt = 1;
>     >  static int has_valid_serial_number = 0;
>     >  static int has_valid_serial_string = 0;
>     >  static int has_valid_ascii_string = 0;
>     > +static int has_valid_GP_ascii_string = 0;
>     >  static int has_valid_name_descriptor = 0;
>     >  static int has_valid_detailed_blocks = 0;
>     >  static int has_valid_descriptor_ordering = 1;
>     > @@ -2528,6 +2530,53 @@ static int parse_cta(const unsigned char *x)
>     >         return ret;
>     >  }
>     >  
>     > +
>     > +static const char *feature_support_flags[] = {
>     > +      "De-interlacing",
>     > +      "Support ACP, ISRC1, or ISRC2packets",
>     > +      "Fixed pixel format",
>     > +      "Fixed timing",
>     > +      "Power management (DPM)",
>     > +      "Audio input override",
>     > +      "Separate audio inputs provided",
>     > +      "Audio support on video interface"
>     > +};
>     > +
>     > +static void print_flag_lines(const char *indent, const char *label, unsigned char flag_byte, const char **flags) {
>     > +      if (flag_byte) {
>     > +                      printf("%s\n", label);
>     > +                      for (int i = 0; i < 8; i++) {
>     > +                                      if (flag_byte & (1<<i)) {
>     > +                                                      printf("%s%s\n", indent, flags[i]);
>     > +                                      }
>     > +                      }
>     > +      }
>     > +}
>     > +
>     > +static void parse_displayid_parameters(const unsigned char *x) {
>     > +      int revisionflags=x[1];
>     > +      int len=x[2];
>     > +      if (revisionflags) {
>     > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
>     > +      }
>     > +      if (len != 12) {
>     > +                      printf("  Length is different than expected (%d != 12)\n", len);
>     > +                      printf("  ");
>     > +                      hex_block(x + 3, len);
>     > +      } else {
>     > +                      printf("  Image size: %.1f mm x %.1f mm\n", ((x[4]<<8) + x[3]) / 10.0, ((x[6]<<8) + x[5]) / 10.0);
>     > +                      printf("  Pixels: %d x %d\n", (x[8]<<8) + x[7], (x[10]<<8) + x[9]);
>     > +                      print_flag_lines("    ", "  Feature support flags:", x[11], feature_support_flags);
>     > +
>     > +                      if (x[12] != 0xff) {
>     > +                                      printf("  Gamma: %.2f\n", ((x[12] + 100.0) / 100.0));
>     > +                      }
>     > +                      printf("  Aspect ratio: %.2f\n", ((x[13] + 100.0) / 100.0));
>     > +                      printf("  Dynamic bpc native: %d\n", (x[14] & 0xf) + 1);
>     > +                      printf("  Dynamic bpc overall: %d\n", ((x[14] >> 4) & 0xf) + 1);
>     > +      } // else
>     > +}
>     > +
>     >  static void parse_displayid_detailed_timing(const unsigned char *x)
>     >  {
>     >         unsigned ha, hbl, hso, hspw;
>     > @@ -2713,18 +2762,343 @@ static const struct {
>     >         {2560, 1600, 120, 16, 10, 203217, 552750, 1},
>     >  };
>     >  
>     > +const char *displayid_vesa_dmt_timings[] = {
>     > +      "640x350@85Hz",
>     > +      "640x400@85Hz",
>     > +      "720x400@85Hz",
>     > +      "640x480@60Hz",
>     > +      "640x480@72Hz",
>     > +      "640x480@75Hz",
>     > +      "640x480@85Hz",
>     > +      "800x600@56Hz",
>     > +      "800x600@60Hz",
>     > +      "800x600@72Hz",
>     > +      "800x600@75Hz",
>     > +      "800x600@85Hz",
>     > +      "800x600@120Hz (RB)",
>     > +      "848x480@60Hz",
>     > +      "1024x768@43Hz (INT)",
>     > +      "1024x768@60Hz",
>     > +      "1024x768@70Hz",
>     > +      "1024x768@75Hz",
>     > +      "1024x768@85Hz",
>     > +      "1024x768@120Hz (RB)",
>     > +      "1152x864@75Hz",
>     > +      "1280x768@60Hz (RB)",
>     > +      "1280x768@60Hz",
>     > +      "1280x768@75Hz",
>     > +      "1280x768@85Hz",
>     > +      "1280x768@120Hz (RB)",
>     > +      "1280x800@60Hz (RB)",
>     > +      "1280x800@60Hz",
>     > +      "1280x800@75Hz",
>     > +      "1280x800@85Hz",
>     > +      "1280x800@120Hz (RB)",
>     > +      "1280x960@60Hz",
>     > +      "1280x960@85Hz",
>     > +      "1280x960@120Hz (RB)",
>     > +      "1280x1024@60Hz",
>     > +      "1280x1024@75Hz",
>     > +      "1280x1024@85Hz",
>     > +      "1280x1024@120Hz (RB)",
>     > +      "1360x768@60Hz",
>     > +      "1360x768@120Hz (RB)",
>     > +      "1400x1050@60Hz (RB)",
>     > +      "1400x1050@60Hz",
>     > +      "1400x1050@75Hz",
>     > +      "1400x1050@85Hz",
>     > +      "1400x1050@120Hz (RB)",
>     > +      "1440x900@60Hz (RB)",
>     > +      "1440x900@60Hz",
>     > +      "1440x900@75Hz",
>     > +      "1440x900@85Hz",
>     > +      "1440x900@120Hz (RB)",
>     > +      "1600x1200@60Hz",
>     > +      "1600x1200@65Hz",
>     > +      "1600x1200@70Hz",
>     > +      "1600x1200@75Hz",
>     > +      "1600x1200@85Hz",
>     > +      "1600x1200@120Hz (RB)",
>     > +      "1680x1050@60Hz (RB)",
>     > +      "1680x1050@60Hz",
>     > +      "1680x1050@75Hz",
>     > +      "1680x1050@85Hz",
>     > +      "1680x1050@120Hz (RB)",
>     > +      "1792x1344@60Hz",
>     > +      "1792x1344@75Hz",
>     > +      "1792x1344@120Hz (RB)",
>     > +      "1856x1392@60Hz",
>     > +      "1856x1392@75Hz",
>     > +      "1856x1392@120Hz (RB)",
>     > +      "1920x1200@60Hz (RB)",
>     > +      "1920x1200@60Hz",
>     > +      "1920x1200@75Hz",
>     > +      "1920x1200@85Hz",
>     > +      "1920x1200@120Hz (RB)",
>     > +      "1920x1440@60Hz",
>     > +      "1920x1440@75Hz",
>     > +      "1920x1440@120Hz (RB)",
>     > +      "2560x1600@60Hz (RB)",
>     > +      "2560x1600@60Hz",
>     > +      "2560x1600@75Hz",
>     > +      "2560x1600@85Hz",
>     > +      "2560x1600@120Hz (RB)",
>     > +};
>     
>     Isn't this effectively the same as the displayid_vesa_dmt array?
>     
>     > +
>     > +const char *displayid_cta_timings[] = {
>     > +      "640x480p@59.94/60Hz 4:3",
>     > +      "720x480p@59.94/60Hz 4:3",
>     > +      "720x480p@59.94/60Hz 16:9",
>     > +      "1280x720p@59.94/60Hz 16:9",
>     > +      "1920x1080i@59.94/60Hz 16:9",
>     > +      "720(1440)x480i@59.94/60Hz 4:3",
>     > +      "720(1440)x480i@59.94/60Hz 16:9",
>     > +      "720(1440)x240p@59.94/60Hz 4:3",
>     > +      "720(1440)x240p@59.94/60Hz 16:9",
>     > +      "2880x480i@59.94/60Hz 4:3",
>     > +      "2880x480i@59.94/60Hz 16:9",
>     > +      "2880x240p@59.94/60Hz 4:3",
>     > +      "2880x240p@59.94/60Hz 16:9",
>     > +      "1440x480p@59.94/60Hz 4:3",
>     > +      "1440x480p@59.94/60Hz 16:9",
>     > +      "1920x1080p@59.94/60Hz 16:9",
>     > +      "720x576p@50Hz 4:3",
>     > +      "720x576p@50Hz 16:9",
>     > +      "1280x720p@50Hz 16:9",
>     > +      "1920x1080i@50Hz 16:9",
>     > +      "720(1440)x576i@50Hz 4:3",
>     > +      "720(1440)x576i@50Hz 16:9",
>     > +      "720(1440)x288p@50Hz 4:3",
>     > +      "720(1440)x288p@50Hz 16:9",
>     > +      "2880x576i@50Hz 4:3",
>     > +      "2880x576i@50Hz 16:9",
>     > +      "2880x288p@50Hz 4:3",
>     > +      "2880x288p@50Hz 16:9",
>     > +      "1440x576p@50Hz 4:3",
>     > +      "1440x576p@50Hz 16:9",
>     > +      "1920x1080p@50Hz 16:9",
>     > +      "1920x1080p@23.97/24Hz 16:9",
>     > +      "1920x1080p@25Hz 16:9",
>     > +      "1920x1080p@29.97/30Hz 16:9",
>     > +      "2880x480p@59.94/60Hz 4:3",
>     > +      "2880x480p@59.94/60Hz 16:9",
>     > +      "2880x576p@50Hz 4:3",
>     > +      "2880x576p@50Hz 16:9",
>     > +      "1920x1080i@50Hz 16:9",
>     > +      "1920x1080i@100Hz 16:9",
>     > +      "1280x720p@100Hz 16:9",
>     > +      "720x576p@100Hz 4:3",
>     > +      "720x576p@100Hz 16:9",
>     > +      "720(1440)x576i@100Hz 4:3",
>     > +      "720(1440)x576i@100Hz 16:9",
>     > +      "1920x1080i@119.88/120Hz 16:9",
>     > +      "1280x720p@119.88/120Hz 16:9",
>     > +      "720x480p@119.88/120Hz 4:3",
>     > +      "720x480p@119.88/120Hz 16:9",
>     > +      "720(1440)x480i@119.88/120Hz 4:3",
>     > +      "720(1440)x480i@119.88/120Hz 16:9",
>     > +      "720x576p@200Hz 4:3",
>     > +      "720x576p@200Hz 16:9",
>     > +      "720(1440)x576i@200Hz 4:3",
>     > +      "720(1440)x576i@200Hz 16:9",
>     > +      "720x480p@239.76/240Hz 4:3",
>     > +      "720x480p@239.76/240Hz 16:9",
>     > +      "720(1440)x480i@239.76/240Hz 4:3",
>     > +      "720(1440)x480i@239.76/240Hz 16:9",
>     > +      "1280x720p@23.97/24Hz 16:9",
>     > +      "1280x720p@25Hz 16:9",
>     > +      "1280x720p@29.97/30Hz 16:9",
>     > +      "1920x1080p@120Hz 16:9",
>     > +      "1920x1080p@100Hz 16:9",
>     > +};
>     
>     And this is the same as edid_cta_modes1[].
>     
>     > +
>     > +static void parse_displayid_timing(const unsigned char *x, int expectedlen, const char** list)
>     > +{
>     > +      int revisionflags=x[1];
>     > +      int len=x[2];
>     > +      if (revisionflags) {
>     > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
>     > +      }
>     > +      if (len > expectedlen) {
>     > +                      printf("  Length is greater than expected (%d > %d)\n", len, expectedlen);
>     > +      } else if (len < expectedlen) {
>     > +                      printf("  Length is less than expected (%d < %d)\n", len, expectedlen);
>     > +      }
>     > +      x += 3;
>     > +      for (int i = 0; i < len * 8; i++) {
>     > +                      if (x[i>>3] & (1<<(i&7))) {
>     > +                                      if ((i>>3) < expectedlen) {
>     > +                                                      printf("  %s\n", list[i]);
>     > +                                      } else {
>     > +                                                      printf("  #%d\n", i+1);
>     > +                                      }
>     > +                      }
>     > +      }
>     > +}
>     > +
>     > +static void parse_displayid_gp_string(const unsigned char *x)
>     > +{
>     > +      int revisionflags=x[1];
>     > +      if (revisionflags) {
>     > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
>     > +      }
>     > +}
>     > +
>     > +static const char *bpc444[] = {"6", "8", "10", "12", "14", "16", NULL, NULL};
>     > +static const char *bpc4xx[] = {"8", "10", "12", "14", "16", NULL, NULL, NULL};
>     > +static const char *audiorates[] = {"32", "44.1", "48", NULL, NULL, NULL, NULL, NULL};
>     > +
>     > +static const char *colorspace_eotf_combinations[] = {
>     > +      "sRGB",
>     > +      "BT.601",
>     > +      "BT.709/BT.1886",
>     > +      "Adobe RGB",
>     > +      "DCI-P3",
>     > +      "BT.2020",
>     > +      "BT.2020/SMPTE ST 2084"
>     > +};
>     > +
>     > +static const char *colorspace_eotf_reserved[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
>     > +
>     > +static const char *colorspaces[] = {
>     > +      "Undefined",
>     > +      "sRGB",
>     > +      "BT.601",
>     > +      "BT.709",
>     > +      "Adobe RGB",
>     > +      "DCI-P3",
>     > +      "BT.2020",
>     > +      "Custom"
>     > +};
>     > +
>     > +static const char *eotfs[] = {
>     > +      "Undefined",
>     > +      "sRGB",
>     > +      "BT.601",
>     > +      "BT.1886",
>     > +      "Adobe RGB",
>     > +      "DCI-P3",
>     > +      "BT.2020",
>     > +      "Gamma function",
>     > +      "SMPTE ST 2084",
>     > +      "Hybrid Log",
>     > +      "Custom"
>     > +};
>     > +
>     > +static void print_flags(const char *label, unsigned char flag_byte, const char **flags, int reverse)
>     > +{
>     > +      if (flag_byte) {
>     > +                      printf("%s: ", label);
>     > +                      int countflags = 0;
>     > +                      for (int i = 0; i < 8; i++) {
>     > +                                      if (flag_byte & (1<<(reverse?7-i:i))) {
>     > +                                                      if (countflags)
>     > +                                                                      printf(", ");
>     > +                                                      if (flags[i])
>     > +                                                                      printf("%s", flags[i]);
>     > +                                                      else
>     > +                                                                      printf("Undefined(%d)", i);
>     > +                                                      countflags++;
>     > +                                      }
>     > +                      }
>     > +                      printf("\n");
>     > +      }
>     > +}
>     > +
>     > +static void parse_displayid_interface_features(const unsigned char *x)
>     > +{
>     > +      int revisionflags=x[1];
>     > +      int len=x[2];
>     > +      if (revisionflags) {
>     > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
>     > +      }
>     > +      if (len < 9) {
>     > +                      printf("  Length is less than expected (%d < 9)\n", len);
>     > +                      printf("  ");
>     > +                      hex_block(x + 3, len);
>     > +      } else {
>    > +                      print_flags("  Supported bpc for RGB encoding", x[3], bpc444, 0);
>     > +                      print_flags("  Supported bpc for YCbCr 4:4:4 encoding", x[4], bpc444, 0);
>     > +                      print_flags("  Supported bpc for YCbCr 4:2:2 encoding", x[5], bpc4xx, 0);
>     > +                      print_flags("  Supported bpc for YCbCr 4:2:0 encoding", x[6], bpc4xx, 0);
>     > +                      if (x[7])
>     > +                                      printf("  Minimum pixel rate at which YCbCr 4:2:0 encoding is supported: %.3f MHz\n", 74.25 * x[7]);
>     > +                      print_flags("  Supported audio capability and features (kHz)", x[8], audiorates, 1);
>     > +                      print_flags("  Supported color space and EOTF standard combination 1", x[9], colorspace_eotf_combinations, 0);
>     > +                      print_flags("  Supported color space and EOTF standard combination 2", x[10], colorspace_eotf_reserved, 0);
>     > +                      int i = 0;
>     > +                      if (len >= 9 && x[11] > 0) {
>     > +                                      printf("  Supported color space and EOTF additional combinations:");
>     > +                                      for (i = 1; i <= x[11]; i++) {
>     > +                                                      if (i > 7) {
>     > +                                                                      printf("\n  Number of additional color space and EOTF combinations (%d) is greater than allowed (7).", x[11]);
>     > +                                                                      break;
>     > +                                                      } else if (9 + i > len) {
>     > +                                                                      printf("\n  Number of additional color space and EOTF combinations (%d) is too many to fit in block (%d).", x[11], len - 9);
>     > +                                                                      break;
>     > +                                                      }
>     > +
>     > +                                                      const char *colorspace = "Out of range";
>     > +                                                      const char *eotf = "Out of range";
>     > +                                                      int colorspace_index = (x[11 + i] >> 4) & 0xf;
>     > +                                                      int eotf_index = x[11 + i] & 0xf;
>     > +                                                      if (colorspace_index < sizeof(colorspaces) / sizeof(colorspaces[0])) {
>     > +                                                                      colorspace = colorspaces[colorspace_index];
>     > +                                                      }
>     > +                                                      if (eotf_index < sizeof(eotfs) / sizeof(eotfs[0])) {
>     > +                                                                      eotf = eotfs[eotf_index];
>     > +                                                      }
>     > +
>     > +                                                      if (i > 1)
>     > +                                                                      printf(", ");
>     > +                                                      if (!strcmp(colorspace, eotf)) {
>     > +                                                                      printf("%s", colorspace);
>     > +                                                      } else {
>     > +                                                                      printf("%s/%s", colorspace, eotf);
>     > +                                                      }
>     > +                                      } // for
>     > +                                      printf("\n");
>     > +                      } // x[11]
>     > +                      if (len > 9 + i) {
>     > +                                      printf("  Length is greater than expected (%d > %d)\n", len, 9 + i);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + 11 + i, len - 9 - i);
>     > +                      } else if (len != 9 + i)  {
>     > +                                      printf("  Length is unexpected (%d != %d)\n", len, 9 + i);
>     > +                      }
>     > +      }
>     > +}
>     > +
>     > +static void parse_displayid_ContainerID(const unsigned char *x)
>     > +{
>     > +      int revisionflags=x[1];
>     > +      int len=x[2];
>     > +      if (revisionflags) {
>     > +                      printf("  Unexpected revision and flags (0x%02x != 0)\n", revisionflags);
>     > +      }
>     > +      x += 3;
>     > +      if (len != 16) {
>     > +                      printf("  Length is unexpected (%d != 16)\n", len);
>     > +                      printf("  ");
>     > +                      hex_block(x, len);
>     > +      } else {
>     > +                      printf("  %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15]);
>     > +      }
>     > +}
>     > +
>     >  static int parse_displayid(const unsigned char *x)
>     >  {
>     >         const unsigned char *orig = x;
>     >         unsigned version = x[1];
>     >         unsigned length = x[2];
>     > +      unsigned producttype = x[3];
>     >         unsigned ext_count = x[4];
>     >         unsigned i;
>     >  
>     >         cur_block = "DisplayID";
>     >  
>     > -       printf("Length %u, version %u.%u, extension count %u\n",
>     > -              length, version >> 4, version & 0xf, ext_count);
>     > +      printf("Length %u, version %u.%u, type %u, extension count %u\n",
>     > +             length, version >> 4, version & 0xf, producttype, ext_count);
>     >  
>     >         unsigned offset = 5;
>     >         while (length > 0) {
>     > @@ -2734,33 +3108,49 @@ static int parse_displayid(const unsigned char *x)
>     >                         if (len == 0)
>     >                                         break;
>     >                         switch (tag) {
>     > +                      
>     > +                      // DisplayID 1.3:
>     >                         case 0:
>     > -                                       printf("Product ID Block\n");
>     > +                                      printf("Product ID Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 1:
>     > -                                       printf("Display Parameters Block\n");
>     > +                                      printf("Display Parameters Block (%02Xh):\n", tag);
>     > +                                      parse_displayid_parameters(x + offset);
>     >                                         break;
>     >                         case 2:
>     > -                                       printf("Color Characteristics Block\n");
>     > +                                      printf("Color Characteristics Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 3: {
>     > -                                       printf("Type 1 Detailed Timings Block\n");
>     > +                                      printf("Type 1 Detailed Timings Block (%02Xh)\n", tag);
>     >                                         for (i = 0; i < len / 20; i++) {
>     >                                                         parse_displayid_detailed_timing(&x[offset + 3 + (i * 20)]);
>     >                                         }
>     >                                         break;
>     >                         }
>     >                         case 4:
>     > -                                       printf("Type 2 Detailed Timings Block\n");
>     > +                                      printf("Type 2 Detailed Timings Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 5:
>     > -                                       printf("Type 3 Short Timings Block\n");
>     > +                                      printf("Type 3 Short Timings Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 6:
>     > -                                       printf("Type 4 DMT Timings Block\n");
>     > +                                      printf("Type 4 DMT Timings Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 7:
>     > -                                       printf("Type 1 VESA DMT Timings Block\n");
>     > +                                      printf("Type 1 VESA DMT Timings Block (%02Xh)\n", tag);
>     > +                                      #if 0
>     > +                                      parse_displayid_timing(x + offset, 10, displayid_vesa_dmt_timings);
>     
>     What is the reason for the #if 0?
>     
>     I now get a warning that displayid_vesa_dmt_timings is unused.
>     
>     > +                                      #else
>     >                                         for (i = 0; i < min(len, 10) * 8; i++) {
>     >                                                         if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
>     >                                                                         printf("  %ux%u%s@%uHz %s%u:%u HorFreq: %.3f kHz Clock: %.3f MHz\n",
>     > @@ -2779,33 +3169,51 @@ static int parse_displayid(const unsigned char *x)
>     >                                                                         max_pixclk_khz = max(max_pixclk_khz, displayid_vesa_dmt[i].pixclk_khz);
>     >                                                         }
>     >                                         }
>     > +                                      #endif
>     >                                         break;
>     >                         case 8:
>     > -                                       printf("CTA Timings Block\n");
>     > +                                      printf("CTA Timings Block (%02Xh):\n", tag);
>     > +                                      parse_displayid_timing(x + offset, 8, displayid_cta_timings);
>     >                                         break;
>     >                         case 9:
>     > -                                       printf("Video Timing Range Block\n");
>     > +                                      printf("Video Timing Range Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0xa:
>     > -                                       printf("Product Serial Number Block\n");
>     > +                                      printf("Product Serial Number Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0xb:
>     > -                                       printf("GP ASCII String Block\n");
>     > +                                      printf("GP ASCII String Block (%02Xh): %s\n", tag, extract_string("GP ASCII String", x + offset + 3, &has_valid_GP_ascii_string, len));
>     > +                                      has_GP_ascii_string = 1;
>     > +                                      parse_displayid_gp_string(x + offset);
>     >                                         break;
>     >                         case 0xc:
>     > -                                       printf("Display Device Data Block\n");
>     > +                                      printf("Display Device Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0xd:
>     > -                                       printf("Interface Power Sequencing Block\n");
>     > +                                      printf("Interface Power Sequencing Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0xe:
>     > -                                       printf("Transfer Characteristics Block\n");
>     > +                                      printf("Transfer Characteristics Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0xf:
>     > -                                       printf("Display Interface Block\n");
>     > +                                      printf("Display Interface Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0x10:
>     > -                                       printf("Stereo Display Interface Block\n");
>     > +                                      printf("Stereo Display Interface Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         case 0x12: {
>     >                                         unsigned capabilities = x[offset + 3];
>     > @@ -2817,7 +3225,7 @@ static int parse_displayid(const unsigned char *x)
>     >                                         unsigned tile_height = x[offset + 9] | (x[offset + 10] << 8);
>     >                                         unsigned pix_mult = x[offset + 11];
>     >  
>     > -                                       printf("Tiled Display Topology Block\n");
>     > +                                      printf("Tiled Display Topology Block (%02Xh)\n", tag);
>     >                                         printf("  Capabilities: 0x%08x\n", capabilities);
>     >                                         printf("  Num horizontal tiles: %u Num vertical tiles: %u\n", num_h_tile + 1, num_v_tile + 1);
>     >                                         printf("  Tile location: %u, %u\n", tile_h_location, tile_v_location);
>     > @@ -2841,8 +3249,80 @@ static int parse_displayid(const unsigned char *x)
>     >                                         }
>     >                                         break;
>     >                         }
>     > +
>     > +                      // DisplayID 2.0
>     > +                      case 0x20:
>     > +                                      printf("Product ID Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x21:
>     > +                                      printf("Display Parameters Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x22:
>     > +                                      printf("Type 7 Timing - Detailed Timing Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x23:
>     > +                                      printf("Type 8 Timing - Enumerated Timing Code Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x24:
>     > +                                      printf("Type 9 Timing - Formula-based Timing Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x25:
>     > +                                      printf("Dynamic Video Timing Range Limits Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x26:
>     > +                                      printf("Display Interface Features Data Block (%02Xh):\n", tag);
>     > +                                      parse_displayid_interface_features(x + offset);
>     > +                                      break;
>     > +                      case 0x27:
>     > +                                      printf("Stereo Display Interface Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x28:
>     > +                                      printf("Tiled Display Topology Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +                      case 0x29:
>     > +                                      printf("ContainerID Data Block (%02Xh):\n", tag);
>     > +                                      parse_displayid_ContainerID(x + offset);
>     > +                                      break;
>     > +
>     > +                      // 2Ah .. 7Dh RESERVED for Additional VESA-defined Data Blocks
>     > +
>     > +                      case 0x7e: // DisplayID 2.0
>     > +                      case 0x7f: // DisplayID 1.3
>     > +                                      printf("Vendor-specific Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +
>     > +                      // 7Fh .. 80h RESERVED
>     > +
>     > +                      case 0x81:
>     > +                                      printf("CTA DisplayID Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     > +                                      break;
>     > +
>     > +                      // 82h .. FFh RESERVED
>     > +                      
>     >                         default:
>     > -                                       printf("Unknown DisplayID Data Block 0x%x\n", tag);
>     > +                                      printf("Unknown DisplayID Data Block (%02Xh)\n", tag);
>     > +                                      printf("  ");
>     > +                                      hex_block(x + offset + 3, len);
>     >                                         break;
>     >                         }
>     >                         length -= len + 3;
>     > @@ -3687,6 +4167,7 @@ static int edid_from_file(const char *from_file, const char *to_file,
>     >             !has_valid_range_descriptor ||
>     >             (has_name_descriptor && !has_valid_name_descriptor) ||
>     >             (has_serial_string && !has_valid_serial_string) ||
>     > +                      (has_GP_ascii_string && !has_valid_GP_ascii_string) ||
>     >             (has_ascii_string && !has_valid_ascii_string)) {
>     >                         conformant = 0;
>     >                         printf("EDID block does not conform:\n");
>     > @@ -3709,6 +4190,8 @@ static int edid_from_file(const char *from_file, const char *to_file,
>     >                                         printf("\tInvalid Monitor Name descriptor\n");
>     >                         if (has_ascii_string && !has_valid_ascii_string)
>     >                                         printf("\tInvalid ASCII string\n");
>     > +                      if (has_GP_ascii_string && !has_valid_GP_ascii_string)
>     > +                                      printf("\tInvalid GP ASCII string\n");
>     >                         if (has_serial_string && !has_valid_serial_string)
>     >                                         printf("\tInvalid serial string\n");
>     >         }
>     > 
>     
>     Regards,
>     
>                 Hans
>     
> 
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2019-11-25  9:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-23 16:45 [PATCH 00/10] edid-decode: bug fixes, additions, changes joevt
2019-11-23 16:45 ` [PATCH 01/10] edid-decode: change horizontal refresh rates to kHz joevt
2019-11-23 16:45 ` [PATCH 02/10] edid-decode: correct horizontal range in Monitor Ranges joevt
2019-11-23 16:45 ` [PATCH 03/10] edid-decode: correct calculation of DisplayID type 1 timings joevt
2019-11-23 16:45 ` [PATCH 04/10] edid-decode: add front porch, pulse width, and back porch joevt
2019-11-23 16:45 ` [PATCH 05/10] edid-decode: output timings for YCbCr 4:2:0 cmdb joevt
2019-11-24 10:26   ` Hans Verkuil
2019-11-25  6:32     ` Joe van Tunen
2019-11-25  8:20       ` Hans Verkuil
2019-11-23 16:46 ` [PATCH 06/10] edid-decode: Dump hex of unknown CTA Vendor-Specific blocks joevt
2019-11-23 16:46 ` [PATCH 07/10] edid-decode: cleanup printf format string compiler warnings joevt
2019-11-23 16:46 ` [PATCH 08/10] edid-decode: Dump hex of non-decoded extension blocks joevt
2019-11-23 16:46 ` [PATCH 09/10] edid-decode: DisplayID additions joevt
2019-11-24 10:03   ` Hans Verkuil
2019-11-25  6:30     ` Joe van Tunen
2019-11-25  9:15       ` Hans Verkuil
2019-11-23 16:46 ` [PATCH 10/10] edid-decode: add example EDIDs joevt
2019-11-24 11:10   ` Hans Verkuil
2019-11-24 11:12 ` [PATCH 00/10] edid-decode: bug fixes, additions, changes Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).