linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] edid-decode: bug fixes, additions, changes
@ 2021-09-14 12:11 joevt
  2021-09-14 12:11 ` [PATCH 01/11] edid-decode: add more example EDIDs joevt
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

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

I made a fork at https://github.com/joevt/edid-decode with the commits listed below.

For the first commit, I have a script to convert C printf format strings in the source code to regular expressions and then use those to find EDIDs in my collection (or in linuxhw/EDID) that contain matches to those regular expressions that are not matched by the EDIDs in the data directory. It prioritizes EDIDs that contain the most matches.

joevt (11):
  edid-decode: add more example EDIDs
  edid-decode: ignore dSYM
  edid-decode: change install directories for macOS
  edid-decode: add bounds checking
  edid-decode: fix standard timing vertical pixels
  edid-decode: linefeed before fail
  edid-decode: always linefeed after hex_block
  edid-decode: output full frequencies for 4:2:0
  edid-decode: allow undefined aspect ratio
  edid-decode: add warnings to VESA VSDB
  edid-decode: cta and displayid changes

 .gitignore                                    |   1 +
 Makefile                                      |  22 +-
 data/_EDID_ACR_0497                           | Bin 0 -> 256 bytes
 data/_EDID_AIC_1005                           | Bin 0 -> 256 bytes
 data/_EDID_APP_921f                           | Bin 0 -> 256 bytes
 data/_EDID_APP_9220                           | Bin 0 -> 256 bytes
 data/_EDID_BNQ_802e                           | Bin 0 -> 256 bytes
 data/_EDID_CMN_152a                           | Bin 0 -> 256 bytes
 data/_EDID_CVT_0003                           | Bin 0 -> 256 bytes
 data/_EDID_DEL_0001                           | Bin 0 -> 128 bytes
 data/_EDID_DEL_a07b                           | Bin 0 -> 384 bytes
 data/_EDID_DLM_0000                           | Bin 0 -> 256 bytes
 data/_EDID_DON_0046                           | Bin 0 -> 256 bytes
 data/_EDID_DVI_0000                           | Bin 0 -> 128 bytes
 data/_EDID_ELE_0938                           | Bin 0 -> 256 bytes
 data/_EDID_GDH_0030                           | Bin 0 -> 256 bytes
 data/_EDID_GSM_0001                           | Bin 0 -> 256 bytes
 data/_EDID_GSM_5b08                           | Bin 0 -> 256 bytes
 data/_EDID_GSM_5b08_2                         | Bin 0 -> 256 bytes
 data/_EDID_HPN_3530                           | Bin 0 -> 256 bytes
 data/_EDID_HPN_3645                           | Bin 0 -> 256 bytes
 data/_EDID_HSD_03e9                           | Bin 0 -> 128 bytes
 data/_EDID_HSD_04bb                           | Bin 0 -> 128 bytes
 data/_EDID_HWP_331b                           | Bin 0 -> 256 bytes
 data/_EDID_HYO_049b                           | Bin 0 -> 256 bytes
 data/_EDID_IVM_6615                           | Bin 0 -> 256 bytes
 data/_EDID_IVM_6640                           | Bin 0 -> 256 bytes
 data/_EDID_KMR_461a                           | Bin 0 -> 256 bytes
 data/_EDID_LEN_65cf                           | Bin 0 -> 256 bytes
 data/_EDID_LEN_65ed                           | Bin 0 -> 384 bytes
 data/_EDID_LEN_b800                           | Bin 0 -> 256 bytes
 data/_EDID_LGD_05c0                           | Bin 0 -> 128 bytes
 data/_EDID_LGD_4601                           | Bin 0 -> 128 bytes
 data/_EDID_LTM_2c02                           | Bin 0 -> 256 bytes
 data/_EDID_MSI_1462                           | Bin 0 -> 256 bytes
 data/_EDID_NOV_0405                           | Bin 0 -> 256 bytes
 data/_EDID_NSO_5605                           | Bin 0 -> 128 bytes
 data/_EDID_OEC_d501                           | Bin 0 -> 128 bytes
 data/_EDID_PDI_0030                           | Bin 0 -> 128 bytes
 data/_EDID_PHL_01ea                           | Bin 0 -> 256 bytes
 data/_EDID_PHL_01ea_2                         | Bin 0 -> 256 bytes
 data/_EDID_PHL_08fa                           | Bin 0 -> 512 bytes
 data/_EDID_PHL_c193                           | Bin 0 -> 256 bytes
 data/_EDID_PIO_0000                           | Bin 0 -> 256 bytes
 data/_EDID_PKB_00f8                           | Bin 0 -> 128 bytes
 data/_EDID_RHT_1234                           | Bin 0 -> 256 bytes
 data/_EDID_RJT_003a                           | Bin 0 -> 256 bytes
 data/_EDID_SAM_08f1                           | Bin 0 -> 256 bytes
 data/_EDID_SAM_0f14                           | Bin 0 -> 256 bytes
 data/_EDID_SAM_0f99                           | Bin 0 -> 512 bytes
 data/_EDID_SAM_7004                           | Bin 0 -> 256 bytes
 data/_EDID_SAN_2400                           | Bin 0 -> 128 bytes
 data/_EDID_SCN_03ff                           | Bin 0 -> 128 bytes
 data/_EDID_SEK_0000                           | Bin 0 -> 256 bytes
 data/_EDID_SHP_1008                           | Bin 0 -> 256 bytes
 data/_EDID_SPT_1801                           | Bin 0 -> 128 bytes
 data/_EDID_SUN_058f                           | Bin 0 -> 256 bytes
 data/_EDID_TCL_5655                           | Bin 0 -> 256 bytes
 data/_EDID_TGL_00f1                           | Bin 0 -> 256 bytes
 data/_EDID_UPD_4843                           | Bin 0 -> 256 bytes
 data/_EDID_USR_0100                           | Bin 0 -> 256 bytes
 data/_EDID_VIT_03dc                           | Bin 0 -> 128 bytes
 data/_EDID_VIZ_0030                           | Bin 0 -> 128 bytes
 data/_EDID_VIZ_0067                           | Bin 0 -> 256 bytes
 data/_EDID_VIZ_0092                           | Bin 0 -> 256 bytes
 data/_EDID_VIZ_1018                           | Bin 0 -> 256 bytes
 data/_EDID_VIZ_1018_2                         | Bin 0 -> 256 bytes
 data/_EDID_VSC_0e23                           | Bin 0 -> 256 bytes
 data/_EDID_VSC_0f1e                           | Bin 0 -> 256 bytes
 data/_EDID_VSC_2034                           | Bin 0 -> 256 bytes
 data/_EDID_VSC_bd2b                           | Bin 0 -> 384 bytes
 data/_EDID_XXX_001a                           | Bin 0 -> 256 bytes
 data/_EDID_YTH_0156                           | Bin 0 -> 256 bytes
 data/_EDID_YTH_1560                           | Bin 0 -> 256 bytes
 data/acer-xb321hk-dp                          | Bin 0 -> 256 bytes
 data/acer-xv273k-corrected_difdb              | Bin 0 -> 384 bytes
 data/{acer-xv273k-dp => acer-xv273k-dp1}      | Bin
 data/acer-xv273k-dp1-corrupted                | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2                          | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2-corrupted                | Bin 0 -> 384 bytes
 data/acer-xv273k-hdmi1                        | Bin 0 -> 256 bytes
 data/acer-xv273k-hdmi2                        | Bin 0 -> 256 bytes
 data/aoc-c24g1-dp                             | Bin 0 -> 256 bytes
 data/aoc-c24g1-hdmi                           | Bin 0 -> 256 bytes
 .../apple-17-inch-studio-display-crt-override | Bin 0 -> 128 bytes
 data/apple-applevision-750-override           | Bin 0 -> 128 bytes
 data/apple-applevision-850-override           | Bin 0 -> 128 bytes
 data/apple-cinemahd-23-2006-dvi               | Bin 0 -> 256 bytes
 data/apple-cinemahd-23-2008-dvi               | Bin 0 -> 256 bytes
 data/apple-imac-27-inch-mid-2010              | Bin 0 -> 128 bytes
 data/apple-imac-retina-5k-27-inch-2017-tile0  | Bin 0 -> 256 bytes
 data/apple-imac-retina-5k-27-inch-2017-tile1  | Bin 0 -> 256 bytes
 data/apple-macbookpro-16inch-2019             | Bin 0 -> 256 bytes
 data/apple-xdr-5k-tile0                       | Bin 0 -> 768 bytes
 data/apple-xdr-5k-tile1                       | Bin 0 -> 512 bytes
 data/apple-xdr-6k                             | Bin 0 -> 640 bytes
 data/apple-xdr-6k-tile0                       | Bin 0 -> 896 bytes
 data/apple-xdr-6k-tile1                       | Bin 0 -> 640 bytes
 data/asus-pb287                               | Bin 0 -> 256 bytes
 data/asus-pq321-dp-tile0                      | Bin 0 -> 384 bytes
 data/asus-xg438q-dp                           | Bin 0 -> 384 bytes
 data/atlona-athd420-hdmi-override             | Bin 0 -> 256 bytes
 data/chiyakeji-r1811-dp                       | Bin 0 -> 384 bytes
 data/chiyakeji-r9a18-dp-tile1                 | Bin 0 -> 384 bytes
 data/dell-up2715k-dp1-optomedia-cmv535        | Bin 0 -> 128 bytes
 data/hisense-h9g-hdmi                         | Bin 0 -> 256 bytes
 data/kds-vs555-vga                            | Bin 0 -> 128 bytes
 data/lg-31mu97-override                       | Bin 0 -> 384 bytes
 data/lg-34gn850b-dp                           | Bin 0 -> 384 bytes
 data/lg-34wk95uw-dp                           | Bin 0 -> 384 bytes
 data/lg-34wk95uw-overlay                      | Bin 0 -> 384 bytes
 data/lg-34wk95uw-thunderbolt-dp1-tile0        | Bin 0 -> 512 bytes
 data/lg-34wk95uw-thunderbolt-dp2-tile1        | Bin 0 -> 256 bytes
 data/lg-55sj850v-hdmi                         | Bin 0 -> 256 bytes
 data/lg-c8-hdmi                               | Bin 0 -> 256 bytes
 data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0 | Bin 0 -> 384 bytes
 data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1 | Bin 0 -> 256 bytes
 data/microsoft-surfacebook                    | Bin 0 -> 128 bytes
 data/optomedia-cmv535-hdmi_dip00-v2018        | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip00-v20180312    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip00-v20180618    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v2018        | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v20180312    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v20180618    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip10-v2018        | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip10-v20180312    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v2018        | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v20180312    | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v20180731    | Bin 0 -> 256 bytes
 data/panasonic-tx65gxr900-hdmi                | Bin 0 -> 256 bytes
 data/philips-ftv-hdmi1.4                      | Bin 0 -> 256 bytes
 data/philips-ftv-hdmi2.0                      | Bin 0 -> 256 bytes
 data/planar-ix2790                            | Bin 0 -> 384 bytes
 data/realtek-r9a18-hdmi                       | Bin 0 -> 256 bytes
 data/samsung-lu28r55-hdmi                     | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.0                    | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.1                    | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.1-game               | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi1                    | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi2                    | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi3                    | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi4                    | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-vga                      | Bin 0 -> 128 bytes
 data/sony-gdmf520-vga                         | Bin 0 -> 128 bytes
 data/sony-snyc901-override                    | Bin 0 -> 256 bytes
 data/sony-snyd301-override                    | Bin 0 -> 256 bytes
 data/sony-x900f-hdmi                          | Bin 0 -> 256 bytes
 data/vizio-e65e0-hdmi                         | Bin 0 -> 256 bytes
 data/vizio-m60c3-hdmi-onkyo-txnr555           | Bin 0 -> 256 bytes
 edid-decode.cpp                               | 109 +++-
 edid-decode.h                                 |  20 +-
 oui.h                                         |  20 +
 parse-base-block.cpp                          |   3 +-
 parse-cta-block.cpp                           | 456 ++++++----------
 parse-displayid-block.cpp                     | 512 +++++++++---------
 parse-vtb-ext-block.cpp                       |  13 +-
 156 files changed, 575 insertions(+), 581 deletions(-)
 create mode 100644 data/_EDID_ACR_0497
 create mode 100644 data/_EDID_AIC_1005
 create mode 100644 data/_EDID_APP_921f
 create mode 100644 data/_EDID_APP_9220
 create mode 100644 data/_EDID_BNQ_802e
 create mode 100644 data/_EDID_CMN_152a
 create mode 100644 data/_EDID_CVT_0003
 create mode 100644 data/_EDID_DEL_0001
 create mode 100644 data/_EDID_DEL_a07b
 create mode 100644 data/_EDID_DLM_0000
 create mode 100644 data/_EDID_DON_0046
 create mode 100644 data/_EDID_DVI_0000
 create mode 100644 data/_EDID_ELE_0938
 create mode 100644 data/_EDID_GDH_0030
 create mode 100644 data/_EDID_GSM_0001
 create mode 100644 data/_EDID_GSM_5b08
 create mode 100644 data/_EDID_GSM_5b08_2
 create mode 100644 data/_EDID_HPN_3530
 create mode 100644 data/_EDID_HPN_3645
 create mode 100644 data/_EDID_HSD_03e9
 create mode 100644 data/_EDID_HSD_04bb
 create mode 100644 data/_EDID_HWP_331b
 create mode 100644 data/_EDID_HYO_049b
 create mode 100644 data/_EDID_IVM_6615
 create mode 100644 data/_EDID_IVM_6640
 create mode 100644 data/_EDID_KMR_461a
 create mode 100644 data/_EDID_LEN_65cf
 create mode 100644 data/_EDID_LEN_65ed
 create mode 100644 data/_EDID_LEN_b800
 create mode 100644 data/_EDID_LGD_05c0
 create mode 100644 data/_EDID_LGD_4601
 create mode 100644 data/_EDID_LTM_2c02
 create mode 100644 data/_EDID_MSI_1462
 create mode 100644 data/_EDID_NOV_0405
 create mode 100644 data/_EDID_NSO_5605
 create mode 100644 data/_EDID_OEC_d501
 create mode 100644 data/_EDID_PDI_0030
 create mode 100644 data/_EDID_PHL_01ea
 create mode 100644 data/_EDID_PHL_01ea_2
 create mode 100644 data/_EDID_PHL_08fa
 create mode 100644 data/_EDID_PHL_c193
 create mode 100644 data/_EDID_PIO_0000
 create mode 100644 data/_EDID_PKB_00f8
 create mode 100644 data/_EDID_RHT_1234
 create mode 100644 data/_EDID_RJT_003a
 create mode 100644 data/_EDID_SAM_08f1
 create mode 100644 data/_EDID_SAM_0f14
 create mode 100644 data/_EDID_SAM_0f99
 create mode 100644 data/_EDID_SAM_7004
 create mode 100644 data/_EDID_SAN_2400
 create mode 100644 data/_EDID_SCN_03ff
 create mode 100644 data/_EDID_SEK_0000
 create mode 100644 data/_EDID_SHP_1008
 create mode 100644 data/_EDID_SPT_1801
 create mode 100644 data/_EDID_SUN_058f
 create mode 100644 data/_EDID_TCL_5655
 create mode 100644 data/_EDID_TGL_00f1
 create mode 100644 data/_EDID_UPD_4843
 create mode 100644 data/_EDID_USR_0100
 create mode 100644 data/_EDID_VIT_03dc
 create mode 100644 data/_EDID_VIZ_0030
 create mode 100644 data/_EDID_VIZ_0067
 create mode 100644 data/_EDID_VIZ_0092
 create mode 100644 data/_EDID_VIZ_1018
 create mode 100644 data/_EDID_VIZ_1018_2
 create mode 100644 data/_EDID_VSC_0e23
 create mode 100644 data/_EDID_VSC_0f1e
 create mode 100644 data/_EDID_VSC_2034
 create mode 100644 data/_EDID_VSC_bd2b
 create mode 100644 data/_EDID_XXX_001a
 create mode 100644 data/_EDID_YTH_0156
 create mode 100644 data/_EDID_YTH_1560
 create mode 100644 data/acer-xb321hk-dp
 create mode 100644 data/acer-xv273k-corrected_difdb
 rename data/{acer-xv273k-dp => acer-xv273k-dp1} (100%)
 create mode 100644 data/acer-xv273k-dp1-corrupted
 create mode 100644 data/acer-xv273k-dp2
 create mode 100644 data/acer-xv273k-dp2-corrupted
 create mode 100644 data/acer-xv273k-hdmi1
 create mode 100644 data/acer-xv273k-hdmi2
 create mode 100644 data/aoc-c24g1-dp
 create mode 100644 data/aoc-c24g1-hdmi
 create mode 100644 data/apple-17-inch-studio-display-crt-override
 create mode 100644 data/apple-applevision-750-override
 create mode 100644 data/apple-applevision-850-override
 create mode 100644 data/apple-cinemahd-23-2006-dvi
 create mode 100644 data/apple-cinemahd-23-2008-dvi
 create mode 100644 data/apple-imac-27-inch-mid-2010
 create mode 100644 data/apple-imac-retina-5k-27-inch-2017-tile0
 create mode 100644 data/apple-imac-retina-5k-27-inch-2017-tile1
 create mode 100644 data/apple-macbookpro-16inch-2019
 create mode 100644 data/apple-xdr-5k-tile0
 create mode 100644 data/apple-xdr-5k-tile1
 create mode 100644 data/apple-xdr-6k
 create mode 100644 data/apple-xdr-6k-tile0
 create mode 100644 data/apple-xdr-6k-tile1
 create mode 100644 data/asus-pb287
 create mode 100644 data/asus-pq321-dp-tile0
 create mode 100644 data/asus-xg438q-dp
 create mode 100644 data/atlona-athd420-hdmi-override
 create mode 100644 data/chiyakeji-r1811-dp
 create mode 100644 data/chiyakeji-r9a18-dp-tile1
 create mode 100644 data/dell-up2715k-dp1-optomedia-cmv535
 create mode 100644 data/hisense-h9g-hdmi
 create mode 100644 data/kds-vs555-vga
 create mode 100644 data/lg-31mu97-override
 create mode 100644 data/lg-34gn850b-dp
 create mode 100644 data/lg-34wk95uw-dp
 create mode 100644 data/lg-34wk95uw-overlay
 create mode 100644 data/lg-34wk95uw-thunderbolt-dp1-tile0
 create mode 100644 data/lg-34wk95uw-thunderbolt-dp2-tile1
 create mode 100644 data/lg-55sj850v-hdmi
 create mode 100644 data/lg-c8-hdmi
 create mode 100644 data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0
 create mode 100644 data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1
 create mode 100644 data/microsoft-surfacebook
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v20180618
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v20180618
 create mode 100644 data/optomedia-cmv535-hdmi_dip10-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip10-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v20180731
 create mode 100644 data/panasonic-tx65gxr900-hdmi
 create mode 100644 data/philips-ftv-hdmi1.4
 create mode 100644 data/philips-ftv-hdmi2.0
 create mode 100644 data/planar-ix2790
 create mode 100644 data/realtek-r9a18-hdmi
 create mode 100644 data/samsung-lu28r55-hdmi
 create mode 100644 data/samsung-q800t-hdmi2.0
 create mode 100644 data/samsung-q800t-hdmi2.1
 create mode 100644 data/samsung-q800t-hdmi2.1-game
 create mode 100644 data/sharp-lc70uq17u-hdmi1
 create mode 100644 data/sharp-lc70uq17u-hdmi2
 create mode 100644 data/sharp-lc70uq17u-hdmi3
 create mode 100644 data/sharp-lc70uq17u-hdmi4
 create mode 100644 data/sharp-lc70uq17u-vga
 create mode 100644 data/sony-gdmf520-vga
 create mode 100644 data/sony-snyc901-override
 create mode 100644 data/sony-snyd301-override
 create mode 100644 data/sony-x900f-hdmi
 create mode 100644 data/vizio-e65e0-hdmi
 create mode 100644 data/vizio-m60c3-hdmi-onkyo-txnr555
 create mode 100644 oui.h

-- 
2.24.3 (Apple Git-128)


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

* [PATCH 01/11] edid-decode: add more example EDIDs
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 02/11] edid-decode: ignore dSYM joevt
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

_EDID_AAA_0000
- EDIDs with names of this format are from https://github.com/linuxhw/EDID
- These EDIDs contain strings not seen in the other EDIDs of the data directory.
- AAA is the vendor ID.
- 0000 is the product ID.

acer-xb321hk-dp
- Acer Predator XB321HK
- This is a G-Sync display. Contains an NVIDIA VSDB.

acer-xv273k-dp1
acer-xv273k-dp2
- Acer XV273K DisplayPort 1.4 inputs when 4K 144K mode is disabled.

acer-xv273k-hdmi1
acer-xv273k-hdmi2
- Acer XV273K HDMI 2.0 inputs.

acer-xv273k-corrected_difdb
- Contains a corrected Display Interface Features Data Block for the Acer XV273K.

acer-xv273k-dp1-corrupted
- Sometimes the 3rd block of DisplayPort EDID from XV273K is a copy of the first or second block.
- Example of "Unknown Extension Block."

acer-xv273k-dp2-corrupted
- Sometimes the 3rd block of DisplayPort EDID from XV273K is a copy of the first or second block.
- Example of "Only one instance of this Data Block is allowed."

aoc-c24g1
- AOC C24G1

apple-17-inch-studio-display-crt-override
- macOS override for the 17 inch Studio Display (CRT).

apple-applevision-850-override
- macOS override for the AppleVision/ColorSync 850 Display

apple-applevision-750-override
- macOS override for the AppleVision/ColorSync 750 Display

apple-cinemahd-23-2008-dvi
- Apple Cinema HD Display, 23 inch, aluminum. This 2008 version supports HDCP.

apple-cinemahd-23-2006-dvi
- Apple Cinema HD Display, 23 inch, aluminum. This 2006 version does not support HDCP.

apple-imac-27-inch-mid-2010
- iMac (27-inch, Mid 2010)
- Example of "Monitor descriptor block has byte 4 nonzero".

apple-imac-retina-5k-27-inch-2017
- iMac (Retina 5K, 27-inch, 2017)
- Contains a dual-tile 5K display.
- Apple VSDB type 1 appears to be constant between different iMacs (sample size of 2)
- Color characteristics for red and blue may vary between different iMacs. Not sure about white and green.

apple-macbookpro-16-inch-2019
- MacBook Pro (16-inch, 2019)
- The EDID may contain different values for Color Characteristics: blue (0.0488, 0.0527, 0.0537, 0.0546)
- Apple VSDB type 3 contains a display panel model number (LP160WT1-SJA1, LP160WT1-SJA2, LP160WT1-SJA3, LP160WT1-SJA4) and some kind of serial number.
- Apple VSDB type 2 contains unknown data that varies.

apple-xdr-5k-tile0
apple-xdr-5k-tile1
- Apple Pro Display XDR. These EDIDs may be used for 6K single tile mode or 5K tiled mode (Thunderbolt connection).
- The Tiled Display Topology has info for 6K tiled but the tiled timings are sized for 5K. Apple uses an mtdd file for tile information.

apple-xdr-6k
- Apple Pro Display XDR. This EDID may be used for 6K. It contains no tile topology or tile timings.

apple-xdr-6k-tile0
apple-xdr-6k-tile1
- These EDIDs may be used for tiled 6K mode (two HBR3 x4 signals over Thunderbolt 3 with no DSC).
- Largest EDID ever with 6 extension blocks.
- Has one 60Hz mode for 1440p (for DisplayPort 1.1 compatibility) and five refresh rates for each of 4K, 5K, 6K, 5K/2 tiled modes, 6K/2 tiled modes.
- The five refresh rates are for 47.95, 48, 50, 59.94, 60Hz.
- For each resolution, only the delay between frames (just the vertical front porch) is different between different refresh rates.
- Tile topology has info for 6K tiled mode only, not 5K tiled mode even though 5K tile timings are also included.

For any of xdr EDIDs above:
- The EDIDs may exclude BT2020RGB from the Colorimetry Data Block and/or HDR and SMPTE ST2084 from the Electro optical transfer functions.
- If HDR is removed from Electro optical transfer functions, then Desired content max luminance is reduced from 1600 nits to 507.620 nits and Desired content min luminance is increased from value 1 to value 2 (both values are 0 nits).
- An alternative SDR mode may have max luminance and max frame-average luminance reduced from 507.620 nits to 161.049 nits while min luminance is increased from value 2 to value 4 (both values are 0 nits).
- Perhaps other presets (selectable in macOS via the Displays preferences panel or in Windows by the Boot Camp control panel) will make other changes to the EDIDs.

asus-pb287
- ASUS PB287Q Monitor - 28 inch 4K UHD (3840x2160), 1ms, Flicker free

asus-pq321
- ASUS PQ321
- 4K MST display.
- macOS doesn't support MST for multiple displays but does support MST for old 4K MST displays which use seperate streams for the left half and right half of the display.
- Left tile only. EDID for right tile of 4K MST display is not easily accessible in macOS.

asus-xg438q
- ASUS ROG Strix XG438Q

atlona-athd420-hdmi-override
- macOS override for the Atlona AT-HD420 HDMI to VGA/Component and Stereo Audio Format Converter

chiyakeji-r9a18
- 5K LCD controller driver board R9A18 LCD hd display motherboard HDR Freesync 4K 144Hz DIY For LCD LED screen LM270QQ2 LM270QQ1.
- Only EDID for tile 1 is included.

chiyakeji-r1811
- 5K universal DIY HD R1811 driver board USB-C HDR Freesync EDP VBO 144Hz DP1.4 LCD driver board for LM270QQ1 LM270QQ2.
- A 5K display, not tiled but I think you can get a tiled firmware.
- Maybe same board used in Geekon 27-inch 5K display.
- Other EDID may have display name "DP 5K3K".
- Supports DSC but I have not seen confirmation of 5K 60Hz 10bpc RGB.

dell-up2715k-dp1-optomedia-cmv535
- A Dell UP2715K connected to the DisplayPort output of a Optomedia CMV-535 HDMI 2.0 to DisplayPort 1.2 adapter.
- Example of "EDID 1.4 block does not set max dotclock.".

hisense-h9g-hdmi
- 65 inch Hisense H9G HDMI 2.0

kds-vs555
- KDS Visual Sensations VS-555 - CRT monitor - 15 inch

lg-31mu97-override
- macOS override for the LG 31MU97-B.
- Example of "DIRECT DRIVE monitor".

lg-34gn850b
- LG UltraGear 34GN850-B 34 inch 21:9 Curved UltraGear QHD 1ms Gaming Monitor with 144Hz

lg-34wk95uw
- LG 34WK95U-W 5K2K display.
- Thunderbolt 3 HBR2 tiled mode (dual 2560x2160).
- DisplayPort 1.4 HBR3 mode 5120x2160.

lg-34wk95uw-overlay
- In macOS, a supported dual-tile display usually has a .mtdd file containing an overlay which is an EDID that represents the display as a single tile.
- Example of "There are more Native DTDs \(\d+\) than DTDs \(\d+\)\.\n"

lg-55sj850v
- LG 55SJ850V

lg-c8
- LG C8 OLED TV

lg-ultrafine-5k-v1
- LG UltraFine 5K v1
- Has some minor differences from v2.

microsoft-surfacebook
- Microsoft Surface Book

optomedia-cmv535
- This converter has two dip switches to select between 4 EDIDs.
- Similar models:
-- Optomedia CMV-535 HDMI 2.0a to DisplayPort 1.2a Converter
-- SIIG HDMI 2.0 to DisplayPort 1.2 Converter - 4Kx2K 60Hz
-- gofanco Prophecy HDMI 2.0 to DisplayPort 1.2 Converter/Adapter

panasonic-tx65gxr900
- Panasonic TX-65GXR900

philips-ftv
- Philips FTV
- The HDMI 2.0 version comes from enabling UHD HDMI.
- Example of Dolby VSDB items "10 bit", "Standard + Low-Latency + Low-Latency-HDMI".

planar-ix2790
- Planar IX2790
- A single tile 5K display

samsung-lu28r55
- Samsung 28 inch UHD resolution monitor with IPS panel
- Example of "The year %d is more than one year in the future."

samsung-q800t
- Samsung 75 inch Q800T 2020 8K monitor has some HDMI 2.0 connectors and one HDMI 2.1 connector. The Game mode option enabled VRR.

sharp-lc70uq17u
- SHARP LC-70UQ17U has four HDMI inputs and a VGA input. Other inputs don’t have EDID.

sony-gdmf520
- Sony GDM-F520

sony-snyc901-override
sony-snyd301-override
- macOS overrides for some unknown Sony TVs.
- Examples of "Interlaced audio" and "Interlaced video".

sony-x900f
- Sony X900F

vizio-e65e0-hdmi
- Vizio E65-E0

vizio-m60c3-hdmi-onkyo-txnr555
- VIZIO M-Series 60" Class Ultra HD Full-Array LED Smart TV | M60-C3
- Connected to Onkyo TX-NR555 (receiver)

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 data/_EDID_ACR_0497                            | Bin 0 -> 256 bytes
 data/_EDID_AIC_1005                            | Bin 0 -> 256 bytes
 data/_EDID_APP_921f                            | Bin 0 -> 256 bytes
 data/_EDID_APP_9220                            | Bin 0 -> 256 bytes
 data/_EDID_BNQ_802e                            | Bin 0 -> 256 bytes
 data/_EDID_CMN_152a                            | Bin 0 -> 256 bytes
 data/_EDID_CVT_0003                            | Bin 0 -> 256 bytes
 data/_EDID_DEL_0001                            | Bin 0 -> 128 bytes
 data/_EDID_DEL_a07b                            | Bin 0 -> 384 bytes
 data/_EDID_DLM_0000                            | Bin 0 -> 256 bytes
 data/_EDID_DON_0046                            | Bin 0 -> 256 bytes
 data/_EDID_DVI_0000                            | Bin 0 -> 128 bytes
 data/_EDID_ELE_0938                            | Bin 0 -> 256 bytes
 data/_EDID_GDH_0030                            | Bin 0 -> 256 bytes
 data/_EDID_GSM_0001                            | Bin 0 -> 256 bytes
 data/_EDID_GSM_5b08                            | Bin 0 -> 256 bytes
 data/_EDID_GSM_5b08_2                          | Bin 0 -> 256 bytes
 data/_EDID_HPN_3530                            | Bin 0 -> 256 bytes
 data/_EDID_HPN_3645                            | Bin 0 -> 256 bytes
 data/_EDID_HSD_03e9                            | Bin 0 -> 128 bytes
 data/_EDID_HSD_04bb                            | Bin 0 -> 128 bytes
 data/_EDID_HWP_331b                            | Bin 0 -> 256 bytes
 data/_EDID_HYO_049b                            | Bin 0 -> 256 bytes
 data/_EDID_IVM_6615                            | Bin 0 -> 256 bytes
 data/_EDID_IVM_6640                            | Bin 0 -> 256 bytes
 data/_EDID_KMR_461a                            | Bin 0 -> 256 bytes
 data/_EDID_LEN_65cf                            | Bin 0 -> 256 bytes
 data/_EDID_LEN_65ed                            | Bin 0 -> 384 bytes
 data/_EDID_LEN_b800                            | Bin 0 -> 256 bytes
 data/_EDID_LGD_05c0                            | Bin 0 -> 128 bytes
 data/_EDID_LGD_4601                            | Bin 0 -> 128 bytes
 data/_EDID_LTM_2c02                            | Bin 0 -> 256 bytes
 data/_EDID_MSI_1462                            | Bin 0 -> 256 bytes
 data/_EDID_NOV_0405                            | Bin 0 -> 256 bytes
 data/_EDID_NSO_5605                            | Bin 0 -> 128 bytes
 data/_EDID_OEC_d501                            | Bin 0 -> 128 bytes
 data/_EDID_PDI_0030                            | Bin 0 -> 128 bytes
 data/_EDID_PHL_01ea                            | Bin 0 -> 256 bytes
 data/_EDID_PHL_01ea_2                          | Bin 0 -> 256 bytes
 data/_EDID_PHL_08fa                            | Bin 0 -> 512 bytes
 data/_EDID_PHL_c193                            | Bin 0 -> 256 bytes
 data/_EDID_PIO_0000                            | Bin 0 -> 256 bytes
 data/_EDID_PKB_00f8                            | Bin 0 -> 128 bytes
 data/_EDID_RHT_1234                            | Bin 0 -> 256 bytes
 data/_EDID_RJT_003a                            | Bin 0 -> 256 bytes
 data/_EDID_SAM_08f1                            | Bin 0 -> 256 bytes
 data/_EDID_SAM_0f14                            | Bin 0 -> 256 bytes
 data/_EDID_SAM_0f99                            | Bin 0 -> 512 bytes
 data/_EDID_SAM_7004                            | Bin 0 -> 256 bytes
 data/_EDID_SAN_2400                            | Bin 0 -> 128 bytes
 data/_EDID_SCN_03ff                            | Bin 0 -> 128 bytes
 data/_EDID_SEK_0000                            | Bin 0 -> 256 bytes
 data/_EDID_SHP_1008                            | Bin 0 -> 256 bytes
 data/_EDID_SPT_1801                            | Bin 0 -> 128 bytes
 data/_EDID_SUN_058f                            | Bin 0 -> 256 bytes
 data/_EDID_TCL_5655                            | Bin 0 -> 256 bytes
 data/_EDID_TGL_00f1                            | Bin 0 -> 256 bytes
 data/_EDID_UPD_4843                            | Bin 0 -> 256 bytes
 data/_EDID_USR_0100                            | Bin 0 -> 256 bytes
 data/_EDID_VIT_03dc                            | Bin 0 -> 128 bytes
 data/_EDID_VIZ_0030                            | Bin 0 -> 128 bytes
 data/_EDID_VIZ_0067                            | Bin 0 -> 256 bytes
 data/_EDID_VIZ_0092                            | Bin 0 -> 256 bytes
 data/_EDID_VIZ_1018                            | Bin 0 -> 256 bytes
 data/_EDID_VIZ_1018_2                          | Bin 0 -> 256 bytes
 data/_EDID_VSC_0e23                            | Bin 0 -> 256 bytes
 data/_EDID_VSC_0f1e                            | Bin 0 -> 256 bytes
 data/_EDID_VSC_2034                            | Bin 0 -> 256 bytes
 data/_EDID_VSC_bd2b                            | Bin 0 -> 384 bytes
 data/_EDID_XXX_001a                            | Bin 0 -> 256 bytes
 data/_EDID_YTH_0156                            | Bin 0 -> 256 bytes
 data/_EDID_YTH_1560                            | Bin 0 -> 256 bytes
 data/acer-xb321hk-dp                           | Bin 0 -> 256 bytes
 data/acer-xv273k-corrected_difdb               | Bin 0 -> 384 bytes
 data/{acer-xv273k-dp => acer-xv273k-dp1}       | Bin
 data/acer-xv273k-dp1-corrupted                 | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2                           | Bin 0 -> 384 bytes
 data/acer-xv273k-dp2-corrupted                 | Bin 0 -> 384 bytes
 data/acer-xv273k-hdmi1                         | Bin 0 -> 256 bytes
 data/acer-xv273k-hdmi2                         | Bin 0 -> 256 bytes
 data/aoc-c24g1-dp                              | Bin 0 -> 256 bytes
 data/aoc-c24g1-hdmi                            | Bin 0 -> 256 bytes
 data/apple-17-inch-studio-display-crt-override | Bin 0 -> 128 bytes
 data/apple-applevision-750-override            | Bin 0 -> 128 bytes
 data/apple-applevision-850-override            | Bin 0 -> 128 bytes
 data/apple-cinemahd-23-2006-dvi                | Bin 0 -> 256 bytes
 data/apple-cinemahd-23-2008-dvi                | Bin 0 -> 256 bytes
 data/apple-imac-27-inch-mid-2010               | Bin 0 -> 128 bytes
 data/apple-imac-retina-5k-27-inch-2017-tile0   | Bin 0 -> 256 bytes
 data/apple-imac-retina-5k-27-inch-2017-tile1   | Bin 0 -> 256 bytes
 data/apple-macbookpro-16inch-2019              | Bin 0 -> 256 bytes
 data/apple-xdr-5k-tile0                        | Bin 0 -> 768 bytes
 data/apple-xdr-5k-tile1                        | Bin 0 -> 512 bytes
 data/apple-xdr-6k                              | Bin 0 -> 640 bytes
 data/apple-xdr-6k-tile0                        | Bin 0 -> 896 bytes
 data/apple-xdr-6k-tile1                        | Bin 0 -> 640 bytes
 data/asus-pb287                                | Bin 0 -> 256 bytes
 data/asus-pq321-dp-tile0                       | Bin 0 -> 384 bytes
 data/asus-xg438q-dp                            | Bin 0 -> 384 bytes
 data/atlona-athd420-hdmi-override              | Bin 0 -> 256 bytes
 data/chiyakeji-r1811-dp                        | Bin 0 -> 384 bytes
 data/chiyakeji-r9a18-dp-tile1                  | Bin 0 -> 384 bytes
 data/dell-up2715k-dp1-optomedia-cmv535         | Bin 0 -> 128 bytes
 data/hisense-h9g-hdmi                          | Bin 0 -> 256 bytes
 data/kds-vs555-vga                             | Bin 0 -> 128 bytes
 data/lg-31mu97-override                        | Bin 0 -> 384 bytes
 data/lg-34gn850b-dp                            | Bin 0 -> 384 bytes
 data/lg-34wk95uw-dp                            | Bin 0 -> 384 bytes
 data/lg-34wk95uw-overlay                       | Bin 0 -> 384 bytes
 data/lg-34wk95uw-thunderbolt-dp1-tile0         | Bin 0 -> 512 bytes
 data/lg-34wk95uw-thunderbolt-dp2-tile1         | Bin 0 -> 256 bytes
 data/lg-55sj850v-hdmi                          | Bin 0 -> 256 bytes
 data/lg-c8-hdmi                                | Bin 0 -> 256 bytes
 data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0  | Bin 0 -> 384 bytes
 data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1  | Bin 0 -> 256 bytes
 data/microsoft-surfacebook                     | Bin 0 -> 128 bytes
 data/optomedia-cmv535-hdmi_dip00-v2018         | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip00-v20180312     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip00-v20180618     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v2018         | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v20180312     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip01-v20180618     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip10-v2018         | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip10-v20180312     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v2018         | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v20180312     | Bin 0 -> 256 bytes
 data/optomedia-cmv535-hdmi_dip11-v20180731     | Bin 0 -> 256 bytes
 data/panasonic-tx65gxr900-hdmi                 | Bin 0 -> 256 bytes
 data/philips-ftv-hdmi1.4                       | Bin 0 -> 256 bytes
 data/philips-ftv-hdmi2.0                       | Bin 0 -> 256 bytes
 data/planar-ix2790                             | Bin 0 -> 384 bytes
 data/realtek-r9a18-hdmi                        | Bin 0 -> 256 bytes
 data/samsung-lu28r55-hdmi                      | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.0                     | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.1                     | Bin 0 -> 256 bytes
 data/samsung-q800t-hdmi2.1-game                | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi1                     | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi2                     | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi3                     | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-hdmi4                     | Bin 0 -> 256 bytes
 data/sharp-lc70uq17u-vga                       | Bin 0 -> 128 bytes
 data/sony-gdmf520-vga                          | Bin 0 -> 128 bytes
 data/sony-snyc901-override                     | Bin 0 -> 256 bytes
 data/sony-snyd301-override                     | Bin 0 -> 256 bytes
 data/sony-x900f-hdmi                           | Bin 0 -> 256 bytes
 data/vizio-e65e0-hdmi                          | Bin 0 -> 256 bytes
 data/vizio-m60c3-hdmi-onkyo-txnr555            | Bin 0 -> 256 bytes
 147 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 data/_EDID_ACR_0497
 create mode 100644 data/_EDID_AIC_1005
 create mode 100644 data/_EDID_APP_921f
 create mode 100644 data/_EDID_APP_9220
 create mode 100644 data/_EDID_BNQ_802e
 create mode 100644 data/_EDID_CMN_152a
 create mode 100644 data/_EDID_CVT_0003
 create mode 100644 data/_EDID_DEL_0001
 create mode 100644 data/_EDID_DEL_a07b
 create mode 100644 data/_EDID_DLM_0000
 create mode 100644 data/_EDID_DON_0046
 create mode 100644 data/_EDID_DVI_0000
 create mode 100644 data/_EDID_ELE_0938
 create mode 100644 data/_EDID_GDH_0030
 create mode 100644 data/_EDID_GSM_0001
 create mode 100644 data/_EDID_GSM_5b08
 create mode 100644 data/_EDID_GSM_5b08_2
 create mode 100644 data/_EDID_HPN_3530
 create mode 100644 data/_EDID_HPN_3645
 create mode 100644 data/_EDID_HSD_03e9
 create mode 100644 data/_EDID_HSD_04bb
 create mode 100644 data/_EDID_HWP_331b
 create mode 100644 data/_EDID_HYO_049b
 create mode 100644 data/_EDID_IVM_6615
 create mode 100644 data/_EDID_IVM_6640
 create mode 100644 data/_EDID_KMR_461a
 create mode 100644 data/_EDID_LEN_65cf
 create mode 100644 data/_EDID_LEN_65ed
 create mode 100644 data/_EDID_LEN_b800
 create mode 100644 data/_EDID_LGD_05c0
 create mode 100644 data/_EDID_LGD_4601
 create mode 100644 data/_EDID_LTM_2c02
 create mode 100644 data/_EDID_MSI_1462
 create mode 100644 data/_EDID_NOV_0405
 create mode 100644 data/_EDID_NSO_5605
 create mode 100644 data/_EDID_OEC_d501
 create mode 100644 data/_EDID_PDI_0030
 create mode 100644 data/_EDID_PHL_01ea
 create mode 100644 data/_EDID_PHL_01ea_2
 create mode 100644 data/_EDID_PHL_08fa
 create mode 100644 data/_EDID_PHL_c193
 create mode 100644 data/_EDID_PIO_0000
 create mode 100644 data/_EDID_PKB_00f8
 create mode 100644 data/_EDID_RHT_1234
 create mode 100644 data/_EDID_RJT_003a
 create mode 100644 data/_EDID_SAM_08f1
 create mode 100644 data/_EDID_SAM_0f14
 create mode 100644 data/_EDID_SAM_0f99
 create mode 100644 data/_EDID_SAM_7004
 create mode 100644 data/_EDID_SAN_2400
 create mode 100644 data/_EDID_SCN_03ff
 create mode 100644 data/_EDID_SEK_0000
 create mode 100644 data/_EDID_SHP_1008
 create mode 100644 data/_EDID_SPT_1801
 create mode 100644 data/_EDID_SUN_058f
 create mode 100644 data/_EDID_TCL_5655
 create mode 100644 data/_EDID_TGL_00f1
 create mode 100644 data/_EDID_UPD_4843
 create mode 100644 data/_EDID_USR_0100
 create mode 100644 data/_EDID_VIT_03dc
 create mode 100644 data/_EDID_VIZ_0030
 create mode 100644 data/_EDID_VIZ_0067
 create mode 100644 data/_EDID_VIZ_0092
 create mode 100644 data/_EDID_VIZ_1018
 create mode 100644 data/_EDID_VIZ_1018_2
 create mode 100644 data/_EDID_VSC_0e23
 create mode 100644 data/_EDID_VSC_0f1e
 create mode 100644 data/_EDID_VSC_2034
 create mode 100644 data/_EDID_VSC_bd2b
 create mode 100644 data/_EDID_XXX_001a
 create mode 100644 data/_EDID_YTH_0156
 create mode 100644 data/_EDID_YTH_1560
 create mode 100644 data/acer-xb321hk-dp
 create mode 100644 data/acer-xv273k-corrected_difdb
 rename data/{acer-xv273k-dp => acer-xv273k-dp1} (100%)
 create mode 100644 data/acer-xv273k-dp1-corrupted
 create mode 100644 data/acer-xv273k-dp2
 create mode 100644 data/acer-xv273k-dp2-corrupted
 create mode 100644 data/acer-xv273k-hdmi1
 create mode 100644 data/acer-xv273k-hdmi2
 create mode 100644 data/aoc-c24g1-dp
 create mode 100644 data/aoc-c24g1-hdmi
 create mode 100644 data/apple-17-inch-studio-display-crt-override
 create mode 100644 data/apple-applevision-750-override
 create mode 100644 data/apple-applevision-850-override
 create mode 100644 data/apple-cinemahd-23-2006-dvi
 create mode 100644 data/apple-cinemahd-23-2008-dvi
 create mode 100644 data/apple-imac-27-inch-mid-2010
 create mode 100644 data/apple-imac-retina-5k-27-inch-2017-tile0
 create mode 100644 data/apple-imac-retina-5k-27-inch-2017-tile1
 create mode 100644 data/apple-macbookpro-16inch-2019
 create mode 100644 data/apple-xdr-5k-tile0
 create mode 100644 data/apple-xdr-5k-tile1
 create mode 100644 data/apple-xdr-6k
 create mode 100644 data/apple-xdr-6k-tile0
 create mode 100644 data/apple-xdr-6k-tile1
 create mode 100644 data/asus-pb287
 create mode 100644 data/asus-pq321-dp-tile0
 create mode 100644 data/asus-xg438q-dp
 create mode 100644 data/atlona-athd420-hdmi-override
 create mode 100644 data/chiyakeji-r1811-dp
 create mode 100644 data/chiyakeji-r9a18-dp-tile1
 create mode 100644 data/dell-up2715k-dp1-optomedia-cmv535
 create mode 100644 data/hisense-h9g-hdmi
 create mode 100644 data/kds-vs555-vga
 create mode 100644 data/lg-31mu97-override
 create mode 100644 data/lg-34gn850b-dp
 create mode 100644 data/lg-34wk95uw-dp
 create mode 100644 data/lg-34wk95uw-overlay
 create mode 100644 data/lg-34wk95uw-thunderbolt-dp1-tile0
 create mode 100644 data/lg-34wk95uw-thunderbolt-dp2-tile1
 create mode 100644 data/lg-55sj850v-hdmi
 create mode 100644 data/lg-c8-hdmi
 create mode 100644 data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0
 create mode 100644 data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1
 create mode 100644 data/microsoft-surfacebook
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip00-v20180618
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip01-v20180618
 create mode 100644 data/optomedia-cmv535-hdmi_dip10-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip10-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v2018
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v20180312
 create mode 100644 data/optomedia-cmv535-hdmi_dip11-v20180731
 create mode 100644 data/panasonic-tx65gxr900-hdmi
 create mode 100644 data/philips-ftv-hdmi1.4
 create mode 100644 data/philips-ftv-hdmi2.0
 create mode 100644 data/planar-ix2790
 create mode 100644 data/realtek-r9a18-hdmi
 create mode 100644 data/samsung-lu28r55-hdmi
 create mode 100644 data/samsung-q800t-hdmi2.0
 create mode 100644 data/samsung-q800t-hdmi2.1
 create mode 100644 data/samsung-q800t-hdmi2.1-game
 create mode 100644 data/sharp-lc70uq17u-hdmi1
 create mode 100644 data/sharp-lc70uq17u-hdmi2
 create mode 100644 data/sharp-lc70uq17u-hdmi3
 create mode 100644 data/sharp-lc70uq17u-hdmi4
 create mode 100644 data/sharp-lc70uq17u-vga
 create mode 100644 data/sony-gdmf520-vga
 create mode 100644 data/sony-snyc901-override
 create mode 100644 data/sony-snyd301-override
 create mode 100644 data/sony-x900f-hdmi
 create mode 100644 data/vizio-e65e0-hdmi
 create mode 100644 data/vizio-m60c3-hdmi-onkyo-txnr555

diff --git a/data/_EDID_ACR_0497 b/data/_EDID_ACR_0497
new file mode 100644
index 0000000000000000000000000000000000000000..619774a21ad0d98c720e91bd368dcfdbd1e772ef
GIT binary patch
literal 256
zcmZSh4+ab@MblXdJqsqQ$}%!H7)V!~vfQvVBw(JJU_i+J_YH;qjSh_sjRzVTrZQ}1
zxOjlcszIXALf0We$CcqOk01ks90LQxUj}m@`Cvf?E(I_Eiu_^lb~G|F@Cbwm0Y&~Z
zgqRw-x*8Z5T9_Idb1`}_F-vUpXJle#VP#{VASfg(A}S`I%*?}pX#=Ay&`udKg$Ny0
oh@JBoWf_VBFUTq6X@o*u(ZhA2OW}d8fPmdJh=>HxPJCcG0AOP}0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_AIC_1005 b/data/_EDID_AIC_1005
new file mode 100644
index 0000000000000000000000000000000000000000..f19a1dc82cd99d1105cbab34fda40b6e8442a49b
GIT binary patch
literal 256
zcmZSh4+adZ%B%u{R~Z=0Bp8_+Y?LarHnA=a^Pi`|9}u$tJ;TKVi9S;qrt)uQXl!5v
z0w${li9!oqhX@^4hOhud1_n6>28O>37Cv&pf(%>=U;q^P!{DPEZe$J>PymYjXD~GZ
zLYN4nI}@|qM{iaU0eKc-W+5g)MrBTR#%4wahE!%A1_6d1t_xiX4|D|t?508NkzkZ%
iC<?qFr;w)+3bh$i4Nzo)f`g#~j{{VV1kh&eKpX(h*);(G

literal 0
HcmV?d00001

diff --git a/data/_EDID_APP_921f b/data/_EDID_APP_921f
new file mode 100644
index 0000000000000000000000000000000000000000..34d578be0b2dc9a348c730d7e8c9370a76f15358
GIT binary patch
literal 256
zcmZSh4+acu0`imAa{pse=3``TFqE&*JHK^tsOL;ofq)PO28N3aj3_|WreQ(B24x2W
z1v7^CW`Yb1Qb0w27@RZnQgag(JX{o9GK;|?1v!b8TtF5M!1&97kqIPM#=y9g;s1YT
QDXA5VV6_fllIBD+0L!o<0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_APP_9220 b/data/_EDID_APP_9220
new file mode 100644
index 0000000000000000000000000000000000000000..548609281e889ff9fa79306247d457d623e35d49
GIT binary patch
literal 256
zcmZSh4+acu0t%D1GBGfz@iDS2b<n8LN_e_B+<T6yU_b~10|O%(*dxubAV5Lfz(B!_
zp>d)j1B29t42A^@9P|<pB0z0_7@RZnQgag(JX{pGfP9dMOJ;FFPGTj5%Q)SEkr^a@
bK!tHB!%_xDCT2;=6(9iy1_v-nV<Hy-%u6Ey

literal 0
HcmV?d00001

diff --git a/data/_EDID_BNQ_802e b/data/_EDID_BNQ_802e
new file mode 100644
index 0000000000000000000000000000000000000000..9f340cdf584ee5bbfa70503fdfc6493982054602
GIT binary patch
literal 256
zcmZSh4+adJ7xfw#fk0M{k!7omQiZ+7)a9Xmi`Do8LY8JXTs+Wtppl`mVda6%3@aTN
z8GSD>Ecj4h*I=Mv$`Bf$$iN`Qz`*dI!8Ihn+{eJs*w8T8#{ekumqEj(r^kkoO92dk
zB7Yd1Qu6{80$hyD4GcoL7%ww1>wOGMOo)w(7hq*!W@2aKmse0!5)l>>V^rp3XK!X;
zc+7f$;Tan%V^pvUlU0L6p@ptPgpMo3TDh<|h6M{2Xa*o0(v!jv@S#AyfkQ!p1@1JU
J%~-)J1_1dsJ^%m!

literal 0
HcmV?d00001

diff --git a/data/_EDID_CMN_152a b/data/_EDID_CMN_152a
new file mode 100644
index 0000000000000000000000000000000000000000..a85a2ddd268eb83a7e9e5bab24d3b8af8c882134
GIT binary patch
literal 256
zcmZSh4+adp>$F4}fIvWwk!7ipa0N5})OA758`Ss%LV%)-XdpS6VZnk0<pBl?Squ>e
z1sE74fQtU|7%XLCa%1FD00W@NKL%%CKPVR{1{U!%G&S?~b=7tEbL3KB+)yA~$-uzO
uC=wvZ*z%uqK7&4kJi~m}G6q%#PM~sXfDlsy%TOa@1IG|U3v~19CjbC;t|b8g

literal 0
HcmV?d00001

diff --git a/data/_EDID_CVT_0003 b/data/_EDID_CVT_0003
new file mode 100644
index 0000000000000000000000000000000000000000..958b9b49ea7c8d89890039c324b37c1f089331c0
GIT binary patch
literal 256
zcmZSh4+ac;SC|<<KtP0%xgo`tq3hk$#UVa3)%XKKmijR;q5&qW28luoU55xAR|b1$
zMFs{bpw_<(5~2J70t{RVU;q^P!{8hi;;Il51`z_8j|v!LnV7Xo{3o!oFtanUG0KYw
z3yBGeDs!?kH#0IY<S_Fv2rxA0DlA}PVC-R(W!MvRK~7<ZMySJ)KA@d)jIs?Eie$tT
r1awpzz#{W{xGr=lJkS*ou$#sp3{oQj6q%slV5q?35DFDRae)i~Ix{f=

literal 0
HcmV?d00001

diff --git a/data/_EDID_DEL_0001 b/data/_EDID_DEL_0001
new file mode 100644
index 0000000000000000000000000000000000000000..4ca9eb597fe1189f9efc62c5825fc9ede47b016a
GIT binary patch
literal 128
zcmZSh4+abZYZw`r7#J8B1sRzel%)T20ohQn_8fa-10xCm%KT?AKn7Sv{xVqj$Om&X
YAPoD%;Nt4zqu}Wh<mk+$puoTd0OVyD0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_DEL_a07b b/data/_EDID_DEL_a07b
new file mode 100644
index 0000000000000000000000000000000000000000..c922b8954253fc81c944dbd055356ec57d05f5ce
GIT binary patch
literal 384
zcmZSh4+abZYpNIccsUvviZZe+HBqRrdN*}(h|f$l{(z8$91M*PjSVXuHZxp2zz7B!
zHVq33HYht7D3~#@xhOI)NHH)l{AY+X^e_!EbP6_b^zz{Xiu_@4arN<02sJV>H1g$A
z0E+x&FtU{k7G&U300V}82B`f8>lk+E_k7*RFU`o@z{Xl3_iiH0exNpVkTJ(0V8a6Y
z01gES9vdT|tVB<yLkUPk0xkj+{lnlJ1hold9Z=*igH4otyA8~K#vM$|8ceCoJPZO1
r={I7JFa|a-l*S01Vq{NMJ-zO&Kt%4O8CH>OMNd?Tv=L|pNni^An;lsJ

literal 0
HcmV?d00001

diff --git a/data/_EDID_DLM_0000 b/data/_EDID_DLM_0000
new file mode 100644
index 0000000000000000000000000000000000000000..c4ebc04a6edc6cc61bb655d54ef2fd0bd7a3580b
GIT binary patch
literal 256
zcmZSh4+ac^y$lRD9nEC5I2l<O7#RLD0SPEjJi*}T(0HJ+VJgE)hs_KZ4_st0&|;Vo
z$e`t5P#_FZBnPDaF!<#w_~z$jmgE<4DJTF%{xgIIJH?wA8yV=P8=0Fylp>RiTLl=I
xm>GQ)!xjZH$QgKaSV3fEin%UqP<S9BAmIQLkrxn17ZH$F5qNk2*#rvNrU3VYC;<Qf

literal 0
HcmV?d00001

diff --git a/data/_EDID_DON_0046 b/data/_EDID_DON_0046
new file mode 100644
index 0000000000000000000000000000000000000000..f7e506192b5399f4209ef777bebf80631546bc07
GIT binary patch
literal 256
zcmZSh4+ac^@7x#|fq+4hk-1?(R0Y?&iHk#gW~%WAge>G>Fm!NrNOUN4XlwwfVPxcZ
z!C>&IAgW<QL>GfYOELq49FtXpM4^SQLxheiRD^+n;SYn0tDnE0u47mbmx6)<P~<Oz
zm7QFN4FiY^1dP^9%#|PG1m?2{vx+b?2`MNli83Z6#>T~`rX?k(@G0}F$f=p~*R$Ko
z9S~&?h_7P~XJbyUV~($5Y>sDOsAuM3P+{0%qi|p%BNH<Vqa&XUhk%3tn}C>rhCo^d
nL;8)_Ba9Ud%uo0k4oEy^V`qHKdVt}XpxXt84~#&^0D(FHC2c_g

literal 0
HcmV?d00001

diff --git a/data/_EDID_DVI_0000 b/data/_EDID_DVI_0000
new file mode 100644
index 0000000000000000000000000000000000000000..b48d7ea70316a9324c24316e5cb609e0b13e62a0
GIT binary patch
literal 128
zcmZSh4+acECmFziQJ9grK}WLU-TAGHLp^7z3Iv2K&2K35Z#>Y*(C9Fgq0nLF0Y=6e
zJqLlL76pTZ6~YX=ehM%!NTn$TYzSnKHgG5~gNgu+`^#YDBNrsdz@-2NK#@NTE@7Tr
IaKIo002w|c0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_ELE_0938 b/data/_EDID_ELE_0938
new file mode 100644
index 0000000000000000000000000000000000000000..7fde31eed1e30b84355769865c0eddf5131a44ca
GIT binary patch
literal 256
zcmZSh4+adPtrnb&3=9ln(u~Xvl`a)r=Svoc`)p9=^zc#SU}$t`Y*^{Q2nQ@B3<jSH
zq8c_tbTRDeRAgX~W3p<HD74UZh|qCmIMN3a0UGv)!PUpa+tD}5)YQ<NO93eImqFZ?
z-$jmrO92cRmoYJ$fA(i&W)~9@W>HX75@DS`K~9IWo?VnZAe@cy4}(B6&{cWNJPZm9
zJ6seP8W@?FSsw8v_HbS3Qh1;%AYeBQVx0s~WP*Z&p#qOXC{%<|mSIoO1v!Ns8letw
KCjs4n48#EkA3Fg6

literal 0
HcmV?d00001

diff --git a/data/_EDID_GDH_0030 b/data/_EDID_GDH_0030
new file mode 100644
index 0000000000000000000000000000000000000000..97e6ba6e3910dfe3fbe4eb95f8d8c12720204c4c
GIT binary patch
literal 256
zcmZSh4+ab}9R>`H3=9m6vW(0P#f}wR=Svoc`)p9=^zZ?RGBW;W{Qn<Ffq??Y3kHKv
z1yKzfBDxrk^eHkh$T3+pNEBM=Iz;HWLPdbu{xAgRCKi<_goJS^00B_sFN3w4e2)zS
zn6IF~_?C$|;!`wh3p1mTu!tD@1bGFe*!YCRq?FXOxMU_aK~ZJSdiG|Z!}6GU7>pQx
z*eEbGFfuW-q~C}=!dTJ3{)plJW7hkOkJ(rmAM(Fubi2Ud7H%}lLT+mh*M%;H2f6|R
PcGDp4kpS9`30?pIodQAu

literal 0
HcmV?d00001

diff --git a/data/_EDID_GSM_0001 b/data/_EDID_GSM_0001
new file mode 100644
index 0000000000000000000000000000000000000000..f153ad6392ddcf3d7ba60b0dbdeec94b75fa919d
GIT binary patch
literal 256
zcmZSh4+ac!xr_{qARx}j+^`_3g6rMH#UVa3)%XKK7IH8cI=DI{IutrIHh|SIGFdf9
z6k6yyMCiCOIJ6`)Fvz7T25bmqkT!5AFoTLPFfjaOu(Fd27GU5~00W@N9|j+Hg^)0)
zfCA$SCT8=G9ut%lSXr2v7<Ej=J#5(yh_VN8hO<{N^Dr1NG{`9&;A8Y>_{Sl@CLkf8
uAz&f!n3aJ6(*caKKqtwFDMaX~LL4xUQI?@7@PeE|o<=CbNkBIsgW~|2X*U4?

literal 0
HcmV?d00001

diff --git a/data/_EDID_GSM_5b08 b/data/_EDID_GSM_5b08
new file mode 100644
index 0000000000000000000000000000000000000000..26efc68e9e6c6469c63f82eba2be0bf2cc938479
GIT binary patch
literal 256
zcmZSh4+ac!xg603qD%~2GK|a(HcAz*3{01Y`Yl%D4+v4@U?_BGY-l{N^1#IdjSP%H
z!13Zp&ZB~;h7A#23=tuU3=C2%CFmjy3=Dr6ENtc4Z5X%|zyK)nhr!2PAvC9?C{e+~
zg-e0)2@|tIq5A|S1r}x|MrBTR_H<?*1_y>6Ht9EFk1$qzbYQY-kSMg!b%@Y$h1wJr
V$FN|*0?hye1yiU9&|GqX8vwCDIRO9w

literal 0
HcmV?d00001

diff --git a/data/_EDID_GSM_5b08_2 b/data/_EDID_GSM_5b08_2
new file mode 100644
index 0000000000000000000000000000000000000000..67ccd2698b6b9597324027c9ed017f6fcb13693a
GIT binary patch
literal 256
zcmZSh4+ac!xg60G=W{S{NHH=u*eF%JGB8~p>bF>pKOjVrgQ3u&v7zz6$^#b<G%_#(
z0ZR#k!KZ?#h7A#23=tuU3=DE%aSRI<EYJ)vP%wpvNHH)l{9*8MR|w51DN0oEaN$w_
ziu`4;u$60<W8hK%14dsaX2n9c2}-Oi%#6yM?CiPBJPZm9J8Tpf5*V47nXDQl3N3UU
zB6M6C1UP}(<rrlfE))Sp1aw>*;35)*GGYo5I;s#g^B83riUKdlDdcH{LUr|UUFcGH
RperC?Hw_{p0W=E?908UaI{^Ry

literal 0
HcmV?d00001

diff --git a/data/_EDID_HPN_3530 b/data/_EDID_HPN_3530
new file mode 100644
index 0000000000000000000000000000000000000000..c3af9bab176144ac21f4e31b0fca57db02a91807
GIT binary patch
literal 256
zcmZSh4+acMd<LeBKwv1t$lPF~RH3CYb$O`YVm1DNkcAu!7Y{TZXl$6uu=2o4hs_KZ
z8GJ7=Ecj4h*I?ja$`Bf$$iN`Qz`*dALBdA5-G+fn0Stg5e;7Oh6oQS+4f4QZK#~6p
zX3oAACYDCdE<r#s#zrP)^^M+%2?Fvg!puTUf{c$Cw9}b+7z7wBY|?MU9$~C#V0g^W
uzz`P4uwcOg%>V-hn1w7Q3<jSHq8c_tbU~aT_dXEhD9Hwd8lZ&)fDZt$Nj(7o

literal 0
HcmV?d00001

diff --git a/data/_EDID_HPN_3645 b/data/_EDID_HPN_3645
new file mode 100644
index 0000000000000000000000000000000000000000..ffaab68198c44a7477e9a19c386dcdae52cf0484
GIT binary patch
literal 256
zcmZSh4+acMe6D7UK%g$m$lPF~RH2vIx;nspl^S0_$Wm{Hiw9O7XgqL{VKc*2hDL^!
z4q<T&3l=QU3@}hIWe5#WWMGhDU|{&mU@$@Mz6}GH0vG^A{xJCay80<ZC>WW81c4&|
z8JzvREsZS=3`0zSLX7K~n4Ld*3CObuGYc^ZGTJM1va>fcGBBhw^Dqc7Sh%F$h&{qs
z(ZG-kw1A1*;KN(?Op8p5XKd_@nVI^JSsyn(V#r>2x1plIBEUgLVFnMxG4oz9R4iDK
X9>Ae6g9Rdze+cB@P*ev4-6I14Vx~p`

literal 0
HcmV?d00001

diff --git a/data/_EDID_HSD_03e9 b/data/_EDID_HSD_03e9
new file mode 100644
index 0000000000000000000000000000000000000000..8de2ea924568a66caf89bf7f2e5453e8c66a8594
GIT binary patch
literal 128
zcmZSh4+acMDKD8npJrgt6Jlg;5aX@jYEzpM9ymc=(LaQNfq@YXOc7+*;1D6HV5;oO
laHkQdKvGPE;f6zmnnJ9yC<|BwD9G>+M4$kK2qReh9RN|f836zQ

literal 0
HcmV?d00001

diff --git a/data/_EDID_HSD_04bb b/data/_EDID_HSD_04bb
new file mode 100644
index 0000000000000000000000000000000000000000..73d568ade34e9d7891ac9595aa2bf814ec158f6b
GIT binary patch
literal 128
zcmZSh4+acMDZ5z`7#J8hgczAKG^HxEKDaCi_L{3A;vc^MeM6#Kp?~9n#)b(F6a1$#
zOy!@Yx!^)zi;_XW3^Rrq{{<KrWPn=#Gguf{ctjXFMH(0wSegMv{xX;w8ygzI5K!a~
QgQJI`r6HFB1TbU+0HPu%0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_HWP_331b b/data/_EDID_HWP_331b
new file mode 100644
index 0000000000000000000000000000000000000000..9a6d7b889f8aa1dd4336e7cc32d7bc99514125ba
GIT binary patch
literal 256
zcmZSh4+acMAEb>L85kH;q#2nTjN~e`L=~2Y1<g_C4+vSv!Eo`wW`>mqrZO}(G%_?E
zU}R*nYLF<j&~=E=ab>u}BgnuY2h{qP!N^7~K#+k;0Stg5e;7Oh6pV~giy=Zlk^c<F
x&c5cxW(H2C5kOUpIZVvb8$Bn;vj{T_F)|4%bJnvrq%-p{0F6`vDyKP+0RYqRCIJ8d

literal 0
HcmV?d00001

diff --git a/data/_EDID_HYO_049b b/data/_EDID_HYO_049b
new file mode 100644
index 0000000000000000000000000000000000000000..2b3a1dbf828125d753b61a3476325ebec8c829dd
GIT binary patch
literal 256
zcmZSh4+ad%`m<RWfIvf(k$I_&QiW3f#^s?t^Hg~PLV%)-Xdo<(VZnk0ngIq1rVOD0
niVO@=Kt+ETTtXdvbX~$cxfFl^ECObMcp!i&!YBx_e&9#|5>c6f

literal 0
HcmV?d00001

diff --git a/data/_EDID_IVM_6615 b/data/_EDID_IVM_6615
new file mode 100644
index 0000000000000000000000000000000000000000..15615f7996d96d9c4fc796a2606a445c63175539
GIT binary patch
literal 256
zcmZSh4+acsXGPN(f#AP5Bg;}7r3$MPtjj~a7pU<BgzSIc(AY4QVda694x1S+9=OQx
z@IY7`!-541Gy@D2Oc_E06d4$#7#JA-GZ=6wAOKM0FN3*{T$CgekO>8U7y^8Z%*`zW
zAu1UkGcjv^2oR8G6=4x(W)c!)XA=`uVASMfXXjvG0HS6_28Ps~A`C1HOjZpNg%-LF
z5jw6AE9HP97m9!)0y?e@U`NO?$}$uMUXWAB(+GvC>EXK2rSL#kK)`MqL_`AS5(s?<
E00p`{0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_IVM_6640 b/data/_EDID_IVM_6640
new file mode 100644
index 0000000000000000000000000000000000000000..a1c22d3db9520468a67d2e1813dcdc59fb77461a
GIT binary patch
literal 256
zcmZSh4+acsXC2ZQfk0S>k-5P}u|n(m*R_Gp8`XFNLiWFJczEC<!^H!e8CE*1JkZ$C
z$iVS}!QfLtRKtddE{0%#MFs{r1_p-z42FiLrbZTqmIelfh9*FfzYO9&{9QH-Tnb<S
z6#2st;A3QNZW$N|7Gun0Vs`luEFjM!%q+wt$ST4v#wN;`7#|m_%vsOg%*eoy%gn<d
zz+h3Kz>vVm#GHO3_6TFe0p>>x51;TeG_XJA1F6My4NFObL?O_95jrsU9o@sQV1Yx>
R1_K2vh>N9wu3=zc2LPdzNdW)=

literal 0
HcmV?d00001

diff --git a/data/_EDID_KMR_461a b/data/_EDID_KMR_461a
new file mode 100644
index 0000000000000000000000000000000000000000..d94efb9b31abf4b4332261556605dd67816f03e7
GIT binary patch
literal 256
zcmZSh4+adno21+r85kJY#28r)smS)cnxil$#J^unF(^#`JVRr{W`>mqCOE8gXmn^~
zDD-EtYLF<j&~=E=ab-|Y0BVz)r@$~FP(j|nqrr?pfD0%hrD!?9AW2HyA!CCXR1Hw{
z4?|dhu8El;mjW0tu47_W`s_PFo<*2dgh`N1R7p`mnUjUR8R(RBW*!Cs1`FL;nhP!j
zwkR0{%n*Q@lcpH9Dv&|Wz^&gHDxzW2u%KXrvV(yF%q|;Ch6N24Qa}+asG3ds5Rm}5
I2+%#703vZa0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_LEN_65cf b/data/_EDID_LEN_65cf
new file mode 100644
index 0000000000000000000000000000000000000000..28d497b74e2a1627a01aa972edc9638255e95f0f
GIT binary patch
literal 256
zcmZSh4+abd>&~Y#0)e<RBg;}#xeBZQS62qRE>PtS2-$z0;o^ad44WBN9+=9|*wA>O
z&_67WVZnk0ngIq1rVRWViVO@=3=9na8A44049qMe{J0c=04Va8LEMKwN|FK02aEh+
z@G&we)HO7K2r(KlG0T1M7GPyzW|9{X77}Ds=45AYW@KPUb$`IX!oXzJAW>+c>ky&i
z3b99?Q5Gm7Bc>3cqY4q3&nU}K6nH^SAx|R|A|ltrb)ie)fv$jn-86`Z1kjudML=@|
QbX*(2?v(?&4g}@_0BZp~0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_LEN_65ed b/data/_EDID_LEN_65ed
new file mode 100644
index 0000000000000000000000000000000000000000..77f2063aba080ffee05fd39be8677a8414b4a05e
GIT binary patch
literal 384
zcmZSh4+abd>)xh<S+a~QTWypotY2MR9pJH2l{X+nk%NH|4TQxpELgBWGr&N>lp!=g
zk%2*qfq~&agR*0=Z(g{oeyVA*c?wYEF9YL;|NpZXxfH+vDDsEF$JI|E(#Sl$P}j(m
zi)kSfv%*JZPIks-Mh1pdZx*0Uk68~eJYvXt#>UE+8l{$h2xL<zl1)(yKq78PBAjnP
zBI!sXK%0mI7Yc+cnHl&QxR!|U@v$>1xH2#>G4dMj%?ju!Ss81@%jg=y%&5T>$jI`a
hb3TK9gFM50)`<*E3@i+%<{*o00*eu6Cz2|W2>>FoPXPb`

literal 0
HcmV?d00001

diff --git a/data/_EDID_LEN_b800 b/data/_EDID_LEN_b800
new file mode 100644
index 0000000000000000000000000000000000000000..e5d772cf890f52858f7abcb12f101b978c400c4b
GIT binary patch
literal 256
zcmZSh4+abd>lk))w2JNImu6&cU}LS2dpB`$h|f$l{(uk$Opr0hAz;G-`v49F2_73G
zpu9v+rb7uxL;@}X6#c{C8^omm2SAa(3^q~n?KTWhQAS%PW(}rPW*!CshV&b;M;HSe
l7)oP=PBF48_UnH8q8u*0vTx^sy)%1Qh_n&YsrW^X0st{lH30ws

literal 0
HcmV?d00001

diff --git a/data/_EDID_LGD_05c0 b/data/_EDID_LGD_05c0
new file mode 100644
index 0000000000000000000000000000000000000000..1dae4ac301753a3a87233042fb8059d3eb67d975
GIT binary patch
literal 128
zcmZSh4+abdPY$p$fPge3%Tj-aidPR>7l-)GR^tl@0SYprfw=aD1qBwq4h9OQ3=xL}
efVwg)&_%$ep%Y9DJO-cmZKml78O#I8tpEVW+8hA@

literal 0
HcmV?d00001

diff --git a/data/_EDID_LGD_4601 b/data/_EDID_LGD_4601
new file mode 100644
index 0000000000000000000000000000000000000000..1731fa93cb410087f1e460157cc54874ba939e32
GIT binary patch
literal 128
zcmZSh4+abdPZ-@8KtPC5c!I1@1(#gww5ZS?HTi%Lpdcd}_#(y76rdnrV4z^eAh%h7
yfkC20h+#p1f;f^0P}@I-@K8&0;|4=x<M0S0F0cp(pNOP!Z2f;mMlJ;fhC=|pqZ|PM

literal 0
HcmV?d00001

diff --git a/data/_EDID_LTM_2c02 b/data/_EDID_LTM_2c02
new file mode 100644
index 0000000000000000000000000000000000000000..6b4c06f74ac9d82c7d1e7e0bf244329dd29bd5d1
GIT binary patch
literal 256
zcmZSh4+acIy-YfcARx-f+z@G0!Nq%WLAd)2bs-NQ1qKGN3=+X))gV!5q3aN#<I1og
zih+Saj!~AODDZ-uLY_t_L)j-opa@X(FN2YdoDnAjmjW07MgB1O`1^%;hWbK;7<rhO
z6%Tk$kY{BP7GY*$ROV!7Y-VI&NN46@`2U|l?hyk&qb$%W88L+j9aV-SeTobW^MJ-s
H4b%YuU+5+Q

literal 0
HcmV?d00001

diff --git a/data/_EDID_MSI_1462 b/data/_EDID_MSI_1462
new file mode 100644
index 0000000000000000000000000000000000000000..41e2a8550cd5f980f09334ffd481e6c4f5a00b58
GIT binary patch
literal 256
zcmZSh4+aconMopy3=9lXvWzTCP2?)9??f*S@tLW{@9w$&JVRqcVol?osSHzXHZyFt
zx%h|4szIXALf0We$CZIoRgr-~4yg4HgMUFuW`%;gk%=>xf&x(FFN48^MT^)OfjkfZ
ziu`9VKmvx0-<X)W4k~l9vp2W3<u@!SuyAlNP%wp>`Kzv>qrgJQK>{uUG=aJx3jl<0
BF#!Mo

literal 0
HcmV?d00001

diff --git a/data/_EDID_NOV_0405 b/data/_EDID_NOV_0405
new file mode 100644
index 0000000000000000000000000000000000000000..3bff6da7ac767ee85a022614905b2f589f4f0f51
GIT binary patch
literal 256
zcmZSh4+adD-&k3M+4vX)#2J|z<;1tVI{0*PxZfOQ*?<s54hBXv5N+15puj@e!9c-`
z;k1Sz1A`m`1H*p?KmRbt;1I_kUt=H_2>yUY6g*rMoE?K)Kq7w`460>L2r_UffC1ws
zCT3el-zHWT76CyKVR<%DW+6NNdPZ@13wd^+asiMYRM70tz>v<&1C-jK%P7lG#Bf25
yAy0#Wq0tklPVO3K!vcl}x(osdK#>Fn4i1SPt_u?w91IzF9Ka$B3=+uZ=>q_3&oBW1

literal 0
HcmV?d00001

diff --git a/data/_EDID_NSO_5605 b/data/_EDID_NSO_5605
new file mode 100644
index 0000000000000000000000000000000000000000..25abf431714025d8555e0f4dd575fb067e6c2e4c
GIT binary patch
literal 128
zcmZSh4+acY`K)1#K%l_K$iyKh&hUcObWxc1TvdsHkoD&nKr+aHfq~%{iXazI<S&Df
jx122p1D66A07d>Y7#LWX7(fLSfFgewd|XV85h7&(?BN#y

literal 0
HcmV?d00001

diff --git a/data/_EDID_OEC_d501 b/data/_EDID_OEC_d501
new file mode 100644
index 0000000000000000000000000000000000000000..7df3f9a36f0dac806382aeeae2f91f94fb1e7efb
GIT binary patch
literal 128
zcmZSh4+ac2iy5yn0D%!VBcqO-c*TpWZx=*)%}^2Z4PO6_fe{U)NHRD$GN>6ybeJ(1
zJP}}EkN|4^!(eEtq!8j3qTu7~!leKfQSi;r%Ph$+;!*$tpvYeaBX2ny4km*zBLz1f
HZ-#FG8jc_V

literal 0
HcmV?d00001

diff --git a/data/_EDID_PDI_0030 b/data/_EDID_PDI_0030
new file mode 100644
index 0000000000000000000000000000000000000000..141de06475d0cb0d3096cdde00a23c55bfcc6f89
GIT binary patch
literal 128
zcmZSh4+ablodyhy3=9mcVvH<}#<CS$m$ojB2%e+L9}uF*!N7<Hn5-Hk3N3UUB6M6C
z{>lk5FvtP5{$((-lZz4wWjNBO2oVurSfCkTpkT@n8UPfL0;>7L5aOom66VRJ00s=U
E0PHmz0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_PHL_01ea b/data/_EDID_PHL_01ea
new file mode 100644
index 0000000000000000000000000000000000000000..0c5f3f62218b62df85a20edf9961d80ca76214b1
GIT binary patch
literal 256
zcmZSh4+ad5Jg*o*Ku?B|xnV+J1y?ffve4jZs=V%AiX04^8KyF<beQ1K$k5o(=)lOx
zWYr*1Xrb#6q2tQ1Kr5JmK@KQ#p$I4<pyS#A5n*6p_`?v8k(rZOP^{n<62_$f6#2_w
zV8`!f!@#8g28;zv%(WlG6BFX&Vg=+CloUl+goOl|#Mnhynb{akIoa7o*#m6Z4}`Nb
zR<I?+vNNQ!FgG(YFyu4yFbFVM*euZ0WJq9SV$Qe`dxWu~ftl$MgXbfD=EtlD7#_3n
oGCpHxVPRlldCJ(`GJ)|mquT`rm-*g{ELAr@69lpgfbQuB05r5h0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_PHL_01ea_2 b/data/_EDID_PHL_01ea_2
new file mode 100644
index 0000000000000000000000000000000000000000..4c1671b0797c32937c3be3247aebfdee8cc940a5
GIT binary patch
literal 256
zcmZSh4+ad5Jg*o*Kv0g6xnV+J1y?ffve4jZs=V%AiX04^8KyF<beQ1K$k5o(=)lOx
zWYr*1Xrb#6q2tQ1Kr5JmK@KQ#p$I4<pyS#A5n*6p_`?v8k(rZOP^{n<62_$f6#2_w
zV8`!f!@#8g28`WI%n2Vu<Ktol<Q0?@MOcJ|1ewIxMOm5I7)?3Z*+tm{Y}pTlvolt(
zMa0)Jrn4|NGcqvbGxIPAFj&|u(9~o|U}R!`#Nhdu^#H?THeSZ3jNL607@rBcU0^6+
Oc+8iO2(%L)r~?3xC^-QD

literal 0
HcmV?d00001

diff --git a/data/_EDID_PHL_08fa b/data/_EDID_PHL_08fa
new file mode 100644
index 0000000000000000000000000000000000000000..e8439abe935c17229d5275edf03fb39bd53d2419
GIT binary patch
literal 512
zcmZSh4+ad5Jij=sbr={}WEfet#+y}GMc6J44W6UQ<L<TpJ;TKVn;E7uG&VFkG#+3C
z0^bV^3qBOsH5e$EGVGK$VqlO8i(^=@V1Z@;Tttq6f#ENMc!1mj8%8b#FaV1DVF>W>
zQE+ncH8D0d;8I{TU}9GL=*`H?D#9WxFT^A`L79`Cy_u1LA(xqlL4iS{LV+QHk%^g6
zmZ2!{f}BF0MkvHSxgM?yT?!9$1qAG-K|~~gA`=uG3>A1BplT$1a~c*DfL&<?btTXR
zs34XB>VKt6jH^IW|D_n28yFZWm=gA^3U%0~%;OUT6b1Pi8L*TTWHoHyaMTbv#8Tw~
zR3L#V0u=qj;1S}i8|E423Jw9F$X^DL3daAkun=Lq$HXk^;KaxT^fn{N+o?cr3osxX
QcAx^?c;ZEXIthS{0Du8>0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_PHL_c193 b/data/_EDID_PHL_c193
new file mode 100644
index 0000000000000000000000000000000000000000..cc054a4f3d119d011dce56a2adf0f9e875de0bb5
GIT binary patch
literal 256
zcmZSh4+ad5Jd+PzU}0e3mStqw>ZV>{9m%@h-)X%%UqHzI_Y4;gY-X6s(Ad!E(0G6m
z2z)OvEcj4h*I=Mv%CM_Xk%2)fERJEpf(4oZ2oVMbhCd7e9zF`jMrOWdVO$CdK#{);
z8a4|S*f0WlAi!9|#H{zxmywxOghg0hh)HllLZUJ!J9{%D149Ng4}$=MM1{g**2j#`
z*w`7%62zIT8YBuWbR8meTp{+#`Q|h%C;+>}3hI(AX&|@BH*hFOut3}fv=<k61^}m{
BK>+{&

literal 0
HcmV?d00001

diff --git a/data/_EDID_PIO_0000 b/data/_EDID_PIO_0000
new file mode 100644
index 0000000000000000000000000000000000000000..b79762b5007357f100e026dd801bfa49fc8712ba
GIT binary patch
literal 256
zcmZSh4+ad5`V0(=K)@ix$lQ=+UBUHk;^GjWnQHt2A$#996#6$FXk=(?n98v7z-FL2
zCaVUCLJM7o2pw03@-K!A404RJ4Ht@J#1sT{R2#q|^B5Qy{xV2-^9PDEa4CQRP~;Co
zSa5`{fpJKL2S||d2NSc$$KVO_EW)fJ%t8u^O6+3%DspPvQr4XH?ELlYqU-^7atC~w
z7{b{Y;_DdG>ln)AnVbC?7;>0-7=#&i=rUa3V03uIzz?)vq7Z0*gpMl2Me`VC8TJHS
SkW<*95$XVOBhY?y5CZ@=$vy!9

literal 0
HcmV?d00001

diff --git a/data/_EDID_PKB_00f8 b/data/_EDID_PKB_00f8
new file mode 100644
index 0000000000000000000000000000000000000000..17f3aea9b4c83c49ba586b03f3026389b29bfa4f
GIT binary patch
literal 128
zcmZSh4+ad5Nk14i1t?6>5@uxP(2=ardpC7)h|f$l{(zAE?;2JfDD-bU(8$0D1%`SK
z3`s3Y1`#Vv8Fv2^U|?WjU|{&mVD2p!Ai%(-00uyjKMY}+#i{v51_mJ@L7>Qg1{WhE
Q11AFmLvvF@0|kbq03b#s0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_RHT_1234 b/data/_EDID_RHT_1234
new file mode 100644
index 0000000000000000000000000000000000000000..87f99444ea81b6281542ce3b2223febb69bfb6e8
GIT binary patch
literal 256
zcmZSh4+adLA|^r%K%gbT$g)&QxPtB7#Kj>#Gu8M5LKHa|9v--OfDs9(DlnuuGDsOP
z$Qe6K))Qo4kN|4^%V1P1x1fTNO92dkB7YbHU426peDm`%OY)1jfFj=+xEQ<^sc0$y
Y*+9T(#Kg?S;98rS5GfB4p)>gj0LG0W0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_RJT_003a b/data/_EDID_RJT_003a
new file mode 100644
index 0000000000000000000000000000000000000000..c47d29e8e4440ad6d9a7c85748b6ff2caabbc1fc
GIT binary patch
literal 256
zcmZSh4+adLAyy0)6L=Y9WEq(o8ayg?)d<dubf2v*5D>EVJVRqc<AFqniw7DR7$HEG
zp(yZzoI;*XC<DWVAO;4RG{vx0fedm6ZvDm#VGO|x3~~$%41XC6efUEK8MqX{04VZD
z!NbMZ6UtXmV7$S^tn?wkl0BfAQJ#@eRtRFMG9v>+1~U(X0K*Pl1xA=%8c@6BfFgT>
zfVS_@2z3D4E_ao)VS&N}T>*{+C5DCviX0pgOjZpNg%-LF5jw664HhL3_W&J$1}*^r
DQd>O%

literal 0
HcmV?d00001

diff --git a/data/_EDID_SAM_08f1 b/data/_EDID_SAM_08f1
new file mode 100644
index 0000000000000000000000000000000000000000..a62c77b5ca853a0cfbdac4651c44040f2490771f
GIT binary patch
literal 256
zcmZSh4+acAx*s_VEe(y>#Tc0z45TZxCLLT989Gm$FCawMzkv}AFj+N76k6yyMCiCO
z+~pBuV31>AVED^m;Vl;^$iSrl20)QN48cZ5PR6DN5Fwz*e+Ca9KW8HY0}EqgpdjN4
QCZ;|I2ZaQn)PR6I0OPnH0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_SAM_0f14 b/data/_EDID_SAM_0f14
new file mode 100644
index 0000000000000000000000000000000000000000..f523f09f13a0b25f2b6dd357dc426da07dde40c3
GIT binary patch
literal 256
zcmZSh4+acAx+44xd<=|?GK|a(kwz6<%4?T|_|8=0clX-+zM;^+@jxR(W5ZO2l?OHh
z6>+>^F!)pu)vzI=iy=U^gn>bh$*Mu3&_dTCLdO*<!oa}rmqEgtzuks`O92dkB7Ycy
z9esmC{oEl!jO9$sVIRU11>{+TSw$2Sm15)K6H?QXl2h2ln1wVs+1W+e1H#!En;97x
X9x?boW<AW9$IQbZz_1_UY|2RhR%UqC

literal 0
HcmV?d00001

diff --git a/data/_EDID_SAM_0f99 b/data/_EDID_SAM_0f99
new file mode 100644
index 0000000000000000000000000000000000000000..d763840314c977692f3600ed2579016223381d1a
GIT binary patch
literal 512
zcmZSh4+acAx-<C=fIwY>k-4E<sX}Yf!nOWx%T@RSLiWFJDD-b+Xgtu^u=2oWhN%n}
z4@hM&Ecjp{?_i){#jrBKk%2*qfq~&KgG7bg0viS{1uy`L{9$l5u?%vztbhmsMgB8*
z7&>~Jf^0GX3NpKVU@8C#4;Yxo#BBS~XF_6vJd3apb5v|xyfP;{dov>g!(-M147toa
z3<3;0Y!nz07@3&UZ^Ry9tY~0<#>UFnT`cs7pDiqoVZnk0ngIq1rqE!B@MYMs&_cxF
zhmI>mL=L~#>I;M_85o!uHH^12bo>{d&!FER&oG}=gMo>GlOZIEfde5X0v5w>9I3LM
F69521P5}S_

literal 0
HcmV?d00001

diff --git a/data/_EDID_SAM_7004 b/data/_EDID_SAM_7004
new file mode 100644
index 0000000000000000000000000000000000000000..357c3ccf6af0c9a5dbd87b7196b844843261085d
GIT binary patch
literal 256
zcmZSh4+acAx-10@d<=|?a*WIkl`a)rD~wkMxGq)a_3+sHzM;^+@jxR(W5ZO2l?OI6
zTs*+>g2CWZK~%$rh%SZz*%Af@xv)5f1q&8v1{f%qLPVq(7#RLCNL29uFK6IV00W@N
zABJE@-{4R`cZd+<3?}B}4>5@eX{n`Uw{8o_vk0?_C@3n$#>FS4u!}JZ**oZPva^e_
z2ZXaTq=zsxGcqtdV(@>=dYCbfnTNrFVTO$cLjxldGfVD`*dvS;4UtR?3<r%_AG7f?
bKH~rXl(D;I0%QImkkdj@od$FZ2yg=c+M-DT

literal 0
HcmV?d00001

diff --git a/data/_EDID_SAN_2400 b/data/_EDID_SAN_2400
new file mode 100644
index 0000000000000000000000000000000000000000..ed6f364b5932c63a1b138e9f96a6b7be3f94c001
GIT binary patch
literal 128
zcmZSh4+acAdJHNTFD_))7hz;>FjcP5GHqNI<}ph}C?G_cgQ1b3(V?+nD#J>L%?yk{
zz+}}RQD~v-5TWDBaF<7rfgxUB&0#@8i<E(Zf+@r9p8^aFG7Jn1e;F*i<>G}HxD>zu
XDDsEF$Js@}*Wb@G#6O5jfguh6O0y#Y

literal 0
HcmV?d00001

diff --git a/data/_EDID_SCN_03ff b/data/_EDID_SCN_03ff
new file mode 100644
index 0000000000000000000000000000000000000000..675be4badbf5bdcf8b46505bed888e683060ee2e
GIT binary patch
literal 128
zcmZSh4+acAdH<O;85tPV`5Bq3)Z{Ak-b5~q@S3Hj7!<buJp&^e*ki&lBalJML12O~
xL#~P-1A`m`1H)ei4IjBcJ_arYFaV1DXMixFBv9lJgS(Hep{0?56Id049{{An9033T

literal 0
HcmV?d00001

diff --git a/data/_EDID_SEK_0000 b/data/_EDID_SEK_0000
new file mode 100644
index 0000000000000000000000000000000000000000..004769c067f81519f5de9b520c97e3ba5505b8b7
GIT binary patch
literal 256
zcmZSh4+acAs~H#=85kIp#Tl6!!wf3Ami8?R@tUJ1<m$He97Cf6BMM+CVKDeq5Y@0D
zqKhHyp&<i<+$_xn7Xn+93<74DF(iOQWPpbKWiaxVu;FIlQUC*>$RCDaS7Xc2NCOkF
z7-K3EvsR%$8#@!T=rlngVHOcq`3VZjob2q)K*!`V^DrndaM&m~WH2%@_i$a9px|Jr
zz~c}Ku~ULkwn3s$Mob|>M-?J64=8e>2q+?;quKy=7f^&@PtXN9g&i894iJ|DU4Z}{
E0K>#P0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_SHP_1008 b/data/_EDID_SHP_1008
new file mode 100644
index 0000000000000000000000000000000000000000..c0a060185b3028f2ba49929b4d4134c8d2c4b0b0
GIT binary patch
literal 256
zcmZSh4+adr0vrMiK=5CXk+~sAuR=?D-=a{H&1xcEK|oPPbRf&HC+LEl!VZm42a_{~
z3=DFNvJ6FmK#@F+PzHzyP}?7dU=PQj00j>hUr#Ot1)#`Z218qZJq`vS4+I#eF)^za
z`A%*TVHIK)WD;W+Wn)z4WM^+?WMIf*=3!7^Xy9)UWn`3XxKJb`rXZlB+5k3u9#BN0
S5GWF%qYANZ9?)<yfH?q%&?^A|

literal 0
HcmV?d00001

diff --git a/data/_EDID_SPT_1801 b/data/_EDID_SPT_1801
new file mode 100644
index 0000000000000000000000000000000000000000..61bfc673a2e322b410d7f9a96e3a165f404e319d
GIT binary patch
literal 128
zcmZSh4+ac=B8(D@Kp-W|$ef`mUZG{%x-86VmWoh7$o_W>h5m+IAXyklQw-P;$RKUt
zP+-O|>zM!pgFOQS!+!=#BQq~ULoY{110!>DpvYeaBX7ANJ_arYFaV1DVTdraG!57F
MOH5A$iZUnx0F5{v0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_SUN_058f b/data/_EDID_SUN_058f
new file mode 100644
index 0000000000000000000000000000000000000000..4e252d2a96df8c7500fee67ee7ed1a5dd01259e7
GIT binary patch
literal 256
zcmZSh4+ac=>-t#(oO2o31Q?kcj1{J7y`Q=`#Amh|e?Z9o_YD^rE*@xXXq>Rpp|Fh+
z2n4JfItn%@IdC|rFtE8OGBC)UG6jlQC?JU#XfezPWYBUjC=iCIkyvN!upwcCI#5j%
zR2SnT2S%m?0!*9?Dw0bX{{LrWVwRR(!IQ8-mP5gbk+Fe+fddRKFc1xL!771nWMXDv
oW#{DK7ZR0}RZ`bAv3BzGk4VZcscG$>yL{8`Ll<wq{P;r(0AI>I0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_TCL_5655 b/data/_EDID_TCL_5655
new file mode 100644
index 0000000000000000000000000000000000000000..10c1a4e49c38124c14f24ad0b41aa74a4b8a9ee5
GIT binary patch
literal 256
zcmZSh4+abYIiX>K0*nkIl8np^l`a)ryeAigyU$P;^6*jQU~qLvbZB%~>Co8Fc%b{h
z$^%SR4HAVGx(*RKt_%u?3>g^Y(iFp11v1DPxak-(>|Egl6k%Xs_`?w5?4uCu>lhTG
z5E8}(6#2_w<SiGV%)q4p28^vt%#NReCd_9QQD6}k5@co)6J=*(R8-RBWM>x@4+s}$
zd@sbp#K_Ie2*Ugf3<AxJ3=EGLxHFh}7z7x0xG*9+1!6IyEJIP?1v!O0jZlPBfOca8
F_W))`H~|0v

literal 0
HcmV?d00001

diff --git a/data/_EDID_TGL_00f1 b/data/_EDID_TGL_00f1
new file mode 100644
index 0000000000000000000000000000000000000000..4064d14d37bd878b911f13d0dd2b9dacc78c57c1
GIT binary patch
literal 256
zcmZSh4+abYZ$2_GGB7Ymi88V*GL@_NUNLD|u**zUnSfYD4hBXbXgmNSAz+>Y!-PNu
zc>|9IGoT(IkW;jrV2~uG?vSy;jDb^Ck%2*i$*Mu3&_dTCLdO-NMgmCvVQ>jka4|A5
zbo1d-P*7kz%EYYv(XX+oxuvzOeZs^^lc!9brp#H--dxYXkj~7*AiyASuZQcx1O*2}
z1s;b`h7dkMpwW!7K%-^E6e4s~AtLj7xE6>6eh_0&t8s>i%mC`@Qh1;%AYeBQstc$_
RAy7d=K%!0=D#E~!1prB{J^=s#

literal 0
HcmV?d00001

diff --git a/data/_EDID_UPD_4843 b/data/_EDID_UPD_4843
new file mode 100644
index 0000000000000000000000000000000000000000..fa4d430c45b98f95293a9558072ae759076c104c
GIT binary patch
literal 256
zcmZSh4+acjEY2Q`3=9k+VvNiUZt4}U8EP29JsDI5J-pwaZ&-PtF|x5CG14{CFw#)c
z@FtU0gG8Z)u0w>5D}%6>A_Ie557&h*g$KF<0(R3Fj`RUVB!GtfWsr=Lj22+vQUC*>
z$R7qDXBP_tL#PmACKI#fM_+bkF(DRVR*?zvib@K~ob~L=EcHCfto1z2j0^&4%sdPN
b3=NnTFv<cQAtR;`p`!}1avsnE62U?MZ5cEH

literal 0
HcmV?d00001

diff --git a/data/_EDID_USR_0100 b/data/_EDID_USR_0100
new file mode 100644
index 0000000000000000000000000000000000000000..983cc4e8b22094428bc3d99f236ed1c8d08cd56b
GIT binary patch
literal 256
zcmZSh4+ad^iWnFf85kHiWEhzn7#J$JmdMSG51Otb?31+jeM94cMux_QsSGO}E*?m%
zX|!RoYLF<j&~=E=ab*aQEn#4gW0Ykm3cMhvkf#yKaHLNWC;~L>FM~t`f0`g81D65_
z07d>V7&&_=7#dg@fccCYn3#>fcniq02(yYPC@L`v>2TJwOV$S{)(2?T2Q&j+l*P=$
zAi`jw%fP|#h~fWZRt5%QEN7GjI#5PTAwowL;+%OsTo<|&9_R`P*iB;)202gy=p2Tn
E0Eaq20RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIT_03dc b/data/_EDID_VIT_03dc
new file mode 100644
index 0000000000000000000000000000000000000000..48dca8b008fdadd53e5a116c2f19c820390342ec
GIT binary patch
literal 128
zcmZSh4+ad8CU=+_85kH0_!*fQl%)T^;?G+U?lDVEz}<hTKSN^!PzniHX)(+QWYBUj
sC=h0-&=q80kONBoVF(Mcw6Ne(fB=Z{)V$Q<%wmWbP~<0)As}W209V}_0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIZ_0030 b/data/_EDID_VIZ_0030
new file mode 100644
index 0000000000000000000000000000000000000000..1ee1210c36473974ce71903b24c7b9fc54710b91
GIT binary patch
literal 128
zcmZSh4+ad8Rt5}=K%g$j$ZQ{LQt_%adr^evTvdK|uccmK8IUXtq$!4N2xO2pXlPPn
zSj26_z#zrI!0?yBC{*5!n~7o11VxC*e}-U3M_(roV@o3=10xflnm-I-5hg}H3LY*Y
KVTJ~d41xf3wH^Tg

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIZ_0067 b/data/_EDID_VIZ_0067
new file mode 100644
index 0000000000000000000000000000000000000000..e2cdba04a1ce6f692b3c59d03f18553d549aceba
GIT binary patch
literal 256
zcmZSh4+ad8R_P2NAR)@g+~B5OVWc9vD9CHJ8jrh|>Ny5RG{9ulAW>+c>ky&i%CM_L
zk%2)DsP!*{g%5uaKLeKn7yw27Ft{2U8Tz^+L<AThl2DRyA``Prp~nPP7G@@PHb!Mm
z_P}OF28J|d9tHsh1{7O5LAEf;G86?~kW<Lh2!-0)!*!uc;eoDzfZa5Rhy<f7&}}ke
Q3K2T05RrKxf8hY@03Y`+0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIZ_0092 b/data/_EDID_VIZ_0092
new file mode 100644
index 0000000000000000000000000000000000000000..8662e51802f52351ff85e5d3500cdcabb087e0b8
GIT binary patch
literal 256
zcmZSh4+ad8R+AVQfxtnOk+~t(q=M`E?j@mqv()(9y_TK>%YbBIfXS*sqR>LuAwtKM
zVG*|x1A`m`1H)eiBVTzpeg-ZDFaV1DX9)H7b#(MKFf;%HL!ihX2452+gJ2)18pbjv
zX0<|ZMrIb)2@0Y@!XomTob0Tk;Q<Wn49$!T4C%}~3=Rw$x(NG1q4qJ#G86?~kW<Lh
MfQbN2Cmoys05|F?0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIZ_1018 b/data/_EDID_VIZ_1018
new file mode 100644
index 0000000000000000000000000000000000000000..0c7373f4b6f86bf90ed3f46da7a13d8ccbc46dc4
GIT binary patch
literal 256
zcmZSh4+ad8RuTe?K)@lz$lOrrQla%|?&6T3nQHv*UQ5q0Ts#1hLjaZ%27^xpQ4Jd+
zx)^q@aAIJPW3p<HD74UZh|qC`iZC!R{9*7lHPv-7;8FkspvYeaaUcF3H3p~%V+a#-
zUSW8AN^DYGvVf9;ydo=$FgqJFlc12O7^6`*8&C@raI&+DvIjIXGBD&b^Dr1NSlBFx
zj%G*z@);Q1E-*0MUJ}~xKfO<lM<gJ`nPsg8Nc<7Q|EGM3X$h&1+4vbBvpxWcp@R1S
D-1a#D

literal 0
HcmV?d00001

diff --git a/data/_EDID_VIZ_1018_2 b/data/_EDID_VIZ_1018_2
new file mode 100644
index 0000000000000000000000000000000000000000..d7895ce31192b67641482fb8ebb8208d471a63ac
GIT binary patch
literal 256
zcmZSh4+ad8RuTe?K)@lz$lOrrQla%|?&6T3nQHv*UQ5q0Ts#1hLjaZ%27^xpQ4Jd+
zx)^q@aAIJPW3p<HD74UZh|qC`iZC!R{9*7lHPv-7;8FkspvYeaaUcF3H3p~%V+a#-
zUSW8AN^DYGvVf9;ydo=$FgqJFlc12O7^6`*8&C@raI&+DvIjIXGBD&b^Dr1NSlBFx
zj%G+;WM=uv=yrjD;r5cye*fuxYCIwVA<isoH9*=PG5mkZmzb82`k0NM@iFTIs8LAN
FdjJ|sIspIx

literal 0
HcmV?d00001

diff --git a/data/_EDID_VSC_0e23 b/data/_EDID_VSC_0e23
new file mode 100644
index 0000000000000000000000000000000000000000..4a8eccc3fa4311aa085c663fca3d7a300c4fdd5f
GIT binary patch
literal 256
zcmZSh4+acT$;y0;K%gwb$lRbWSD{z&by=v#Y&D^Pkp1r)Rys^&nBdUZ(CAR;Z^*^S
zsAxICAW2HyA!CCX!z~R#1_l`h28RC(L5}W*2F9ia29_4)TtJb(3`P|ayA&C?6u<x|
x@`oWT!pO+XqC6KY#@Nop$in<LZbDol&@>SdsA+Nw($Pht!_Y;5rcn-#0RYMAG64Vp

literal 0
HcmV?d00001

diff --git a/data/_EDID_VSC_0f1e b/data/_EDID_VSC_0f1e
new file mode 100644
index 0000000000000000000000000000000000000000..fd1e40b2854994e850a8cc0615c543c88951895f
GIT binary patch
literal 256
zcmZSh4+acT$#VRRK%gwZ$h<&Fx?<O@)TLn_GgU+bLiWFJXl!V7DD+Q^bd5BO1gSF6
zVwe%gpygmtAj}ZNC&<7c$H2hwpCQn~)WFQx)X3Dx%zz6h@|VFVR4#~*flC1lfFgew
z!W_*Fj1_`igFIb>xfm}oF-s>YbJnvrGcquwGxIPgFf`~oGYYgkV&G?BFk^6dk<7p#
fB_+$y5O_gG!J)yF!J!2xA_FuE20~#Ba_9p9QS2@O

literal 0
HcmV?d00001

diff --git a/data/_EDID_VSC_2034 b/data/_EDID_VSC_2034
new file mode 100644
index 0000000000000000000000000000000000000000..c52b9a346530bad0bf9c4a38c70b8000e75d898e
GIT binary patch
literal 256
zcmZSh4+acT$tDVnK)^4}$g<T&slq-jb!CXpTs47!kp1r)9v--OU^Bx?hm{8!8yXoJ
z4}`@rELgBWGr&N>lp!=gk%2*qfq~&aLujO_p}C={fq}7sITujmFN2Y{M3f|pAhW`8
z>;E=Dkv|M!0Y>I#77D?sMVYC^j0>2Ur9b*jU}a%u;ujK@lUGnwVpQg=XK!X?U|_Op
zkSMg!b%@Y$g;*lTC<_#k5mSiJQH6-iW0Ykm3cMhvkf#v}Rnx<Dp-bU`u7H5uG>C`<
X(3}fJKyw6iTpPfSl><5i3YGx?5i3Ih

literal 0
HcmV?d00001

diff --git a/data/_EDID_VSC_bd2b b/data/_EDID_VSC_bd2b
new file mode 100644
index 0000000000000000000000000000000000000000..568b5ec15f8ee5499c2a3d3cbb6c7300d392eabd
GIT binary patch
literal 384
zcmZSh4+acT$=Z7vfq+Atk-5P@x<W7i>x$s$+3ErTA^YDqY-U*Lu=2oEh6xUh4UG<s
z3`|xH5``AJ4iP%840m}185rak7#RLDgqTGb8XH&`7@3%ua{)#EG8lPF1PL;5DS!b`
z<PSrbqmhxJkwS24QD$l}!*m9y{gKmFOzhukT>M`KXg>o(1((P4h0!4k)P%hPfZ9MV
zLk2)00U$;Ne;7RTQc^1vJbYb176K(P)u4$m&MXiDI-QwOB$bDe!JgZnft^8~!Jdtq
Xfr){Yp^=$InUjUF9Mu}C@+JTP5I#Qv

literal 0
HcmV?d00001

diff --git a/data/_EDID_XXX_001a b/data/_EDID_XXX_001a
new file mode 100644
index 0000000000000000000000000000000000000000..1adf346f1ba604c90f037ad06bab33c3400403c5
GIT binary patch
literal 256
zcmZSh4+ad$5>gC|3=9lH;*87<ilP-<&R1uI2lc2c2866X$H0gN(i8(W1Tsh)I24!x
z^#Fk!5DS1=Fajj<m%-eZ-;JMvO92dkB7YcsgDs2#!k{9IMoi2~g#i;-S(w?G*cjzS
zgoVTeMHQ4e+1WFgd4MMF&^^E?%TN?}K~5o0BNSq`To2cUE`<lW0s?l^AR-csvJDrC
tWW*E%bW|I_Li2#S_5=ZS?a&ByIMSyGbRkgJ1O*2}1s(^eITApX4*+&hFaZDn

literal 0
HcmV?d00001

diff --git a/data/_EDID_YTH_0156 b/data/_EDID_YTH_0156
new file mode 100644
index 0000000000000000000000000000000000000000..5587ee8edd12ca0d4fbbf417d7d1d039c60c3d74
GIT binary patch
literal 256
zcmZSh4+acr9bt?NKp-Z=$lM?&RbiK6x-`Upp1M##$o}^Y7Y|%~aq-Voh6xUh4UG<s
z2X0JkSa5*Dq`*MIltG6@kbyx8sPzwnN3gD;shM{GmjVy~MgB8@Ss)$=07d>XNKD|r
zX9E*woWaDL_%V!yRX|uoUO`bw-NVz%+b1?IJ|U5T;W6t024&8A_GX~Np7Jv=@GxXC
z^Dqc7SX2N_O1}|%gt4N7@fjN{V`ip*2G9YF3<fsOtQsT=Ep#0sbW|Ba0~8q;<lcCo
MIkg_>3^-5%0H<O?0RR91

literal 0
HcmV?d00001

diff --git a/data/_EDID_YTH_1560 b/data/_EDID_YTH_1560
new file mode 100644
index 0000000000000000000000000000000000000000..28fd3f216318213b3d459bcf2f947677e9578c0b
GIT binary patch
literal 256
zcmZSh4+acr9SNe0K)@}>$g;skvBECJbZLnHJawUf5Je7#iw8C{tUNH4VS+<rL!(3E
z0Zp@p1qBxJ4h9OQ3_2`=3=DD%3=Dr5B11e3P0a$FxfFl^DDs~H%mVR104Va8!N5Kv
zLzodN&KSeQZ1T}rK%PaJlbyYpk%1wdnTJ7u!9p$lM(hzrmj=eC{0t0i43Ak4Fg#-T
e|BQ{5F*4FK+@L|C&_dTCLPr&0JJ4`4z-s_HTQdOw

literal 0
HcmV?d00001

diff --git a/data/acer-xb321hk-dp b/data/acer-xb321hk-dp
new file mode 100644
index 0000000000000000000000000000000000000000..ddcf44fa135c0b6e41c1704b299816828a6abd34
GIT binary patch
literal 256
zcmZSh4+ab@MRQpK7!nfLq!?M2x@%Ohy_>i=#Al`&e?W*L2LmG-@V&sW;6s63gMor6
z!;yYP1_mhx28RC(%8tQ)Zl11LS^nnwDL|3G401Lmt!9i|3Sa;f`NI(5WNc*U;SCXD
r>}6sWa#ZGIXKZF<U`X|50owFF5M;I_lG%&XKqB%;B0!U<1119iZVWB~

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-corrected_difdb b/data/acer-xv273k-corrected_difdb
new file mode 100644
index 0000000000000000000000000000000000000000..1fa60db7b2b053691f9b776f6cacbc96d1d9391b
GIT binary patch
literal 384
zcmZSh4+ab@MH|@|z<`lutBq2HrMlpnK+~;id;uZK9t@2RjSY<l8X2ZCY-YH4fRWMn
z0>gq21$GSv3Z@L90g4O^Qd`nMBJvF!3KA?35ujmzIV2`<{m*9PQUC*>$RCD?Fe7tg
zZ>R{<OD1NIkAaNLEJDJpBJva1nPTJO6B6x}Ioa8p85tNJF&xNc=3!7^u&7XANMK}Q
z&X8hYU}Q9?V0g^>nDGfe!wH6GZ0wAQVKPis4HAVGx(*RKt`HZ=G0HL&1zwO-$kPag
zisT<+Sg>G0XaL;RatxLQLX`{*Y79X8n3)+K)H5(JGic0Oz{v8SZvlgTgCavdhaFIe
fm0{Ii#+Ltl{tWC5@<6ef4BZUukl><-jGq7iPx4Oz

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-dp b/data/acer-xv273k-dp1
similarity index 100%
rename from data/acer-xv273k-dp
rename to data/acer-xv273k-dp1
diff --git a/data/acer-xv273k-dp1-corrupted b/data/acer-xv273k-dp1-corrupted
new file mode 100644
index 0000000000000000000000000000000000000000..a635fdfdcfc13bfaedc5699464a33665ee061222
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
dWCd_2%z(Nm{}9811q(t0;I5Vf>K|bL0|1)VZ2<rP

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-corrupted b/data/acer-xv273k-dp2-corrupted
new file mode 100644
index 0000000000000000000000000000000000000000..2acbe16e41aa462dc64e9422d3eeae91de30420f
GIT binary patch
literal 384
zcmZSh4+ab@MH|_I`x#n|WEfet+9*|6s|&6PG~KGk7Z9TC!O-Z?*wA>Okzp#sW`>Ig
z7#Wq$Fa&%kuxpSIFl7i0P-I|`+LFew;6s6Y1BZeH3q*v0f#ENY!G!<+vl+P*zyK)n
zhan=&$lTZ)D#CPviP__0AR{x2kT9!=`~-HU*tqzFM0;gUcJ^jQ28Krr2XdKt7!(*J
zDijzJ7@3$eq!<_&84V^dJZ62&_=KO~0K+pjcE-do8KBu{z~MPV)`A6D0UQc5pf1Wk
V#IRt&g3tg11*og#81e_&egNS}TLAz7

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-hdmi1 b/data/acer-xv273k-hdmi1
new file mode 100644
index 0000000000000000000000000000000000000000..5de1ca80071cab5df9da248e65cff96621201dfe
GIT binary patch
literal 256
zcmZSh4+ab@MH|_I`x#n|WEhznY?Lar)CJcBnr>C&3kcc&zM;^+(V?-S@jxTPREEtA
z7Z3PeU|8^>z^=hS!IU91K#_q#YD*eOM81JTL4pM$!oa}rmqEiuZh;L0mjW07MgA~E
zgc+F|dqYJS4=^zYd<<b^W)Tu*6_FQUXJd+ui%&>YP*hUpWM^+?WMIf;=3x+Eu&_~J
zNMK}QPQMX*gt4N5IYWwpfss+e=GkM`$Ba+-85$U$v9U8IhRHBlHAoa%=sHB`xI$be
Y*TZ$8OW}d8fPmdJh=>Hx9WbyG0BxQ^0RR91

literal 0
HcmV?d00001

diff --git a/data/acer-xv273k-hdmi2 b/data/acer-xv273k-hdmi2
new file mode 100644
index 0000000000000000000000000000000000000000..7536555cf50a8c379d155295db021b686fac6376
GIT binary patch
literal 256
zcmZSh4+ab@MH|_I`x#n|WEhznY?Lar)CJcBnr>C&3kcc&zM;^+(V?-S@jxTPREEtA
z7Z3PeU|8^>z^=hS!IU91K#_q#YD*eOM81JTL4pM$!oa}rmqEiuZh;L0mjW07MgA~E
zgc+F|dqYJS4=^zYd<<b^W)Tu*6_FQUXJd+ui%&>YP*hUpWM^+?WMIf;=3!7^u&_~J
zNMK}QPQMX*gt4N5IYWwpfss+e=GkM`$Ba+-85$U$v9U8IhRHBlHAoa%=sHB`xI$be
Y*TZ$8OW}d8fPmdJh=>Hx9WXEx0CPS<0RR91

literal 0
HcmV?d00001

diff --git a/data/aoc-c24g1-dp b/data/aoc-c24g1-dp
new file mode 100644
index 0000000000000000000000000000000000000000..331b910ed221574011d853e5ce45aba3052ce030
GIT binary patch
literal 256
zcmZSh4+adZj~P|oOk`nDmt|yGY9d=<Etj|=G-$S}U_i+J_Y4;gG&UG!7}mIExYi_Q
zB-SulHAoa%=sHB`xH536Dl#z0{i$o{D6kN6kWes%iZC!R{9!OMaW@QiH{ntM0ieiV
z27?I;7AP`81QZxQGcjv?^kHOX6=4yU7h)2eV6V){&fd((z>vz!!yv$rA;rMJ$Y?Nu
zp)J2*L4k#Xg8|(9f6*WjQzQ{aS%#v(3vvp18lg}()aXrEkRT-oRAUAa0UCz_v;YlW
BI{^Ry

literal 0
HcmV?d00001

diff --git a/data/aoc-c24g1-hdmi b/data/aoc-c24g1-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..45d1c4be90a385ea0c65b1f7af520810406ea8ee
GIT binary patch
literal 256
zcmZSh4+adZj~P|oOk`nDmt|ybFp;g$l1p3>8Z=u~Fd$_Adxnb#8XF8V3~O97Tx$|D
z5^I>O8YBuWbR8meTp2i36&V=h{?s*e6j%s3NGO;>MHm<u{xBGsxEqGMn{X+B08r#F
zgTVy31#%1!0R_elOw1Y|eFWrLMOcKHg_r~x?Ugy%*_#;|7*d&e7z7wHq!<_&84V^p
zYs+s~P+;NUU;sD&Uo=R>6iH;Y(t-s6Em8&s3T6;DNY&^~Sdbtk2UG(S0lEPhd;|ct
CoIC*l

literal 0
HcmV?d00001

diff --git a/data/apple-17-inch-studio-display-crt-override b/data/apple-17-inch-studio-display-crt-override
new file mode 100644
index 0000000000000000000000000000000000000000..0efe5a4db7d5cc3c72594f4a2ee2b885d3c21fc9
GIT binary patch
literal 128
zcmZSh4+acu0!(umfq;R7kugI-qUQxm=Ynvr*=j-_K8D&2hLNt3iIFQEKq^2WLCnFy
zus~Zu!9kh9;*|gcgM^2@gHh53BL{~=!cY+g28O>31`Fgu1sJ##zyK)nhatG6G$k|N
NrMMuc($Jh?9{?LiA^`vZ

literal 0
HcmV?d00001

diff --git a/data/apple-applevision-750-override b/data/apple-applevision-750-override
new file mode 100644
index 0000000000000000000000000000000000000000..1a0599105571011e21335711a1ba2ad30f8d39da
GIT binary patch
literal 128
zcmZSh4+acu0`Hg@p+G}HqU{Ca$pzt_Gt`AVd`z<&U@|aTfUn_z!UI_W3kzX}8YMvn
q202U-1_p+|3<ec)!Ga823Sa;f`NQB?kQ0_!oSC0zZfc;wFdYCrMjinG

literal 0
HcmV?d00001

diff --git a/data/apple-applevision-850-override b/data/apple-applevision-850-override
new file mode 100644
index 0000000000000000000000000000000000000000..4d5fae7f6e936351df0bfd46d2d29ef325a65433
GIT binary patch
literal 128
zcmZSh4+acu0zu4-Ai&1RsG%m?_JZ-`f^g3n>Ovkq_Wv6g84V*{BO4<VBUk!^6bbM(
z98h>5D_~(E%uu5w$iN`?Q&i!HL4>@5f&)y1fq~&KgF%H{+<yix1uy`L{9$k`$O+3V
O&dkrVFg4&}SONf+6C(it

literal 0
HcmV?d00001

diff --git a/data/apple-cinemahd-23-2006-dvi b/data/apple-cinemahd-23-2006-dvi
new file mode 100644
index 0000000000000000000000000000000000000000..e36f75231670084b76b698ba511d5d501dc17e06
GIT binary patch
literal 256
zcmZSh4+acu0?Lz;D;b!?1Q?kc4CO2I{<<y>_nN0F91z05z;Ka)5d~=2G%P6CpzL6v
zV8-y?Opt*=3aIEmgOQ_|k&%(JNvOL4mjY1a4})`NUTSWlf`<#2f&xec4KRLlU}OS`
Zm8mc;W%&P}SxRaJBUp_Cn4~!o4*<ubAprmY

literal 0
HcmV?d00001

diff --git a/data/apple-cinemahd-23-2008-dvi b/data/apple-cinemahd-23-2008-dvi
new file mode 100644
index 0000000000000000000000000000000000000000..5c9831129adc92d112e15b832a262673d5f14888
GIT binary patch
literal 256
zcmZSh4+acu0y2~4ePd)26=Gy=FqE&*`|G+m+-shya6kwH1H(lIMiii7)3BgmgR+Bx
zf*HemGeHIhDWIbN3`UL?MutWKz7f8DTna#uKMc;9d8xUH3LY+83JM?*G{E@PfsqL$
ZR;R+al;Qt>W+|x^j9@hmV3OuUH~^^)A^`vZ

literal 0
HcmV?d00001

diff --git a/data/apple-imac-27-inch-mid-2010 b/data/apple-imac-27-inch-mid-2010
new file mode 100644
index 0000000000000000000000000000000000000000..48e0c219769bde1d3f36e27dadbbdbc9fe7ef1a9
GIT binary patch
literal 128
zcmZSh4+acu0{7-H0D+hYBg;|)=?bO%jmtxQ=Be@ogaAbu(SVd$!-4_}c?SapQ-<5z
pf(#5&Kt)W9Yyym2j385>;17dyeolUof{(Kcmx6)<Oc;sw004MP76AYN

literal 0
HcmV?d00001

diff --git a/data/apple-imac-retina-5k-27-inch-2017-tile0 b/data/apple-imac-retina-5k-27-inch-2017-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..109bb1441bc8c0a1044019d27e75373b44b8d1af
GIT binary patch
literal 256
zcmZSh4+acu0&?r>k0uuyOEI!+l~bxv3MgC`=(t&pHz0(8fq@YX9NojPV1Yx>1_K2v
z2JHYr1_r7ADux9O3{DdeB0z0_7&3hmlerY204VaG!Q9Ni$->px+|Ak4$e8hDfp8@=
zgAjvQlK@bX)1DishJnE`AV3)8nn-2_8=ngdEdTlDGw3(SGvssFGB7c)Fr1mlz*5fx
z5o2dJ28)Hp0o8Fr#OAYVfW_(?C4LD29nT<CX85P#_kSjVj-<=Ke*F0N|3BCshDj3u
Df2u+O

literal 0
HcmV?d00001

diff --git a/data/apple-imac-retina-5k-27-inch-2017-tile1 b/data/apple-imac-retina-5k-27-inch-2017-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..62153230ce5afe913701a129932954d16288fdef
GIT binary patch
literal 256
zcmZSh4+acu0&?r>k0uuyOEI!+l~bxv3MgC`=(t&pHz0(8fq@YX9NojPV1Yx>1_K2v
z2JHYr1_r7ADux9O3{DdeB0z0_7&3hmlerY204VaG!Q9Ni$->px+|Ak4$e8hDfp8@=
igAjvQgMa|Te@=UDpc)1S$AAD~kZU5rJQ@;PCjbB`w<rMs

literal 0
HcmV?d00001

diff --git a/data/apple-macbookpro-16inch-2019 b/data/apple-macbookpro-16inch-2019
new file mode 100644
index 0000000000000000000000000000000000000000..ee4535da3090340233a224f70ff9d3b51db63ca0
GIT binary patch
literal 256
zcmZSh4+acu0xk;}fIvl-k!7orSOpXR#&to?8`O9MLV%)-XyExohJXVN<^>!IGdLoz
z3otN90TumWaL&)kFH-PvcHvS`PymVmCC~tx2xE1DP$e@%eWU#^0S0D934RT6Gz~rh
zhGqugA%?oaUXCVQ3Jh)rk(MSFW(G#4<^euo<`#w^s}vOK8#RF@FflR+GB7YrV76y5
kW^G`1=iJK6Be+ETufj=PW;=n<7v)jQQeNyrvSIB6040qv0RR91

literal 0
HcmV?d00001

diff --git a/data/apple-xdr-5k-tile0 b/data/apple-xdr-5k-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..d3fdc898d7a0c4c060dae668d5e19a23047878fe
GIT binary patch
literal 768
zcmZSh4+acu0!r(6czC%PWf@tHx~W$%@K0P9<h((RKOlsGfq@YXIGtk%_)rkqz@bpV
zu)9-{fk6r)BG$yA&;b=$5W^6#V1Z=-hr$jHh#H_le;5La@?A2E3vv=GBV2-5e=#xh
zH#}x-V0gyH&bT0((FSaAIMCo3P-AStB5fdpc_79(f<-!kB0HcWK!eEyj0HlK3=EnK
z0<t!i^SBTAI&AUWb9Ehma3muGPmpvRe}lLMuRw+0?)padUjhs)j0_Ay3}Q_J3=I3Z
z&3VCgItBzNgF~*4fz^s>QX>O1g9gxrEdTlZ8Q2@-8S*(o7~B}x8UF2N;P}s34i>ZL
zE?`IkiZPT;0Nc;Z5bzE~x`-hKDE$pZ>=@GyCU%D3C}J_pe$4C)A5p~OnFE1h#DNVk
z`%{kOFtYp?hBz7Kyrn2&5I1c_5repCABq^nO{-DFaJh*KZhyo##+G_<i2dfg%?zbL
t|GR!;WI>3vF;oD>f>6Yqm`#9w1?ojo_lfxlP|OEK>>Kk7tYNZc0sw$Xp8)^>

literal 0
HcmV?d00001

diff --git a/data/apple-xdr-5k-tile1 b/data/apple-xdr-5k-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..68d8c24be053f20bdf0a8c37f2d1a83f9f2a7d1d
GIT binary patch
literal 512
zcmZSh4+acu0!r(6czC%PWf@tHx~W$%@K0P9<h((RKOlsGfq@YX0EGmA7!?pB@`oXy
zDBmTsxF9F7GQuT@xtWQXzu_@!1H&^mcE$zSjHo8kp2t!kRLQ`g$sizWV>yrefUm<A
z&plVy@drmTGVlaR$MH9aTkr~0`0cK5Wd9|=zyfri5QA8QfB?gOZgXC+^Be;Ll))ia
z$G~dEG^vq+nL*^=ZU&D3oaGGc4e|{3+yx9t4D8swvT_30erAS%cPLtl7*c>*zM+U6
fW7@&Q&hQ&WEQZ;SnVsPyidZ~zAW)1ruweoKgkDDh

literal 0
HcmV?d00001

diff --git a/data/apple-xdr-6k b/data/apple-xdr-6k
new file mode 100644
index 0000000000000000000000000000000000000000..461b940c5c553835af396ef27db966c0ca4ced20
GIT binary patch
literal 640
zcmZSh4+acu0=ny%_;^(rWf@tHx~W$%@K0P9<h((RKOlsGfq@YXIGtk%_)rkqz@bpV
zu)9-{fk6r)BG$yA&;b=$5W^6#V1Z=-hr$jHh#H_le;5La@?A2E3vv=GBV2-5?lCd*
zH#}x-V0gyH&bT0((FSaAIMCo3P-AStB5fdpc_79(f<-!kB0HcWK!eEyj0HlK3=EnK
z0{8EQ=nGrAc(1K3D7<L6{|6%jPmpvRe}lLMuRw+0?)padUjhs)j0_BQ46Ig6lNuSA
z88nXMFtYp?_Ge&kkY}*xE?`JvU}uQ<#@JFX4iPiwZDuG1is1&|CV=f{W=O$i)>0Jn
zix^UXW^F|gJI1twiJf5|idYP@A2U0{Y80_}=0KnrCg6hGkImh#-xygCeraQ<0NNjf
fBId+w0yGz>7fIbG<|jZg9~7}~%rCIozhwddU5$nT

literal 0
HcmV?d00001

diff --git a/data/apple-xdr-6k-tile0 b/data/apple-xdr-6k-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..f6e2c47aba1a62e12a6ae40c24a84bff69e0b6c2
GIT binary patch
literal 896
zcmZSh4+acu0($G1_;^(rWf@tvx~W$%@K0P9<h((RKOlsGfq@YXIGtk%_)rkqz@bpV
zu)9-{fk6r)BG$yA&;b=$5W^6#V1Z=-hr$jHh#H_le;5La@?A2E3vv=GBV2;mUNbTC
zH#}x-V0gyH&bT0((FSaAIMCo3P-AStB5fdpc_79(f<-!kB0HcWK!eEyj0HlK3=EnK
z0{8EQ=nGrAc(1K3D7<L6{|6%jPmpvRe}lLMuRw+0?)padUjhs)j0_Ay3}Q_J3=I3Z
z&3VCgItB#jgF~*4fz^s>QX>O1g9gxrEdTlZ8Q2@-8S*(o7~B}x8LIv=aO~%H28)^V
zHZzn0#Ta@ffbC~yNcp#$f#W}CIau1ByMQ4HDE$satcW26DE19S>=@GyCU%D3C}J_p
ze$4C)A5p~OnFE1hm|!y8er(PwKyh*#Lj}<OauhKqW)q;fsCqv!KLLuBps4%C`~s`}
zb#VKS<S?@Q7ls5G%>PSK#326PiXsN_|2`Bki2qlkh~e@-7u^1cZ;UPV;t=~`(c}7!
dkp&?J@qZAC7{vcTy-4aH{`Wx<!{z@i699XFzX1RM

literal 0
HcmV?d00001

diff --git a/data/apple-xdr-6k-tile1 b/data/apple-xdr-6k-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..f402a858b194bd17baff88e345bfe3f374adf191
GIT binary patch
literal 640
zcmZSh4+acu0($G1_;^(rWf@tvx~W$%@K0P9<h((RKOlsGfq@YX0EGmA7!?pB@`oXy
zDBmTsxF9F7GQuT@rG$x@zu_@!1H&^mcE$zSjHo8kp2t!kRLQ`g$sln5UWmT1rHl94
z+JeH1hWmdoGVlaR$MH9aTkr~0`0cK5Wd9|=zyfri5QA8QfB?gOZgXC+^Be;L^uZxl
z$G~dEG^vq+nL(uLF9XMZZf6Ge26+Z^-e!hU26pUT**^hnKQlwhzugQR|2fOSTI{(C
z7?OZm-l2#UF{A*+zM+U6W7@&Q&hQ&WEQZ;SnVsPyidZ~zAW#ewOorQ!&B+BQ-e_Z}
h0NP)UBId+w0yGy@?<eLbK(P`Ob>Em@V70$)0s!#&X8`~J

literal 0
HcmV?d00001

diff --git a/data/asus-pb287 b/data/asus-pb287
new file mode 100644
index 0000000000000000000000000000000000000000..d08cb5b0897068b508a4e1073580992997edbb5c
GIT binary patch
literal 256
zcmZSh4+ab@nTs^u9%N(?kYHq4YNu3TC9`#Lxc>rm-hhzB91Ir^G&(dkOl8>2(0G6m
z2m&rJEcj4h*I*FQ#gH4S$iN`QQo>;HsUWIh16+iGf#ENMT!6#^8x}!^4?iqE*Z@WT
zFgON>1}g+O8CjTfDJU>%GBK+c`ZF>y3knIdh_K2};NzE-Q|1(BZ)Rj*$YSPU5MW@a
zP+(x_;kwYJ@IY5Uz-}7ELJ3A$hN8d=ate7Gp%4){pvayepvVr5PzSK1<bb*+C^#4@
P@Hjx#NC2IH0$u|Ew_QO2

literal 0
HcmV?d00001

diff --git a/data/asus-pq321-dp-tile0 b/data/asus-pq321-dp-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..9914442d9f110a352b19ab076954671d8c5dd446
GIT binary patch
literal 384
zcmZSh4+ab@nTw1VfZ)G4Bg;}Z^$I0{uS+8W7pn>dgzSIcFqNV4K%+xr!%Bw<4x1So
z8CXghBnk_n8X|PM7-BmG85rb%TK_VL_)7H1F>oosME)=Y1R5I|aw$LnP|ZJ}ED~UP
z%)~5n&|iR6UPOUKn3+jPkd0kbOqr9Nv6+zpWXpvjpe+JAT@4Uhn5=;ITIf1N=(sZM
z>Qn^Ut6|fypkRZtgMoq>L_`YY3!;H!fsiBvgAjvQg8&0VJ$pU}Sf``2=OUxy-?M~V
Ki8hE#g%befMLq!l

literal 0
HcmV?d00001

diff --git a/data/asus-xg438q-dp b/data/asus-xg438q-dp
new file mode 100644
index 0000000000000000000000000000000000000000..f60715a26a8b604198366b365bb7a7f58db30060
GIT binary patch
literal 384
zcmZSh4+acun;$wyI59Cu$uhERjWeyV-etPZ-+h(3KtRa;^9&acY-X6s(Ady;pwPe3
zfsxVo0>gq21$GSv3Z@Ke1&tUOq<AwL0t$d4910vf5D^9jhQAC3761R|Fmfq?0Z`-*
zgJW=LutJ2piLnJxlu4P1+4ZA8BQuMzybzP%1b#kQxr9VzPImTYMh1p-W*!Cs1`CJu
z8?i?iD;gMbr5G5Pm<=izm`gM`^d7T5V0^~L&R85Jj%oRiREB^L7V-`p3KA@E=K$?T
v2P_3bl?)8bj2g2RFtYsTo6n%%V9$`xVave8z`|e<&B%!^hHe05{Ie4PJ~T@K

literal 0
HcmV?d00001

diff --git a/data/atlona-athd420-hdmi-override b/data/atlona-athd420-hdmi-override
new file mode 100644
index 0000000000000000000000000000000000000000..2b2ce6ac774b9ed5918bae77c51d73700837c448
GIT binary patch
literal 256
zcmZSh4+acuJ>e{jKwv1w$lTzjUcvWl#^MmKnQHvre(TROG#=Q@Fu|eFtI=Vl!&HVw
z21Z$iqQDDs3V9l#3`hDD85rak7#RLC7=_Ba2{3RefB{hCKZB8hp^>4HfjL+VDDsEF
zF+|tH#l*+}EW&u0iCOZaTMLtbps>6$r#yQzBLhP!GY^9R1D`xYLm-2kfkT5i!=9f&
zD`Yfm8Wt36P<Aj-FoTFl0iCfY2<VI*8letgHF8W=4HAVGx(*RKu0S;c5QhQnMFBuz
I38+9S0M=tW0RR91

literal 0
HcmV?d00001

diff --git a/data/chiyakeji-r1811-dp b/data/chiyakeji-r1811-dp
new file mode 100644
index 0000000000000000000000000000000000000000..699f4ad401c288a1455a6f555b3ff4afd8ab46d7
GIT binary patch
literal 384
zcmZSh4+adplEOv|K)^4@$g<U4qr$pKbxnZrb~WyR5Je7#MuyD{7a3MMG&Wp3zz76^
z7Z?_ND6ne?P)Owo_E%(JkOFG`57LhU{xG<wre^2oDMT2V2NdN4<^D1l*vM}&W8_i*
z1ExSGW|NQpjLa-T!mJ|l0!*=S@d=5_ob2q)j0_AJKvNkR4Qv=5vmR!A%+KKPjE$W!
zF-*o6$@b6ypzRW2aSRI<EYJ)vP%vcxi-6oi47gSxRLQ`=%xKe5$=LE=*q$-I!JfgM
z+m?ZefrUXJmVxCz=X?hJ26>>E22hNX;m96ju|TjGI|CO-BLfEu0}GP?F_t3Ke3<|M
D)NV!r

literal 0
HcmV?d00001

diff --git a/data/chiyakeji-r9a18-dp-tile1 b/data/chiyakeji-r9a18-dp-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..7c80bfff721533640b98de169dd41578e37cbd16
GIT binary patch
literal 384
zcmZSh4+acg-P;_3%}fkbB^X(@+9*{R7pblZFy5}l9T1|(!O+OCnc*VCN{7aViw78i
z!1n^ff)53D4FL+NJfQ)K3=C2X3=IDnTp}VOf=nze4NS~}xqu>n7+eAr0s}o<xD-GD
zDDs!VV8YFtW{eO41*Uo?X48+#ob2q)j0_A>EUW^;BJv7~O6ne-Ufv9`aq&sXDd`!R
z35kyw4m@T(!0?QXl`$!a0mFKUusDVV3l?Yw7$}%Bz#Rm%j}S;J5UONg5MmH(5)fec
z&uPyM)({lp4G9fq2AjLtj4l6#=QHRx$TQe;+cGdQurLV3GO+yTgo$YY#W)#`>|tm@
Zhy{Yh*crGu8W}iP7+9DDu)0Kl0s#LDQvm<~

literal 0
HcmV?d00001

diff --git a/data/dell-up2715k-dp1-optomedia-cmv535 b/data/dell-up2715k-dp1-optomedia-cmv535
new file mode 100644
index 0000000000000000000000000000000000000000..bbe2c5140622f54853fd35203eca660d8aae6555
GIT binary patch
literal 128
zcmZSh4+abZYqmKATUr<hNiwo*wNa|DDpFk&V7y(8J0L`ngQ1aOGs8uOl@5&!7Y{H3
z!AFM+3yNN-88lq5Vu%P)WMB|sU|{&q;AZIM>}zTgYG7d*%mozr!{FlT<D(E7U}SD+
R>J1Y43&dc+r2qm9-vKOnB>?~c

literal 0
HcmV?d00001

diff --git a/data/hisense-h9g-hdmi b/data/hisense-h9g-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..81783c5721aa8474b316d1369dbbde66da0adedb
GIT binary patch
literal 256
zcmZSh4+abhiwzhU85kINWEq(oiXAJs&X+6>_t~J#>EWZu!O(c1(V?+{5e{~oV+i<A
z5Y-?d(8aK;Ly>_&j>)P)qR>LuAwtKMAwaeSC;~L>4}*tiu&ZCNE0+QY07d>XNO<#i
z*f2l@6c{6zn9B>I664|%VzaUtnOIl_1cgQ96%>_(m{Ze|l2eR0+1W+e1H#!DZP^c`
zvoOckF*XC8`H11?W7hwSdCWWv3Jel93JeX5Ow249H)4-4RsfmL1l=w$6f`_$<7Ir!
e2xPh>7uDqC*F0tHZkfRNgg=uZ0q7JkNCf}|V?qG{

literal 0
HcmV?d00001

diff --git a/data/kds-vs555-vga b/data/kds-vs555-vga
new file mode 100644
index 0000000000000000000000000000000000000000..433b38d8d4ed6f3332d23486e89ae2b992fda3e8
GIT binary patch
literal 128
zcmZSh4+acEUnE!=85kHexEL8KWJDQGuuWPJ?mt~kz{CIl4+g_X!wlC*pfnU*<!o4>
X5SJ_<kPyVd!py+ICIOQnk&XiZzTFf7

literal 0
HcmV?d00001

diff --git a/data/lg-31mu97-override b/data/lg-31mu97-override
new file mode 100644
index 0000000000000000000000000000000000000000..47af3018cc0557ef51f5fd98563a7326e786d60e
GIT binary patch
literal 384
zcmZSh4+ac!xzEZNfxtk5k-5Q5wc>^B$94Xun^k!OLKHa|3LP378V{^IaPa_04I?8<
z34_6>f~bZK5nT*B@)a2vq{8AD7A#nx8DOAb3Kd~sU=RReRPcwv*w8oB(ws{H447J(
zm?b~B2(U0SDs!^4H#0IYq%-q?^w}_3HAoa%=sHB`xIzq+W0Ykm3cMhvkf#v}73tx+
z(53J|S3tmS8bm|_)i%OBp8~;3HU?$}5#|zx_W%6VtiPMX8S*(I8Q2>*3G1d<#f%96
D0)IRK

literal 0
HcmV?d00001

diff --git a/data/lg-34gn850b-dp b/data/lg-34gn850b-dp
new file mode 100644
index 0000000000000000000000000000000000000000..afca8e56333fdf7fd23dc43c2e3f1f4df03b3a8a
GIT binary patch
literal 384
zcmZSh4+ac!x!&axcUTyh<r!JF1}Ij{|5m!*&uO(9UqFZ=Cqtn_V?*PCl?OI6Ts+Xo
zaPj=D<plv(7nlT0P_Qyk@Hb>&kYZq9_{(50;o-voMlJ;~0E+x!@NriN^$7`bba!<O
z;sT2NXD~D{_6zZGwRASIu;60yW@0udROV!7cNbt`W|S8eYG!0$c+7f$;SodDGd5Pn
z#6;U%pxI2U1``-q5^WQ0{jL;TxUj$|z(B!@0d6zUU^2nG0-;I<24+T)Gz-SIeBSpA
W`VI07^I2UPm>4+8G?El;+!FwJ%s~MF

literal 0
HcmV?d00001

diff --git a/data/lg-34wk95uw-dp b/data/lg-34wk95uw-dp
new file mode 100644
index 0000000000000000000000000000000000000000..7fbb03419ccb2a18fee91574adfbf185ffee6719
GIT binary patch
literal 384
zcmZSh4+ac!xeDbSPgoc@Wf)nu1}Ij{<2<-7z-7G}UqFZ=2ScGlV?*PCl?N^!Xk=gn
zg6A~_3ob0s3@}izVo>lhWMGh*n+_6DLK0zMVED^mU@O<|!@#8g20)QN3_k7(9xg!&
zrrsbyrXVI}$wHS2EX<6`ob2q)j0_BqSr0HgW@Baay}+>GLxEj`fkG+|#0rfJhzQ37
zm<Z573c=$7p-N^3W(JJ{S;n^i!WoPb4G9eS9JUPl3>*wQ`WP_8D6|hv`|1e*<9<T{

literal 0
HcmV?d00001

diff --git a/data/lg-34wk95uw-overlay b/data/lg-34wk95uw-overlay
new file mode 100644
index 0000000000000000000000000000000000000000..45cd52ee58bfc02de87033bb9ed6f436440328b7
GIT binary patch
literal 384
zcmZSh4+ac!xr*fsV8F<-H9)bV0m6ZjjA#HTEP$c_#K9E#%V1zD*Y3l>r2qy%HGdd<
z+!Z`rf)q@>L4r(|n3zQzl{wkjn;97x9<v@`c+AEMWYG--76?@`FfcOk*olkrGKds#
kOsMFb$;=?~Oo*}Vzwmqp{RVl4d=6U%CI(JgxG8M{0Ammz0RR91

literal 0
HcmV?d00001

diff --git a/data/lg-34wk95uw-thunderbolt-dp1-tile0 b/data/lg-34wk95uw-thunderbolt-dp1-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..7548eb940aff67fbf2112d2333e49a68121e4153
GIT binary patch
literal 512
zcmZSh4+ac!xr*iSP0S2TvWzTS0~9OfaUNV3;IdwgFCavbgQ3u&v7zz6$^#b<G%_#(
z!SkAe1s4`*1{f$<F(`N$GB8NZO$Ui6A&D?BF#KgOu$61~Vc=2#1E9zs1|N3?50@YX
zQ*V$U^CKo^$wHS2EX<6`ob2q)j0_BqSr0HgW@Baay}+>GLxEj`fkG+|#0rfJhzQ37
zm<Z573c=$7p-N^3Mg|@S`6oOKA_W{1DmrH}Gl)E>Vc^K;ozI}(AkQ$LRfB<vfs;a;
zuxeMG0JdL<L99uDf#E-AJ_lHtd$6x!IVhZgF8R>O!115cpMf3dl6;OppgcQPqsS5r
Gng9S%4od+5

literal 0
HcmV?d00001

diff --git a/data/lg-34wk95uw-thunderbolt-dp2-tile1 b/data/lg-34wk95uw-thunderbolt-dp2-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..50fcae0db30e565e1e11d6896779dafc2ea205f8
GIT binary patch
literal 256
zcmZSh4+ac!xr*iSP0S2TvWzTS0~9OfaUNV3;IdwgFCavLfq@YXFc1g+G8ov(wfit|
zDS!b`(;o&OcLfiZAO%xzkRYRcflwtg10w^EgZvX729W}e2^F0)g&4#d1OyoVbLMk^
p?QswGRV)X&fSEz$Lni~re@=e}_6B)|e2ze%JUel2!K%t=0svNRBLM&a

literal 0
HcmV?d00001

diff --git a/data/lg-55sj850v-hdmi b/data/lg-55sj850v-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..6d8156c58237cde15302d24ae576a5916806353e
GIT binary patch
literal 256
zcmZSh4+ac!xr_{qARx`i+^`_3g6rMH#UVa3)%XKK7IH8cI=DI{IutrIHh|SIa=c(L
z_*4+pupy$0!J#FYfkBSRszIXALf0We#}z8Vz`*dA!KzZO!-j!N0Stg5e;9n+6+*(G
z0t$@DOw6$#qY@JY<kM1Fgjq$HnS>M+l|&h1<KmN&Q|ujdIK$aR*#kn^8Ex4P<T3Lw
zC@}1>QDA6bWMXDXzY%+cv7&+b5ySb%tOpn#v+*)M;x~TH=yriYP1NG&1c&G}#efZg
R4AKS;1!f3G0bPLrM*+(vKmh;%

literal 0
HcmV?d00001

diff --git a/data/lg-c8-hdmi b/data/lg-c8-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..0cfd6876a950fe9b6492f007e64139c95b47d489
GIT binary patch
literal 256
zcmZSh4+ac!xr_{qARxoY+^`_3g6rMH#UVa3)%XKK7IH8cI=DI{IutrIHh|SIa=c(L
z_*4+pupy$0!J#FYfkBSRszIXALf0We#}z8Vz`*dA!KzZO!-j!N0Stg5e;9n+6+*(G
z0t$>tOw7q2qY@JY<kM1Fgjq$HnS>M+l|&h1<KmN&Q|uj#IK$aR*#pAa8Pi#qZRHNc
z*D>ZX^Dqc7?66T_XkcVwW=X#hdxWu~f%y@``NymW7#_3nGCtxre$D81fk91zd16y$
XO`2lBhCl{s1BU`Lgwud-0fB=6xDr7D

literal 0
HcmV?d00001

diff --git a/data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0 b/data/lg-ultrafine-5k-v1-thunderbolt-dp1-tile0
new file mode 100644
index 0000000000000000000000000000000000000000..8eebf47187d336d6c92f20d4b28b82593f9fdb01
GIT binary patch
literal 384
zcmZSh4+ac!xq{KcUzr(rq!?MY+9*{t@K0P9<h((RKOjVbfq@YXsGea6_)uWiz@Z?)
z5D}utz#z3anjv7p0?hz~2m=Gde+Dx{Bfk*mD05$96LT)0$R7qDcZJZLlA=Vn%)C@C
zCbI&eN@fN|1|B<cF<u4{2kw9hznPj00xSn*G*XXw%-%8UL+FpaJUz?|8eg9?u>9xu
zXJBuTXZX+I2sDhHA+C>srJe^O#?EdG76TGQgJ~1M_6sqHH3<Nn%W2OI*6JSYD;N#(
dGBbmS>vjf?|C|sj?70Jh^6W$#Pf%g#1OT#yJ^=s#

literal 0
HcmV?d00001

diff --git a/data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1 b/data/lg-ultrafine-5k-v1-thunderbolt-dp2-tile1
new file mode 100644
index 0000000000000000000000000000000000000000..675bfb5592ad3d11d44073590bf79a9838582c25
GIT binary patch
literal 256
zcmZSh4+ac!xq{KcUzr(rq!?MY+9*{t@K0P9<h((RKOlsGfq@YX0EGmA7!_cO{AVyT
zH1Z2^jxzT(HZkV{D*waa<E{{zQ&N=ZmYJ8z#rV2FsFIn1k%7lfT#T1N#DP1Y!f&P~
zg8<7x8I9Cq9<z7M`VjhKFHesUgII%r0K<Pydv36$?!mr-(I7`LGl;luXW;nH>CeF4
TAkSdW9SD?XM|Bu(Uc&?cWtJ=f

literal 0
HcmV?d00001

diff --git a/data/microsoft-surfacebook b/data/microsoft-surfacebook
new file mode 100644
index 0000000000000000000000000000000000000000..aa1304c5cf84936b2143e1860da45f71ae0fe73b
GIT binary patch
literal 128
zcmZSh4+aco^~?;+3_!rc$g)&M_`f~_!-8<n*=hnF{y;%SG{DlkBV*$QhXM|c4hGqM
n0t^gtKt+ETJR(9|4ULUmjm$lb1Arob8B9zzY)}QVaDlS`!+aS5

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip00-v2018 b/data/optomedia-cmv535-hdmi_dip00-v2018
new file mode 100644
index 0000000000000000000000000000000000000000..9b8c5476b40f2b50bef37f7473342e2141c3f3be
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<EjP{&|K*hDL|Rh6xTU9WEZY$k2Fz
z;{}7kr-G=44G~=o2V{&G8046&8YBuWbR8meTp1ql2?9lchW%l1&d)1LEh<SZ;!;ph
z0E!3zF%n>GWn%XH5E#X(pv1z=#Lku&8=sbxl8~y;S<lX2&u%YrAe@CkoSmVZnTNrF
zVTX<Wi7ZBDmPSVgF*Xi{un30q8?i?iD>@h+F?ch|0v#YDrVyc{%J85aXwST`IEDoa
k7H9?-D3~%dWGFH)NTn%;tqNq2GjQuSW(Yk1R3oPi0G1g;0RR91

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip00-v20180312 b/data/optomedia-cmv535-hdmi_dip00-v20180312
new file mode 100644
index 0000000000000000000000000000000000000000..f76b7cff409112a85fdaf2611f839981631a946c
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iPb
z#|s97PX$p88zQ<Gc6BH+Fvu}kHAoa%=sHB`xH2dlG6aeM4g163oS#>gT2zu+#HFC1
z02KMlAa2XwVZ#980s-SbCT7nMfl;gqN-WGw>}-j#@o7mZ390&=_3Zrh?DirD!dV!^
z*%`{2c^DiRcG&2j$YNw>X>?=|W8+{5i(p8<5qpHOqJ!ZPgEylr&;c@H3K2T05GTzG
gi(^=@V1Z_Ufr2SSL@G@&Y*iqGoPk@vG1S@10pX)b0RR91

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip00-v20180618 b/data/optomedia-cmv535-hdmi_dip00-v20180618
new file mode 100644
index 0000000000000000000000000000000000000000..ba897780863079d1a77e92e7d4f824669371953d
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iQ`
z?*)bh9}4Um3=~WmLIV^T7^FB}Fc^F)h-%mn(Z#T<11KT~H0%$9bADb~YEemQ5to93
z0#M{HgSah!hYbUW3j~ZwOw67i0;5<JlvtRV*aZ?}<I|E-5>oX!>)HA1+3iIRgtIV+
zvon-4^DsCt?6A>4k;TZ&(&)$_#>T-A7Qv8yBlZYmMF+zp25&~$28lu$F@*>nRfq%T
hg~c%}Sg=4d0OUxplcdrV!&U_{$Qiix8$%sA7XX~{N&x@>

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip01-v2018 b/data/optomedia-cmv535-hdmi_dip01-v2018
new file mode 100644
index 0000000000000000000000000000000000000000..0240d175154a5bcbfc8673ecd864a0761e19c153
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<EjP{&|K*hDL|Rh6xTU9WEZY$k2Fz
zrG&xYQ$bY2hKMeP12RSo4023X4HAVGx(*RKt_%<O1c4$z!~QTh=jWBB7L}wHaVaP$
z07V3V7zr@`Wnwlc@Q6=oWr>m(5!UCdXXmeHw--4O&cYzh&XC8<1JuD`qrlL>$i&R@
zm^VI!QMTbik&KvvfR1XzgLa^C^B83riUKdlDdcH{GB|7jipceFU6`QYV5q?35X!J+
b0?;}Mph%a(16=_DyJ-wtDnKGoNBji<-Dg1o

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip01-v20180312 b/data/optomedia-cmv535-hdmi_dip01-v20180312
new file mode 100644
index 0000000000000000000000000000000000000000..98d45c5d9ad69a0a7cc76fccfee4183eb79e5754
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iPb
zO9_L)r-G=44G~=o3Wp3C8046&8YBuWbR8meT%jUB!~QTh=jWBB7L}wHaVaP$07d>X
zh=1hh5oZ8#fq?NB6SG;NM|?^vOO(8bus&x!JAXa9y~u%Z76x&4hCF5-1_1^R8wG|2
zMkZ#K$9#!tPkG~064MxE8!i;dh$#r@s5TtwQ)FP6$0*BC6nH^SAx|Te0W2cd!*yYT
ef`g#~j{`^qXt@MXq)Xv}u7H5uG>94rhN%F7F-ZXc

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip01-v20180618 b/data/optomedia-cmv535-hdmi_dip01-v20180618
new file mode 100644
index 0000000000000000000000000000000000000000..876031e0520b97e7ac76733b42e38ed75313fafd
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iPb
zO9_L)r-G=44G~=o3Wp3C8046&8YBuWbR8meT%jUB!~QTh=jWBB7L}wHaVaP$07d>X
zh=1hh5oZ8#fq?NB6SF~~M|?^vOO(8bus&x!JAXa9y~u%Z76x&4hCF5-1_1^R8wG|2
zMkZ#K$Gq_=jIs?Eie$tT1awpzj`S%qFwA3=Whe@~Ag7S05y}7-k?Y~QFhRk=P=Ut*
bBm%Tn0w~g@@IY5Uz-}5ujRepwARq$(GSWr?

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip10-v2018 b/data/optomedia-cmv535-hdmi_dip10-v2018
new file mode 100644
index 0000000000000000000000000000000000000000..610692f1eb02795fd255e801f7501930a9d93e31
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<EjP{&|K*hDL|Rh6xTU9WEZY$k2Fz
z;{}7kr-G=44G~=o2V{&G8046&8YBuWbR8meTp1ql2?9lchW%l1&d)1LEh<SZ;!;ph
z0E!3zF%n>GWn%Vt;G33|lA0JBpAf~Wpv0ojS<lX2&u%YrAe@CkoSmVZnTNrFVTX<W
zi7ZBDmPSVgF*Xi{un30q8?i?iD>@h+F?c`XO=FY=+Akxf5TT>W@Sq)N&AhNUh6M{2
kXa*Q4m@+hEC^9fer74E33S^KoaO*c_2t5E)BggO;04CQ(0RR91

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip10-v20180312 b/data/optomedia-cmv535-hdmi_dip10-v20180312
new file mode 100644
index 0000000000000000000000000000000000000000..4de55e082f30b55180595ce39a80906a1d2aa06a
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;03^FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iPb
z#|s97PX$p88zQ<Gc6BH+Fvu}kHAoa%=sHB`xH2dlG6aeM4g163oS#>gT2zu+#HFC1
z02KMlAa2XwVZ#980s-RzCT5QZzG+D*sfn@i2~n&HN-X-E_3Zrh?DirD!dV!^*%`{2
zc^DiRcG&2j$YNw>X>?=|W8+{5i(p8<5qpHOqJ!ZPgZCreG)7sV{W4+-5jv_67tITc
gV_2|Yfo6b#f+<8qDortLRUm_$fm^>Z)YS}?0C5*e0RR91

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip11-v2018 b/data/optomedia-cmv535-hdmi_dip11-v2018
new file mode 100644
index 0000000000000000000000000000000000000000..12606253deb606b0b36176fb84c50c78322f57f7
GIT binary patch
literal 256
zcmZSh4+adTCZY-qK)@);$lPF}Sn=-N#Kj>#Gu8M5LiEowtaMm;U^By1hVBE64vh?r
z2bioHBnmBb9U^pG86NNnGBC(#*fcCC*r4oSpkT)EKnExy1vKmrgL8gfS!z*9Y7v)$
z0?2#;AVva=o0yoj3VbKXD<~?lim(U^F^jS5bJnx-*R$J;90+G&5NBsdXXXKEQ^d5B
zQI?@7@PeE|o<=Bx!xo?#IYwEayJW-^B6L(49<&2R=Jjx0=u&u~D<EJujbTd#&}s=J
J>lqjh0RZU_JOKaz

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip11-v20180312 b/data/optomedia-cmv535-hdmi_dip11-v20180312
new file mode 100644
index 0000000000000000000000000000000000000000..111b2a4d79b54a607314dadd37d90351ace51c74
GIT binary patch
literal 256
zcmZSh4+adTCZY-q3=Hgyl8np^CW;mB-c4K_;xki?KOkiP`-YVcD-UdDn99(7pwXd`
zq45BdRf9yKg|0({jw{2FK1BuwISreJ1qB<F9SjuAAR<yg)BZ3x=jWBB7L}wHaVaQ(
z%>T<^;UgC;$Oz&B0pn*TX01Zs3GxbxN~|I*!a~eq?E0Mb?ELlY_96$uSs29G8Pb_~
z7z7v?6fx~&lw~LiydbBLrx6Nu1*0s`T{2<{5jv_6k$F8_7rGQ4=n4qfO@oL?09}Cq
FvjJm-LID5(

literal 0
HcmV?d00001

diff --git a/data/optomedia-cmv535-hdmi_dip11-v20180731 b/data/optomedia-cmv535-hdmi_dip11-v20180731
new file mode 100644
index 0000000000000000000000000000000000000000..ddb9def04a410dfd05bf6c74405f0933dd336bcc
GIT binary patch
literal 256
zcmZSh4+ac=BCHG`U?k4S+)(UTp;aR|FVcOsx<Ek4|Njk*42=$r4HFzzI$S((k)iQ`
z?*)bh9}4Um3=~WmLIV^T7^Il28YBuWbR8meTp1J&88R@)0S)`Z;GCaVmReMjTEwNG
zpa2y4%OGyc-(kZ5;sOEVTP9}r5B^cC3Q8=@OzZ-&@kuEOsrsDt?ELlY_96$uSs29G
z8OoV?7#tXO*yx|gVq|7%bYu`?<6sDjU`W3adxWu~gW(Z_H=``jdKoc=2pv_1T^&FN
j%?pcTSg>G$W&p^EU=gV_#jsU@3~~l;{l*Xxpc69y{enjU

literal 0
HcmV?d00001

diff --git a/data/panasonic-tx65gxr900-hdmi b/data/panasonic-tx65gxr900-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..0950e03dbb563e236b375ecb4635e93fd0df4a1f
GIT binary patch
literal 256
zcmZSh4+ab-E2k}D1Of(GM&^bFj|#3^{})GiEz%VC^j6?tFmy<C0Lj7t#|s97PX$p8
z8zQ<Gc6BH+Fvu}kHAoa%=sHB`xI#r37#RLA1SIAq7U$<>ChLZTaREjCGKkyqci1p+
zDS!c^EE99ihw#J%0r|94RuKh7B^F_3A$GCYxcH>x6dhi6Mp5>FaCXLY7UpJt28KLl
z9tHsh3mbio21X`kmW&&*M;I#_n3*0ict2+S&-jSn_%Rzl<5R}&mI;in8Qm^0xD-dU
cxy08!69lpg7}6BORs}N18MyTu!`!$B07wBv0RR91

literal 0
HcmV?d00001

diff --git a/data/philips-ftv-hdmi1.4 b/data/philips-ftv-hdmi1.4
new file mode 100644
index 0000000000000000000000000000000000000000..786e68514e5dd7cbeb39e7bd3af41d0cb4806a7b
GIT binary patch
literal 256
zcmZSh4+ad5Jg*o*Ku?yDxnV+J1y?ffve4jZs=V%AiX04^8KyF<beQ1K$k5o(=)lOx
zWYr*1Xrb#6q2tQ1Kr5JmK@KQ#p$I4<pyS#A5n*6p_`?v8k(rZOP^{n<62_$f6#2_w
zV8`z!$H1ik28_K-%)uW+<Ktol<Q0?@Sw&ccg_s4I#MnjI7)?3Z*+tm{Y}pTlvolt(
zCB)Y;rn4|NGcqvbGxIPAFj&~E(9~o|U}R!`#Nhdu^#H?THeSZZe2ED_YlsGQ0MUdr
A0RR91

literal 0
HcmV?d00001

diff --git a/data/philips-ftv-hdmi2.0 b/data/philips-ftv-hdmi2.0
new file mode 100644
index 0000000000000000000000000000000000000000..09d4fdce5a72cf416d5049d4765bd3204fafc6e9
GIT binary patch
literal 256
zcmZSh4+ad5Jg*o*Ku?yDxnV+J1y?ffve4jZs=V%AiX04^8KyF<beQ1K$k5o(=)lOx
zWYr*1Xrb#6q2tQ1Kr5JmK@KQ#p$I4<pyS#A5n*6p_`?v8k(rZOP^{n<62_$f6#2_w
zV8`!f!@#8g28{Vk%w-?L6BFX&Vg=+CloUl+goOl|#Mnhynb{akIoa7o*#m6Z4}`Nb
zR<I?+*D<EEFgG(YFyu4yFbFVM*sRdhWJq9SV$Qe`dxWu~ftl$MgXbfD=EtlD7#_3n
iGCpPOZkfRNn$hh7gNwiS3~TYl&jf+&0-!^npdA2oJwX8g

literal 0
HcmV?d00001

diff --git a/data/planar-ix2790 b/data/planar-ix2790
new file mode 100644
index 0000000000000000000000000000000000000000..954ac0f66a426f4352fba25ba500bf10aab0fd73
GIT binary patch
literal 384
zcmZSh4+ad5eG}9ffq+4pk!7ikVujW9uWJLHH>&XlgzSIc@bJJzhKmO_Gpux2d7!bO
zk-_%@!-5Y5b`1s!rVPRUiVO@=VQ~x#7A(*VK!`9fF#Kf@_u=1?$iSrl20)QN44x52
z=9UIf5hgVzW`)ne0`e>(%tB0ptRn1UY@&>b@o}-rob~L@j0_AcB@70i3Zfb|M07!H
zl4B`pkSGL-MCiaon5=*z7P<}*I<8PPjIs<xffwWy@-#xBB1iWC-RBUr!9c+Z>SCa4
z7#Jc8gjARrm>EU(R5G^w7fxpsZ-{5G=eA|gXJ7|HE{;Y94i*L$CIJQ>uzG3}698Gj
BOaTA@

literal 0
HcmV?d00001

diff --git a/data/realtek-r9a18-hdmi b/data/realtek-r9a18-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..c26751dabebceeae92a7f12e2bb5bada4ffd214a
GIT binary patch
literal 256
zcmZSh4+acg-9~#Dfq+wrk!6vMQiYwm=$b&&t!jJ$A^YDqTs&~`#l=5U874S1HZ(dk
z9&ot8u;4?1U4wywDMN_AA_IdI0|Ub!1`iisPlZqq7X=TOATBrahAjmax(+&GNNWBv
z7}&J6nK5!HfC1xqCg#9TaV)F?!Xoktic0Dpo?hNQv2pPUiAl*RscGpMnOWJ77_L5M
zJ;0#MS<n8IpMimgA(xqlL4d)cLV+QHk%>9|M(h#BiVntSY^;o#nf@=HFa#`EkRHIH
fFoPvD0O&NijyQ$|3l``Gi0POzKtzC!g@PskPK-+d

literal 0
HcmV?d00001

diff --git a/data/samsung-lu28r55-hdmi b/data/samsung-lu28r55-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..1b2544bd35fe3fffd911112b41c318b3952c328b
GIT binary patch
literal 256
zcmZSh4+acAy5a(nZsE>`mW<2|_9_)xC$_E)aG9sd9}u$teM6ytBSYhX#)hd3D-UdD
zU}WTY!C>&IAgW<QL>EIvh9U!l90LQxUj`#@xpo@{E(I_Eiu_^l2{p0^GBt$=0Y&~Z
zc$h@_IvW@m8d?Gc86%jOO+R=h3NZ__$O|OID|525H#0IYJZ3$>kj>1)Ai%K0Mu9<r
zG5tpD5ypxJ=12UEkJ(rmnXDQl3N3UUB6M7#)&oT@6ahs9bX*%C4q_=mcVbu^!-541
PGy@D2Od-0Y7#Jb}95F`$

literal 0
HcmV?d00001

diff --git a/data/samsung-q800t-hdmi2.0 b/data/samsung-q800t-hdmi2.0
new file mode 100644
index 0000000000000000000000000000000000000000..2ce958ff1ba7dfd9e649ca0a8c81d12b35689364
GIT binary patch
literal 256
zcmZSh4+acAx^@K&d<=|?a*WIkOJggzRv51ia9yg->*2BYeM6yt<AFwo#)hd3D-UdD
zxOjl2gu&obK~%$rh%SZz*%Af@xv)5f1q&8v1{f%qLPVq(7#RLCNL28*%Q0{%fB{hC
z4@0n{Z*ZueJ4A>viHSMjLrA=UJc}@^h=QV0Y+O<byBM>Oy@L)XJG&@*KsY-?dI&=^
zBLl-D2LH#b%#3-=JPZyDJ8Tpf8W@?FSst_TGCt)?NK8$8%Glj9fss+R;X;v&n1X<g
bY6IA1^O&p}BnmBb9U^pGp>74b0|o>Dsy9Lb

literal 0
HcmV?d00001

diff --git a/data/samsung-q800t-hdmi2.1 b/data/samsung-q800t-hdmi2.1
new file mode 100644
index 0000000000000000000000000000000000000000..92bff59342d9356db3536e09f0286e7797e55715
GIT binary patch
literal 256
zcmZSh4+acAx()>ld<=|?a*WIkOJggzRv51ia9yg->*2BYeM6yt<AFwo#)hd3D-UdD
zxOjl$1%tt-f~bZK5nT)cvLy@*a`}fC7A#m08epJc3K5ZFU|{&mAW^~pznp<f0Stg5
ze;9%teS<^&+#y1Yc}&ddA7T>)<XMDSMHCd3V&mcyQqz)B>>WzWZrwg~_{g#2I-Kn6
zqU-_T><sB449$!T438N6AG022%wy(ZaA25WqruR?$i&Q&dn5J;V?{$G69dCR6Yj@s
Zyo^uz86SL*f6Cb1GJz4R^MLM22LR`OPXPb`

literal 0
HcmV?d00001

diff --git a/data/samsung-q800t-hdmi2.1-game b/data/samsung-q800t-hdmi2.1-game
new file mode 100644
index 0000000000000000000000000000000000000000..0c17bf5b069b44fdf9b8be0567ec1a4e5c1324d7
GIT binary patch
literal 256
zcmZSh4+acAy7mPOd<=|?a*WIkOJggzRv51ia9yg->*2BYeM6yt<AFwo#)hd3D-UdD
zxOjl$1%tt-f~bZK5nT)cvLy@*a`}fC7A#m08epJc3K5ZFU|{&mAW^~pznp<f0Stg5
ze;9%teS<^&+#y1Y`Ap2EA7T>)<XMDSMHCd3V&mcyQqz)B>>WzWZrwg~_{g#2I-Kn6
zqU-_T><sB449$!T438N6AG022%wy(ZaA25WqruR?$i&Q&dn5J;V?{$GlR?En6Yj@s
fyo^uz86SL*f6Cb1GJ!D{=o}_Sg9@M%P{39I!EH<d

literal 0
HcmV?d00001

diff --git a/data/sharp-lc70uq17u-hdmi1 b/data/sharp-lc70uq17u-hdmi1
new file mode 100644
index 0000000000000000000000000000000000000000..06b517f842197a717d414db74e427a98f1904af4
GIT binary patch
literal 256
zcmZSh4+adr0{;aVfZ)FbBXh&7@Cq&IeTza(Hmiwv1+72Fu+m|ILt_IY957imNEBM=
zIz;HWGB774Gcd@dDF$o^WRNy+C@=#V0~7(`KMcVhjzIwm9xlF~TnY+6k-rS$KK$Nt
z3_u<TFq$$kn-zLZP*7rJVP;}yW7OniXBTA;uw_5c%*ep-n3b8akeP=;fMJJ?!h#e=
zCT2zl0f$En_KdO(cEv#Z>vUWjAoc@ABnoB36e4s~AugK7D9cb3ctK7fPa_oS#vZN<
RT?!9$1qAG-K|~}NqyPjAIspIx

literal 0
HcmV?d00001

diff --git a/data/sharp-lc70uq17u-hdmi2 b/data/sharp-lc70uq17u-hdmi2
new file mode 100644
index 0000000000000000000000000000000000000000..f829ac646bf787ccdb63abddb6f3d2ad08263b5c
GIT binary patch
literal 256
zcmZSh4+adr0{;aVfZ)FbBXh&7@Cq&IeTza(Hmiwv1+72Fu+m|ILt_IY957imNEBM=
zIz;HWGB774Gcd@dDF$o^WRNy+C@=#V0~7(`KMcVhjzIwm9xlF~TnY+6k-rS$KK$Nt
z3_u<TFq$$kn-zLZP*7rJVP;}yW7OniXBTA;uw_5c%*ep-n3b8akeP=;fnkS@!h#e=
zCT2zl0f$En_KdO(cEv#Z>vUWjAoc@ABnoB36e4s~AugK7D9cb3ctK7fPa_oS#vZN<
RT?!9$1qAG-K|~}NxBv;PIspIx

literal 0
HcmV?d00001

diff --git a/data/sharp-lc70uq17u-hdmi3 b/data/sharp-lc70uq17u-hdmi3
new file mode 100644
index 0000000000000000000000000000000000000000..99fba5fc76eff8cdd29247f39a206f3f7be11933
GIT binary patch
literal 256
zcmZSh4+adr0{;aVfZ)FbBXh&7@Cq&IeTza(Hmiwv1+72Fu+m|ILt_IY957imNEBM=
zIz;HWGB774Gcd@dDF$o^WRNy+C@=#V0~7(`KMcVhjzIwm9xlF~TnY+6k-rS$KK$Nt
z3_u<TFq$$kn-zLZP*7rJVP;}yW7OniXBTA;uw_5c%*ep-n3b8akeP?UfMJJ?!h#e=
zCT2zl0f$En_KdO(cEv#Z>vUWjAoc@ABnoB36e4s~AugK7D9cb3ctK7fPa_oS#vZN<
ST?!9$1qAG-K|~}NegOawOgjMp

literal 0
HcmV?d00001

diff --git a/data/sharp-lc70uq17u-hdmi4 b/data/sharp-lc70uq17u-hdmi4
new file mode 100644
index 0000000000000000000000000000000000000000..78d6c766a4f5dcd5824f71a4ac0c2a9dae5999a2
GIT binary patch
literal 256
zcmZSh4+adr0{;aVfZ)FbBXh&7@Cq&IeTza(Hmiwv1+72Fu+m|ILt_IY957imNEBM=
zIz;HWGB774Gcd@dDF$o^WRNy+C@=#V0~7(`KMcVhjzIwm9xlF~TnY+6k-rS$KK$Nt
z3_u<TFq$$kn-zLZP*7rJVP;}yW7OniXBTA;uw_5c%*ep-n3b8akeP?UfnkS@!h#e=
zCT2zl0f$En_KdO(cEv#Z>vUWjAoc@ABnoB36e4s~AugK7D9cb3ctK7fPa_oS#vZN<
ST?!9$1qAG-K|~}NUI73V>^lJf

literal 0
HcmV?d00001

diff --git a/data/sharp-lc70uq17u-vga b/data/sharp-lc70uq17u-vga
new file mode 100644
index 0000000000000000000000000000000000000000..e9177229a888b2d8247e1cf11d6179078e71f4ef
GIT binary patch
literal 128
zcmZSh4+adr0`39~K=5CLky(R*p+ZY~-=a{H&1xcELF>;ktaO;*(AdBT2TWEC5``AJ
z4iP%8AWaMma%qYI8v+@m4IB#0pdvu(FN3*{ytg0&mjW07MgA}ZdpHIKDEK(LfCL%%
E0msc90RR91

literal 0
HcmV?d00001

diff --git a/data/sony-gdmf520-vga b/data/sony-gdmf520-vga
new file mode 100644
index 0000000000000000000000000000000000000000..2d1aee7575bc45baf0127281d79596016df31b98
GIT binary patch
literal 128
zcmZSh4+adrH#e{`0)Yt^BNLy7+%#>TlMBM#XR8Z&`27Fh@X-Ha<jTm#nT3&wk*<-A
z{%y7l2Lc%k92^!1GqflRGBC(7FfjaOFjytmsmj2m00uyjKMd|JzPfIvMh0LppvZp)
PBXa`-Gjnr@B8GARL=z<e

literal 0
HcmV?d00001

diff --git a/data/sony-snyc901-override b/data/sony-snyc901-override
new file mode 100644
index 0000000000000000000000000000000000000000..8d5690bc304326c5332145b7b7f81054ba87e53e
GIT binary patch
literal 256
zcmZSh4+adrHyKYdf`Bk1bHjqD3NGH03&P!Js0(@cC~`0~Hh|^e1d~;RM4^SQLxhei
zgF{O)1A`o+EJIP?1v!O0jZmlv0|Ub!hG2icNQICvE(H((iu`3Tu;X*%XMhMOFg{^o
zHgyP+7f?`C5@8i)5fWr(5))--W7OniXBTA;2xVtzW@KQ<Vdh~_U}#`Cz`-FX_=v$0
zX#IsEp!EVet_^VO_XGj0-=Pue022W^QASK5LPr(ipm~h4KwUr)0UcF{u6Ya$2LVO2
BH~|0v

literal 0
HcmV?d00001

diff --git a/data/sony-snyd301-override b/data/sony-snyd301-override
new file mode 100644
index 0000000000000000000000000000000000000000..18a584420a393e25b0acb83fd12a2d57126ca127
GIT binary patch
literal 256
zcmZSh4+adrHyJN8f`Bk1bHjqD3NGH03&P!Js0(@cC~`1>Wsrz8#efZg4AKS;1!fEm
zEy)ZFa*VPJMS&OO6!J7ep&|?n41XAc{rw^pLc+KdKmaK6m%+e}&yAk}BA~$7%*1T!
z5F{_4pr|CmD$F7z$jl@r%Ff29$;r+x${rBP&d|)rz>vet!{ETsz;J+rLs0M$gC(PE
z!-XOlF$Dn~)dsNj^ME1}g+P%A9aV_+KoN#LK|lxX&<J&aIFZQ;sLMjvK|se9q6_Gr
F{Q!N4Hvs?u

literal 0
HcmV?d00001

diff --git a/data/sony-x900f-hdmi b/data/sony-x900f-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..2292fe8bec299a128ec5855a8b8b443e016a4650
GIT binary patch
literal 256
zcmZSh4+adrH(8n(K|qF)xgp24f{XX$f^hd4>OvkqiX04$4J!{6`fp|cs{j%lFBl9y
z6+|^`i0ERlO>$yjkYloHkSMg!b%@Y$g^DmRF#KT%_V<fa2nkbA&@wRK0*d@)5Vzy&
zuwmd*00YKJOw6etq7xHh<KmO#1w>edSrn9P?1aRa*#$+J*cemOba?C8McD&v+4qFA
zF*NftFyt}wFc>iGu+e8|U}R!uNxu<$gt4N5@in8{1qN5{hPH&V{znX_AG7{ve9F(v
ez`*vHjhB&8mZ2!{f}BF0MkvB@K-VxZ+yVe~nm_>n

literal 0
HcmV?d00001

diff --git a/data/vizio-e65e0-hdmi b/data/vizio-e65e0-hdmi
new file mode 100644
index 0000000000000000000000000000000000000000..2c2d878cfe7573dbfc0f9359adb8ea9192758148
GIT binary patch
literal 256
zcmZSh4+ad8RuTe?K)@iy$lTB$P@$ETyCl?qo;shq*V1zg7Y~5s5P+qG!QfLtRKtdd
zE(VVbCk6&NCaVUCLJM7o2pw0b2m=Gd9|l)5Q(ad>E(I_Eiu`2|_u=nRV}Ob<x-u~b
z7KX>C#3sch3n(ebE3&c(v$HWX2?~jdF&c%l0kuE@Cp)_+dq6WI14BMD4}$`Oh0TKK
dXodtvW|pUXiD?O`kJ<PcAG1DyDJPPC1pq`dE&%`l

literal 0
HcmV?d00001

diff --git a/data/vizio-m60c3-hdmi-onkyo-txnr555 b/data/vizio-m60c3-hdmi-onkyo-txnr555
new file mode 100644
index 0000000000000000000000000000000000000000..93369abc45fd4348188e5b3a3f285f38c27fe3b4
GIT binary patch
literal 256
zcmZSh4+adjrvn5SKtPI-xuMm&f~zxqVYKgJbwLkL1qOzT2N+QRO9_L)r-G=44G~=o
z2V{&G8046&8YBuWbR8meTp1ql2?9lcX8mCZiO}^6GBq{jQUC&=2*eH`0|FQ|nV3Bb
zycwC8Sy=5AV&mc;S##F2^VhSBvj^C-9q?sh2xnuAuVap{V@$7SZ1!hh$YthX2xZt|
yqri{=)b)rjG5tpD5ypxJ29^?-145w=V3cJj3cMhvkf#yK;IIW~GssD3pbG#y;WhyP

literal 0
HcmV?d00001

-- 
2.24.3 (Apple Git-128)


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

* [PATCH 02/11] edid-decode: ignore dSYM
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
  2021-09-14 12:11 ` [PATCH 01/11] edid-decode: add more example EDIDs joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 03/11] edid-decode: change install directories for macOS joevt
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Building in macOS may create a .dSYM file for debugger symbols.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 7f1fdb7..518bb5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 edid-decode
+*.dSYM
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 03/11] edid-decode: change install directories for macOS
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
  2021-09-14 12:11 ` [PATCH 01/11] edid-decode: add more example EDIDs joevt
  2021-09-14 12:11 ` [PATCH 02/11] edid-decode: ignore dSYM joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-15 10:06   ` Hans Verkuil
  2021-09-14 12:11 ` [PATCH 04/11] edid-decode: add bounds checking joevt
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

In macOS, /usr/bin and /usr/share/man belong to root:wheel so install to /usr/local/bin and /usr/local/share/man instead.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 Makefile | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 287b72d..adf6123 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,23 @@
-bindir ?= /usr/bin
-mandir ?= /usr/share/man
+ifeq ($(OS),Windows_NT)
+	bindir ?= /usr/bin
+	mandir ?= /usr/share/man
+else
+	UNAME_S := $(shell uname -s)
+	ifeq ($(UNAME_S),Darwin)
+		bindir ?= /usr/local/sbin
+		mandir ?= /usr/local/share/man
+	else
+		bindir ?= /usr/bin
+		mandir ?= /usr/share/man
+	endif
+endif
 
 EMXX ?= em++
 
-SOURCES = edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
-	  parse-displayid-block.cpp parse-ls-ext-block.cpp \
-	  parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp
+SOURCES = \
+	edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
+	parse-displayid-block.cpp parse-ls-ext-block.cpp \
+	parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp
 WARN_FLAGS = -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter
 
 all: edid-decode
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 04/11] edid-decode: add bounds checking
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (2 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 03/11] edid-decode: change install directories for macOS joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-15 10:07   ` Hans Verkuil
  2021-09-14 12:11 ` [PATCH 05/11] edid-decode: fix standard timing vertical pixels joevt
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 parse-vtb-ext-block.cpp | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/parse-vtb-ext-block.cpp b/parse-vtb-ext-block.cpp
index 05d54f4..edfe887 100644
--- a/parse-vtb-ext-block.cpp
+++ b/parse-vtb-ext-block.cpp
@@ -17,16 +17,21 @@ void edid_state::parse_vtb_ext_block(const unsigned char *x)
 	unsigned num_cvt = x[3];
 	unsigned num_st = x[4];
 
+	const unsigned char *y = x + 0x7f;
 	x += 5;
 	if (num_dtd) {
 		printf("  Detailed Timing Descriptors:\n");
-		for (unsigned i = 0; i < num_dtd; i++, x += 18)
+		for (unsigned i = 0; i < num_dtd; i++, x += 18) {
+			if (x + 18 > y) { fail("Not enough bytes remain for more DTBs in the VTB-EXT\n"); return; }
 			detailed_timings("    ", x, false);
+		}
 	}
 	if (num_cvt) {
 		printf("  Coordinated Video Timings:\n");
-		for (unsigned i = 0; i < num_cvt; i++, x += 3)
+		for (unsigned i = 0; i < num_cvt; i++, x += 3) {
+			if (x + 3 > y) { fail("Not enough bytes remain for more CVTs in the VTB-EXT\n"); return; }
 			detailed_cvt_descriptor("    ", x, false);
+		}
 	}
 	if (num_st) {
 		// Note: the VTB-EXT standard has a mistake in the example EDID
@@ -36,7 +41,9 @@ void edid_state::parse_vtb_ext_block(const unsigned char *x)
 		//
 		// The documentation itself is correct, though.
 		printf("  Standard Timings:\n");
-		for (unsigned i = 0; i < num_st; i++, x += 2)
+		for (unsigned i = 0; i < num_st; i++, x += 2) {
+			if (x + 2 > y) { fail("Not enough bytes remain for more STs in the VTB-EXT\n"); return; }
 			print_standard_timing("    ", x[0], x[1], true);
+		}
 	}
 }
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 05/11] edid-decode: fix standard timing vertical pixels
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (3 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 04/11] edid-decode: add bounds checking joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-15 10:08   ` Hans Verkuil
  2021-09-14 12:11 ` [PATCH 06/11] edid-decode: linefeed before fail joevt
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Don't do ceiling to nearest 8 pixels for active vertical lines. See examples elo-4600l-hdmi and kogan-kaled24144f-hdmi.

Section 3.9 and 3.10.3.6 of EDID 1.4 does not say vertical lines must be a multiple of 8.  This line of code appears to have been added to satisfy the 3rd example in VTB-EXT spec but that example has an incorrect HAP indicator decimal value so it cannot be trusted. Also, all 3 examples have an incorrect vertical refresh value as noted in parse-vtb-ext-block.cpp. The VESA DMT spec has the following examples that are not a multiple of 8 lines which support this change:
1400x1050 4:3
1440x900 16:10
1600x900 16:9
1680x1050 16:10

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 parse-base-block.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/parse-base-block.cpp b/parse-base-block.cpp
index e2901a6..32d2079 100644
--- a/parse-base-block.cpp
+++ b/parse-base-block.cpp
@@ -573,7 +573,6 @@ void edid_state::print_standard_timing(const char *prefix, unsigned char b1, uns
 		break;
 	}
 	vact = (double)hact * vratio / hratio;
-	vact = 8 * ((vact + 7) / 8);
 	refresh = (b2 & 0x3f) + 60;
 
 	formula.hact = hact;
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 06/11] edid-decode: linefeed before fail
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (4 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 05/11] edid-decode: fix standard timing vertical pixels joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 07/11] edid-decode: always linefeed after hex_block joevt
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Always output linefeed before fail message. See example dell-up2715k-dp1-optomedia-cmv535.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 parse-base-block.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/parse-base-block.cpp b/parse-base-block.cpp
index 32d2079..5840fd8 100644
--- a/parse-base-block.cpp
+++ b/parse-base-block.cpp
@@ -700,9 +700,9 @@ void edid_state::detailed_display_range_limits(const unsigned char *x)
 		base.max_display_pixclk_khz = x[9] * 10000;
 		printf(", max dotclock %d MHz\n", x[9] * 10);
 	} else {
+		printf("\n");
 		if (base.edid_minor >= 4)
 			fail("EDID 1.4 block does not set max dotclock.\n");
-		printf("\n");
 	}
 
 	if (has_sec_gtf) {
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 07/11] edid-decode: always linefeed after hex_block
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (5 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 06/11] edid-decode: linefeed before fail joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-15 10:10   ` Hans Verkuil
  2021-09-14 12:11 ` [PATCH 08/11] edid-decode: output full frequencies for 4:2:0 joevt
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

hex_block should not return without printing a newline (which occurs when the length is zero). This causes a missing newline after "Application Version: 1" with cta_hdr10plus for an EDID I have.
Any place that calls hex_block will have the same problem if it's possible for the length to be zero.

In other words, a hex_block needs to have a linefeed even if it has zero length, because the caller assumes it will go to the next line as it does when the hex block is not zero length.

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

diff --git a/edid-decode.cpp b/edid-decode.cpp
index 2316abc..6aa93fb 100644
--- a/edid-decode.cpp
+++ b/edid-decode.cpp
@@ -698,8 +698,10 @@ void hex_block(const char *prefix, const unsigned char *x,
 {
 	unsigned i, j;
 
-	if (!length)
+	if (!length) {
+		printf("\n");
 		return;
+	}
 
 	for (i = 0; i < length; i += step) {
 		unsigned len = min(step, length - i);
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 08/11] edid-decode: output full frequencies for 4:2:0
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (6 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 07/11] edid-decode: always linefeed after hex_block joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 09/11] edid-decode: allow undefined aspect ratio joevt
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Don't half hfreq for 4:2:0 timings - the character clock is halved, but the number of characters per line is also halved (two luminance values per character for 4:2:0), so there's no change in hfreq.
Don't half pixel clock because it looks weird. Character clock is halved but the number of pixels remains the same (two luminance values per character for 4:2:0).
Continue to use the half hfreq and half pixel clock for the ranges calculations because some non-HDMI 2.0 displays have max pixel clock halved when they have 4:2:0 modes and because other reasons that lead to adding this code in the first place?

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

diff --git a/edid-decode.cpp b/edid-decode.cpp
index 6aa93fb..0c83e0e 100644
--- a/edid-decode.cpp
+++ b/edid-decode.cpp
@@ -513,6 +513,7 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t,
 	if (t->interlaced)
 		vact /= 2;
 
+	double out_hor_freq_khz = hor_freq_khz;
 	if (t->ycbcr420)
 		hor_freq_khz /= 2;
 
@@ -558,6 +559,7 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t,
 		dtd_max_vsize_mm = t->vsize_mm;
 	if (!s.empty())
 		s = " (" + s + ")";
+	unsigned out_pixclk_khz = t->pixclk_khz;
 	unsigned pixclk_khz = t->pixclk_khz / (t->ycbcr420 ? 2 : 1);
 
 	char buf[10];
@@ -568,8 +570,8 @@ bool edid_state::print_timings(const char *prefix, const struct timings *t,
 	       t->hact, buf,
 	       refresh,
 	       t->hratio, t->vratio,
-	       hor_freq_khz,
-	       pixclk_khz / 1000.0,
+	       out_hor_freq_khz,
+	       out_pixclk_khz / 1000.0,
 	       s.c_str());
 
 	unsigned len = strlen(prefix) + 2;
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 09/11] edid-decode: allow undefined aspect ratio
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (7 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 08/11] edid-decode: output full frequencies for 4:2:0 joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 10/11] edid-decode: add warnings to VESA VSDB joevt
  2021-09-14 12:11 ` [PATCH 11/11] edid-decode: cta and displayid changes joevt
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Distinguish between "undefined" and "reserved" aspect ratios. See examples apple-xdr-6k-tile0, lg-ultrafine-5k-v1-thunderbolt-dp1-tile0, asus-xg438q-dp
"undefined" is for an aspect ratio that doesn't exist in the list of known aspect ratios. This does not deserve a fail.
"reserved" should not be used and still deserves the fail.

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 parse-displayid-block.cpp | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
index 9713c46..8f4e366 100644
--- a/parse-displayid-block.cpp
+++ b/parse-displayid-block.cpp
@@ -270,10 +270,12 @@ void edid_state::parse_displayid_type_1_7_timing(const unsigned char *x,
 		t.hratio = 256;
 		t.vratio = 135;
 		break;
-	default:
+	case 8:
 		s += "undefined";
-		if ((x[3] & 0xf) > (dispid.version <= 0x12 ? 7 : 8))
-			fail("Unknown aspect 0x%02x.\n", x[3] & 0xf);
+		break;
+	default:
+		s += "reserved";
+		fail("Unknown aspect 0x%02x.\n", x[3] & 0xf);
 		break;
 	}
 	switch ((x[3] >> 5) & 0x3) {
@@ -455,10 +457,12 @@ void edid_state::parse_displayid_type_3_timing(const unsigned char *x)
 		t.hratio = 256;
 		t.vratio = 135;
 		break;
-	default:
+	case 8:
 		s += "undefined";
-		if ((x[3] & 0xf) > (dispid.version <= 0x12 ? 7 : 8))
-			fail("Unknown aspect 0x%02x.\n", x[3] & 0xf);
+		break;
+	default:
+		s += "reserved";
+		fail("Unknown aspect 0x%02x.\n", x[0] & 0xf);
 		break;
 	}
 
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 10/11] edid-decode: add warnings to VESA VSDB
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (8 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 09/11] edid-decode: allow undefined aspect ratio joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-14 12:11 ` [PATCH 11/11] edid-decode: cta and displayid changes joevt
  10 siblings, 0 replies; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Add warnings for VESA vendor specific datablock (bits that should be zero and reserved values).

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 parse-displayid-block.cpp | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
index 8f4e366..5c81294 100644
--- a/parse-displayid-block.cpp
+++ b/parse-displayid-block.cpp
@@ -1461,22 +1461,37 @@ void edid_state::parse_displayid_vesa(const unsigned char *x)
 	unsigned len = x[2];
 	x += 6;
 	printf("    Data Structure Type: ");
-	switch (x[0] & 0x07) {
-	case 0x00: printf("eDP\n"); break;
-	case 0x01: printf("DP\n"); break;
-	default: printf("Reserved\n"); break;
+	switch (x[0] & 7) {
+	case 0: printf("eDP\n"); break;
+	case 1: printf("DP\n"); break;
+	default: printf("Reserved (%d)\n", x[0] & 7); break;
 	}
+
+	if ((x[0] >> 3) & 15)
+		warn("Reserved bits 6:3 (%d) are not 0.\n", (x[0] >> 3) & 15);
+
 	printf("    Default Colorspace and EOTF Handling: %s\n",
 	       (x[0] & 0x80) ? "Native as specified in the Display Parameters DB" : "sRGB");
+
 	printf("    Number of Pixels in Hor Pix Cnt Overlapping an Adjacent Panel: %u\n",
 	       x[1] & 0xf);
+	if ((x[1] & 0xf) > 8)
+		warn("Number of Pixels in Hor Pix Cnt Overlapping an Adjacent Panel exceeds 8.\n");
+
+	if ((x[1] >> 4) & 1)
+		warn("Reserved bit 4 is not 0.\n");
+
 	printf("    Multi-SST Operation: ");
-	switch ((x[1] >> 5) & 0x03) {
-	case 0x00: printf("Not Supported\n"); break;
-	case 0x01: printf("Two Streams (number of links shall be 2 or 4)\n"); break;
-	case 0x02: printf("Four Streams (number of links shall be 4)\n"); break;
-	case 0x03: printf("Reserved\n"); break;
+	switch ((x[1] >> 5) & 3) {
+	case 0: printf("Not Supported\n"); break;
+	case 1: printf("Two Streams (number of links shall be 2 or 4)\n"); break;
+	case 2: printf("Four Streams (number of links shall be 4)\n"); break;
+	case 3: printf("Reserved\n"); warn("Invalid option for Multi-SST Operation.\n"); break;
 	}
+
+	if ((x[1] >> 7) & 1)
+		warn("Reserved bit 7 is not 0.\n");
+
 	if (len >= 7) {
 		double bpp = (x[2] & 0x3f) + (x[3] & 0x0f) / 16.0;
 		printf("    Pass through timing's target DSC bits per pixel: %.4f\n", bpp);
-- 
2.24.3 (Apple Git-128)


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

* [PATCH 11/11] edid-decode: cta and displayid changes
  2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
                   ` (9 preceding siblings ...)
  2021-09-14 12:11 ` [PATCH 10/11] edid-decode: add warnings to VESA VSDB joevt
@ 2021-09-14 12:11 ` joevt
  2021-09-15 13:37   ` Hans Verkuil
  10 siblings, 1 reply; 23+ messages in thread
From: joevt @ 2021-09-14 12:11 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Goal: make OUI blocks equal to normal blocks to simplify decoding and make handling of all types of blocks consistent. This will reduce duplicated code (only one place for checking duplicate blocks, only one place for handling unknown blocks, etc.)

oui.h
- This contains a list of OUI and CID and PNP values.
- It is included in various places with varying definitions of the oneoui macro.

edid-decode.h
- Add list of OUI constants using oui.h.
- Other changes described below.

parse-cta-block.cpp
- Modified oui_name. Returns a name and a number for a OUI.
- Added data_block_oui. For data blocks with an OUI, does size check, OUI endianness check, and PNP vs OUI check. Returns a value representing the OUI (if it is known).
- Modify cta_block. Reduce code by flattening the switch statement. This means constructing a case value from three values.
  Side effects include making reporting of "Only one instance of this Data Block is allowed." more consistant (always report this fail after the block type is output instead of sometimes before and sometimes after). See example acer-xv273k-dp2-corrupted.
  First, get the extended type and append it to the tag type (i.e. add 0x700 if extended), then get the OUI if it's vendor specific, and convert it to a number that can be appended (bitwise or) to the tag/extended type value.
	- Init static variables
	- Replace last_block_was_hdmi_vsdb with previous_cta_tag; this means instead of remembering if the last block was hdmi vsdb, we just remember the previous block's tag.
	- Replace first_block with cta_block_number; this means instead of remembering if this is the first block or not, we just remember the current block number.
	- Remove name and oui, we'll just get the data_block string and a oui index directly.
	- Report OUI for extended tag 11h (Vendor-Specific Audio Data Block)
	- Fix capitalization of "Audio information is present" fail message.
	- Add bounds check on length field (must be at least 1 for extended tags).
	- Don't parse after OUI if there's not enough length for OUI.
	- Adjust x offsets in cta_hdmi_block so it is like other OUI extended blocks such that x points to after the OUI.
	- A block that outputs only hex is reported as an unknown block type even if we know the OUI. See example acer-xb321hk-dp.

parse-disableid-block.cpp
- Add displayid_block to do a single data block - like cta_block does for cta extension block
	- Vendor specific data block for DisplayID 1.3 is assumed to be PNP (string order). See example apple-macbookpro-16inch-2019.
	- Vendor specific data block for DisplayID 2.0 is assumed to have OUI (little endian).
	- Interpret Vendor specific data block 0x7e or 0x7f even if DisplayID is not correct for that type (there's already a FAIL message to identify the problem). See example apple-xdr-6k.
	- Add bounds check: if length is < 3, only check x[1] if length is 2.
	  Don't report "Not enough bytes remain (1) for a DisplayID data block or the DisplayID filler is non-0." if the bytes are zero (also change the word "or" to "and"). See example apple-xdr-6k-tile0.
	- Report datablock name before failing.
	- For unknown vendor specific data blocks, don't output the OUI part as hex since the new data_block_oui function has already reported it. See example apple-macbookpro-16inch-2019.
	- Replace first_data_block with disp.block_number

Signed-off-by: Joe van Tunen <joevt@shaw.ca>
---
 edid-decode.cpp           |  99 ++++++--
 edid-decode.h             |  20 +-
 oui.h                     |  20 ++
 parse-cta-block.cpp       | 456 ++++++++++++++-----------------------
 parse-displayid-block.cpp | 463 ++++++++++++++++++--------------------
 5 files changed, 505 insertions(+), 553 deletions(-)
 create mode 100644 oui.h

diff --git a/edid-decode.cpp b/edid-decode.cpp
index 0c83e0e..ed3223d 100644
--- a/edid-decode.cpp
+++ b/edid-decode.cpp
@@ -657,25 +657,90 @@ std::string utohex(unsigned char x)
 	return buf;
 }
 
-const char *oui_name(unsigned oui, bool reverse)
+const char *oui_name(unsigned oui, unsigned *ouinum)
 {
-	if (reverse)
-		oui = (oui >> 16) | (oui & 0xff00) | ((oui & 0xff) << 16);
-
+	unsigned ouinumscratch;
+	if (!ouinum) ouinum = &ouinumscratch;
+	const char *name;
 	switch (oui) {
-	case 0x00001a: return "AMD";
-	case 0x000c03: return "HDMI";
-	case 0x00044b: return "NVIDIA";
-	case 0x000c6e: return "ASUS";
-	case 0x0010fa: return "Apple";
-	case 0x0014b9: return "MSTAR";
-	case 0x00d046: return "Dolby";
-	case 0x00e047: return "InFocus";
-	case 0x3a0292: return "VESA";
-	case 0x90848b: return "HDR10+";
-	case 0xc45dd8: return "HDMI Forum";
-	case 0xca125c: return "Microsoft";
-	default: return NULL;
+		#define oneoui(c,k,n) case c: *ouinum = kOUI_##k; name = n; break;
+		#include "oui.h"
+		default: *ouinum = 0; name = NULL;
+	}
+	return name;
+}
+
+void edid_state::data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii, bool big_endian)
+{
+	std::string buf;
+	char ascii[4];
+	unsigned oui;
+	const char *ouiname = NULL;
+	bool matched_reverse = false;
+	bool matched_ascii = false;
+	bool valid_ascii = false;
+
+	if (big_endian)
+		oui = ((length > 0 ? x[0] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 2 ? x[2] : 0);
+	else
+		oui = ((length > 2 ? x[2] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 0 ? x[0] : 0);
+
+	buf = ouitohex(oui);
+	if (length < 3) {
+		sprintf(ascii, "?"); // some characters are null
+		if (ouinum) *ouinum = 0; // doesn't match a known OUI
+	} else {
+		valid_ascii = (x[0] >= 'A' && x[1] >= 'A' && x[2] >= 'A' && x[0] <= 'Z' && x[1] <= 'Z' && x[2] <= 'Z');
+		sprintf(ascii, "%c%c%c", x[0], x[1], x[2]);
+
+		ouiname = oui_name(oui, ouinum);
+		if (!ouiname) {
+			big_endian = !big_endian;
+			unsigned reversedoui = ((oui & 0xff) << 16) + (oui & 0x00ff00) + (oui >> 16);
+			ouiname = oui_name(reversedoui, ouinum);
+			if (ouiname) {
+				oui = reversedoui;
+				buf = ouitohex(oui);
+				matched_reverse = true;
+			}
+			else if (do_ascii && valid_ascii)
+			{
+				unsigned asciioui = (x[0] << 24) + (x[1] << 16) + (x[2] << 8);
+				ouiname = oui_name(asciioui, ouinum);
+				if (ouiname) {
+					matched_ascii = true;
+				}
+			}
+		}
+	}
+
+	std::string name;
+	if (ouiname) {
+		if (matched_ascii)
+			name = block_name + " (" + ouiname + ")" + ", PNP ID '" + ascii + "'";
+		else
+			name = block_name + " (" + ouiname + ")" + ", OUI " + buf;
+	} else if (do_ascii && valid_ascii) {
+		name = block_name + ", PNP ID '" + ascii + "'";
+	} else {
+		name = block_name + ", OUI " + buf;
+	}
+	// assign string to data_block before outputting errors
+	data_block = name;
+	
+	if (oui || !ignorezeros) {
+		if (length < 3)
+			fail("Data block length is not enough to contain an OUI.\n");
+		if (ouiname && do_ascii && !valid_ascii)
+			warn("Expected PNP ID but found OUI.\n");
+		if (ouiname && matched_reverse)
+			warn("Endian-ness (%s) of OUI is different than expected (%s).\n", big_endian ? "be" : "le", big_endian ? "le" : "be");
+		if (!ouiname) {
+			if (valid_ascii)
+				warn("Unknown OUI %s (possible PNP %s).\n", buf.c_str(), ascii);
+			else
+				warn("Unknown OUI %s.\n", buf.c_str());
+		}
 	}
 }
 
diff --git a/edid-decode.h b/edid-decode.h
index 612d22a..9e6a955 100644
--- a/edid-decode.h
+++ b/edid-decode.h
@@ -153,8 +153,10 @@ struct edid_state {
 		// CTA-861 block state
 		cta.has_vic_1 = cta.first_svd_might_be_preferred = cta.has_sldb =
 			cta.has_hdmi = cta.has_vcdb = cta.has_vfpdb = false;
-		cta.last_block_was_hdmi_vsdb = cta.have_hf_vsdb = cta.have_hf_scdb = false;
-		cta.first_block = cta.first_svd = true;
+		cta.have_hf_vsdb = cta.have_hf_scdb = false;
+		cta.previous_cta_tag = 0xfff;
+		cta.block_number = 0;
+		cta.first_svd = true;
 		cta.supported_hdmi_vic_codes = cta.supported_hdmi_vic_vsb_codes = 0;
 		memset(cta.vics, 0, sizeof(cta.vics));
 		memset(cta.preparsed_has_vic, 0, sizeof(cta.preparsed_has_vic));
@@ -175,6 +177,7 @@ struct edid_state {
 		dispid.is_display = dispid.has_product_identification =
 			dispid.has_display_parameters = dispid.has_type_1_7 =
 			dispid.has_display_interface_features = false;
+		dispid.block_number = 0;
 
 		// Block Map block state
 		block_map.saw_block_1 = false;
@@ -257,9 +260,9 @@ struct edid_state {
 		bool preparsed_sld;
 		bool has_sldb;
 		unsigned short preparsed_phys_addr;
-		bool last_block_was_hdmi_vsdb;
+		unsigned previous_cta_tag;
 		bool have_hf_vsdb, have_hf_scdb;
-		bool first_block;
+		unsigned block_number;
 		bool first_svd;
 		unsigned supported_hdmi_vic_codes;
 		unsigned supported_hdmi_vic_vsb_codes;
@@ -282,6 +285,7 @@ struct edid_state {
 		bool has_display_interface_features;
 		vec_timings_ext preferred_timings;
 		unsigned native_width, native_height;
+		unsigned block_number;
 		// Keep track of the found CTA-861 Tag/Extended Tag pairs.
 		// The unsigned value is equal to: (tag << 8) | ext_tag
 		std::set<unsigned> found_tags;
@@ -331,6 +335,8 @@ struct edid_state {
 	void list_dmts();
 	void list_established_timings();
 
+	void data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii = false, bool big_endian = false);
+
 	void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false);
 	void hdmi_latency(unsigned char vid_lat, unsigned char aud_lat, bool is_ilaced);
 	void cta_vcdb(const unsigned char *x, unsigned length);
@@ -390,6 +396,7 @@ struct edid_state {
 	void parse_displayid_type_10_timing(const unsigned char *x, unsigned sz,
 					    bool is_cta = false);
 	void preparse_displayid_block(const unsigned char *x);
+	unsigned displayid_block(const unsigned version, const unsigned char *x, unsigned length);
 	void parse_displayid_block(const unsigned char *x);
 	void parse_displayid_vesa(const unsigned char *x);
 	void parse_displayid_cta_data_block(const unsigned char *x);
@@ -454,7 +461,7 @@ void hex_block(const char *prefix, const unsigned char *x, unsigned length,
 	       bool show_ascii = true, unsigned step = 16);
 std::string block_name(unsigned char block);
 void calc_ratio(struct timings *t);
-const char *oui_name(unsigned oui, bool reverse = false);
+const char *oui_name(unsigned oui, unsigned *ouinum = NULL);
 
 bool timings_close_match(const timings &t1, const timings &t2);
 const struct timings *find_dmt_id(unsigned char dmt_id);
@@ -465,4 +472,7 @@ const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic);
 unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic);
 char *extract_string(const unsigned char *x, unsigned len);
 
+#define oneoui(c,k,n) const unsigned kOUI_##k = __LINE__<<12;
+#include "oui.h"
+
 #endif
diff --git a/oui.h b/oui.h
new file mode 100644
index 0000000..c90f025
--- /dev/null
+++ b/oui.h
@@ -0,0 +1,20 @@
+// http://standards-oui.ieee.org/oui/oui.txt
+oneoui(0x000c03, HDMI,         "HDMI"        )
+oneoui(0xc45dd8, HDMIForum,    "HDMI Forum"  )
+oneoui(0x90848b, HDR10,        "HDR10+"      )
+oneoui(0x00001a, AMD,          "AMD"         )
+oneoui(0x00044b, NVIDIA,       "NVIDIA"      )
+oneoui(0x000c6e, ASUS,         "ASUS"        )
+oneoui(0x0010fa, Apple,        "Apple"       )
+oneoui(0x0014b9, MSTAR,        "MSTAR"       )
+oneoui(0x00d046, Dolby,        "Dolby"       )
+oneoui(0x00e047, InFocus,      "InFocus"     )
+oneoui(0xca125c, Microsoft,    "Microsoft"   )
+
+// http://standards-oui.ieee.org/cid/cid.txt
+oneoui(0x3a0292, VESA,         "VESA"        )
+
+// https://uefi.org/pnp_id_list
+oneoui('APP\0' , asciiApple,   "Apple"       )
+
+#undef oneoui
diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
index 4edaa1d..9bc0c77 100644
--- a/parse-cta-block.cpp
+++ b/parse-cta-block.cpp
@@ -652,57 +652,57 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
 {
 	unsigned len_vic, len_3d;
 
-	if (length < 4) {
-		fail("Empty Data Block with length %u.\n", length);
+	if (length < 1) {
+		fail("Empty Data Block.\n");
 		return;
 	}
-	printf("    Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
-	       x[4] >> 4, x[4] & 0x0f);
+	printf("    Source physical address: %x.%x.%x.%x\n", x[0] >> 4, x[0] & 0x0f,
+	       x[1] >> 4, x[1] & 0x0f);
 
-	if (length < 6)
+	if (length < 3)
 		return;
 
-	if (x[5] & 0x80)
+	if (x[2] & 0x80)
 		printf("    Supports_AI\n");
-	if (x[5] & 0x40)
+	if (x[2] & 0x40)
 		printf("    DC_48bit\n");
-	if (x[5] & 0x20)
+	if (x[2] & 0x20)
 		printf("    DC_36bit\n");
-	if (x[5] & 0x10)
+	if (x[2] & 0x10)
 		printf("    DC_30bit\n");
-	if (x[5] & 0x08)
+	if (x[2] & 0x08)
 		printf("    DC_Y444\n");
 	/* two reserved bits */
-	if (x[5] & 0x01)
+	if (x[2] & 0x01)
 		printf("    DVI_Dual\n");
 
-	if (length < 7)
+	if (length < 4)
 		return;
 
-	printf("    Maximum TMDS clock: %u MHz\n", x[6] * 5);
-	if (x[6] * 5 > 340)
+	printf("    Maximum TMDS clock: %u MHz\n", x[3] * 5);
+	if (x[3] * 5 > 340)
 		fail("HDMI VSDB Max TMDS rate is > 340.\n");
 
-	if (length < 8)
+	if (length < 5)
 		return;
 
-	if (x[7] & 0x0f) {
+	if (x[4] & 0x0f) {
 		printf("    Supported Content Types:\n");
-		if (x[7] & 0x01)
+		if (x[4] & 0x01)
 			printf("      Graphics\n");
-		if (x[7] & 0x02)
+		if (x[4] & 0x02)
 			printf("      Photo\n");
-		if (x[7] & 0x04)
+		if (x[4] & 0x04)
 			printf("      Cinema\n");
-		if (x[7] & 0x08)
+		if (x[4] & 0x08)
 			printf("      Game\n");
 	}
 
-	unsigned b = 8;
-	if (x[7] & 0x80) {
+	unsigned b = 5;
+	if (x[4] & 0x80) {
 		hdmi_latency(x[b], x[b + 1], false);
 
-		if (x[7] & 0x40) {
+		if (x[4] & 0x40) {
 			if (x[b] == x[b + 2] &&
 			    x[b + 1] == x[b + 3])
 				warn("Progressive and Interlaced latency values are identical, no need for both.\n");
@@ -712,7 +712,7 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
 		b += 2;
 	}
 
-	if (!(x[7] & 0x20))
+	if (!(x[4] & 0x20))
 		return;
 
 	bool mask = false;
@@ -1990,293 +1990,169 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
 	}
 }
 
-void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
-			       bool duplicate)
+#define data_block_o(n) do { data_block_oui(n, x, length, false, &ouinum); if (length < 3) return; length -= 3; x += 3; } while(0)
+
+void edid_state::cta_block(const unsigned char *x, bool duplicate)
 {
-	const char *name;
-	unsigned oui;
-	bool reverse = false;
+	unsigned length = x[0] & 0x1f; // number of bytes after the tag/length byte
+	unsigned ouinum = 0;
+	unsigned tag=(x[0] & 0xe0) >> 5;
+	unsigned extended = (tag == 0x07) ? 1 : 0;
+	x++;
+	if (extended) {
+		if (!length) {
+			fail("Extended tag cannot have length 0.\n");
+			return;
+		}
+		length--;
+		tag = 0x700 + x[0];
+		x++;
+	}
+
 	bool audio_block = false;
 
-	switch (x[0]) {
-	case 0x00: data_block = "Video Capability Data Block"; break;
-	case 0x01: data_block.clear(); break;
-	case 0x02: data_block = "VESA Video Display Device Data Block"; break;
-	case 0x03: data_block = "VESA Video Timing Block Extension"; break;
-	case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
-	case 0x05: data_block = "Colorimetry Data Block"; break;
-	case 0x06: data_block = "HDR Static Metadata Data Block"; break;
-	case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
-
-	case 0x0d: data_block = "Video Format Preference Data Block"; break;
-	case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
-	case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
-	case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
-	case 0x11: data_block.clear(); audio_block = true; break;
-	case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
-	case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
-	case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
-
-	case 0x20: data_block = "InfoFrame Data Block"; break;
-
-	case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
-	case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
-	case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
-
-	case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
-	case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
+	switch (tag) {
+	case 0x001: data_block = "Audio Data Block"; audio_block = true; break;
+	case 0x002: data_block = "Video Data Block"; break;
+	case 0x003: data_block_o("Vendor-Specific Data Block"); break;
+	case 0x004: data_block = "Speaker Allocation Data Block"; audio_block = true; break;
+	case 0x005: data_block = "VESA Display Transfer Characteristics Data Block"; break;
+
+	case 0x700: data_block = "Video Capability Data Block"; break;
+	case 0x701: data_block_o("Vendor-Specific Video Data Block"); break;
+	case 0x702: data_block = "VESA Video Display Device Data Block"; break;
+	case 0x703: data_block = "VESA Video Timing Block Extension"; break; // not implemented
+	case 0x704: data_block = "Reserved for HDMI Video Data Block"; break; // reserved
+	case 0x705: data_block = "Colorimetry Data Block"; break;
+	case 0x706: data_block = "HDR Static Metadata Data Block"; break;
+	case 0x707: data_block = "HDR Dynamic Metadata Data Block"; break;
+
+	case 0x70d: data_block = "Video Format Preference Data Block"; break;
+	case 0x70e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
+	case 0x70f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
+	case 0x710: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break; // reserved
+	case 0x711: data_block_o("Vendor-Specific Audio Data Block"); audio_block = true; break; // no vendors implemented
+	case 0x712: data_block = "HDMI Audio Data Block"; audio_block = true; break;
+	case 0x713: data_block = "Room Configuration Data Block"; audio_block = true; break;
+	case 0x714: data_block = "Speaker Location Data Block"; audio_block = true; break;
+
+	case 0x720: data_block = "InfoFrame Data Block"; break;
+
+	case 0x734: data_block = "DisplayID Type VII Video Timing Data Block"; break;
+	case 0x735: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
+	case 0x742: data_block = "DisplayID Type X Video Timing Data Block"; break;
+
+	case 0x778: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
+	case 0x779: data_block = "HDMI Forum Sink Capability Data Block"; break;
 	default:
-		if (x[0] <= 12)
-			printf("  Unknown CTA-861 Video-Related");
-		else if (x[0] <= 31)
-			printf("  Unknown CTA-861 Audio-Related");
-		else if (x[0] >= 120 && x[0] <= 127)
-			printf("  Unknown CTA-861 HDMI-Related");
-		else
-			printf("  Unknown CTA-861");
-		printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
-		hex_block("    ", x + 1, length);
-		data_block.clear();
-		warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
-		return;
-	}
-
-	switch (x[0]) {
-	case 0x00:
-	case 0x02:
-	case 0x05:
-	case 0x06:
-	case 0x0d:
-	case 0x0f:
-	case 0x12:
-	case 0x13:
-	case 0x78:
-	case 0x79:
+		     if (tag < 0x700) data_block = "Unknown CTA-861 Data Block";
+		else if (tag < 0x70d) data_block = "Unknown CTA-861 Video-Related Data Block";
+		else if (tag < 0x720) data_block = "Unknown CTA-861 Audio-Related Data Block";
+		else if (tag < 0x778) data_block = "Unknown CTA-861 Data Block";
+		else if (tag < 0x780) data_block = "Unknown CTA-861 HDMI-Related Data Block";
+		else                  data_block = "Unknown CTA-861 Data Block";
+		data_block += std::string(" (") + (extended ? "extended " : "") + "tag " + utohex(tag & 0xff) + ")";
+	}
+
+	printf("  %s:\n", data_block.c_str());
+
+	switch (tag) {
+	case 0x004:
+	case 0x005:
+	case 0x700:
+	case 0x702:
+	case 0x705:
+	case 0x706:
+	case 0x70d:
+	case 0x70f:
+	case 0x712:
+	case 0x713:
+	case 0x778:
+	case 0x779:
 		if (duplicate)
 			fail("Only one instance of this Data Block is allowed.\n");
-		break;
 	}
 
-
 	// See Table 52 of CTA-861-G for a description of Byte 3
 	if (audio_block && !(cta.byte3 & 0x40))
-		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
-
-	if (data_block.length())
-		printf("  %s:\n", data_block.c_str());
-
-	switch (x[0]) {
-	case 0x00: cta_vcdb(x + 1, length); return;
-	case 0x01:
-		if (length < 3) {
-			data_block = std::string("Vendor-Specific Video Data Block");
-			fail("Invalid length %u < 3.\n", length);
-			return;
-		}
-		oui = (x[3] << 16) + (x[2] << 8) + x[1];
-		name = oui_name(oui);
-		if (!name) {
-			name = oui_name(oui, true);
-			if (name)
-				reverse = true;
-		}
-		if (!name) {
-			printf("  Vendor-Specific Video Data Block, OUI %s:\n",
-			       ouitohex(oui).c_str());
-			hex_block("    ", x + 4, length - 3);
-			data_block.clear();
-			warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
-			     ouitohex(oui).c_str());
-			return;
-		}
-		data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
-		if (reverse)
-			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
-		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
-		if (oui == 0x90848b)
-			cta_hdr10plus(x + 4, length - 3);
-		else if (oui == 0x00d046)
-			cta_dolby_video(x + 4, length - 3);
-		else
-			hex_block("    ", x + 4, length - 3);
-		return;
-	case 0x02: cta_vesa_vdddb(x + 1, length); return;
-	case 0x05: cta_colorimetry_block(x + 1, length); return;
-	case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
-	case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
-	case 0x0d: cta_vfpdb(x + 1, length); return;
-	case 0x0e: cta_svd(x + 1, length, true); return;
-	case 0x0f: cta_y420cmdb(x + 1, length); return;
-	case 0x11:
-		if (length < 3) {
-			data_block = std::string("Vendor-Specific Audio Data Block");
-			fail("Invalid length %u < 3.\n", length);
-			return;
-		}
-		oui = (x[3] << 16) + (x[2] << 8) + x[1];
-		name = oui_name(oui);
-		if (!name) {
-			name = oui_name(oui, true);
-			if (name)
-				reverse = true;
-		}
-		if (!name) {
-			printf("  Vendor-Specific Audio Data Block, OUI %s:\n",
-			       ouitohex(oui).c_str());
-			hex_block("    ", x + 4, length - 3);
-			data_block.clear();
-			warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
-			     ouitohex(oui).c_str());
-			return;
-		}
-		data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
-		if (reverse)
-			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
-		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
-		if (oui == 0x00d046)
-			cta_dolby_audio(x + 4, length - 3);
+		fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
+
+	tag |= ouinum;
+	switch (tag) {
+	case 0x001: cta_audio_block(x, length); break;
+	case 0x002: cta_svd(x, length, false); break;
+	case 0x003|kOUI_HDMI:
+		cta_hdmi_block(x, length);
+		// The HDMI OUI is present, so this EDID represents an HDMI
+		// interface. And HDMI interfaces must use EDID version 1.3
+		// according to the HDMI Specification, so check for this.
+		if (base.edid_minor != 3)
+			fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
+				 base.edid_minor);
+		break;
+	case 0x003|kOUI_HDMIForum:
+		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
+			fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
+		if (cta.have_hf_scdb || cta.have_hf_vsdb)
+			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
+		cta_hf_scdb(x, length);
+		cta.have_hf_vsdb = true;
+		break;
+	case 0x003|kOUI_AMD: cta_amd(x, length); break;
+	case 0x003|kOUI_Microsoft:
+		if (length == 0x12)
+			cta_microsoft(x, length);
 		else
-			hex_block("    ", x + 4, length - 3);
-		return;
-	case 0x12: cta_hdmi_audio_block(x + 1, length); return;
-	case 0x13: cta_rcdb(x + 1, length); return;
-	case 0x14: cta_sldb(x + 1, length); return;
-	case 0x20: cta_ifdb(x + 1, length); return;
-	case 0x34: cta_displayid_type_7(x + 1, length); return;
-	case 0x35: cta_displayid_type_8(x + 1, length); return;
-	case 0x42: cta_displayid_type_10(x + 1, length); return;
-	case 0x78:
-		cta_hf_eeodb(x + 1, length);
+			goto dohex;
+		break;
+	case 0x004: cta_sadb(x, length); break;
+	case 0x005: cta_vesa_dtcdb(x, length); break;
+	case 0x700: cta_vcdb(x, length); break;
+	case 0x701|kOUI_HDR10: cta_hdr10plus(x, length); break;
+	case 0x701|kOUI_Dolby: cta_dolby_video(x, length); break;
+	case 0x702: cta_vesa_vdddb(x, length); break;
+	case 0x705: cta_colorimetry_block(x, length); break;
+	case 0x706: cta_hdr_static_metadata_block(x, length); break;
+	case 0x707: cta_hdr_dyn_metadata_block(x, length); break;
+	case 0x70d: cta_vfpdb(x, length); break;
+	case 0x70e: cta_svd(x, length, true); break;
+	case 0x70f: cta_y420cmdb(x, length); break;
+	case 0x711|kOUI_Dolby: cta_dolby_audio(x, length); break;
+	case 0x712: cta_hdmi_audio_block(x, length); break;
+	case 0x713: cta_rcdb(x, length); break;
+	case 0x714: cta_sldb(x, length); break;
+	case 0x720: cta_ifdb(x, length); break;
+	case 0x734: cta_displayid_type_7(x, length); break;
+	case 0x735: cta_displayid_type_8(x, length); break;
+	case 0x742: cta_displayid_type_10(x, length); break;
+	case 0x778:
+		cta_hf_eeodb(x, length);
 		// This must be the first CTA-861 block
-		if (!cta.first_block)
+		if (cta.block_number > 0)
 			fail("Block starts at a wrong offset.\n");
-		return;
-	case 0x79:
-		if (!cta.last_block_was_hdmi_vsdb)
+		break;
+	case 0x779:
+		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
 			fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
 		if (cta.have_hf_scdb || cta.have_hf_vsdb)
 			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
 		if (length < 2) {
 			data_block = std::string("HDMI Forum SCDB");
 			fail("Invalid length %u < 2.\n", length);
-			return;
-		}
-		if (x[1] || x[2])
-			printf("  Non-zero SCDB reserved fields!\n");
-		cta_hf_scdb(x + 3, length - 2);
-		cta.have_hf_scdb = 1;
-		return;
-	}
-
-	hex_block("    ", x + 1, length);
-}
-
-void edid_state::cta_block(const unsigned char *x, bool duplicate)
-{
-	unsigned length = x[0] & 0x1f;
-	const char *name;
-	unsigned oui;
-	bool reverse = false;
-	bool audio_block = false;
-
-	switch ((x[0] & 0xe0) >> 5) {
-	case 0x01:
-		data_block = "Audio Data Block";
-		printf("  %s:\n", data_block.c_str());
-		cta_audio_block(x + 1, length);
-		audio_block = true;
-		break;
-	case 0x02:
-		data_block = "Video Data Block";
-		printf("  %s:\n", data_block.c_str());
-		cta_svd(x + 1, length, false);
-		break;
-	case 0x03:
-		oui = (x[3] << 16) + (x[2] << 8) + x[1];
-		name = oui_name(oui);
-		if (!name) {
-			name = oui_name(oui, true);
-			if (name)
-				reverse = true;
-		}
-		if (!name) {
-			printf("  Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
-			hex_block("    ", x + 4, length - 3);
-			data_block.clear();
-			warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
-			     ouitohex(oui).c_str());
-			return;
-		}
-		data_block = std::string("Vendor-Specific Data Block (") + name + ")";
-		if (reverse)
-			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
-		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
-		if (oui == 0x000c03) {
-			cta_hdmi_block(x + 1, length);
-			cta.last_block_was_hdmi_vsdb = 1;
-			cta.first_block = 0;
-			// The HDMI OUI is present, so this EDID represents an HDMI
-			// interface. And HDMI interfaces must use EDID version 1.3
-			// according to the HDMI Specification, so check for this.
-			if (base.edid_minor != 3)
-				fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
-				     base.edid_minor);
-			return;
-		}
-		if (oui == 0xc45dd8) {
-			if (!cta.last_block_was_hdmi_vsdb)
-				fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
-			if (cta.have_hf_scdb || cta.have_hf_vsdb)
-				fail("Duplicate HDMI Forum VSDB/SCDB.\n");
-			cta_hf_scdb(x + 4, length - 3);
-			cta.have_hf_vsdb = 1;
-			break;
-		}
-		if (oui == 0x00001a) {
-			cta_amd(x + 4, length - 3);
-			break;
-		}
-		if (oui == 0xca125c && length == 0x15) {
-			cta_microsoft(x + 4, length - 3);
 			break;
 		}
-		hex_block("    ", x + 4, length - 3);
-		break;
-	case 0x04:
-		data_block = "Speaker Allocation Data Block";
-		printf("  %s:\n", data_block.c_str());
-		cta_sadb(x + 1, length);
-		audio_block = true;
-		if (duplicate)
-			fail("Only one instance of this Data Block is allowed.\n");
-		break;
-	case 0x05:
-		data_block = "VESA Display Transfer Characteristics Data Block";
-		printf("  %s:\n", data_block.c_str());
-		cta_vesa_dtcdb(x + 1, length);
-		if (duplicate)
-			fail("Only one instance of this Data Block is allowed.\n");
-		break;
-	case 0x07:
-		cta_ext_block(x + 1, length - 1, duplicate);
-		break;
-	default: {
-		unsigned tag = (*x & 0xe0) >> 5;
-		unsigned length = *x & 0x1f;
-
-		printf("  Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
-		hex_block("    ", x + 1, length);
-		data_block.clear();
-		warn("Unknown CTA-861 Data Block %u.\n", tag);
+		if (x[0] || x[1])
+			printf("  Non-zero SCDB reserved fields!\n");
+		cta_hf_scdb(x + 2, length - 2);
+		cta.have_hf_scdb = true;
 		break;
+dohex:
+	default:
+		hex_block("    ", x, length);
+		warn("Unknown block type: %s.\n", data_block.c_str());
 	}
-	}
-
-	// See Table 52 of CTA-861-G for a description of Byte 3
-	if (audio_block && !(cta.byte3 & 0x40))
-		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
-	cta.first_block = 0;
-	cta.last_block_was_hdmi_vsdb = 0;
+	cta.block_number++;
+	cta.previous_cta_tag = tag;
 }
 
 void edid_state::preparse_cta_block(const unsigned char *x)
@@ -2392,11 +2268,11 @@ void edid_state::parse_cta_block(const unsigned char *x)
 //				msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
 //				    cta.has_hdmi ? "shall" : "should");
 			printf("  Native detailed modes: %u\n", x[3] & 0x0f);
-			if (cta.first_block)
+			if (cta.block_number == 0)
 				cta.byte3 = x[3];
 			else if (x[3] != cta.byte3)
 				fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
-			if (cta.first_block) {
+			if (cta.block_number == 0) {
 				unsigned native_dtds = x[3] & 0x0f;
 
 				cta.native_timings.clear();
diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
index 5c81294..ff7a6db 100644
--- a/parse-displayid-block.cpp
+++ b/parse-displayid-block.cpp
@@ -1609,13 +1609,230 @@ void edid_state::preparse_displayid_block(const unsigned char *x)
 	}
 }
 
+#define data_block_o(n, a, b) data_block_oui(n, x + 3, len, tag == 0, &ouinum, a, b)
+
+unsigned edid_state::displayid_block(const unsigned version, const unsigned char *x, unsigned length)
+{
+	unsigned i;
+	unsigned tag = x[0];
+	unsigned ouinum = 0;
+	unsigned len = (length < 3) ? 0 : x[2];
+
+	switch (tag) {
+	// DisplayID 1.3:
+	case 0x00: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", true, false); ouinum = 0; break;
+	case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
+	case 0x02: data_block = "Color Characteristics Data Block"; break;
+	case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
+	case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
+	case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
+	case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
+	case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
+	case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
+	case 0x09: data_block = "Video Timing Range Data Block"; break;
+	case 0x0a: data_block = "Product Serial Number Data Block"; break;
+	case 0x0b: data_block = "GP ASCII String Data Block"; break;
+	case 0x0c: data_block = "Display Device Data Data Block"; break;
+	case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
+	case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
+	case 0x0f: data_block = "Display Interface Data Block"; break;
+	case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
+	case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
+	case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
+	case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
+	// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
+	// DisplayID 2.0
+	case 0x20: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", false, false); ouinum = 0; break;
+	case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
+	case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
+	case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
+	case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
+	case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
+	case 0x26: data_block = "Display Interface Features Data Block"; break;
+	case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
+	case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
+	case 0x29: data_block = "ContainerID Data Block"; break;
+	case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
+	// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
+	case 0x7e: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", false, true); break; // DisplayID 2.0
+	case 0x7f: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", true, false); break; // DisplayID 1.3
+	// 0x80 RESERVED
+	case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
+	// 0x82 .. 0xff RESERVED
+	default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
+	}
+
+	if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
+		fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
+			 version >> 4, version & 0xf);
+	if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
+		fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
+			 version >> 4, version & 0xf);
+
+	if (length < 3) {
+		// report a problem when the remaining bytes are not 0.
+		if (tag || (length > 1 && x[1])) {
+			fail("Not enough bytes remain (%d) for a DisplayID data block and the DisplayID filler is non-0.\n", length);
+		}
+		return length;
+	}
+
+	unsigned block_rev = x[1] & 0x07;
+
+	if (length < len + 3) {
+		fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d)\n", len + 3, length);
+		return length;
+	}
+
+	if (!tag && !len) {
+		// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
+		if (!memchk(x, length)) {
+			fail("Non-0 filler bytes in the DisplayID block.\n");
+		}
+		return length;
+	}
+
+	printf("  %s:\n", data_block.c_str());
+
+	tag |= ouinum;
+	switch (tag) {
+	case 0x00: parse_displayid_product_id(x); break;
+	case 0x01: parse_displayid_parameters(x); break;
+	case 0x02: parse_displayid_color_characteristics(x); break;
+	case 0x03:
+		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
+		   for (i = 0; i < len / 20; i++)
+			   parse_displayid_type_1_7_timing(&x[3 + (i * 20)], false, block_rev);
+		   break;
+	case 0x04:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < len / 11; i++)
+			   parse_displayid_type_2_timing(&x[3 + (i * 11)]);
+		   break;
+	case 0x05:
+		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
+		   for (i = 0; i < len / 3; i++)
+			   parse_displayid_type_3_timing(&x[3 + (i * 3)]);
+		   break;
+	case 0x06:
+		   check_displayid_datablock_revision(x[1], 0xc0, 1);
+		   for (i = 0; i < len; i++)
+			   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6, x[3 + i]);
+		   break;
+	case 0x07:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < min(len, 10) * 8; i++)
+			   if (x[3 + i / 8] & (1 << (i % 8))) {
+				   char type[16];
+				   sprintf(type, "DMT 0x%02x", i + 1);
+				   print_timings("    ", find_dmt_id(i + 1), type);
+			   }
+		   break;
+	case 0x08:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < min(len, 8) * 8; i++)
+			   if (x[3 + i / 8] & (1 << (i % 8))) {
+				   char type[16];
+				   sprintf(type, "VIC %3u", i + 1);
+				   print_timings("    ", find_vic_id(i + 1), type);
+			   }
+		   break;
+	case 0x09: parse_displayid_video_timing_range_limits(x); break;
+	case 0x0a:
+	case 0x0b: parse_displayid_string(x); break;
+	case 0x0c: parse_displayid_display_device(x); break;
+	case 0x0d: parse_displayid_intf_power_sequencing(x); break;
+	case 0x0e: parse_displayid_transfer_characteristics(x); break;
+	case 0x0f: parse_displayid_display_intf(x); break;
+	case 0x10: parse_displayid_stereo_display_intf(x); break;
+	case 0x11:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < len / 7; i++)
+			   parse_displayid_type_5_timing(&x[3 + (i * 7)]);
+		   break;
+	case 0x12: parse_displayid_tiled_display_topology(x, false); break;
+	case 0x13:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < len; i += (x[3 + i + 2] & 0x40) ? 17 : 14)
+			   parse_displayid_type_6_timing(&x[3 + i]);
+		   break;
+	case 0x20: parse_displayid_product_id(x); break;
+	case 0x21:
+		   if (block_rev >= 1)
+			   check_displayid_datablock_revision(x[1], 0x80, 1);
+		   else
+			   check_displayid_datablock_revision(x[1], 0x80, 0);
+		   parse_displayid_parameters_v2(x, block_rev);
+		   break;
+	case 0x22: {
+		   unsigned sz = 20;
+
+		   if (block_rev >= 2)
+			   check_displayid_datablock_revision(x[1], 0x08, 2);
+		   else if (block_rev == 1)
+			   check_displayid_datablock_revision(x[1], 0x08, 1);
+		   else
+			   check_displayid_datablock_revision(x[1]);
+		   sz += (x[1] & 0x70) >> 4;
+		   if (block_rev >= 1 && (x[1] & 0x08))
+			   printf("    These timings support DSC pass-through\n");
+		   for (i = 0; i < len / sz; i++)
+			   parse_displayid_type_1_7_timing(&x[3 + i * sz], true, block_rev);
+		   break;
+	}
+	case 0x23:
+		   if (block_rev)
+			   check_displayid_datablock_revision(x[1], 0xe8, 1);
+		   else
+			   check_displayid_datablock_revision(x[1], 0xc8);
+		   if (x[1] & 0x08) {
+			   for (i = 0; i < len / 2; i++)
+				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
+								   x[3 + i * 2] |
+								   (x[4 + i * 2] << 8));
+		   } else {
+			   for (i = 0; i < len; i++)
+				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
+								   x[3 + i]);
+		   }
+		   break;
+	case 0x24:
+		   check_displayid_datablock_revision(x[1]);
+		   for (i = 0; i < len / 6; i++)
+			   parse_displayid_type_9_timing(&x[3 + i * 6]);
+		   break;
+	case 0x25: parse_displayid_dynamic_video_timings_range_limits(x); break;
+	case 0x26: parse_displayid_interface_features(x); break;
+	case 0x27: parse_displayid_stereo_display_intf(x); break;
+	case 0x28: parse_displayid_tiled_display_topology(x, true); break;
+	case 0x29: parse_displayid_ContainerID(x); break;
+	case 0x32: {
+		   unsigned sz = 6 + ((x[1] & 0x70) >> 4);
+
+		   check_displayid_datablock_revision(x[1], 0x70);
+		   for (i = 0; i < len / sz; i++)
+			   parse_displayid_type_10_timing(&x[3 + i * sz], sz);
+		   break;
+	}
+	case 0x81: parse_displayid_cta_data_block(x); break;
+	case 0x7e|kOUI_VESA: parse_displayid_vesa(x); break;
+	default: hex_block("    ", x + 3 + (ouinum ? 3 : 0), len - (ouinum ? 3 : 0)); break;
+	}
+
+	if ((tag == 0x00 || tag == 0x20) &&
+		(!dispid.is_base_block || dispid.block_number > 0))
+		fail("%s is required to be the first DisplayID Data Block.\n",
+			 data_block.c_str());
+	dispid.block_number++;
+	return len + 3;
+}
+
 void edid_state::parse_displayid_block(const unsigned char *x)
 {
 	unsigned version = x[1];
 	unsigned length = x[2];
 	unsigned prod_type = x[3]; // future check: based on type, check for required data blocks
 	unsigned ext_count = x[4];
-	unsigned i;
 
 	printf("  Version: %u.%u\n  Extension Count: %u\n",
 	       version >> 4, version & 0xf, ext_count);
@@ -1647,246 +1864,10 @@ void edid_state::parse_displayid_block(const unsigned char *x)
 		length = 121;
 	}
 
-	unsigned offset = 5;
-	bool first_data_block = true;
-	while (length > 0) {
-		unsigned tag = x[offset];
-		unsigned oui = 0;
-
-		switch (tag) {
-		// DisplayID 1.3:
-		case 0x00: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
-		case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
-		case 0x02: data_block = "Color Characteristics Data Block"; break;
-		case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
-		case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
-		case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
-		case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
-		case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
-		case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
-		case 0x09: data_block = "Video Timing Range Data Block"; break;
-		case 0x0a: data_block = "Product Serial Number Data Block"; break;
-		case 0x0b: data_block = "GP ASCII String Data Block"; break;
-		case 0x0c: data_block = "Display Device Data Data Block"; break;
-		case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
-		case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
-		case 0x0f: data_block = "Display Interface Data Block"; break;
-		case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
-		case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
-		case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
-		case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
-		// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
-		// DisplayID 2.0
-		case 0x20: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
-		case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
-		case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
-		case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
-		case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
-		case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
-		case 0x26: data_block = "Display Interface Features Data Block"; break;
-		case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
-		case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
-		case 0x29: data_block = "ContainerID Data Block"; break;
-		case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
-		// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
-		case 0x7e: // DisplayID 2.0
-		case 0x7f: // DisplayID 1.3
-			if ((tag == 0x7e && version >= 0x20) ||
-			    (tag == 0x7f && version < 0x20)) {
-				oui = (x[offset + 3] << 16) + (x[offset + 4] << 8) + x[offset + 5];
-				const char *name = oui_name(oui);
-				bool reversed = false;
-
-				if (!name) {
-					name = oui_name(oui, true);
-					if (name)
-						reversed = true;
-				}
-				if (name)
-					data_block = std::string("Vendor-Specific Data Block (") + name + ")";
-				else
-					data_block = "Vendor-Specific Data Block, OUI " + ouitohex(oui);
-				if (reversed)
-					fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order.\n").c_str());
-			} else {
-				data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")";
-			}
-			break;
-		// 0x80 RESERVED
-		case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
-		// 0x82 .. 0xff RESERVED
-		default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
-		}
-
-		if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
-			fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
-			     version >> 4, version & 0xf);
-		if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
-			fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
-			     version >> 4, version & 0xf);
-
-		if (length < 3) {
-			// report a problem when the remaining bytes are not 0.
-			if (tag || x[offset + 1]) {
-				fail("Not enough bytes remain (%d) for a DisplayID data block or the DisplayID filler is non-0.\n", length);
-			}
-			break;
-		}
-
-		unsigned block_rev = x[offset + 1] & 0x07;
-		unsigned len = x[offset + 2];
-
-		if (length < len + 3) {
-			fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d).\n", len + 3, length);
-			break;
-		}
-
-		if (!tag && !len) {
-			// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
-			if (!memchk(x + offset, length)) {
-				fail("Non-0 filler bytes in the DisplayID block.\n");
-			}
-			break;
-		}
-
-		printf("  %s:\n", data_block.c_str());
-
-		switch (tag) {
-		case 0x00: parse_displayid_product_id(x + offset); break;
-		case 0x01: parse_displayid_parameters(x + offset); break;
-		case 0x02: parse_displayid_color_characteristics(x + offset); break;
-		case 0x03:
-			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
-			   for (i = 0; i < len / 20; i++)
-				   parse_displayid_type_1_7_timing(&x[offset + 3 + (i * 20)], false, block_rev);
-			   break;
-		case 0x04:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < len / 11; i++)
-				   parse_displayid_type_2_timing(&x[offset + 3 + (i * 11)]);
-			   break;
-		case 0x05:
-			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
-			   for (i = 0; i < len / 3; i++)
-				   parse_displayid_type_3_timing(&x[offset + 3 + (i * 3)]);
-			   break;
-		case 0x06:
-			   check_displayid_datablock_revision(x[offset + 1], 0xc0, 1);
-			   for (i = 0; i < len; i++)
-				   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6, x[offset + 3 + i]);
-			   break;
-		case 0x07:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < min(len, 10) * 8; i++)
-				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
-					   char type[16];
-					   sprintf(type, "DMT 0x%02x", i + 1);
-					   print_timings("    ", find_dmt_id(i + 1), type);
-				   }
-			   break;
-		case 0x08:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < min(len, 8) * 8; i++)
-				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
-					   char type[16];
-					   sprintf(type, "VIC %3u", i + 1);
-					   print_timings("    ", find_vic_id(i + 1), type);
-				   }
-			   break;
-		case 0x09: parse_displayid_video_timing_range_limits(x + offset); break;
-		case 0x0a:
-		case 0x0b: parse_displayid_string(x + offset); break;
-		case 0x0c: parse_displayid_display_device(x + offset); break;
-		case 0x0d: parse_displayid_intf_power_sequencing(x + offset); break;
-		case 0x0e: parse_displayid_transfer_characteristics(x + offset); break;
-		case 0x0f: parse_displayid_display_intf(x + offset); break;
-		case 0x10: parse_displayid_stereo_display_intf(x + offset); break;
-		case 0x11:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < len / 7; i++)
-				   parse_displayid_type_5_timing(&x[offset + 3 + (i * 7)]);
-			   break;
-		case 0x12: parse_displayid_tiled_display_topology(x + offset, false); break;
-		case 0x13:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < len; i += (x[offset + 3 + i + 2] & 0x40) ? 17 : 14)
-				   parse_displayid_type_6_timing(&x[offset + 3 + i]);
-			   break;
-		case 0x20: parse_displayid_product_id(x + offset); break;
-		case 0x21:
-			   if (block_rev >= 1)
-				   check_displayid_datablock_revision(x[offset + 1], 0x80, 1);
-			   else
-				   check_displayid_datablock_revision(x[offset + 1], 0x80, 0);
-			   parse_displayid_parameters_v2(x + offset, block_rev);
-			   break;
-		case 0x22: {
-			   unsigned sz = 20;
-
-			   if (block_rev >= 2)
-				   check_displayid_datablock_revision(x[offset + 1], 0x08, 2);
-			   else if (block_rev == 1)
-				   check_displayid_datablock_revision(x[offset + 1], 0x08, 1);
-			   else
-				   check_displayid_datablock_revision(x[offset + 1]);
-			   sz += (x[offset + 1] & 0x70) >> 4;
-			   if (block_rev >= 1 && (x[offset + 1] & 0x08))
-				   printf("    These timings support DSC pass-through\n");
-			   for (i = 0; i < len / sz; i++)
-				   parse_displayid_type_1_7_timing(&x[offset + 3 + i * sz], true, block_rev);
-			   break;
-		}
-		case 0x23:
-			   if (block_rev)
-				   check_displayid_datablock_revision(x[offset + 1], 0xe8, 1);
-			   else
-				   check_displayid_datablock_revision(x[offset + 1], 0xc8);
-			   if (x[offset + 1] & 0x08) {
-				   for (i = 0; i < len / 2; i++)
-					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
-									   x[offset + 3 + i * 2] |
-									   (x[offset + 4 + i * 2] << 8));
-			   } else {
-				   for (i = 0; i < len; i++)
-					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
-									   x[offset + 3 + i]);
-			   }
-			   break;
-		case 0x24:
-			   check_displayid_datablock_revision(x[offset + 1]);
-			   for (i = 0; i < len / 6; i++)
-				   parse_displayid_type_9_timing(&x[offset + 3 + i * 6]);
-			   break;
-		case 0x25: parse_displayid_dynamic_video_timings_range_limits(x + offset); break;
-		case 0x26: parse_displayid_interface_features(x + offset); break;
-		case 0x27: parse_displayid_stereo_display_intf(x + offset); break;
-		case 0x28: parse_displayid_tiled_display_topology(x + offset, true); break;
-		case 0x29: parse_displayid_ContainerID(x + offset); break;
-		case 0x32: {
-			   unsigned sz = 6 + ((x[offset + 1] & 0x70) >> 4);
-
-			   check_displayid_datablock_revision(x[offset + 1], 0x70);
-			   for (i = 0; i < len / sz; i++)
-				   parse_displayid_type_10_timing(&x[offset + 3 + i * sz], sz);
-			   break;
-		}
-		case 0x81: parse_displayid_cta_data_block(x + offset); break;
-		case 0x7e:
-			if (oui == 0x3a0292) {
-				parse_displayid_vesa(x + offset);
-				break;
-			}
-			// fall-through
-		default: hex_block("    ", x + offset + 3, len); break;
-		}
-
-		if ((tag == 0x00 || tag == 0x20) &&
-		    (!dispid.is_base_block || !first_data_block))
-			fail("%s is required to be the first DisplayID Data Block.\n",
-			     data_block.c_str());
-		length -= len + 3;
-		offset += len + 3;
-		first_data_block = false;
+	unsigned len;
+	for (const unsigned char *y = x + 5; length > 0; y += len) {
+		len = displayid_block(version, y, length);
+		length -= len;
 	}
 
 	/*
-- 
2.24.3 (Apple Git-128)


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

* Re: [PATCH 03/11] edid-decode: change install directories for macOS
  2021-09-14 12:11 ` [PATCH 03/11] edid-decode: change install directories for macOS joevt
@ 2021-09-15 10:06   ` Hans Verkuil
  2021-09-15 15:25     ` Joe van Tunen
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 10:06 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 14/09/2021 14:11, joevt wrote:
> In macOS, /usr/bin and /usr/share/man belong to root:wheel so install to /usr/local/bin and /usr/local/share/man instead.
> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  Makefile | 22 +++++++++++++++++-----
>  1 file changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 287b72d..adf6123 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,11 +1,23 @@
> -bindir ?= /usr/bin
> -mandir ?= /usr/share/man
> +ifeq ($(OS),Windows_NT)
> +	bindir ?= /usr/bin
> +	mandir ?= /usr/share/man
> +else
> +	UNAME_S := $(shell uname -s)
> +	ifeq ($(UNAME_S),Darwin)
> +		bindir ?= /usr/local/sbin
> +		mandir ?= /usr/local/share/man
> +	else
> +		bindir ?= /usr/bin
> +		mandir ?= /usr/share/man
> +	endif
> +endif
>  
>  EMXX ?= em++
>  
> -SOURCES = edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
> -	  parse-displayid-block.cpp parse-ls-ext-block.cpp \
> -	  parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp
> +SOURCES = \
> +	edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
> +	parse-displayid-block.cpp parse-ls-ext-block.cpp \
> +	parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp

This last change is a spurious change, I'll drop this and keep the rest.

No need for you to do anything.

Regards,

	Hans

>  WARN_FLAGS = -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter
>  
>  all: edid-decode
> 


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

* Re: [PATCH 04/11] edid-decode: add bounds checking
  2021-09-14 12:11 ` [PATCH 04/11] edid-decode: add bounds checking joevt
@ 2021-09-15 10:07   ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 10:07 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 14/09/2021 14:11, joevt wrote:

Please always add a commit log here, even if it is just a copy of the subject.

No need to do anything, I'll take care of it this time.

Regards,

	Hans

> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  parse-vtb-ext-block.cpp | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/parse-vtb-ext-block.cpp b/parse-vtb-ext-block.cpp
> index 05d54f4..edfe887 100644
> --- a/parse-vtb-ext-block.cpp
> +++ b/parse-vtb-ext-block.cpp
> @@ -17,16 +17,21 @@ void edid_state::parse_vtb_ext_block(const unsigned char *x)
>  	unsigned num_cvt = x[3];
>  	unsigned num_st = x[4];
>  
> +	const unsigned char *y = x + 0x7f;
>  	x += 5;
>  	if (num_dtd) {
>  		printf("  Detailed Timing Descriptors:\n");
> -		for (unsigned i = 0; i < num_dtd; i++, x += 18)
> +		for (unsigned i = 0; i < num_dtd; i++, x += 18) {
> +			if (x + 18 > y) { fail("Not enough bytes remain for more DTBs in the VTB-EXT\n"); return; }
>  			detailed_timings("    ", x, false);
> +		}
>  	}
>  	if (num_cvt) {
>  		printf("  Coordinated Video Timings:\n");
> -		for (unsigned i = 0; i < num_cvt; i++, x += 3)
> +		for (unsigned i = 0; i < num_cvt; i++, x += 3) {
> +			if (x + 3 > y) { fail("Not enough bytes remain for more CVTs in the VTB-EXT\n"); return; }
>  			detailed_cvt_descriptor("    ", x, false);
> +		}
>  	}
>  	if (num_st) {
>  		// Note: the VTB-EXT standard has a mistake in the example EDID
> @@ -36,7 +41,9 @@ void edid_state::parse_vtb_ext_block(const unsigned char *x)
>  		//
>  		// The documentation itself is correct, though.
>  		printf("  Standard Timings:\n");
> -		for (unsigned i = 0; i < num_st; i++, x += 2)
> +		for (unsigned i = 0; i < num_st; i++, x += 2) {
> +			if (x + 2 > y) { fail("Not enough bytes remain for more STs in the VTB-EXT\n"); return; }
>  			print_standard_timing("    ", x[0], x[1], true);
> +		}
>  	}
>  }
> 


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

* Re: [PATCH 05/11] edid-decode: fix standard timing vertical pixels
  2021-09-14 12:11 ` [PATCH 05/11] edid-decode: fix standard timing vertical pixels joevt
@ 2021-09-15 10:08   ` Hans Verkuil
  2021-09-15 11:10     ` Hans Verkuil
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 10:08 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 14/09/2021 14:11, joevt wrote:
> Don't do ceiling to nearest 8 pixels for active vertical lines. See examples elo-4600l-hdmi and kogan-kaled24144f-hdmi.
> 
> Section 3.9 and 3.10.3.6 of EDID 1.4 does not say vertical lines must be a multiple of 8.  This line of code appears to have been added to satisfy the 3rd example in VTB-EXT spec but that example has an incorrect HAP indicator decimal value so it cannot be trusted. Also, all 3 examples have an incorrect vertical refresh value as noted in parse-vtb-ext-block.cpp. The VESA DMT spec has the following examples that are not a multiple of 8 lines which support this change:
> 1400x1050 4:3
> 1440x900 16:10
> 1600x900 16:9
> 1680x1050 16:10
> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  parse-base-block.cpp | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/parse-base-block.cpp b/parse-base-block.cpp
> index e2901a6..32d2079 100644
> --- a/parse-base-block.cpp
> +++ b/parse-base-block.cpp
> @@ -573,7 +573,6 @@ void edid_state::print_standard_timing(const char *prefix, unsigned char b1, uns
>  		break;
>  	}
>  	vact = (double)hact * vratio / hratio;
> -	vact = 8 * ((vact + 7) / 8);

I need to look closer at this. I think it was added to help with 1360x768, which without
this line maps to 1360x765.

I'll get back to you on this.

Regards,

	Hans

>  	refresh = (b2 & 0x3f) + 60;
>  
>  	formula.hact = hact;
> 


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

* Re: [PATCH 07/11] edid-decode: always linefeed after hex_block
  2021-09-14 12:11 ` [PATCH 07/11] edid-decode: always linefeed after hex_block joevt
@ 2021-09-15 10:10   ` Hans Verkuil
  2021-09-15 15:43     ` Joe van Tunen
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 10:10 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 14/09/2021 14:11, joevt wrote:
> hex_block should not return without printing a newline (which occurs when the length is zero). This causes a missing newline after "Application Version: 1" with cta_hdr10plus for an EDID I have.
> Any place that calls hex_block will have the same problem if it's possible for the length to be zero.
> 
> In other words, a hex_block needs to have a linefeed even if it has zero length, because the caller assumes it will go to the next line as it does when the hex block is not zero length.
> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  edid-decode.cpp | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/edid-decode.cpp b/edid-decode.cpp
> index 2316abc..6aa93fb 100644
> --- a/edid-decode.cpp
> +++ b/edid-decode.cpp
> @@ -698,8 +698,10 @@ void hex_block(const char *prefix, const unsigned char *x,
>  {
>  	unsigned i, j;
>  
> -	if (!length)
> +	if (!length) {
> +		printf("\n");
>  		return;
> +	}

Hmm, with this change I get this:

edid-decode -c Digital/Acer/ACR0282/B12D637C1F12 with the linuxhw database:

  Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
    Source physical address: 2.0.0.0
  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

  Unknown CTA-861 tag 0x00, length 0

That looks pretty ugly.

Regards,

	Hans

>  
>  	for (i = 0; i < length; i += step) {
>  		unsigned len = min(step, length - i);
> 


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

* Re: [PATCH 05/11] edid-decode: fix standard timing vertical pixels
  2021-09-15 10:08   ` Hans Verkuil
@ 2021-09-15 11:10     ` Hans Verkuil
  2021-09-15 18:28       ` Joe van Tunen
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 11:10 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 15/09/2021 12:08, Hans Verkuil wrote:
> On 14/09/2021 14:11, joevt wrote:
>> Don't do ceiling to nearest 8 pixels for active vertical lines. See examples elo-4600l-hdmi and kogan-kaled24144f-hdmi.
>>
>> Section 3.9 and 3.10.3.6 of EDID 1.4 does not say vertical lines must be a multiple of 8.  This line of code appears to have been added to satisfy the 3rd example in VTB-EXT spec but that example has an incorrect HAP indicator decimal value so it cannot be trusted. Also, all 3 examples have an incorrect vertical refresh value as noted in parse-vtb-ext-block.cpp. The VESA DMT spec has the following examples that are not a multiple of 8 lines which support this change:
>> 1400x1050 4:3
>> 1440x900 16:10
>> 1600x900 16:9
>> 1680x1050 16:10
>>
>> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
>> ---
>>  parse-base-block.cpp | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/parse-base-block.cpp b/parse-base-block.cpp
>> index e2901a6..32d2079 100644
>> --- a/parse-base-block.cpp
>> +++ b/parse-base-block.cpp
>> @@ -573,7 +573,6 @@ void edid_state::print_standard_timing(const char *prefix, unsigned char b1, uns
>>  		break;
>>  	}
>>  	vact = (double)hact * vratio / hratio;
>> -	vact = 8 * ((vact + 7) / 8);
> 
> I need to look closer at this. I think it was added to help with 1360x768, which without
> this line maps to 1360x765.
> 
> I'll get back to you on this.

I did some more reading on this, and appendix D of the EDID 1.4 spec
says this (D-8):

"If calculated aspect ratio is not 16 : 10 AR, 4 : 3 AR, 5 : 4 AR or 16 : 9 AR
 what timing description should be used?"

"Ref.: Section 3.9 (E-EDID Standard Release A, Revision 2)
 The Standard Timings Identification code may not be used to
 identify timings which do not match one of these standard aspect
 ratios. Support for such timings must be indicated elsewhere,
 e.g., by use of a Detailed Timing Descriptor."

So you are correct with your change, but I think it would make
sense to add a new check:

// See also Ref. D-8 in the EDID-1.4 spec
if (vact & 1)
	warn("Standard Timing %ux%u has a dubious odd vertical resolution.\n", hact, vact);

So that way an attempt to use ST to describe 1360x768 will result in a warning.

Regards,

	Hans

> 
> Regards,
> 
> 	Hans
> 
>>  	refresh = (b2 & 0x3f) + 60;
>>  
>>  	formula.hact = hact;
>>
> 


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

* Re: [PATCH 11/11] edid-decode: cta and displayid changes
  2021-09-14 12:11 ` [PATCH 11/11] edid-decode: cta and displayid changes joevt
@ 2021-09-15 13:37   ` Hans Verkuil
  2021-09-16  9:15     ` Joe van Tunen
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2021-09-15 13:37 UTC (permalink / raw)
  To: joevt; +Cc: linux-media

On 14/09/2021 14:11, joevt wrote:
> Goal: make OUI blocks equal to normal blocks to simplify decoding and make handling of all types of blocks consistent. This will reduce duplicated code (only one place for checking duplicate blocks, only one place for handling unknown blocks, etc.)
> 
> oui.h
> - This contains a list of OUI and CID and PNP values.
> - It is included in various places with varying definitions of the oneoui macro.
> 
> edid-decode.h
> - Add list of OUI constants using oui.h.
> - Other changes described below.
> 
> parse-cta-block.cpp
> - Modified oui_name. Returns a name and a number for a OUI.
> - Added data_block_oui. For data blocks with an OUI, does size check, OUI endianness check, and PNP vs OUI check. Returns a value representing the OUI (if it is known).
> - Modify cta_block. Reduce code by flattening the switch statement. This means constructing a case value from three values.
>   Side effects include making reporting of "Only one instance of this Data Block is allowed." more consistant (always report this fail after the block type is output instead of sometimes before and sometimes after). See example acer-xv273k-dp2-corrupted.
>   First, get the extended type and append it to the tag type (i.e. add 0x700 if extended), then get the OUI if it's vendor specific, and convert it to a number that can be appended (bitwise or) to the tag/extended type value.
> 	- Init static variables
> 	- Replace last_block_was_hdmi_vsdb with previous_cta_tag; this means instead of remembering if the last block was hdmi vsdb, we just remember the previous block's tag.
> 	- Replace first_block with cta_block_number; this means instead of remembering if this is the first block or not, we just remember the current block number.
> 	- Remove name and oui, we'll just get the data_block string and a oui index directly.
> 	- Report OUI for extended tag 11h (Vendor-Specific Audio Data Block)
> 	- Fix capitalization of "Audio information is present" fail message.
> 	- Add bounds check on length field (must be at least 1 for extended tags).
> 	- Don't parse after OUI if there's not enough length for OUI.
> 	- Adjust x offsets in cta_hdmi_block so it is like other OUI extended blocks such that x points to after the OUI.
> 	- A block that outputs only hex is reported as an unknown block type even if we know the OUI. See example acer-xb321hk-dp.
> 
> parse-disableid-block.cpp
> - Add displayid_block to do a single data block - like cta_block does for cta extension block
> 	- Vendor specific data block for DisplayID 1.3 is assumed to be PNP (string order). See example apple-macbookpro-16inch-2019.
> 	- Vendor specific data block for DisplayID 2.0 is assumed to have OUI (little endian).
> 	- Interpret Vendor specific data block 0x7e or 0x7f even if DisplayID is not correct for that type (there's already a FAIL message to identify the problem). See example apple-xdr-6k.
> 	- Add bounds check: if length is < 3, only check x[1] if length is 2.
> 	  Don't report "Not enough bytes remain (1) for a DisplayID data block or the DisplayID filler is non-0." if the bytes are zero (also change the word "or" to "and"). See example apple-xdr-6k-tile0.
> 	- Report datablock name before failing.
> 	- For unknown vendor specific data blocks, don't output the OUI part as hex since the new data_block_oui function has already reported it. See example apple-macbookpro-16inch-2019.
> 	- Replace first_data_block with disp.block_number

I've decided not to merge this patch. It does too many things at the same time,
so it really should be split up into smaller pieces.

I'm also getting ugly lines like this:

Unknown CTA-861 Data Block (tag 0x00): Unknown block type: Unknown CTA-861 Data Block (tag 0x00).

or this:

Vendor-Specific Data Block (NVIDIA), OUI 00-04-4B: Unknown block type: Vendor-Specific Data Block (NVIDIA),
OUI 00-04-4B.

(which shouldn't be a warning anyway)

> 
> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
> ---
>  edid-decode.cpp           |  99 ++++++--
>  edid-decode.h             |  20 +-
>  oui.h                     |  20 ++
>  parse-cta-block.cpp       | 456 ++++++++++++++-----------------------
>  parse-displayid-block.cpp | 463 ++++++++++++++++++--------------------
>  5 files changed, 505 insertions(+), 553 deletions(-)

While it does reduce the code size a bit, it really isn't by all that much,
so I am not convinced that all the churn is worth it.

If this is split up into first fixes and small improvements, and then rework
the tag handling, then I can take another look at whether it makes sense to
apply this.

I've applied patches 1, 2, 3, 4, 6, 8, 9 and 10. The others need more work.

Regards,

	Hans

>  create mode 100644 oui.h
> 
> diff --git a/edid-decode.cpp b/edid-decode.cpp
> index 0c83e0e..ed3223d 100644
> --- a/edid-decode.cpp
> +++ b/edid-decode.cpp
> @@ -657,25 +657,90 @@ std::string utohex(unsigned char x)
>  	return buf;
>  }
>  
> -const char *oui_name(unsigned oui, bool reverse)
> +const char *oui_name(unsigned oui, unsigned *ouinum)
>  {
> -	if (reverse)
> -		oui = (oui >> 16) | (oui & 0xff00) | ((oui & 0xff) << 16);
> -
> +	unsigned ouinumscratch;
> +	if (!ouinum) ouinum = &ouinumscratch;
> +	const char *name;
>  	switch (oui) {
> -	case 0x00001a: return "AMD";
> -	case 0x000c03: return "HDMI";
> -	case 0x00044b: return "NVIDIA";
> -	case 0x000c6e: return "ASUS";
> -	case 0x0010fa: return "Apple";
> -	case 0x0014b9: return "MSTAR";
> -	case 0x00d046: return "Dolby";
> -	case 0x00e047: return "InFocus";
> -	case 0x3a0292: return "VESA";
> -	case 0x90848b: return "HDR10+";
> -	case 0xc45dd8: return "HDMI Forum";
> -	case 0xca125c: return "Microsoft";
> -	default: return NULL;
> +		#define oneoui(c,k,n) case c: *ouinum = kOUI_##k; name = n; break;
> +		#include "oui.h"
> +		default: *ouinum = 0; name = NULL;
> +	}
> +	return name;
> +}
> +
> +void edid_state::data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii, bool big_endian)
> +{
> +	std::string buf;
> +	char ascii[4];
> +	unsigned oui;
> +	const char *ouiname = NULL;
> +	bool matched_reverse = false;
> +	bool matched_ascii = false;
> +	bool valid_ascii = false;
> +
> +	if (big_endian)
> +		oui = ((length > 0 ? x[0] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 2 ? x[2] : 0);
> +	else
> +		oui = ((length > 2 ? x[2] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 0 ? x[0] : 0);
> +
> +	buf = ouitohex(oui);
> +	if (length < 3) {
> +		sprintf(ascii, "?"); // some characters are null
> +		if (ouinum) *ouinum = 0; // doesn't match a known OUI
> +	} else {
> +		valid_ascii = (x[0] >= 'A' && x[1] >= 'A' && x[2] >= 'A' && x[0] <= 'Z' && x[1] <= 'Z' && x[2] <= 'Z');
> +		sprintf(ascii, "%c%c%c", x[0], x[1], x[2]);
> +
> +		ouiname = oui_name(oui, ouinum);
> +		if (!ouiname) {
> +			big_endian = !big_endian;
> +			unsigned reversedoui = ((oui & 0xff) << 16) + (oui & 0x00ff00) + (oui >> 16);
> +			ouiname = oui_name(reversedoui, ouinum);
> +			if (ouiname) {
> +				oui = reversedoui;
> +				buf = ouitohex(oui);
> +				matched_reverse = true;
> +			}
> +			else if (do_ascii && valid_ascii)
> +			{
> +				unsigned asciioui = (x[0] << 24) + (x[1] << 16) + (x[2] << 8);
> +				ouiname = oui_name(asciioui, ouinum);
> +				if (ouiname) {
> +					matched_ascii = true;
> +				}
> +			}
> +		}
> +	}
> +
> +	std::string name;
> +	if (ouiname) {
> +		if (matched_ascii)
> +			name = block_name + " (" + ouiname + ")" + ", PNP ID '" + ascii + "'";
> +		else
> +			name = block_name + " (" + ouiname + ")" + ", OUI " + buf;
> +	} else if (do_ascii && valid_ascii) {
> +		name = block_name + ", PNP ID '" + ascii + "'";
> +	} else {
> +		name = block_name + ", OUI " + buf;
> +	}
> +	// assign string to data_block before outputting errors
> +	data_block = name;
> +	
> +	if (oui || !ignorezeros) {
> +		if (length < 3)
> +			fail("Data block length is not enough to contain an OUI.\n");
> +		if (ouiname && do_ascii && !valid_ascii)
> +			warn("Expected PNP ID but found OUI.\n");
> +		if (ouiname && matched_reverse)
> +			warn("Endian-ness (%s) of OUI is different than expected (%s).\n", big_endian ? "be" : "le", big_endian ? "le" : "be");
> +		if (!ouiname) {
> +			if (valid_ascii)
> +				warn("Unknown OUI %s (possible PNP %s).\n", buf.c_str(), ascii);
> +			else
> +				warn("Unknown OUI %s.\n", buf.c_str());
> +		}
>  	}
>  }
>  
> diff --git a/edid-decode.h b/edid-decode.h
> index 612d22a..9e6a955 100644
> --- a/edid-decode.h
> +++ b/edid-decode.h
> @@ -153,8 +153,10 @@ struct edid_state {
>  		// CTA-861 block state
>  		cta.has_vic_1 = cta.first_svd_might_be_preferred = cta.has_sldb =
>  			cta.has_hdmi = cta.has_vcdb = cta.has_vfpdb = false;
> -		cta.last_block_was_hdmi_vsdb = cta.have_hf_vsdb = cta.have_hf_scdb = false;
> -		cta.first_block = cta.first_svd = true;
> +		cta.have_hf_vsdb = cta.have_hf_scdb = false;
> +		cta.previous_cta_tag = 0xfff;
> +		cta.block_number = 0;
> +		cta.first_svd = true;
>  		cta.supported_hdmi_vic_codes = cta.supported_hdmi_vic_vsb_codes = 0;
>  		memset(cta.vics, 0, sizeof(cta.vics));
>  		memset(cta.preparsed_has_vic, 0, sizeof(cta.preparsed_has_vic));
> @@ -175,6 +177,7 @@ struct edid_state {
>  		dispid.is_display = dispid.has_product_identification =
>  			dispid.has_display_parameters = dispid.has_type_1_7 =
>  			dispid.has_display_interface_features = false;
> +		dispid.block_number = 0;
>  
>  		// Block Map block state
>  		block_map.saw_block_1 = false;
> @@ -257,9 +260,9 @@ struct edid_state {
>  		bool preparsed_sld;
>  		bool has_sldb;
>  		unsigned short preparsed_phys_addr;
> -		bool last_block_was_hdmi_vsdb;
> +		unsigned previous_cta_tag;
>  		bool have_hf_vsdb, have_hf_scdb;
> -		bool first_block;
> +		unsigned block_number;
>  		bool first_svd;
>  		unsigned supported_hdmi_vic_codes;
>  		unsigned supported_hdmi_vic_vsb_codes;
> @@ -282,6 +285,7 @@ struct edid_state {
>  		bool has_display_interface_features;
>  		vec_timings_ext preferred_timings;
>  		unsigned native_width, native_height;
> +		unsigned block_number;
>  		// Keep track of the found CTA-861 Tag/Extended Tag pairs.
>  		// The unsigned value is equal to: (tag << 8) | ext_tag
>  		std::set<unsigned> found_tags;
> @@ -331,6 +335,8 @@ struct edid_state {
>  	void list_dmts();
>  	void list_established_timings();
>  
> +	void data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii = false, bool big_endian = false);
> +
>  	void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false);
>  	void hdmi_latency(unsigned char vid_lat, unsigned char aud_lat, bool is_ilaced);
>  	void cta_vcdb(const unsigned char *x, unsigned length);
> @@ -390,6 +396,7 @@ struct edid_state {
>  	void parse_displayid_type_10_timing(const unsigned char *x, unsigned sz,
>  					    bool is_cta = false);
>  	void preparse_displayid_block(const unsigned char *x);
> +	unsigned displayid_block(const unsigned version, const unsigned char *x, unsigned length);
>  	void parse_displayid_block(const unsigned char *x);
>  	void parse_displayid_vesa(const unsigned char *x);
>  	void parse_displayid_cta_data_block(const unsigned char *x);
> @@ -454,7 +461,7 @@ void hex_block(const char *prefix, const unsigned char *x, unsigned length,
>  	       bool show_ascii = true, unsigned step = 16);
>  std::string block_name(unsigned char block);
>  void calc_ratio(struct timings *t);
> -const char *oui_name(unsigned oui, bool reverse = false);
> +const char *oui_name(unsigned oui, unsigned *ouinum = NULL);
>  
>  bool timings_close_match(const timings &t1, const timings &t2);
>  const struct timings *find_dmt_id(unsigned char dmt_id);
> @@ -465,4 +472,7 @@ const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic);
>  unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic);
>  char *extract_string(const unsigned char *x, unsigned len);
>  
> +#define oneoui(c,k,n) const unsigned kOUI_##k = __LINE__<<12;
> +#include "oui.h"
> +
>  #endif
> diff --git a/oui.h b/oui.h
> new file mode 100644
> index 0000000..c90f025
> --- /dev/null
> +++ b/oui.h
> @@ -0,0 +1,20 @@
> +// http://standards-oui.ieee.org/oui/oui.txt
> +oneoui(0x000c03, HDMI,         "HDMI"        )
> +oneoui(0xc45dd8, HDMIForum,    "HDMI Forum"  )
> +oneoui(0x90848b, HDR10,        "HDR10+"      )
> +oneoui(0x00001a, AMD,          "AMD"         )
> +oneoui(0x00044b, NVIDIA,       "NVIDIA"      )
> +oneoui(0x000c6e, ASUS,         "ASUS"        )
> +oneoui(0x0010fa, Apple,        "Apple"       )
> +oneoui(0x0014b9, MSTAR,        "MSTAR"       )
> +oneoui(0x00d046, Dolby,        "Dolby"       )
> +oneoui(0x00e047, InFocus,      "InFocus"     )
> +oneoui(0xca125c, Microsoft,    "Microsoft"   )
> +
> +// http://standards-oui.ieee.org/cid/cid.txt
> +oneoui(0x3a0292, VESA,         "VESA"        )
> +
> +// https://uefi.org/pnp_id_list
> +oneoui('APP\0' , asciiApple,   "Apple"       )
> +
> +#undef oneoui
> diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
> index 4edaa1d..9bc0c77 100644
> --- a/parse-cta-block.cpp
> +++ b/parse-cta-block.cpp
> @@ -652,57 +652,57 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
>  {
>  	unsigned len_vic, len_3d;
>  
> -	if (length < 4) {
> -		fail("Empty Data Block with length %u.\n", length);
> +	if (length < 1) {
> +		fail("Empty Data Block.\n");
>  		return;
>  	}
> -	printf("    Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
> -	       x[4] >> 4, x[4] & 0x0f);
> +	printf("    Source physical address: %x.%x.%x.%x\n", x[0] >> 4, x[0] & 0x0f,
> +	       x[1] >> 4, x[1] & 0x0f);
>  
> -	if (length < 6)
> +	if (length < 3)
>  		return;
>  
> -	if (x[5] & 0x80)
> +	if (x[2] & 0x80)
>  		printf("    Supports_AI\n");
> -	if (x[5] & 0x40)
> +	if (x[2] & 0x40)
>  		printf("    DC_48bit\n");
> -	if (x[5] & 0x20)
> +	if (x[2] & 0x20)
>  		printf("    DC_36bit\n");
> -	if (x[5] & 0x10)
> +	if (x[2] & 0x10)
>  		printf("    DC_30bit\n");
> -	if (x[5] & 0x08)
> +	if (x[2] & 0x08)
>  		printf("    DC_Y444\n");
>  	/* two reserved bits */
> -	if (x[5] & 0x01)
> +	if (x[2] & 0x01)
>  		printf("    DVI_Dual\n");
>  
> -	if (length < 7)
> +	if (length < 4)
>  		return;
>  
> -	printf("    Maximum TMDS clock: %u MHz\n", x[6] * 5);
> -	if (x[6] * 5 > 340)
> +	printf("    Maximum TMDS clock: %u MHz\n", x[3] * 5);
> +	if (x[3] * 5 > 340)
>  		fail("HDMI VSDB Max TMDS rate is > 340.\n");
>  
> -	if (length < 8)
> +	if (length < 5)
>  		return;
>  
> -	if (x[7] & 0x0f) {
> +	if (x[4] & 0x0f) {
>  		printf("    Supported Content Types:\n");
> -		if (x[7] & 0x01)
> +		if (x[4] & 0x01)
>  			printf("      Graphics\n");
> -		if (x[7] & 0x02)
> +		if (x[4] & 0x02)
>  			printf("      Photo\n");
> -		if (x[7] & 0x04)
> +		if (x[4] & 0x04)
>  			printf("      Cinema\n");
> -		if (x[7] & 0x08)
> +		if (x[4] & 0x08)
>  			printf("      Game\n");
>  	}
>  
> -	unsigned b = 8;
> -	if (x[7] & 0x80) {
> +	unsigned b = 5;
> +	if (x[4] & 0x80) {
>  		hdmi_latency(x[b], x[b + 1], false);
>  
> -		if (x[7] & 0x40) {
> +		if (x[4] & 0x40) {
>  			if (x[b] == x[b + 2] &&
>  			    x[b + 1] == x[b + 3])
>  				warn("Progressive and Interlaced latency values are identical, no need for both.\n");
> @@ -712,7 +712,7 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
>  		b += 2;
>  	}
>  
> -	if (!(x[7] & 0x20))
> +	if (!(x[4] & 0x20))
>  		return;
>  
>  	bool mask = false;
> @@ -1990,293 +1990,169 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
>  	}
>  }
>  
> -void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
> -			       bool duplicate)
> +#define data_block_o(n) do { data_block_oui(n, x, length, false, &ouinum); if (length < 3) return; length -= 3; x += 3; } while(0)
> +
> +void edid_state::cta_block(const unsigned char *x, bool duplicate)
>  {
> -	const char *name;
> -	unsigned oui;
> -	bool reverse = false;
> +	unsigned length = x[0] & 0x1f; // number of bytes after the tag/length byte
> +	unsigned ouinum = 0;
> +	unsigned tag=(x[0] & 0xe0) >> 5;
> +	unsigned extended = (tag == 0x07) ? 1 : 0;
> +	x++;
> +	if (extended) {
> +		if (!length) {
> +			fail("Extended tag cannot have length 0.\n");
> +			return;
> +		}
> +		length--;
> +		tag = 0x700 + x[0];
> +		x++;
> +	}
> +
>  	bool audio_block = false;
>  
> -	switch (x[0]) {
> -	case 0x00: data_block = "Video Capability Data Block"; break;
> -	case 0x01: data_block.clear(); break;
> -	case 0x02: data_block = "VESA Video Display Device Data Block"; break;
> -	case 0x03: data_block = "VESA Video Timing Block Extension"; break;
> -	case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
> -	case 0x05: data_block = "Colorimetry Data Block"; break;
> -	case 0x06: data_block = "HDR Static Metadata Data Block"; break;
> -	case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
> -
> -	case 0x0d: data_block = "Video Format Preference Data Block"; break;
> -	case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
> -	case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
> -	case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
> -	case 0x11: data_block.clear(); audio_block = true; break;
> -	case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
> -	case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
> -	case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
> -
> -	case 0x20: data_block = "InfoFrame Data Block"; break;
> -
> -	case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
> -	case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
> -	case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
> -
> -	case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
> -	case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
> +	switch (tag) {
> +	case 0x001: data_block = "Audio Data Block"; audio_block = true; break;
> +	case 0x002: data_block = "Video Data Block"; break;
> +	case 0x003: data_block_o("Vendor-Specific Data Block"); break;
> +	case 0x004: data_block = "Speaker Allocation Data Block"; audio_block = true; break;
> +	case 0x005: data_block = "VESA Display Transfer Characteristics Data Block"; break;
> +
> +	case 0x700: data_block = "Video Capability Data Block"; break;
> +	case 0x701: data_block_o("Vendor-Specific Video Data Block"); break;
> +	case 0x702: data_block = "VESA Video Display Device Data Block"; break;
> +	case 0x703: data_block = "VESA Video Timing Block Extension"; break; // not implemented
> +	case 0x704: data_block = "Reserved for HDMI Video Data Block"; break; // reserved
> +	case 0x705: data_block = "Colorimetry Data Block"; break;
> +	case 0x706: data_block = "HDR Static Metadata Data Block"; break;
> +	case 0x707: data_block = "HDR Dynamic Metadata Data Block"; break;
> +
> +	case 0x70d: data_block = "Video Format Preference Data Block"; break;
> +	case 0x70e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
> +	case 0x70f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
> +	case 0x710: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break; // reserved
> +	case 0x711: data_block_o("Vendor-Specific Audio Data Block"); audio_block = true; break; // no vendors implemented
> +	case 0x712: data_block = "HDMI Audio Data Block"; audio_block = true; break;
> +	case 0x713: data_block = "Room Configuration Data Block"; audio_block = true; break;
> +	case 0x714: data_block = "Speaker Location Data Block"; audio_block = true; break;
> +
> +	case 0x720: data_block = "InfoFrame Data Block"; break;
> +
> +	case 0x734: data_block = "DisplayID Type VII Video Timing Data Block"; break;
> +	case 0x735: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
> +	case 0x742: data_block = "DisplayID Type X Video Timing Data Block"; break;
> +
> +	case 0x778: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
> +	case 0x779: data_block = "HDMI Forum Sink Capability Data Block"; break;
>  	default:
> -		if (x[0] <= 12)
> -			printf("  Unknown CTA-861 Video-Related");
> -		else if (x[0] <= 31)
> -			printf("  Unknown CTA-861 Audio-Related");
> -		else if (x[0] >= 120 && x[0] <= 127)
> -			printf("  Unknown CTA-861 HDMI-Related");
> -		else
> -			printf("  Unknown CTA-861");
> -		printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
> -		hex_block("    ", x + 1, length);
> -		data_block.clear();
> -		warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
> -		return;
> -	}
> -
> -	switch (x[0]) {
> -	case 0x00:
> -	case 0x02:
> -	case 0x05:
> -	case 0x06:
> -	case 0x0d:
> -	case 0x0f:
> -	case 0x12:
> -	case 0x13:
> -	case 0x78:
> -	case 0x79:
> +		     if (tag < 0x700) data_block = "Unknown CTA-861 Data Block";
> +		else if (tag < 0x70d) data_block = "Unknown CTA-861 Video-Related Data Block";
> +		else if (tag < 0x720) data_block = "Unknown CTA-861 Audio-Related Data Block";
> +		else if (tag < 0x778) data_block = "Unknown CTA-861 Data Block";
> +		else if (tag < 0x780) data_block = "Unknown CTA-861 HDMI-Related Data Block";
> +		else                  data_block = "Unknown CTA-861 Data Block";
> +		data_block += std::string(" (") + (extended ? "extended " : "") + "tag " + utohex(tag & 0xff) + ")";
> +	}
> +
> +	printf("  %s:\n", data_block.c_str());
> +
> +	switch (tag) {
> +	case 0x004:
> +	case 0x005:
> +	case 0x700:
> +	case 0x702:
> +	case 0x705:
> +	case 0x706:
> +	case 0x70d:
> +	case 0x70f:
> +	case 0x712:
> +	case 0x713:
> +	case 0x778:
> +	case 0x779:
>  		if (duplicate)
>  			fail("Only one instance of this Data Block is allowed.\n");
> -		break;
>  	}
>  
> -
>  	// See Table 52 of CTA-861-G for a description of Byte 3
>  	if (audio_block && !(cta.byte3 & 0x40))
> -		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
> -
> -	if (data_block.length())
> -		printf("  %s:\n", data_block.c_str());
> -
> -	switch (x[0]) {
> -	case 0x00: cta_vcdb(x + 1, length); return;
> -	case 0x01:
> -		if (length < 3) {
> -			data_block = std::string("Vendor-Specific Video Data Block");
> -			fail("Invalid length %u < 3.\n", length);
> -			return;
> -		}
> -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
> -		name = oui_name(oui);
> -		if (!name) {
> -			name = oui_name(oui, true);
> -			if (name)
> -				reverse = true;
> -		}
> -		if (!name) {
> -			printf("  Vendor-Specific Video Data Block, OUI %s:\n",
> -			       ouitohex(oui).c_str());
> -			hex_block("    ", x + 4, length - 3);
> -			data_block.clear();
> -			warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
> -			     ouitohex(oui).c_str());
> -			return;
> -		}
> -		data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
> -		if (reverse)
> -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
> -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
> -		if (oui == 0x90848b)
> -			cta_hdr10plus(x + 4, length - 3);
> -		else if (oui == 0x00d046)
> -			cta_dolby_video(x + 4, length - 3);
> -		else
> -			hex_block("    ", x + 4, length - 3);
> -		return;
> -	case 0x02: cta_vesa_vdddb(x + 1, length); return;
> -	case 0x05: cta_colorimetry_block(x + 1, length); return;
> -	case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
> -	case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
> -	case 0x0d: cta_vfpdb(x + 1, length); return;
> -	case 0x0e: cta_svd(x + 1, length, true); return;
> -	case 0x0f: cta_y420cmdb(x + 1, length); return;
> -	case 0x11:
> -		if (length < 3) {
> -			data_block = std::string("Vendor-Specific Audio Data Block");
> -			fail("Invalid length %u < 3.\n", length);
> -			return;
> -		}
> -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
> -		name = oui_name(oui);
> -		if (!name) {
> -			name = oui_name(oui, true);
> -			if (name)
> -				reverse = true;
> -		}
> -		if (!name) {
> -			printf("  Vendor-Specific Audio Data Block, OUI %s:\n",
> -			       ouitohex(oui).c_str());
> -			hex_block("    ", x + 4, length - 3);
> -			data_block.clear();
> -			warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
> -			     ouitohex(oui).c_str());
> -			return;
> -		}
> -		data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
> -		if (reverse)
> -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
> -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
> -		if (oui == 0x00d046)
> -			cta_dolby_audio(x + 4, length - 3);
> +		fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
> +
> +	tag |= ouinum;
> +	switch (tag) {
> +	case 0x001: cta_audio_block(x, length); break;
> +	case 0x002: cta_svd(x, length, false); break;
> +	case 0x003|kOUI_HDMI:
> +		cta_hdmi_block(x, length);
> +		// The HDMI OUI is present, so this EDID represents an HDMI
> +		// interface. And HDMI interfaces must use EDID version 1.3
> +		// according to the HDMI Specification, so check for this.
> +		if (base.edid_minor != 3)
> +			fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
> +				 base.edid_minor);
> +		break;
> +	case 0x003|kOUI_HDMIForum:
> +		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
> +			fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
> +		if (cta.have_hf_scdb || cta.have_hf_vsdb)
> +			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
> +		cta_hf_scdb(x, length);
> +		cta.have_hf_vsdb = true;
> +		break;
> +	case 0x003|kOUI_AMD: cta_amd(x, length); break;
> +	case 0x003|kOUI_Microsoft:
> +		if (length == 0x12)
> +			cta_microsoft(x, length);
>  		else
> -			hex_block("    ", x + 4, length - 3);
> -		return;
> -	case 0x12: cta_hdmi_audio_block(x + 1, length); return;
> -	case 0x13: cta_rcdb(x + 1, length); return;
> -	case 0x14: cta_sldb(x + 1, length); return;
> -	case 0x20: cta_ifdb(x + 1, length); return;
> -	case 0x34: cta_displayid_type_7(x + 1, length); return;
> -	case 0x35: cta_displayid_type_8(x + 1, length); return;
> -	case 0x42: cta_displayid_type_10(x + 1, length); return;
> -	case 0x78:
> -		cta_hf_eeodb(x + 1, length);
> +			goto dohex;
> +		break;
> +	case 0x004: cta_sadb(x, length); break;
> +	case 0x005: cta_vesa_dtcdb(x, length); break;
> +	case 0x700: cta_vcdb(x, length); break;
> +	case 0x701|kOUI_HDR10: cta_hdr10plus(x, length); break;
> +	case 0x701|kOUI_Dolby: cta_dolby_video(x, length); break;
> +	case 0x702: cta_vesa_vdddb(x, length); break;
> +	case 0x705: cta_colorimetry_block(x, length); break;
> +	case 0x706: cta_hdr_static_metadata_block(x, length); break;
> +	case 0x707: cta_hdr_dyn_metadata_block(x, length); break;
> +	case 0x70d: cta_vfpdb(x, length); break;
> +	case 0x70e: cta_svd(x, length, true); break;
> +	case 0x70f: cta_y420cmdb(x, length); break;
> +	case 0x711|kOUI_Dolby: cta_dolby_audio(x, length); break;
> +	case 0x712: cta_hdmi_audio_block(x, length); break;
> +	case 0x713: cta_rcdb(x, length); break;
> +	case 0x714: cta_sldb(x, length); break;
> +	case 0x720: cta_ifdb(x, length); break;
> +	case 0x734: cta_displayid_type_7(x, length); break;
> +	case 0x735: cta_displayid_type_8(x, length); break;
> +	case 0x742: cta_displayid_type_10(x, length); break;
> +	case 0x778:
> +		cta_hf_eeodb(x, length);
>  		// This must be the first CTA-861 block
> -		if (!cta.first_block)
> +		if (cta.block_number > 0)
>  			fail("Block starts at a wrong offset.\n");
> -		return;
> -	case 0x79:
> -		if (!cta.last_block_was_hdmi_vsdb)
> +		break;
> +	case 0x779:
> +		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
>  			fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
>  		if (cta.have_hf_scdb || cta.have_hf_vsdb)
>  			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
>  		if (length < 2) {
>  			data_block = std::string("HDMI Forum SCDB");
>  			fail("Invalid length %u < 2.\n", length);
> -			return;
> -		}
> -		if (x[1] || x[2])
> -			printf("  Non-zero SCDB reserved fields!\n");
> -		cta_hf_scdb(x + 3, length - 2);
> -		cta.have_hf_scdb = 1;
> -		return;
> -	}
> -
> -	hex_block("    ", x + 1, length);
> -}
> -
> -void edid_state::cta_block(const unsigned char *x, bool duplicate)
> -{
> -	unsigned length = x[0] & 0x1f;
> -	const char *name;
> -	unsigned oui;
> -	bool reverse = false;
> -	bool audio_block = false;
> -
> -	switch ((x[0] & 0xe0) >> 5) {
> -	case 0x01:
> -		data_block = "Audio Data Block";
> -		printf("  %s:\n", data_block.c_str());
> -		cta_audio_block(x + 1, length);
> -		audio_block = true;
> -		break;
> -	case 0x02:
> -		data_block = "Video Data Block";
> -		printf("  %s:\n", data_block.c_str());
> -		cta_svd(x + 1, length, false);
> -		break;
> -	case 0x03:
> -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
> -		name = oui_name(oui);
> -		if (!name) {
> -			name = oui_name(oui, true);
> -			if (name)
> -				reverse = true;
> -		}
> -		if (!name) {
> -			printf("  Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
> -			hex_block("    ", x + 4, length - 3);
> -			data_block.clear();
> -			warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
> -			     ouitohex(oui).c_str());
> -			return;
> -		}
> -		data_block = std::string("Vendor-Specific Data Block (") + name + ")";
> -		if (reverse)
> -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
> -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
> -		if (oui == 0x000c03) {
> -			cta_hdmi_block(x + 1, length);
> -			cta.last_block_was_hdmi_vsdb = 1;
> -			cta.first_block = 0;
> -			// The HDMI OUI is present, so this EDID represents an HDMI
> -			// interface. And HDMI interfaces must use EDID version 1.3
> -			// according to the HDMI Specification, so check for this.
> -			if (base.edid_minor != 3)
> -				fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
> -				     base.edid_minor);
> -			return;
> -		}
> -		if (oui == 0xc45dd8) {
> -			if (!cta.last_block_was_hdmi_vsdb)
> -				fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
> -			if (cta.have_hf_scdb || cta.have_hf_vsdb)
> -				fail("Duplicate HDMI Forum VSDB/SCDB.\n");
> -			cta_hf_scdb(x + 4, length - 3);
> -			cta.have_hf_vsdb = 1;
> -			break;
> -		}
> -		if (oui == 0x00001a) {
> -			cta_amd(x + 4, length - 3);
> -			break;
> -		}
> -		if (oui == 0xca125c && length == 0x15) {
> -			cta_microsoft(x + 4, length - 3);
>  			break;
>  		}
> -		hex_block("    ", x + 4, length - 3);
> -		break;
> -	case 0x04:
> -		data_block = "Speaker Allocation Data Block";
> -		printf("  %s:\n", data_block.c_str());
> -		cta_sadb(x + 1, length);
> -		audio_block = true;
> -		if (duplicate)
> -			fail("Only one instance of this Data Block is allowed.\n");
> -		break;
> -	case 0x05:
> -		data_block = "VESA Display Transfer Characteristics Data Block";
> -		printf("  %s:\n", data_block.c_str());
> -		cta_vesa_dtcdb(x + 1, length);
> -		if (duplicate)
> -			fail("Only one instance of this Data Block is allowed.\n");
> -		break;
> -	case 0x07:
> -		cta_ext_block(x + 1, length - 1, duplicate);
> -		break;
> -	default: {
> -		unsigned tag = (*x & 0xe0) >> 5;
> -		unsigned length = *x & 0x1f;
> -
> -		printf("  Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
> -		hex_block("    ", x + 1, length);
> -		data_block.clear();
> -		warn("Unknown CTA-861 Data Block %u.\n", tag);
> +		if (x[0] || x[1])
> +			printf("  Non-zero SCDB reserved fields!\n");
> +		cta_hf_scdb(x + 2, length - 2);
> +		cta.have_hf_scdb = true;
>  		break;
> +dohex:
> +	default:
> +		hex_block("    ", x, length);
> +		warn("Unknown block type: %s.\n", data_block.c_str());
>  	}
> -	}
> -
> -	// See Table 52 of CTA-861-G for a description of Byte 3
> -	if (audio_block && !(cta.byte3 & 0x40))
> -		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
> -	cta.first_block = 0;
> -	cta.last_block_was_hdmi_vsdb = 0;
> +	cta.block_number++;
> +	cta.previous_cta_tag = tag;
>  }
>  
>  void edid_state::preparse_cta_block(const unsigned char *x)
> @@ -2392,11 +2268,11 @@ void edid_state::parse_cta_block(const unsigned char *x)
>  //				msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
>  //				    cta.has_hdmi ? "shall" : "should");
>  			printf("  Native detailed modes: %u\n", x[3] & 0x0f);
> -			if (cta.first_block)
> +			if (cta.block_number == 0)
>  				cta.byte3 = x[3];
>  			else if (x[3] != cta.byte3)
>  				fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
> -			if (cta.first_block) {
> +			if (cta.block_number == 0) {
>  				unsigned native_dtds = x[3] & 0x0f;
>  
>  				cta.native_timings.clear();
> diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
> index 5c81294..ff7a6db 100644
> --- a/parse-displayid-block.cpp
> +++ b/parse-displayid-block.cpp
> @@ -1609,13 +1609,230 @@ void edid_state::preparse_displayid_block(const unsigned char *x)
>  	}
>  }
>  
> +#define data_block_o(n, a, b) data_block_oui(n, x + 3, len, tag == 0, &ouinum, a, b)
> +
> +unsigned edid_state::displayid_block(const unsigned version, const unsigned char *x, unsigned length)
> +{
> +	unsigned i;
> +	unsigned tag = x[0];
> +	unsigned ouinum = 0;
> +	unsigned len = (length < 3) ? 0 : x[2];
> +
> +	switch (tag) {
> +	// DisplayID 1.3:
> +	case 0x00: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", true, false); ouinum = 0; break;
> +	case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
> +	case 0x02: data_block = "Color Characteristics Data Block"; break;
> +	case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
> +	case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
> +	case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
> +	case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
> +	case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
> +	case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
> +	case 0x09: data_block = "Video Timing Range Data Block"; break;
> +	case 0x0a: data_block = "Product Serial Number Data Block"; break;
> +	case 0x0b: data_block = "GP ASCII String Data Block"; break;
> +	case 0x0c: data_block = "Display Device Data Data Block"; break;
> +	case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
> +	case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
> +	case 0x0f: data_block = "Display Interface Data Block"; break;
> +	case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
> +	case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
> +	case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
> +	case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
> +	// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
> +	// DisplayID 2.0
> +	case 0x20: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", false, false); ouinum = 0; break;
> +	case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
> +	case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
> +	case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
> +	case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
> +	case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
> +	case 0x26: data_block = "Display Interface Features Data Block"; break;
> +	case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
> +	case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
> +	case 0x29: data_block = "ContainerID Data Block"; break;
> +	case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
> +	// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
> +	case 0x7e: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", false, true); break; // DisplayID 2.0
> +	case 0x7f: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", true, false); break; // DisplayID 1.3
> +	// 0x80 RESERVED
> +	case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
> +	// 0x82 .. 0xff RESERVED
> +	default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
> +	}
> +
> +	if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
> +		fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
> +			 version >> 4, version & 0xf);
> +	if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
> +		fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
> +			 version >> 4, version & 0xf);
> +
> +	if (length < 3) {
> +		// report a problem when the remaining bytes are not 0.
> +		if (tag || (length > 1 && x[1])) {
> +			fail("Not enough bytes remain (%d) for a DisplayID data block and the DisplayID filler is non-0.\n", length);
> +		}
> +		return length;
> +	}
> +
> +	unsigned block_rev = x[1] & 0x07;
> +
> +	if (length < len + 3) {
> +		fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d)\n", len + 3, length);
> +		return length;
> +	}
> +
> +	if (!tag && !len) {
> +		// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
> +		if (!memchk(x, length)) {
> +			fail("Non-0 filler bytes in the DisplayID block.\n");
> +		}
> +		return length;
> +	}
> +
> +	printf("  %s:\n", data_block.c_str());
> +
> +	tag |= ouinum;
> +	switch (tag) {
> +	case 0x00: parse_displayid_product_id(x); break;
> +	case 0x01: parse_displayid_parameters(x); break;
> +	case 0x02: parse_displayid_color_characteristics(x); break;
> +	case 0x03:
> +		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
> +		   for (i = 0; i < len / 20; i++)
> +			   parse_displayid_type_1_7_timing(&x[3 + (i * 20)], false, block_rev);
> +		   break;
> +	case 0x04:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < len / 11; i++)
> +			   parse_displayid_type_2_timing(&x[3 + (i * 11)]);
> +		   break;
> +	case 0x05:
> +		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
> +		   for (i = 0; i < len / 3; i++)
> +			   parse_displayid_type_3_timing(&x[3 + (i * 3)]);
> +		   break;
> +	case 0x06:
> +		   check_displayid_datablock_revision(x[1], 0xc0, 1);
> +		   for (i = 0; i < len; i++)
> +			   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6, x[3 + i]);
> +		   break;
> +	case 0x07:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < min(len, 10) * 8; i++)
> +			   if (x[3 + i / 8] & (1 << (i % 8))) {
> +				   char type[16];
> +				   sprintf(type, "DMT 0x%02x", i + 1);
> +				   print_timings("    ", find_dmt_id(i + 1), type);
> +			   }
> +		   break;
> +	case 0x08:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < min(len, 8) * 8; i++)
> +			   if (x[3 + i / 8] & (1 << (i % 8))) {
> +				   char type[16];
> +				   sprintf(type, "VIC %3u", i + 1);
> +				   print_timings("    ", find_vic_id(i + 1), type);
> +			   }
> +		   break;
> +	case 0x09: parse_displayid_video_timing_range_limits(x); break;
> +	case 0x0a:
> +	case 0x0b: parse_displayid_string(x); break;
> +	case 0x0c: parse_displayid_display_device(x); break;
> +	case 0x0d: parse_displayid_intf_power_sequencing(x); break;
> +	case 0x0e: parse_displayid_transfer_characteristics(x); break;
> +	case 0x0f: parse_displayid_display_intf(x); break;
> +	case 0x10: parse_displayid_stereo_display_intf(x); break;
> +	case 0x11:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < len / 7; i++)
> +			   parse_displayid_type_5_timing(&x[3 + (i * 7)]);
> +		   break;
> +	case 0x12: parse_displayid_tiled_display_topology(x, false); break;
> +	case 0x13:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < len; i += (x[3 + i + 2] & 0x40) ? 17 : 14)
> +			   parse_displayid_type_6_timing(&x[3 + i]);
> +		   break;
> +	case 0x20: parse_displayid_product_id(x); break;
> +	case 0x21:
> +		   if (block_rev >= 1)
> +			   check_displayid_datablock_revision(x[1], 0x80, 1);
> +		   else
> +			   check_displayid_datablock_revision(x[1], 0x80, 0);
> +		   parse_displayid_parameters_v2(x, block_rev);
> +		   break;
> +	case 0x22: {
> +		   unsigned sz = 20;
> +
> +		   if (block_rev >= 2)
> +			   check_displayid_datablock_revision(x[1], 0x08, 2);
> +		   else if (block_rev == 1)
> +			   check_displayid_datablock_revision(x[1], 0x08, 1);
> +		   else
> +			   check_displayid_datablock_revision(x[1]);
> +		   sz += (x[1] & 0x70) >> 4;
> +		   if (block_rev >= 1 && (x[1] & 0x08))
> +			   printf("    These timings support DSC pass-through\n");
> +		   for (i = 0; i < len / sz; i++)
> +			   parse_displayid_type_1_7_timing(&x[3 + i * sz], true, block_rev);
> +		   break;
> +	}
> +	case 0x23:
> +		   if (block_rev)
> +			   check_displayid_datablock_revision(x[1], 0xe8, 1);
> +		   else
> +			   check_displayid_datablock_revision(x[1], 0xc8);
> +		   if (x[1] & 0x08) {
> +			   for (i = 0; i < len / 2; i++)
> +				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
> +								   x[3 + i * 2] |
> +								   (x[4 + i * 2] << 8));
> +		   } else {
> +			   for (i = 0; i < len; i++)
> +				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
> +								   x[3 + i]);
> +		   }
> +		   break;
> +	case 0x24:
> +		   check_displayid_datablock_revision(x[1]);
> +		   for (i = 0; i < len / 6; i++)
> +			   parse_displayid_type_9_timing(&x[3 + i * 6]);
> +		   break;
> +	case 0x25: parse_displayid_dynamic_video_timings_range_limits(x); break;
> +	case 0x26: parse_displayid_interface_features(x); break;
> +	case 0x27: parse_displayid_stereo_display_intf(x); break;
> +	case 0x28: parse_displayid_tiled_display_topology(x, true); break;
> +	case 0x29: parse_displayid_ContainerID(x); break;
> +	case 0x32: {
> +		   unsigned sz = 6 + ((x[1] & 0x70) >> 4);
> +
> +		   check_displayid_datablock_revision(x[1], 0x70);
> +		   for (i = 0; i < len / sz; i++)
> +			   parse_displayid_type_10_timing(&x[3 + i * sz], sz);
> +		   break;
> +	}
> +	case 0x81: parse_displayid_cta_data_block(x); break;
> +	case 0x7e|kOUI_VESA: parse_displayid_vesa(x); break;
> +	default: hex_block("    ", x + 3 + (ouinum ? 3 : 0), len - (ouinum ? 3 : 0)); break;
> +	}
> +
> +	if ((tag == 0x00 || tag == 0x20) &&
> +		(!dispid.is_base_block || dispid.block_number > 0))
> +		fail("%s is required to be the first DisplayID Data Block.\n",
> +			 data_block.c_str());
> +	dispid.block_number++;
> +	return len + 3;
> +}
> +
>  void edid_state::parse_displayid_block(const unsigned char *x)
>  {
>  	unsigned version = x[1];
>  	unsigned length = x[2];
>  	unsigned prod_type = x[3]; // future check: based on type, check for required data blocks
>  	unsigned ext_count = x[4];
> -	unsigned i;
>  
>  	printf("  Version: %u.%u\n  Extension Count: %u\n",
>  	       version >> 4, version & 0xf, ext_count);
> @@ -1647,246 +1864,10 @@ void edid_state::parse_displayid_block(const unsigned char *x)
>  		length = 121;
>  	}
>  
> -	unsigned offset = 5;
> -	bool first_data_block = true;
> -	while (length > 0) {
> -		unsigned tag = x[offset];
> -		unsigned oui = 0;
> -
> -		switch (tag) {
> -		// DisplayID 1.3:
> -		case 0x00: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
> -		case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
> -		case 0x02: data_block = "Color Characteristics Data Block"; break;
> -		case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
> -		case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
> -		case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
> -		case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
> -		case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
> -		case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
> -		case 0x09: data_block = "Video Timing Range Data Block"; break;
> -		case 0x0a: data_block = "Product Serial Number Data Block"; break;
> -		case 0x0b: data_block = "GP ASCII String Data Block"; break;
> -		case 0x0c: data_block = "Display Device Data Data Block"; break;
> -		case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
> -		case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
> -		case 0x0f: data_block = "Display Interface Data Block"; break;
> -		case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
> -		case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
> -		case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
> -		case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
> -		// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
> -		// DisplayID 2.0
> -		case 0x20: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
> -		case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
> -		case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
> -		case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
> -		case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
> -		case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
> -		case 0x26: data_block = "Display Interface Features Data Block"; break;
> -		case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
> -		case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
> -		case 0x29: data_block = "ContainerID Data Block"; break;
> -		case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
> -		// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
> -		case 0x7e: // DisplayID 2.0
> -		case 0x7f: // DisplayID 1.3
> -			if ((tag == 0x7e && version >= 0x20) ||
> -			    (tag == 0x7f && version < 0x20)) {
> -				oui = (x[offset + 3] << 16) + (x[offset + 4] << 8) + x[offset + 5];
> -				const char *name = oui_name(oui);
> -				bool reversed = false;
> -
> -				if (!name) {
> -					name = oui_name(oui, true);
> -					if (name)
> -						reversed = true;
> -				}
> -				if (name)
> -					data_block = std::string("Vendor-Specific Data Block (") + name + ")";
> -				else
> -					data_block = "Vendor-Specific Data Block, OUI " + ouitohex(oui);
> -				if (reversed)
> -					fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order.\n").c_str());
> -			} else {
> -				data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")";
> -			}
> -			break;
> -		// 0x80 RESERVED
> -		case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
> -		// 0x82 .. 0xff RESERVED
> -		default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
> -		}
> -
> -		if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
> -			fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
> -			     version >> 4, version & 0xf);
> -		if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
> -			fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
> -			     version >> 4, version & 0xf);
> -
> -		if (length < 3) {
> -			// report a problem when the remaining bytes are not 0.
> -			if (tag || x[offset + 1]) {
> -				fail("Not enough bytes remain (%d) for a DisplayID data block or the DisplayID filler is non-0.\n", length);
> -			}
> -			break;
> -		}
> -
> -		unsigned block_rev = x[offset + 1] & 0x07;
> -		unsigned len = x[offset + 2];
> -
> -		if (length < len + 3) {
> -			fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d).\n", len + 3, length);
> -			break;
> -		}
> -
> -		if (!tag && !len) {
> -			// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
> -			if (!memchk(x + offset, length)) {
> -				fail("Non-0 filler bytes in the DisplayID block.\n");
> -			}
> -			break;
> -		}
> -
> -		printf("  %s:\n", data_block.c_str());
> -
> -		switch (tag) {
> -		case 0x00: parse_displayid_product_id(x + offset); break;
> -		case 0x01: parse_displayid_parameters(x + offset); break;
> -		case 0x02: parse_displayid_color_characteristics(x + offset); break;
> -		case 0x03:
> -			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
> -			   for (i = 0; i < len / 20; i++)
> -				   parse_displayid_type_1_7_timing(&x[offset + 3 + (i * 20)], false, block_rev);
> -			   break;
> -		case 0x04:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < len / 11; i++)
> -				   parse_displayid_type_2_timing(&x[offset + 3 + (i * 11)]);
> -			   break;
> -		case 0x05:
> -			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
> -			   for (i = 0; i < len / 3; i++)
> -				   parse_displayid_type_3_timing(&x[offset + 3 + (i * 3)]);
> -			   break;
> -		case 0x06:
> -			   check_displayid_datablock_revision(x[offset + 1], 0xc0, 1);
> -			   for (i = 0; i < len; i++)
> -				   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6, x[offset + 3 + i]);
> -			   break;
> -		case 0x07:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < min(len, 10) * 8; i++)
> -				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
> -					   char type[16];
> -					   sprintf(type, "DMT 0x%02x", i + 1);
> -					   print_timings("    ", find_dmt_id(i + 1), type);
> -				   }
> -			   break;
> -		case 0x08:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < min(len, 8) * 8; i++)
> -				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
> -					   char type[16];
> -					   sprintf(type, "VIC %3u", i + 1);
> -					   print_timings("    ", find_vic_id(i + 1), type);
> -				   }
> -			   break;
> -		case 0x09: parse_displayid_video_timing_range_limits(x + offset); break;
> -		case 0x0a:
> -		case 0x0b: parse_displayid_string(x + offset); break;
> -		case 0x0c: parse_displayid_display_device(x + offset); break;
> -		case 0x0d: parse_displayid_intf_power_sequencing(x + offset); break;
> -		case 0x0e: parse_displayid_transfer_characteristics(x + offset); break;
> -		case 0x0f: parse_displayid_display_intf(x + offset); break;
> -		case 0x10: parse_displayid_stereo_display_intf(x + offset); break;
> -		case 0x11:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < len / 7; i++)
> -				   parse_displayid_type_5_timing(&x[offset + 3 + (i * 7)]);
> -			   break;
> -		case 0x12: parse_displayid_tiled_display_topology(x + offset, false); break;
> -		case 0x13:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < len; i += (x[offset + 3 + i + 2] & 0x40) ? 17 : 14)
> -				   parse_displayid_type_6_timing(&x[offset + 3 + i]);
> -			   break;
> -		case 0x20: parse_displayid_product_id(x + offset); break;
> -		case 0x21:
> -			   if (block_rev >= 1)
> -				   check_displayid_datablock_revision(x[offset + 1], 0x80, 1);
> -			   else
> -				   check_displayid_datablock_revision(x[offset + 1], 0x80, 0);
> -			   parse_displayid_parameters_v2(x + offset, block_rev);
> -			   break;
> -		case 0x22: {
> -			   unsigned sz = 20;
> -
> -			   if (block_rev >= 2)
> -				   check_displayid_datablock_revision(x[offset + 1], 0x08, 2);
> -			   else if (block_rev == 1)
> -				   check_displayid_datablock_revision(x[offset + 1], 0x08, 1);
> -			   else
> -				   check_displayid_datablock_revision(x[offset + 1]);
> -			   sz += (x[offset + 1] & 0x70) >> 4;
> -			   if (block_rev >= 1 && (x[offset + 1] & 0x08))
> -				   printf("    These timings support DSC pass-through\n");
> -			   for (i = 0; i < len / sz; i++)
> -				   parse_displayid_type_1_7_timing(&x[offset + 3 + i * sz], true, block_rev);
> -			   break;
> -		}
> -		case 0x23:
> -			   if (block_rev)
> -				   check_displayid_datablock_revision(x[offset + 1], 0xe8, 1);
> -			   else
> -				   check_displayid_datablock_revision(x[offset + 1], 0xc8);
> -			   if (x[offset + 1] & 0x08) {
> -				   for (i = 0; i < len / 2; i++)
> -					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
> -									   x[offset + 3 + i * 2] |
> -									   (x[offset + 4 + i * 2] << 8));
> -			   } else {
> -				   for (i = 0; i < len; i++)
> -					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
> -									   x[offset + 3 + i]);
> -			   }
> -			   break;
> -		case 0x24:
> -			   check_displayid_datablock_revision(x[offset + 1]);
> -			   for (i = 0; i < len / 6; i++)
> -				   parse_displayid_type_9_timing(&x[offset + 3 + i * 6]);
> -			   break;
> -		case 0x25: parse_displayid_dynamic_video_timings_range_limits(x + offset); break;
> -		case 0x26: parse_displayid_interface_features(x + offset); break;
> -		case 0x27: parse_displayid_stereo_display_intf(x + offset); break;
> -		case 0x28: parse_displayid_tiled_display_topology(x + offset, true); break;
> -		case 0x29: parse_displayid_ContainerID(x + offset); break;
> -		case 0x32: {
> -			   unsigned sz = 6 + ((x[offset + 1] & 0x70) >> 4);
> -
> -			   check_displayid_datablock_revision(x[offset + 1], 0x70);
> -			   for (i = 0; i < len / sz; i++)
> -				   parse_displayid_type_10_timing(&x[offset + 3 + i * sz], sz);
> -			   break;
> -		}
> -		case 0x81: parse_displayid_cta_data_block(x + offset); break;
> -		case 0x7e:
> -			if (oui == 0x3a0292) {
> -				parse_displayid_vesa(x + offset);
> -				break;
> -			}
> -			// fall-through
> -		default: hex_block("    ", x + offset + 3, len); break;
> -		}
> -
> -		if ((tag == 0x00 || tag == 0x20) &&
> -		    (!dispid.is_base_block || !first_data_block))
> -			fail("%s is required to be the first DisplayID Data Block.\n",
> -			     data_block.c_str());
> -		length -= len + 3;
> -		offset += len + 3;
> -		first_data_block = false;
> +	unsigned len;
> +	for (const unsigned char *y = x + 5; length > 0; y += len) {
> +		len = displayid_block(version, y, length);
> +		length -= len;
>  	}
>  
>  	/*
> 


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

* Re: [PATCH 03/11] edid-decode: change install directories for macOS
  2021-09-15 10:06   ` Hans Verkuil
@ 2021-09-15 15:25     ` Joe van Tunen
  0 siblings, 0 replies; 23+ messages in thread
From: Joe van Tunen @ 2021-09-15 15:25 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Thanks. That last change was made because I don't like to do aligning between lines that have different indents. That way you don't have to mix tabs and spaces or worry about different tab widths used by different people using different editors.


On 2021-09-15, 3:06 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    On 14/09/2021 14:11, joevt wrote:
    > In macOS, /usr/bin and /usr/share/man belong to root:wheel so install to /usr/local/bin and /usr/local/share/man instead.
    > 
    > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    > ---
    >  Makefile | 22 +++++++++++++++++-----
    >  1 file changed, 17 insertions(+), 5 deletions(-)
    > 
    > diff --git a/Makefile b/Makefile
    > index 287b72d..adf6123 100644
    > --- a/Makefile
    > +++ b/Makefile
    > @@ -1,11 +1,23 @@
    > -bindir ?= /usr/bin
    > -mandir ?= /usr/share/man
    > +ifeq ($(OS),Windows_NT)
    > +	bindir ?= /usr/bin
    > +	mandir ?= /usr/share/man
    > +else
    > +	UNAME_S := $(shell uname -s)
    > +	ifeq ($(UNAME_S),Darwin)
    > +		bindir ?= /usr/local/sbin
    > +		mandir ?= /usr/local/share/man
    > +	else
    > +		bindir ?= /usr/bin
    > +		mandir ?= /usr/share/man
    > +	endif
    > +endif
    >  
    >  EMXX ?= em++
    >  
    > -SOURCES = edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
    > -	  parse-displayid-block.cpp parse-ls-ext-block.cpp \
    > -	  parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp
    > +SOURCES = \
    > +	edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
    > +	parse-displayid-block.cpp parse-ls-ext-block.cpp \
    > +	parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp

    This last change is a spurious change, I'll drop this and keep the rest.

    No need for you to do anything.

    Regards,

    	Hans

    >  WARN_FLAGS = -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter
    >  
    >  all: edid-decode
    > 




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

* Re: [PATCH 07/11] edid-decode: always linefeed after hex_block
  2021-09-15 10:10   ` Hans Verkuil
@ 2021-09-15 15:43     ` Joe van Tunen
  2021-09-15 18:27       ` Joe van Tunen
  0 siblings, 1 reply; 23+ messages in thread
From: Joe van Tunen @ 2021-09-15 15:43 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Yes, that's ugly. I will do a search for the EDID that prompted me to make this change. Maybe it's not a problem anymore.
...
Seems like the problem I had was fixed in cta_hdr10plus. I'll do more checking and testing with other calls to hex_block.


On 2021-09-15, 3:10 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    On 14/09/2021 14:11, joevt wrote:
    > hex_block should not return without printing a newline (which occurs when the length is zero). This causes a missing newline after "Application Version: 1" with cta_hdr10plus for an EDID I have.
    > Any place that calls hex_block will have the same problem if it's possible for the length to be zero.
    > 
    > In other words, a hex_block needs to have a linefeed even if it has zero length, because the caller assumes it will go to the next line as it does when the hex block is not zero length.
    > 
    > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    > ---
    >  edid-decode.cpp | 4 +++-
    >  1 file changed, 3 insertions(+), 1 deletion(-)
    > 
    > diff --git a/edid-decode.cpp b/edid-decode.cpp
    > index 2316abc..6aa93fb 100644
    > --- a/edid-decode.cpp
    > +++ b/edid-decode.cpp
    > @@ -698,8 +698,10 @@ void hex_block(const char *prefix, const unsigned char *x,
    >  {
    >  	unsigned i, j;
    >  
    > -	if (!length)
    > +	if (!length) {
    > +		printf("\n");
    >  		return;
    > +	}

    Hmm, with this change I get this:

    edid-decode -c Digital/Acer/ACR0282/B12D637C1F12 with the linuxhw database:

      Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
        Source physical address: 2.0.0.0
      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

      Unknown CTA-861 tag 0x00, length 0

    That looks pretty ugly.

    Regards,

    	Hans

    >  
    >  	for (i = 0; i < length; i += step) {
    >  		unsigned len = min(step, length - i);
    > 




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

* Re: [PATCH 07/11] edid-decode: always linefeed after hex_block
  2021-09-15 15:43     ` Joe van Tunen
@ 2021-09-15 18:27       ` Joe van Tunen
  0 siblings, 0 replies; 23+ messages in thread
From: Joe van Tunen @ 2021-09-15 18:27 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

I found no place that requires this change to hex_block.
This patch should be ignored.

I did find one call to hex_block that should be modified:
cta_hdr10plus outputs hex on the same line as the "Application Version: %u".

It either needs to always output a linefeed before calling hex_block like this:

	printf("    Application Version: %u\n", x[0]);
	hex_block("    ", x + 1, length - 1);

Or it needs to set step to the same value as length, like this:

	printf("    Application Version: %u", x[0]);
	if (length > 1)
		hex_block("  ", x + 1, length - 1, true, length - 1);
	else
		printf("\n");

Those are probably the only acceptable ways to call hex_block (first is multi-line or no-line, second is one-line)

It should also probably check the length:

	if (length == 0) {
		fail("Empty Data Block with length %u.\n", length);
		return;
	}


On 2021-09-15, 8:43 AM, "Joe van Tunen" <joevt@shaw.ca> wrote:

    Yes, that's ugly. I will do a search for the EDID that prompted me to make this change. Maybe it's not a problem anymore.
    ...
    Seems like the problem I had was fixed in cta_hdr10plus. I'll do more checking and testing with other calls to hex_block.


    On 2021-09-15, 3:10 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

        On 14/09/2021 14:11, joevt wrote:
        > hex_block should not return without printing a newline (which occurs when the length is zero). This causes a missing newline after "Application Version: 1" with cta_hdr10plus for an EDID I have.
        > Any place that calls hex_block will have the same problem if it's possible for the length to be zero.
        > 
        > In other words, a hex_block needs to have a linefeed even if it has zero length, because the caller assumes it will go to the next line as it does when the hex block is not zero length.
        > 
        > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
        > ---
        >  edid-decode.cpp | 4 +++-
        >  1 file changed, 3 insertions(+), 1 deletion(-)
        > 
        > diff --git a/edid-decode.cpp b/edid-decode.cpp
        > index 2316abc..6aa93fb 100644
        > --- a/edid-decode.cpp
        > +++ b/edid-decode.cpp
        > @@ -698,8 +698,10 @@ void hex_block(const char *prefix, const unsigned char *x,
        >  {
        >  	unsigned i, j;
        >  
        > -	if (!length)
        > +	if (!length) {
        > +		printf("\n");
        >  		return;
        > +	}

        Hmm, with this change I get this:

        edid-decode -c Digital/Acer/ACR0282/B12D637C1F12 with the linuxhw database:

          Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
            Source physical address: 2.0.0.0
          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

          Unknown CTA-861 tag 0x00, length 0

        That looks pretty ugly.

        Regards,

        	Hans

        >  
        >  	for (i = 0; i < length; i += step) {
        >  		unsigned len = min(step, length - i);
        > 






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

* Re: [PATCH 05/11] edid-decode: fix standard timing vertical pixels
  2021-09-15 11:10     ` Hans Verkuil
@ 2021-09-15 18:28       ` Joe van Tunen
  0 siblings, 0 replies; 23+ messages in thread
From: Joe van Tunen @ 2021-09-15 18:28 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Good find. I agree with that warning.

On 2021-09-15, 4:10 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    On 15/09/2021 12:08, Hans Verkuil wrote:
    > On 14/09/2021 14:11, joevt wrote:
    >> Don't do ceiling to nearest 8 pixels for active vertical lines. See examples elo-4600l-hdmi and kogan-kaled24144f-hdmi.
    >>
    >> Section 3.9 and 3.10.3.6 of EDID 1.4 does not say vertical lines must be a multiple of 8.  This line of code appears to have been added to satisfy the 3rd example in VTB-EXT spec but that example has an incorrect HAP indicator decimal value so it cannot be trusted. Also, all 3 examples have an incorrect vertical refresh value as noted in parse-vtb-ext-block.cpp. The VESA DMT spec has the following examples that are not a multiple of 8 lines which support this change:
    >> 1400x1050 4:3
    >> 1440x900 16:10
    >> 1600x900 16:9
    >> 1680x1050 16:10
    >>
    >> Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    >> ---
    >>  parse-base-block.cpp | 1 -
    >>  1 file changed, 1 deletion(-)
    >>
    >> diff --git a/parse-base-block.cpp b/parse-base-block.cpp
    >> index e2901a6..32d2079 100644
    >> --- a/parse-base-block.cpp
    >> +++ b/parse-base-block.cpp
    >> @@ -573,7 +573,6 @@ void edid_state::print_standard_timing(const char *prefix, unsigned char b1, uns
    >>  		break;
    >>  	}
    >>  	vact = (double)hact * vratio / hratio;
    >> -	vact = 8 * ((vact + 7) / 8);
    > 
    > I need to look closer at this. I think it was added to help with 1360x768, which without
    > this line maps to 1360x765.
    > 
    > I'll get back to you on this.

    I did some more reading on this, and appendix D of the EDID 1.4 spec
    says this (D-8):

    "If calculated aspect ratio is not 16 : 10 AR, 4 : 3 AR, 5 : 4 AR or 16 : 9 AR
     what timing description should be used?"

    "Ref.: Section 3.9 (E-EDID Standard Release A, Revision 2)
     The Standard Timings Identification code may not be used to
     identify timings which do not match one of these standard aspect
     ratios. Support for such timings must be indicated elsewhere,
     e.g., by use of a Detailed Timing Descriptor."

    So you are correct with your change, but I think it would make
    sense to add a new check:

    // See also Ref. D-8 in the EDID-1.4 spec
    if (vact & 1)
    	warn("Standard Timing %ux%u has a dubious odd vertical resolution.\n", hact, vact);

    So that way an attempt to use ST to describe 1360x768 will result in a warning.

    Regards,

    	Hans

    > 
    > Regards,
    > 
    > 	Hans
    > 
    >>  	refresh = (b2 & 0x3f) + 60;
    >>  
    >>  	formula.hact = hact;
    >>
    > 




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

* Re: [PATCH 11/11] edid-decode: cta and displayid changes
  2021-09-15 13:37   ` Hans Verkuil
@ 2021-09-16  9:15     ` Joe van Tunen
  0 siblings, 0 replies; 23+ messages in thread
From: Joe van Tunen @ 2021-09-16  9:15 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

1) Regarding large changes:
I will try making smaller changes with commits that build on each other. Git is good for code changes but not for code moving/rearranging. Many of the changes don't actually change anything (wanting to keep the output the same as before). Some fixes are easier to apply after doing the rearranging so I'll think about what order to make each change.


2) Regarding code reduction:
The code reduction for cta tag parsing (288 lines originally) is 43%. Not insignificant.
The code reduction for displayid tag parsing (241 lines originally) is 8% which is not as much (no extended tags and only one oui), but it's nice that it's arranged like cta tag parsing.


3) Regarding ugly lines:
The ugly lines were because of hex_block issues discussed in [PATCH 07/11]. What you should see (when hex_block is working properly) is something like this:

  Unknown CTA-861 Data Block (tag 0x00):
WARN: Unknown block type: Unknown CTA-861 Data Block (tag 0x00).

The warning is "Unknown block type: %s\n" where %s is the block type which is determined in the first switch statement.

Here's an example from _EDID_BNQ_802e with non-zero length hex:
Before patches:

  Unknown CTA-861 tag 0x00, length 5
    c0 00 e6 06 05                                  '.....'
WARN: Unknown CTA-861 Data Block 0.

Length is unnecessary since you can just count the hex bytes.
Block 0 sounds like it's referring to block index 0 instead of block tag 0x00.
After all patches:

  Unknown CTA-861 Data Block (tag 0x00):
    c0 00 e6 06 05                                  '.....'
WARN: Unknown block type: Unknown CTA-861 Data Block (tag 0x00).

With these changes, we have a consistent naming scheme for the block type (having " Data Block" suffix and adding tag in cases where the name is not enough to determine the tag) and the warning refers to that block type. Might be better if the warning comes after the block type instead of after the hex.


4) Regarding the NVIDIA oui:
You are saying that only blocks with an invalid tag should have the unknown block type warning. Not knowing how to parse a tag/oui should not be the cause of a warning. I can agree with that. If the user sees only hex then they know that edid-decode doesn't know how to decode it.



On 2021-09-15, 6:37 AM, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:

    On 14/09/2021 14:11, joevt wrote:
    > Goal: make OUI blocks equal to normal blocks to simplify decoding and make handling of all types of blocks consistent. This will reduce duplicated code (only one place for checking duplicate blocks, only one place for handling unknown blocks, etc.)
    > 
    > oui.h
    > - This contains a list of OUI and CID and PNP values.
    > - It is included in various places with varying definitions of the oneoui macro.
    > 
    > edid-decode.h
    > - Add list of OUI constants using oui.h.
    > - Other changes described below.
    > 
    > parse-cta-block.cpp
    > - Modified oui_name. Returns a name and a number for a OUI.
    > - Added data_block_oui. For data blocks with an OUI, does size check, OUI endianness check, and PNP vs OUI check. Returns a value representing the OUI (if it is known).
    > - Modify cta_block. Reduce code by flattening the switch statement. This means constructing a case value from three values.
    >   Side effects include making reporting of "Only one instance of this Data Block is allowed." more consistant (always report this fail after the block type is output instead of sometimes before and sometimes after). See example acer-xv273k-dp2-corrupted.
    >   First, get the extended type and append it to the tag type (i.e. add 0x700 if extended), then get the OUI if it's vendor specific, and convert it to a number that can be appended (bitwise or) to the tag/extended type value.
    > 	- Init static variables
    > 	- Replace last_block_was_hdmi_vsdb with previous_cta_tag; this means instead of remembering if the last block was hdmi vsdb, we just remember the previous block's tag.
    > 	- Replace first_block with cta_block_number; this means instead of remembering if this is the first block or not, we just remember the current block number.
    > 	- Remove name and oui, we'll just get the data_block string and a oui index directly.
    > 	- Report OUI for extended tag 11h (Vendor-Specific Audio Data Block)
    > 	- Fix capitalization of "Audio information is present" fail message.
    > 	- Add bounds check on length field (must be at least 1 for extended tags).
    > 	- Don't parse after OUI if there's not enough length for OUI.
    > 	- Adjust x offsets in cta_hdmi_block so it is like other OUI extended blocks such that x points to after the OUI.
    > 	- A block that outputs only hex is reported as an unknown block type even if we know the OUI. See example acer-xb321hk-dp.
    > 
    > parse-disableid-block.cpp
    > - Add displayid_block to do a single data block - like cta_block does for cta extension block
    > 	- Vendor specific data block for DisplayID 1.3 is assumed to be PNP (string order). See example apple-macbookpro-16inch-2019.
    > 	- Vendor specific data block for DisplayID 2.0 is assumed to have OUI (little endian).
    > 	- Interpret Vendor specific data block 0x7e or 0x7f even if DisplayID is not correct for that type (there's already a FAIL message to identify the problem). See example apple-xdr-6k.
    > 	- Add bounds check: if length is < 3, only check x[1] if length is 2.
    > 	  Don't report "Not enough bytes remain (1) for a DisplayID data block or the DisplayID filler is non-0." if the bytes are zero (also change the word "or" to "and"). See example apple-xdr-6k-tile0.
    > 	- Report datablock name before failing.
    > 	- For unknown vendor specific data blocks, don't output the OUI part as hex since the new data_block_oui function has already reported it. See example apple-macbookpro-16inch-2019.
    > 	- Replace first_data_block with disp.block_number

    I've decided not to merge this patch. It does too many things at the same time,
    so it really should be split up into smaller pieces.

    I'm also getting ugly lines like this:

    Unknown CTA-861 Data Block (tag 0x00): Unknown block type: Unknown CTA-861 Data Block (tag 0x00).

    or this:

    Vendor-Specific Data Block (NVIDIA), OUI 00-04-4B: Unknown block type: Vendor-Specific Data Block (NVIDIA),
    OUI 00-04-4B.

    (which shouldn't be a warning anyway)

    > 
    > Signed-off-by: Joe van Tunen <joevt@shaw.ca>
    > ---
    >  edid-decode.cpp           |  99 ++++++--
    >  edid-decode.h             |  20 +-
    >  oui.h                     |  20 ++
    >  parse-cta-block.cpp       | 456 ++++++++++++++-----------------------
    >  parse-displayid-block.cpp | 463 ++++++++++++++++++--------------------
    >  5 files changed, 505 insertions(+), 553 deletions(-)

    While it does reduce the code size a bit, it really isn't by all that much,
    so I am not convinced that all the churn is worth it.

    If this is split up into first fixes and small improvements, and then rework
    the tag handling, then I can take another look at whether it makes sense to
    apply this.

    I've applied patches 1, 2, 3, 4, 6, 8, 9 and 10. The others need more work.

    Regards,

    	Hans

    >  create mode 100644 oui.h
    > 
    > diff --git a/edid-decode.cpp b/edid-decode.cpp
    > index 0c83e0e..ed3223d 100644
    > --- a/edid-decode.cpp
    > +++ b/edid-decode.cpp
    > @@ -657,25 +657,90 @@ std::string utohex(unsigned char x)
    >  	return buf;
    >  }
    >  
    > -const char *oui_name(unsigned oui, bool reverse)
    > +const char *oui_name(unsigned oui, unsigned *ouinum)
    >  {
    > -	if (reverse)
    > -		oui = (oui >> 16) | (oui & 0xff00) | ((oui & 0xff) << 16);
    > -
    > +	unsigned ouinumscratch;
    > +	if (!ouinum) ouinum = &ouinumscratch;
    > +	const char *name;
    >  	switch (oui) {
    > -	case 0x00001a: return "AMD";
    > -	case 0x000c03: return "HDMI";
    > -	case 0x00044b: return "NVIDIA";
    > -	case 0x000c6e: return "ASUS";
    > -	case 0x0010fa: return "Apple";
    > -	case 0x0014b9: return "MSTAR";
    > -	case 0x00d046: return "Dolby";
    > -	case 0x00e047: return "InFocus";
    > -	case 0x3a0292: return "VESA";
    > -	case 0x90848b: return "HDR10+";
    > -	case 0xc45dd8: return "HDMI Forum";
    > -	case 0xca125c: return "Microsoft";
    > -	default: return NULL;
    > +		#define oneoui(c,k,n) case c: *ouinum = kOUI_##k; name = n; break;
    > +		#include "oui.h"
    > +		default: *ouinum = 0; name = NULL;
    > +	}
    > +	return name;
    > +}
    > +
    > +void edid_state::data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii, bool big_endian)
    > +{
    > +	std::string buf;
    > +	char ascii[4];
    > +	unsigned oui;
    > +	const char *ouiname = NULL;
    > +	bool matched_reverse = false;
    > +	bool matched_ascii = false;
    > +	bool valid_ascii = false;
    > +
    > +	if (big_endian)
    > +		oui = ((length > 0 ? x[0] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 2 ? x[2] : 0);
    > +	else
    > +		oui = ((length > 2 ? x[2] : 0) << 16) + ((length > 1 ? x[1] : 0) << 8) + (length > 0 ? x[0] : 0);
    > +
    > +	buf = ouitohex(oui);
    > +	if (length < 3) {
    > +		sprintf(ascii, "?"); // some characters are null
    > +		if (ouinum) *ouinum = 0; // doesn't match a known OUI
    > +	} else {
    > +		valid_ascii = (x[0] >= 'A' && x[1] >= 'A' && x[2] >= 'A' && x[0] <= 'Z' && x[1] <= 'Z' && x[2] <= 'Z');
    > +		sprintf(ascii, "%c%c%c", x[0], x[1], x[2]);
    > +
    > +		ouiname = oui_name(oui, ouinum);
    > +		if (!ouiname) {
    > +			big_endian = !big_endian;
    > +			unsigned reversedoui = ((oui & 0xff) << 16) + (oui & 0x00ff00) + (oui >> 16);
    > +			ouiname = oui_name(reversedoui, ouinum);
    > +			if (ouiname) {
    > +				oui = reversedoui;
    > +				buf = ouitohex(oui);
    > +				matched_reverse = true;
    > +			}
    > +			else if (do_ascii && valid_ascii)
    > +			{
    > +				unsigned asciioui = (x[0] << 24) + (x[1] << 16) + (x[2] << 8);
    > +				ouiname = oui_name(asciioui, ouinum);
    > +				if (ouiname) {
    > +					matched_ascii = true;
    > +				}
    > +			}
    > +		}
    > +	}
    > +
    > +	std::string name;
    > +	if (ouiname) {
    > +		if (matched_ascii)
    > +			name = block_name + " (" + ouiname + ")" + ", PNP ID '" + ascii + "'";
    > +		else
    > +			name = block_name + " (" + ouiname + ")" + ", OUI " + buf;
    > +	} else if (do_ascii && valid_ascii) {
    > +		name = block_name + ", PNP ID '" + ascii + "'";
    > +	} else {
    > +		name = block_name + ", OUI " + buf;
    > +	}
    > +	// assign string to data_block before outputting errors
    > +	data_block = name;
    > +
    > +	if (oui || !ignorezeros) {
    > +		if (length < 3)
    > +			fail("Data block length is not enough to contain an OUI.\n");
    > +		if (ouiname && do_ascii && !valid_ascii)
    > +			warn("Expected PNP ID but found OUI.\n");
    > +		if (ouiname && matched_reverse)
    > +			warn("Endian-ness (%s) of OUI is different than expected (%s).\n", big_endian ? "be" : "le", big_endian ? "le" : "be");
    > +		if (!ouiname) {
    > +			if (valid_ascii)
    > +				warn("Unknown OUI %s (possible PNP %s).\n", buf.c_str(), ascii);
    > +			else
    > +				warn("Unknown OUI %s.\n", buf.c_str());
    > +		}
    >  	}
    >  }
    >  
    > diff --git a/edid-decode.h b/edid-decode.h
    > index 612d22a..9e6a955 100644
    > --- a/edid-decode.h
    > +++ b/edid-decode.h
    > @@ -153,8 +153,10 @@ struct edid_state {
    >  		// CTA-861 block state
    >  		cta.has_vic_1 = cta.first_svd_might_be_preferred = cta.has_sldb =
    >  			cta.has_hdmi = cta.has_vcdb = cta.has_vfpdb = false;
    > -		cta.last_block_was_hdmi_vsdb = cta.have_hf_vsdb = cta.have_hf_scdb = false;
    > -		cta.first_block = cta.first_svd = true;
    > +		cta.have_hf_vsdb = cta.have_hf_scdb = false;
    > +		cta.previous_cta_tag = 0xfff;
    > +		cta.block_number = 0;
    > +		cta.first_svd = true;
    >  		cta.supported_hdmi_vic_codes = cta.supported_hdmi_vic_vsb_codes = 0;
    >  		memset(cta.vics, 0, sizeof(cta.vics));
    >  		memset(cta.preparsed_has_vic, 0, sizeof(cta.preparsed_has_vic));
    > @@ -175,6 +177,7 @@ struct edid_state {
    >  		dispid.is_display = dispid.has_product_identification =
    >  			dispid.has_display_parameters = dispid.has_type_1_7 =
    >  			dispid.has_display_interface_features = false;
    > +		dispid.block_number = 0;
    >  
    >  		// Block Map block state
    >  		block_map.saw_block_1 = false;
    > @@ -257,9 +260,9 @@ struct edid_state {
    >  		bool preparsed_sld;
    >  		bool has_sldb;
    >  		unsigned short preparsed_phys_addr;
    > -		bool last_block_was_hdmi_vsdb;
    > +		unsigned previous_cta_tag;
    >  		bool have_hf_vsdb, have_hf_scdb;
    > -		bool first_block;
    > +		unsigned block_number;
    >  		bool first_svd;
    >  		unsigned supported_hdmi_vic_codes;
    >  		unsigned supported_hdmi_vic_vsb_codes;
    > @@ -282,6 +285,7 @@ struct edid_state {
    >  		bool has_display_interface_features;
    >  		vec_timings_ext preferred_timings;
    >  		unsigned native_width, native_height;
    > +		unsigned block_number;
    >  		// Keep track of the found CTA-861 Tag/Extended Tag pairs.
    >  		// The unsigned value is equal to: (tag << 8) | ext_tag
    >  		std::set<unsigned> found_tags;
    > @@ -331,6 +335,8 @@ struct edid_state {
    >  	void list_dmts();
    >  	void list_established_timings();
    >  
    > +	void data_block_oui(std::string block_name, const unsigned char *x, unsigned length, bool ignorezeros, unsigned *ouinum, bool do_ascii = false, bool big_endian = false);
    > +
    >  	void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false);
    >  	void hdmi_latency(unsigned char vid_lat, unsigned char aud_lat, bool is_ilaced);
    >  	void cta_vcdb(const unsigned char *x, unsigned length);
    > @@ -390,6 +396,7 @@ struct edid_state {
    >  	void parse_displayid_type_10_timing(const unsigned char *x, unsigned sz,
    >  					    bool is_cta = false);
    >  	void preparse_displayid_block(const unsigned char *x);
    > +	unsigned displayid_block(const unsigned version, const unsigned char *x, unsigned length);
    >  	void parse_displayid_block(const unsigned char *x);
    >  	void parse_displayid_vesa(const unsigned char *x);
    >  	void parse_displayid_cta_data_block(const unsigned char *x);
    > @@ -454,7 +461,7 @@ void hex_block(const char *prefix, const unsigned char *x, unsigned length,
    >  	       bool show_ascii = true, unsigned step = 16);
    >  std::string block_name(unsigned char block);
    >  void calc_ratio(struct timings *t);
    > -const char *oui_name(unsigned oui, bool reverse = false);
    > +const char *oui_name(unsigned oui, unsigned *ouinum = NULL);
    >  
    >  bool timings_close_match(const timings &t1, const timings &t2);
    >  const struct timings *find_dmt_id(unsigned char dmt_id);
    > @@ -465,4 +472,7 @@ const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic);
    >  unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic);
    >  char *extract_string(const unsigned char *x, unsigned len);
    >  
    > +#define oneoui(c,k,n) const unsigned kOUI_##k = __LINE__<<12;
    > +#include "oui.h"
    > +
    >  #endif
    > diff --git a/oui.h b/oui.h
    > new file mode 100644
    > index 0000000..c90f025
    > --- /dev/null
    > +++ b/oui.h
    > @@ -0,0 +1,20 @@
    > +// http://standards-oui.ieee.org/oui/oui.txt
    > +oneoui(0x000c03, HDMI,         "HDMI"        )
    > +oneoui(0xc45dd8, HDMIForum,    "HDMI Forum"  )
    > +oneoui(0x90848b, HDR10,        "HDR10+"      )
    > +oneoui(0x00001a, AMD,          "AMD"         )
    > +oneoui(0x00044b, NVIDIA,       "NVIDIA"      )
    > +oneoui(0x000c6e, ASUS,         "ASUS"        )
    > +oneoui(0x0010fa, Apple,        "Apple"       )
    > +oneoui(0x0014b9, MSTAR,        "MSTAR"       )
    > +oneoui(0x00d046, Dolby,        "Dolby"       )
    > +oneoui(0x00e047, InFocus,      "InFocus"     )
    > +oneoui(0xca125c, Microsoft,    "Microsoft"   )
    > +
    > +// http://standards-oui.ieee.org/cid/cid.txt
    > +oneoui(0x3a0292, VESA,         "VESA"        )
    > +
    > +// https://uefi.org/pnp_id_list
    > +oneoui('APP\0' , asciiApple,   "Apple"       )
    > +
    > +#undef oneoui
    > diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
    > index 4edaa1d..9bc0c77 100644
    > --- a/parse-cta-block.cpp
    > +++ b/parse-cta-block.cpp
    > @@ -652,57 +652,57 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
    >  {
    >  	unsigned len_vic, len_3d;
    >  
    > -	if (length < 4) {
    > -		fail("Empty Data Block with length %u.\n", length);
    > +	if (length < 1) {
    > +		fail("Empty Data Block.\n");
    >  		return;
    >  	}
    > -	printf("    Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
    > -	       x[4] >> 4, x[4] & 0x0f);
    > +	printf("    Source physical address: %x.%x.%x.%x\n", x[0] >> 4, x[0] & 0x0f,
    > +	       x[1] >> 4, x[1] & 0x0f);
    >  
    > -	if (length < 6)
    > +	if (length < 3)
    >  		return;
    >  
    > -	if (x[5] & 0x80)
    > +	if (x[2] & 0x80)
    >  		printf("    Supports_AI\n");
    > -	if (x[5] & 0x40)
    > +	if (x[2] & 0x40)
    >  		printf("    DC_48bit\n");
    > -	if (x[5] & 0x20)
    > +	if (x[2] & 0x20)
    >  		printf("    DC_36bit\n");
    > -	if (x[5] & 0x10)
    > +	if (x[2] & 0x10)
    >  		printf("    DC_30bit\n");
    > -	if (x[5] & 0x08)
    > +	if (x[2] & 0x08)
    >  		printf("    DC_Y444\n");
    >  	/* two reserved bits */
    > -	if (x[5] & 0x01)
    > +	if (x[2] & 0x01)
    >  		printf("    DVI_Dual\n");
    >  
    > -	if (length < 7)
    > +	if (length < 4)
    >  		return;
    >  
    > -	printf("    Maximum TMDS clock: %u MHz\n", x[6] * 5);
    > -	if (x[6] * 5 > 340)
    > +	printf("    Maximum TMDS clock: %u MHz\n", x[3] * 5);
    > +	if (x[3] * 5 > 340)
    >  		fail("HDMI VSDB Max TMDS rate is > 340.\n");
    >  
    > -	if (length < 8)
    > +	if (length < 5)
    >  		return;
    >  
    > -	if (x[7] & 0x0f) {
    > +	if (x[4] & 0x0f) {
    >  		printf("    Supported Content Types:\n");
    > -		if (x[7] & 0x01)
    > +		if (x[4] & 0x01)
    >  			printf("      Graphics\n");
    > -		if (x[7] & 0x02)
    > +		if (x[4] & 0x02)
    >  			printf("      Photo\n");
    > -		if (x[7] & 0x04)
    > +		if (x[4] & 0x04)
    >  			printf("      Cinema\n");
    > -		if (x[7] & 0x08)
    > +		if (x[4] & 0x08)
    >  			printf("      Game\n");
    >  	}
    >  
    > -	unsigned b = 8;
    > -	if (x[7] & 0x80) {
    > +	unsigned b = 5;
    > +	if (x[4] & 0x80) {
    >  		hdmi_latency(x[b], x[b + 1], false);
    >  
    > -		if (x[7] & 0x40) {
    > +		if (x[4] & 0x40) {
    >  			if (x[b] == x[b + 2] &&
    >  			    x[b + 1] == x[b + 3])
    >  				warn("Progressive and Interlaced latency values are identical, no need for both.\n");
    > @@ -712,7 +712,7 @@ void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
    >  		b += 2;
    >  	}
    >  
    > -	if (!(x[7] & 0x20))
    > +	if (!(x[4] & 0x20))
    >  		return;
    >  
    >  	bool mask = false;
    > @@ -1990,293 +1990,169 @@ static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
    >  	}
    >  }
    >  
    > -void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
    > -			       bool duplicate)
    > +#define data_block_o(n) do { data_block_oui(n, x, length, false, &ouinum); if (length < 3) return; length -= 3; x += 3; } while(0)
    > +
    > +void edid_state::cta_block(const unsigned char *x, bool duplicate)
    >  {
    > -	const char *name;
    > -	unsigned oui;
    > -	bool reverse = false;
    > +	unsigned length = x[0] & 0x1f; // number of bytes after the tag/length byte
    > +	unsigned ouinum = 0;
    > +	unsigned tag=(x[0] & 0xe0) >> 5;
    > +	unsigned extended = (tag == 0x07) ? 1 : 0;
    > +	x++;
    > +	if (extended) {
    > +		if (!length) {
    > +			fail("Extended tag cannot have length 0.\n");
    > +			return;
    > +		}
    > +		length--;
    > +		tag = 0x700 + x[0];
    > +		x++;
    > +	}
    > +
    >  	bool audio_block = false;
    >  
    > -	switch (x[0]) {
    > -	case 0x00: data_block = "Video Capability Data Block"; break;
    > -	case 0x01: data_block.clear(); break;
    > -	case 0x02: data_block = "VESA Video Display Device Data Block"; break;
    > -	case 0x03: data_block = "VESA Video Timing Block Extension"; break;
    > -	case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
    > -	case 0x05: data_block = "Colorimetry Data Block"; break;
    > -	case 0x06: data_block = "HDR Static Metadata Data Block"; break;
    > -	case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
    > -
    > -	case 0x0d: data_block = "Video Format Preference Data Block"; break;
    > -	case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
    > -	case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
    > -	case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
    > -	case 0x11: data_block.clear(); audio_block = true; break;
    > -	case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
    > -	case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
    > -	case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
    > -
    > -	case 0x20: data_block = "InfoFrame Data Block"; break;
    > -
    > -	case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
    > -	case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
    > -	case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
    > -
    > -	case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
    > -	case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
    > +	switch (tag) {
    > +	case 0x001: data_block = "Audio Data Block"; audio_block = true; break;
    > +	case 0x002: data_block = "Video Data Block"; break;
    > +	case 0x003: data_block_o("Vendor-Specific Data Block"); break;
    > +	case 0x004: data_block = "Speaker Allocation Data Block"; audio_block = true; break;
    > +	case 0x005: data_block = "VESA Display Transfer Characteristics Data Block"; break;
    > +
    > +	case 0x700: data_block = "Video Capability Data Block"; break;
    > +	case 0x701: data_block_o("Vendor-Specific Video Data Block"); break;
    > +	case 0x702: data_block = "VESA Video Display Device Data Block"; break;
    > +	case 0x703: data_block = "VESA Video Timing Block Extension"; break; // not implemented
    > +	case 0x704: data_block = "Reserved for HDMI Video Data Block"; break; // reserved
    > +	case 0x705: data_block = "Colorimetry Data Block"; break;
    > +	case 0x706: data_block = "HDR Static Metadata Data Block"; break;
    > +	case 0x707: data_block = "HDR Dynamic Metadata Data Block"; break;
    > +
    > +	case 0x70d: data_block = "Video Format Preference Data Block"; break;
    > +	case 0x70e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
    > +	case 0x70f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
    > +	case 0x710: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break; // reserved
    > +	case 0x711: data_block_o("Vendor-Specific Audio Data Block"); audio_block = true; break; // no vendors implemented
    > +	case 0x712: data_block = "HDMI Audio Data Block"; audio_block = true; break;
    > +	case 0x713: data_block = "Room Configuration Data Block"; audio_block = true; break;
    > +	case 0x714: data_block = "Speaker Location Data Block"; audio_block = true; break;
    > +
    > +	case 0x720: data_block = "InfoFrame Data Block"; break;
    > +
    > +	case 0x734: data_block = "DisplayID Type VII Video Timing Data Block"; break;
    > +	case 0x735: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
    > +	case 0x742: data_block = "DisplayID Type X Video Timing Data Block"; break;
    > +
    > +	case 0x778: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
    > +	case 0x779: data_block = "HDMI Forum Sink Capability Data Block"; break;
    >  	default:
    > -		if (x[0] <= 12)
    > -			printf("  Unknown CTA-861 Video-Related");
    > -		else if (x[0] <= 31)
    > -			printf("  Unknown CTA-861 Audio-Related");
    > -		else if (x[0] >= 120 && x[0] <= 127)
    > -			printf("  Unknown CTA-861 HDMI-Related");
    > -		else
    > -			printf("  Unknown CTA-861");
    > -		printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
    > -		hex_block("    ", x + 1, length);
    > -		data_block.clear();
    > -		warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
    > -		return;
    > -	}
    > -
    > -	switch (x[0]) {
    > -	case 0x00:
    > -	case 0x02:
    > -	case 0x05:
    > -	case 0x06:
    > -	case 0x0d:
    > -	case 0x0f:
    > -	case 0x12:
    > -	case 0x13:
    > -	case 0x78:
    > -	case 0x79:
    > +		     if (tag < 0x700) data_block = "Unknown CTA-861 Data Block";
    > +		else if (tag < 0x70d) data_block = "Unknown CTA-861 Video-Related Data Block";
    > +		else if (tag < 0x720) data_block = "Unknown CTA-861 Audio-Related Data Block";
    > +		else if (tag < 0x778) data_block = "Unknown CTA-861 Data Block";
    > +		else if (tag < 0x780) data_block = "Unknown CTA-861 HDMI-Related Data Block";
    > +		else                  data_block = "Unknown CTA-861 Data Block";
    > +		data_block += std::string(" (") + (extended ? "extended " : "") + "tag " + utohex(tag & 0xff) + ")";
    > +	}
    > +
    > +	printf("  %s:\n", data_block.c_str());
    > +
    > +	switch (tag) {
    > +	case 0x004:
    > +	case 0x005:
    > +	case 0x700:
    > +	case 0x702:
    > +	case 0x705:
    > +	case 0x706:
    > +	case 0x70d:
    > +	case 0x70f:
    > +	case 0x712:
    > +	case 0x713:
    > +	case 0x778:
    > +	case 0x779:
    >  		if (duplicate)
    >  			fail("Only one instance of this Data Block is allowed.\n");
    > -		break;
    >  	}
    >  
    > -
    >  	// See Table 52 of CTA-861-G for a description of Byte 3
    >  	if (audio_block && !(cta.byte3 & 0x40))
    > -		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
    > -
    > -	if (data_block.length())
    > -		printf("  %s:\n", data_block.c_str());
    > -
    > -	switch (x[0]) {
    > -	case 0x00: cta_vcdb(x + 1, length); return;
    > -	case 0x01:
    > -		if (length < 3) {
    > -			data_block = std::string("Vendor-Specific Video Data Block");
    > -			fail("Invalid length %u < 3.\n", length);
    > -			return;
    > -		}
    > -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
    > -		name = oui_name(oui);
    > -		if (!name) {
    > -			name = oui_name(oui, true);
    > -			if (name)
    > -				reverse = true;
    > -		}
    > -		if (!name) {
    > -			printf("  Vendor-Specific Video Data Block, OUI %s:\n",
    > -			       ouitohex(oui).c_str());
    > -			hex_block("    ", x + 4, length - 3);
    > -			data_block.clear();
    > -			warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
    > -			     ouitohex(oui).c_str());
    > -			return;
    > -		}
    > -		data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
    > -		if (reverse)
    > -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
    > -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
    > -		if (oui == 0x90848b)
    > -			cta_hdr10plus(x + 4, length - 3);
    > -		else if (oui == 0x00d046)
    > -			cta_dolby_video(x + 4, length - 3);
    > -		else
    > -			hex_block("    ", x + 4, length - 3);
    > -		return;
    > -	case 0x02: cta_vesa_vdddb(x + 1, length); return;
    > -	case 0x05: cta_colorimetry_block(x + 1, length); return;
    > -	case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
    > -	case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
    > -	case 0x0d: cta_vfpdb(x + 1, length); return;
    > -	case 0x0e: cta_svd(x + 1, length, true); return;
    > -	case 0x0f: cta_y420cmdb(x + 1, length); return;
    > -	case 0x11:
    > -		if (length < 3) {
    > -			data_block = std::string("Vendor-Specific Audio Data Block");
    > -			fail("Invalid length %u < 3.\n", length);
    > -			return;
    > -		}
    > -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
    > -		name = oui_name(oui);
    > -		if (!name) {
    > -			name = oui_name(oui, true);
    > -			if (name)
    > -				reverse = true;
    > -		}
    > -		if (!name) {
    > -			printf("  Vendor-Specific Audio Data Block, OUI %s:\n",
    > -			       ouitohex(oui).c_str());
    > -			hex_block("    ", x + 4, length - 3);
    > -			data_block.clear();
    > -			warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
    > -			     ouitohex(oui).c_str());
    > -			return;
    > -		}
    > -		data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
    > -		if (reverse)
    > -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
    > -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
    > -		if (oui == 0x00d046)
    > -			cta_dolby_audio(x + 4, length - 3);
    > +		fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
    > +
    > +	tag |= ouinum;
    > +	switch (tag) {
    > +	case 0x001: cta_audio_block(x, length); break;
    > +	case 0x002: cta_svd(x, length, false); break;
    > +	case 0x003|kOUI_HDMI:
    > +		cta_hdmi_block(x, length);
    > +		// The HDMI OUI is present, so this EDID represents an HDMI
    > +		// interface. And HDMI interfaces must use EDID version 1.3
    > +		// according to the HDMI Specification, so check for this.
    > +		if (base.edid_minor != 3)
    > +			fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
    > +				 base.edid_minor);
    > +		break;
    > +	case 0x003|kOUI_HDMIForum:
    > +		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
    > +			fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
    > +		if (cta.have_hf_scdb || cta.have_hf_vsdb)
    > +			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
    > +		cta_hf_scdb(x, length);
    > +		cta.have_hf_vsdb = true;
    > +		break;
    > +	case 0x003|kOUI_AMD: cta_amd(x, length); break;
    > +	case 0x003|kOUI_Microsoft:
    > +		if (length == 0x12)
    > +			cta_microsoft(x, length);
    >  		else
    > -			hex_block("    ", x + 4, length - 3);
    > -		return;
    > -	case 0x12: cta_hdmi_audio_block(x + 1, length); return;
    > -	case 0x13: cta_rcdb(x + 1, length); return;
    > -	case 0x14: cta_sldb(x + 1, length); return;
    > -	case 0x20: cta_ifdb(x + 1, length); return;
    > -	case 0x34: cta_displayid_type_7(x + 1, length); return;
    > -	case 0x35: cta_displayid_type_8(x + 1, length); return;
    > -	case 0x42: cta_displayid_type_10(x + 1, length); return;
    > -	case 0x78:
    > -		cta_hf_eeodb(x + 1, length);
    > +			goto dohex;
    > +		break;
    > +	case 0x004: cta_sadb(x, length); break;
    > +	case 0x005: cta_vesa_dtcdb(x, length); break;
    > +	case 0x700: cta_vcdb(x, length); break;
    > +	case 0x701|kOUI_HDR10: cta_hdr10plus(x, length); break;
    > +	case 0x701|kOUI_Dolby: cta_dolby_video(x, length); break;
    > +	case 0x702: cta_vesa_vdddb(x, length); break;
    > +	case 0x705: cta_colorimetry_block(x, length); break;
    > +	case 0x706: cta_hdr_static_metadata_block(x, length); break;
    > +	case 0x707: cta_hdr_dyn_metadata_block(x, length); break;
    > +	case 0x70d: cta_vfpdb(x, length); break;
    > +	case 0x70e: cta_svd(x, length, true); break;
    > +	case 0x70f: cta_y420cmdb(x, length); break;
    > +	case 0x711|kOUI_Dolby: cta_dolby_audio(x, length); break;
    > +	case 0x712: cta_hdmi_audio_block(x, length); break;
    > +	case 0x713: cta_rcdb(x, length); break;
    > +	case 0x714: cta_sldb(x, length); break;
    > +	case 0x720: cta_ifdb(x, length); break;
    > +	case 0x734: cta_displayid_type_7(x, length); break;
    > +	case 0x735: cta_displayid_type_8(x, length); break;
    > +	case 0x742: cta_displayid_type_10(x, length); break;
    > +	case 0x778:
    > +		cta_hf_eeodb(x, length);
    >  		// This must be the first CTA-861 block
    > -		if (!cta.first_block)
    > +		if (cta.block_number > 0)
    >  			fail("Block starts at a wrong offset.\n");
    > -		return;
    > -	case 0x79:
    > -		if (!cta.last_block_was_hdmi_vsdb)
    > +		break;
    > +	case 0x779:
    > +		if (cta.previous_cta_tag != (0x003|kOUI_HDMI))
    >  			fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
    >  		if (cta.have_hf_scdb || cta.have_hf_vsdb)
    >  			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
    >  		if (length < 2) {
    >  			data_block = std::string("HDMI Forum SCDB");
    >  			fail("Invalid length %u < 2.\n", length);
    > -			return;
    > -		}
    > -		if (x[1] || x[2])
    > -			printf("  Non-zero SCDB reserved fields!\n");
    > -		cta_hf_scdb(x + 3, length - 2);
    > -		cta.have_hf_scdb = 1;
    > -		return;
    > -	}
    > -
    > -	hex_block("    ", x + 1, length);
    > -}
    > -
    > -void edid_state::cta_block(const unsigned char *x, bool duplicate)
    > -{
    > -	unsigned length = x[0] & 0x1f;
    > -	const char *name;
    > -	unsigned oui;
    > -	bool reverse = false;
    > -	bool audio_block = false;
    > -
    > -	switch ((x[0] & 0xe0) >> 5) {
    > -	case 0x01:
    > -		data_block = "Audio Data Block";
    > -		printf("  %s:\n", data_block.c_str());
    > -		cta_audio_block(x + 1, length);
    > -		audio_block = true;
    > -		break;
    > -	case 0x02:
    > -		data_block = "Video Data Block";
    > -		printf("  %s:\n", data_block.c_str());
    > -		cta_svd(x + 1, length, false);
    > -		break;
    > -	case 0x03:
    > -		oui = (x[3] << 16) + (x[2] << 8) + x[1];
    > -		name = oui_name(oui);
    > -		if (!name) {
    > -			name = oui_name(oui, true);
    > -			if (name)
    > -				reverse = true;
    > -		}
    > -		if (!name) {
    > -			printf("  Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
    > -			hex_block("    ", x + 4, length - 3);
    > -			data_block.clear();
    > -			warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
    > -			     ouitohex(oui).c_str());
    > -			return;
    > -		}
    > -		data_block = std::string("Vendor-Specific Data Block (") + name + ")";
    > -		if (reverse)
    > -			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
    > -		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
    > -		if (oui == 0x000c03) {
    > -			cta_hdmi_block(x + 1, length);
    > -			cta.last_block_was_hdmi_vsdb = 1;
    > -			cta.first_block = 0;
    > -			// The HDMI OUI is present, so this EDID represents an HDMI
    > -			// interface. And HDMI interfaces must use EDID version 1.3
    > -			// according to the HDMI Specification, so check for this.
    > -			if (base.edid_minor != 3)
    > -				fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
    > -				     base.edid_minor);
    > -			return;
    > -		}
    > -		if (oui == 0xc45dd8) {
    > -			if (!cta.last_block_was_hdmi_vsdb)
    > -				fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
    > -			if (cta.have_hf_scdb || cta.have_hf_vsdb)
    > -				fail("Duplicate HDMI Forum VSDB/SCDB.\n");
    > -			cta_hf_scdb(x + 4, length - 3);
    > -			cta.have_hf_vsdb = 1;
    > -			break;
    > -		}
    > -		if (oui == 0x00001a) {
    > -			cta_amd(x + 4, length - 3);
    > -			break;
    > -		}
    > -		if (oui == 0xca125c && length == 0x15) {
    > -			cta_microsoft(x + 4, length - 3);
    >  			break;
    >  		}
    > -		hex_block("    ", x + 4, length - 3);
    > -		break;
    > -	case 0x04:
    > -		data_block = "Speaker Allocation Data Block";
    > -		printf("  %s:\n", data_block.c_str());
    > -		cta_sadb(x + 1, length);
    > -		audio_block = true;
    > -		if (duplicate)
    > -			fail("Only one instance of this Data Block is allowed.\n");
    > -		break;
    > -	case 0x05:
    > -		data_block = "VESA Display Transfer Characteristics Data Block";
    > -		printf("  %s:\n", data_block.c_str());
    > -		cta_vesa_dtcdb(x + 1, length);
    > -		if (duplicate)
    > -			fail("Only one instance of this Data Block is allowed.\n");
    > -		break;
    > -	case 0x07:
    > -		cta_ext_block(x + 1, length - 1, duplicate);
    > -		break;
    > -	default: {
    > -		unsigned tag = (*x & 0xe0) >> 5;
    > -		unsigned length = *x & 0x1f;
    > -
    > -		printf("  Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
    > -		hex_block("    ", x + 1, length);
    > -		data_block.clear();
    > -		warn("Unknown CTA-861 Data Block %u.\n", tag);
    > +		if (x[0] || x[1])
    > +			printf("  Non-zero SCDB reserved fields!\n");
    > +		cta_hf_scdb(x + 2, length - 2);
    > +		cta.have_hf_scdb = true;
    >  		break;
    > +dohex:
    > +	default:
    > +		hex_block("    ", x, length);
    > +		warn("Unknown block type: %s.\n", data_block.c_str());
    >  	}
    > -	}
    > -
    > -	// See Table 52 of CTA-861-G for a description of Byte 3
    > -	if (audio_block && !(cta.byte3 & 0x40))
    > -		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
    > -	cta.first_block = 0;
    > -	cta.last_block_was_hdmi_vsdb = 0;
    > +	cta.block_number++;
    > +	cta.previous_cta_tag = tag;
    >  }
    >  
    >  void edid_state::preparse_cta_block(const unsigned char *x)
    > @@ -2392,11 +2268,11 @@ void edid_state::parse_cta_block(const unsigned char *x)
    >  //				msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
    >  //				    cta.has_hdmi ? "shall" : "should");
    >  			printf("  Native detailed modes: %u\n", x[3] & 0x0f);
    > -			if (cta.first_block)
    > +			if (cta.block_number == 0)
    >  				cta.byte3 = x[3];
    >  			else if (x[3] != cta.byte3)
    >  				fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
    > -			if (cta.first_block) {
    > +			if (cta.block_number == 0) {
    >  				unsigned native_dtds = x[3] & 0x0f;
    >  
    >  				cta.native_timings.clear();
    > diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
    > index 5c81294..ff7a6db 100644
    > --- a/parse-displayid-block.cpp
    > +++ b/parse-displayid-block.cpp
    > @@ -1609,13 +1609,230 @@ void edid_state::preparse_displayid_block(const unsigned char *x)
    >  	}
    >  }
    >  
    > +#define data_block_o(n, a, b) data_block_oui(n, x + 3, len, tag == 0, &ouinum, a, b)
    > +
    > +unsigned edid_state::displayid_block(const unsigned version, const unsigned char *x, unsigned length)
    > +{
    > +	unsigned i;
    > +	unsigned tag = x[0];
    > +	unsigned ouinum = 0;
    > +	unsigned len = (length < 3) ? 0 : x[2];
    > +
    > +	switch (tag) {
    > +	// DisplayID 1.3:
    > +	case 0x00: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", true, false); ouinum = 0; break;
    > +	case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x02: data_block = "Color Characteristics Data Block"; break;
    > +	case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
    > +	case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
    > +	case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
    > +	case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
    > +	case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
    > +	case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
    > +	case 0x09: data_block = "Video Timing Range Data Block"; break;
    > +	case 0x0a: data_block = "Product Serial Number Data Block"; break;
    > +	case 0x0b: data_block = "GP ASCII String Data Block"; break;
    > +	case 0x0c: data_block = "Display Device Data Data Block"; break;
    > +	case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
    > +	case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
    > +	case 0x0f: data_block = "Display Interface Data Block"; break;
    > +	case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
    > +	case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
    > +	// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
    > +	// DisplayID 2.0
    > +	case 0x20: data_block_o("Product Identification Data Block (" + utohex(tag) + ")", false, false); ouinum = 0; break;
    > +	case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
    > +	case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
    > +	case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
    > +	case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
    > +	case 0x26: data_block = "Display Interface Features Data Block"; break;
    > +	case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
    > +	case 0x29: data_block = "ContainerID Data Block"; break;
    > +	case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
    > +	// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
    > +	case 0x7e: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", false, true); break; // DisplayID 2.0
    > +	case 0x7f: data_block_o("Vendor-Specific Data Block (" + utohex(tag) + ")", true, false); break; // DisplayID 1.3
    > +	// 0x80 RESERVED
    > +	case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
    > +	// 0x82 .. 0xff RESERVED
    > +	default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
    > +	}
    > +
    > +	if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
    > +		fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
    > +			 version >> 4, version & 0xf);
    > +	if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
    > +		fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
    > +			 version >> 4, version & 0xf);
    > +
    > +	if (length < 3) {
    > +		// report a problem when the remaining bytes are not 0.
    > +		if (tag || (length > 1 && x[1])) {
    > +			fail("Not enough bytes remain (%d) for a DisplayID data block and the DisplayID filler is non-0.\n", length);
    > +		}
    > +		return length;
    > +	}
    > +
    > +	unsigned block_rev = x[1] & 0x07;
    > +
    > +	if (length < len + 3) {
    > +		fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d)\n", len + 3, length);
    > +		return length;
    > +	}
    > +
    > +	if (!tag && !len) {
    > +		// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
    > +		if (!memchk(x, length)) {
    > +			fail("Non-0 filler bytes in the DisplayID block.\n");
    > +		}
    > +		return length;
    > +	}
    > +
    > +	printf("  %s:\n", data_block.c_str());
    > +
    > +	tag |= ouinum;
    > +	switch (tag) {
    > +	case 0x00: parse_displayid_product_id(x); break;
    > +	case 0x01: parse_displayid_parameters(x); break;
    > +	case 0x02: parse_displayid_color_characteristics(x); break;
    > +	case 0x03:
    > +		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
    > +		   for (i = 0; i < len / 20; i++)
    > +			   parse_displayid_type_1_7_timing(&x[3 + (i * 20)], false, block_rev);
    > +		   break;
    > +	case 0x04:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < len / 11; i++)
    > +			   parse_displayid_type_2_timing(&x[3 + (i * 11)]);
    > +		   break;
    > +	case 0x05:
    > +		   check_displayid_datablock_revision(x[1], 0, block_rev & 1);
    > +		   for (i = 0; i < len / 3; i++)
    > +			   parse_displayid_type_3_timing(&x[3 + (i * 3)]);
    > +		   break;
    > +	case 0x06:
    > +		   check_displayid_datablock_revision(x[1], 0xc0, 1);
    > +		   for (i = 0; i < len; i++)
    > +			   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6, x[3 + i]);
    > +		   break;
    > +	case 0x07:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < min(len, 10) * 8; i++)
    > +			   if (x[3 + i / 8] & (1 << (i % 8))) {
    > +				   char type[16];
    > +				   sprintf(type, "DMT 0x%02x", i + 1);
    > +				   print_timings("    ", find_dmt_id(i + 1), type);
    > +			   }
    > +		   break;
    > +	case 0x08:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < min(len, 8) * 8; i++)
    > +			   if (x[3 + i / 8] & (1 << (i % 8))) {
    > +				   char type[16];
    > +				   sprintf(type, "VIC %3u", i + 1);
    > +				   print_timings("    ", find_vic_id(i + 1), type);
    > +			   }
    > +		   break;
    > +	case 0x09: parse_displayid_video_timing_range_limits(x); break;
    > +	case 0x0a:
    > +	case 0x0b: parse_displayid_string(x); break;
    > +	case 0x0c: parse_displayid_display_device(x); break;
    > +	case 0x0d: parse_displayid_intf_power_sequencing(x); break;
    > +	case 0x0e: parse_displayid_transfer_characteristics(x); break;
    > +	case 0x0f: parse_displayid_display_intf(x); break;
    > +	case 0x10: parse_displayid_stereo_display_intf(x); break;
    > +	case 0x11:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < len / 7; i++)
    > +			   parse_displayid_type_5_timing(&x[3 + (i * 7)]);
    > +		   break;
    > +	case 0x12: parse_displayid_tiled_display_topology(x, false); break;
    > +	case 0x13:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < len; i += (x[3 + i + 2] & 0x40) ? 17 : 14)
    > +			   parse_displayid_type_6_timing(&x[3 + i]);
    > +		   break;
    > +	case 0x20: parse_displayid_product_id(x); break;
    > +	case 0x21:
    > +		   if (block_rev >= 1)
    > +			   check_displayid_datablock_revision(x[1], 0x80, 1);
    > +		   else
    > +			   check_displayid_datablock_revision(x[1], 0x80, 0);
    > +		   parse_displayid_parameters_v2(x, block_rev);
    > +		   break;
    > +	case 0x22: {
    > +		   unsigned sz = 20;
    > +
    > +		   if (block_rev >= 2)
    > +			   check_displayid_datablock_revision(x[1], 0x08, 2);
    > +		   else if (block_rev == 1)
    > +			   check_displayid_datablock_revision(x[1], 0x08, 1);
    > +		   else
    > +			   check_displayid_datablock_revision(x[1]);
    > +		   sz += (x[1] & 0x70) >> 4;
    > +		   if (block_rev >= 1 && (x[1] & 0x08))
    > +			   printf("    These timings support DSC pass-through\n");
    > +		   for (i = 0; i < len / sz; i++)
    > +			   parse_displayid_type_1_7_timing(&x[3 + i * sz], true, block_rev);
    > +		   break;
    > +	}
    > +	case 0x23:
    > +		   if (block_rev)
    > +			   check_displayid_datablock_revision(x[1], 0xe8, 1);
    > +		   else
    > +			   check_displayid_datablock_revision(x[1], 0xc8);
    > +		   if (x[1] & 0x08) {
    > +			   for (i = 0; i < len / 2; i++)
    > +				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
    > +								   x[3 + i * 2] |
    > +								   (x[4 + i * 2] << 8));
    > +		   } else {
    > +			   for (i = 0; i < len; i++)
    > +				   parse_displayid_type_4_8_timing((x[1] & 0xc0) >> 6,
    > +								   x[3 + i]);
    > +		   }
    > +		   break;
    > +	case 0x24:
    > +		   check_displayid_datablock_revision(x[1]);
    > +		   for (i = 0; i < len / 6; i++)
    > +			   parse_displayid_type_9_timing(&x[3 + i * 6]);
    > +		   break;
    > +	case 0x25: parse_displayid_dynamic_video_timings_range_limits(x); break;
    > +	case 0x26: parse_displayid_interface_features(x); break;
    > +	case 0x27: parse_displayid_stereo_display_intf(x); break;
    > +	case 0x28: parse_displayid_tiled_display_topology(x, true); break;
    > +	case 0x29: parse_displayid_ContainerID(x); break;
    > +	case 0x32: {
    > +		   unsigned sz = 6 + ((x[1] & 0x70) >> 4);
    > +
    > +		   check_displayid_datablock_revision(x[1], 0x70);
    > +		   for (i = 0; i < len / sz; i++)
    > +			   parse_displayid_type_10_timing(&x[3 + i * sz], sz);
    > +		   break;
    > +	}
    > +	case 0x81: parse_displayid_cta_data_block(x); break;
    > +	case 0x7e|kOUI_VESA: parse_displayid_vesa(x); break;
    > +	default: hex_block("    ", x + 3 + (ouinum ? 3 : 0), len - (ouinum ? 3 : 0)); break;
    > +	}
    > +
    > +	if ((tag == 0x00 || tag == 0x20) &&
    > +		(!dispid.is_base_block || dispid.block_number > 0))
    > +		fail("%s is required to be the first DisplayID Data Block.\n",
    > +			 data_block.c_str());
    > +	dispid.block_number++;
    > +	return len + 3;
    > +}
    > +
    >  void edid_state::parse_displayid_block(const unsigned char *x)
    >  {
    >  	unsigned version = x[1];
    >  	unsigned length = x[2];
    >  	unsigned prod_type = x[3]; // future check: based on type, check for required data blocks
    >  	unsigned ext_count = x[4];
    > -	unsigned i;
    >  
    >  	printf("  Version: %u.%u\n  Extension Count: %u\n",
    >  	       version >> 4, version & 0xf, ext_count);
    > @@ -1647,246 +1864,10 @@ void edid_state::parse_displayid_block(const unsigned char *x)
    >  		length = 121;
    >  	}
    >  
    > -	unsigned offset = 5;
    > -	bool first_data_block = true;
    > -	while (length > 0) {
    > -		unsigned tag = x[offset];
    > -		unsigned oui = 0;
    > -
    > -		switch (tag) {
    > -		// DisplayID 1.3:
    > -		case 0x00: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x02: data_block = "Color Characteristics Data Block"; break;
    > -		case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
    > -		case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
    > -		case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
    > -		case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
    > -		case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
    > -		case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
    > -		case 0x09: data_block = "Video Timing Range Data Block"; break;
    > -		case 0x0a: data_block = "Product Serial Number Data Block"; break;
    > -		case 0x0b: data_block = "GP ASCII String Data Block"; break;
    > -		case 0x0c: data_block = "Display Device Data Data Block"; break;
    > -		case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
    > -		case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
    > -		case 0x0f: data_block = "Display Interface Data Block"; break;
    > -		case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
    > -		case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
    > -		// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
    > -		// DisplayID 2.0
    > -		case 0x20: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
    > -		case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
    > -		case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
    > -		case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
    > -		case 0x26: data_block = "Display Interface Features Data Block"; break;
    > -		case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
    > -		case 0x29: data_block = "ContainerID Data Block"; break;
    > -		case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
    > -		// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
    > -		case 0x7e: // DisplayID 2.0
    > -		case 0x7f: // DisplayID 1.3
    > -			if ((tag == 0x7e && version >= 0x20) ||
    > -			    (tag == 0x7f && version < 0x20)) {
    > -				oui = (x[offset + 3] << 16) + (x[offset + 4] << 8) + x[offset + 5];
    > -				const char *name = oui_name(oui);
    > -				bool reversed = false;
    > -
    > -				if (!name) {
    > -					name = oui_name(oui, true);
    > -					if (name)
    > -						reversed = true;
    > -				}
    > -				if (name)
    > -					data_block = std::string("Vendor-Specific Data Block (") + name + ")";
    > -				else
    > -					data_block = "Vendor-Specific Data Block, OUI " + ouitohex(oui);
    > -				if (reversed)
    > -					fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order.\n").c_str());
    > -			} else {
    > -				data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")";
    > -			}
    > -			break;
    > -		// 0x80 RESERVED
    > -		case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
    > -		// 0x82 .. 0xff RESERVED
    > -		default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
    > -		}
    > -
    > -		if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
    > -			fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
    > -			     version >> 4, version & 0xf);
    > -		if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
    > -			fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
    > -			     version >> 4, version & 0xf);
    > -
    > -		if (length < 3) {
    > -			// report a problem when the remaining bytes are not 0.
    > -			if (tag || x[offset + 1]) {
    > -				fail("Not enough bytes remain (%d) for a DisplayID data block or the DisplayID filler is non-0.\n", length);
    > -			}
    > -			break;
    > -		}
    > -
    > -		unsigned block_rev = x[offset + 1] & 0x07;
    > -		unsigned len = x[offset + 2];
    > -
    > -		if (length < len + 3) {
    > -			fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d).\n", len + 3, length);
    > -			break;
    > -		}
    > -
    > -		if (!tag && !len) {
    > -			// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
    > -			if (!memchk(x + offset, length)) {
    > -				fail("Non-0 filler bytes in the DisplayID block.\n");
    > -			}
    > -			break;
    > -		}
    > -
    > -		printf("  %s:\n", data_block.c_str());
    > -
    > -		switch (tag) {
    > -		case 0x00: parse_displayid_product_id(x + offset); break;
    > -		case 0x01: parse_displayid_parameters(x + offset); break;
    > -		case 0x02: parse_displayid_color_characteristics(x + offset); break;
    > -		case 0x03:
    > -			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
    > -			   for (i = 0; i < len / 20; i++)
    > -				   parse_displayid_type_1_7_timing(&x[offset + 3 + (i * 20)], false, block_rev);
    > -			   break;
    > -		case 0x04:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < len / 11; i++)
    > -				   parse_displayid_type_2_timing(&x[offset + 3 + (i * 11)]);
    > -			   break;
    > -		case 0x05:
    > -			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
    > -			   for (i = 0; i < len / 3; i++)
    > -				   parse_displayid_type_3_timing(&x[offset + 3 + (i * 3)]);
    > -			   break;
    > -		case 0x06:
    > -			   check_displayid_datablock_revision(x[offset + 1], 0xc0, 1);
    > -			   for (i = 0; i < len; i++)
    > -				   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6, x[offset + 3 + i]);
    > -			   break;
    > -		case 0x07:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < min(len, 10) * 8; i++)
    > -				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
    > -					   char type[16];
    > -					   sprintf(type, "DMT 0x%02x", i + 1);
    > -					   print_timings("    ", find_dmt_id(i + 1), type);
    > -				   }
    > -			   break;
    > -		case 0x08:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < min(len, 8) * 8; i++)
    > -				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
    > -					   char type[16];
    > -					   sprintf(type, "VIC %3u", i + 1);
    > -					   print_timings("    ", find_vic_id(i + 1), type);
    > -				   }
    > -			   break;
    > -		case 0x09: parse_displayid_video_timing_range_limits(x + offset); break;
    > -		case 0x0a:
    > -		case 0x0b: parse_displayid_string(x + offset); break;
    > -		case 0x0c: parse_displayid_display_device(x + offset); break;
    > -		case 0x0d: parse_displayid_intf_power_sequencing(x + offset); break;
    > -		case 0x0e: parse_displayid_transfer_characteristics(x + offset); break;
    > -		case 0x0f: parse_displayid_display_intf(x + offset); break;
    > -		case 0x10: parse_displayid_stereo_display_intf(x + offset); break;
    > -		case 0x11:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < len / 7; i++)
    > -				   parse_displayid_type_5_timing(&x[offset + 3 + (i * 7)]);
    > -			   break;
    > -		case 0x12: parse_displayid_tiled_display_topology(x + offset, false); break;
    > -		case 0x13:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < len; i += (x[offset + 3 + i + 2] & 0x40) ? 17 : 14)
    > -				   parse_displayid_type_6_timing(&x[offset + 3 + i]);
    > -			   break;
    > -		case 0x20: parse_displayid_product_id(x + offset); break;
    > -		case 0x21:
    > -			   if (block_rev >= 1)
    > -				   check_displayid_datablock_revision(x[offset + 1], 0x80, 1);
    > -			   else
    > -				   check_displayid_datablock_revision(x[offset + 1], 0x80, 0);
    > -			   parse_displayid_parameters_v2(x + offset, block_rev);
    > -			   break;
    > -		case 0x22: {
    > -			   unsigned sz = 20;
    > -
    > -			   if (block_rev >= 2)
    > -				   check_displayid_datablock_revision(x[offset + 1], 0x08, 2);
    > -			   else if (block_rev == 1)
    > -				   check_displayid_datablock_revision(x[offset + 1], 0x08, 1);
    > -			   else
    > -				   check_displayid_datablock_revision(x[offset + 1]);
    > -			   sz += (x[offset + 1] & 0x70) >> 4;
    > -			   if (block_rev >= 1 && (x[offset + 1] & 0x08))
    > -				   printf("    These timings support DSC pass-through\n");
    > -			   for (i = 0; i < len / sz; i++)
    > -				   parse_displayid_type_1_7_timing(&x[offset + 3 + i * sz], true, block_rev);
    > -			   break;
    > -		}
    > -		case 0x23:
    > -			   if (block_rev)
    > -				   check_displayid_datablock_revision(x[offset + 1], 0xe8, 1);
    > -			   else
    > -				   check_displayid_datablock_revision(x[offset + 1], 0xc8);
    > -			   if (x[offset + 1] & 0x08) {
    > -				   for (i = 0; i < len / 2; i++)
    > -					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
    > -									   x[offset + 3 + i * 2] |
    > -									   (x[offset + 4 + i * 2] << 8));
    > -			   } else {
    > -				   for (i = 0; i < len; i++)
    > -					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
    > -									   x[offset + 3 + i]);
    > -			   }
    > -			   break;
    > -		case 0x24:
    > -			   check_displayid_datablock_revision(x[offset + 1]);
    > -			   for (i = 0; i < len / 6; i++)
    > -				   parse_displayid_type_9_timing(&x[offset + 3 + i * 6]);
    > -			   break;
    > -		case 0x25: parse_displayid_dynamic_video_timings_range_limits(x + offset); break;
    > -		case 0x26: parse_displayid_interface_features(x + offset); break;
    > -		case 0x27: parse_displayid_stereo_display_intf(x + offset); break;
    > -		case 0x28: parse_displayid_tiled_display_topology(x + offset, true); break;
    > -		case 0x29: parse_displayid_ContainerID(x + offset); break;
    > -		case 0x32: {
    > -			   unsigned sz = 6 + ((x[offset + 1] & 0x70) >> 4);
    > -
    > -			   check_displayid_datablock_revision(x[offset + 1], 0x70);
    > -			   for (i = 0; i < len / sz; i++)
    > -				   parse_displayid_type_10_timing(&x[offset + 3 + i * sz], sz);
    > -			   break;
    > -		}
    > -		case 0x81: parse_displayid_cta_data_block(x + offset); break;
    > -		case 0x7e:
    > -			if (oui == 0x3a0292) {
    > -				parse_displayid_vesa(x + offset);
    > -				break;
    > -			}
    > -			// fall-through
    > -		default: hex_block("    ", x + offset + 3, len); break;
    > -		}
    > -
    > -		if ((tag == 0x00 || tag == 0x20) &&
    > -		    (!dispid.is_base_block || !first_data_block))
    > -			fail("%s is required to be the first DisplayID Data Block.\n",
    > -			     data_block.c_str());
    > -		length -= len + 3;
    > -		offset += len + 3;
    > -		first_data_block = false;
    > +	unsigned len;
    > +	for (const unsigned char *y = x + 5; length > 0; y += len) {
    > +		len = displayid_block(version, y, length);
    > +		length -= len;
    >  	}
    >  
    >  	/*
    > 




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

end of thread, other threads:[~2021-09-16  9:16 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-14 12:11 [PATCH 00/11] edid-decode: bug fixes, additions, changes joevt
2021-09-14 12:11 ` [PATCH 01/11] edid-decode: add more example EDIDs joevt
2021-09-14 12:11 ` [PATCH 02/11] edid-decode: ignore dSYM joevt
2021-09-14 12:11 ` [PATCH 03/11] edid-decode: change install directories for macOS joevt
2021-09-15 10:06   ` Hans Verkuil
2021-09-15 15:25     ` Joe van Tunen
2021-09-14 12:11 ` [PATCH 04/11] edid-decode: add bounds checking joevt
2021-09-15 10:07   ` Hans Verkuil
2021-09-14 12:11 ` [PATCH 05/11] edid-decode: fix standard timing vertical pixels joevt
2021-09-15 10:08   ` Hans Verkuil
2021-09-15 11:10     ` Hans Verkuil
2021-09-15 18:28       ` Joe van Tunen
2021-09-14 12:11 ` [PATCH 06/11] edid-decode: linefeed before fail joevt
2021-09-14 12:11 ` [PATCH 07/11] edid-decode: always linefeed after hex_block joevt
2021-09-15 10:10   ` Hans Verkuil
2021-09-15 15:43     ` Joe van Tunen
2021-09-15 18:27       ` Joe van Tunen
2021-09-14 12:11 ` [PATCH 08/11] edid-decode: output full frequencies for 4:2:0 joevt
2021-09-14 12:11 ` [PATCH 09/11] edid-decode: allow undefined aspect ratio joevt
2021-09-14 12:11 ` [PATCH 10/11] edid-decode: add warnings to VESA VSDB joevt
2021-09-14 12:11 ` [PATCH 11/11] edid-decode: cta and displayid changes joevt
2021-09-15 13:37   ` Hans Verkuil
2021-09-16  9:15     ` Joe van Tunen

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).