Skip to content

RobertoNegro/edid-generator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

edid-generator

An interactive command-line wizard to generate custom EDID binary files, compliant with VESA and CTA-861 standards.

What is EDID?

EDID (Extended Display Identification Data) is a block of binary data that every monitor transmits to the computer to describe its capabilities: supported resolutions, refresh rates, color depth, audio support, and more. The operating system reads this information to automatically configure the video output.

In certain scenarios (custom monitors, KVM emulators, headless setups, virtual displays) it is useful to generate a custom EDID. This tool lets you do so through an interactive wizard, producing a .bin file that can be loaded directly into the Linux kernel.

Features

  • Interactive wizard with step-by-step TUI interface
  • Preset resolutions (from 640x480 up to 7680x4320) and arbitrary custom resolutions
  • Multiple refresh rates per resolution (24-360 Hz and beyond)
  • HDMI and DisplayPort interfaces with automatic protocol-specific handling
  • Color depth: 6, 8, 10, or 12 bits per channel
  • HDR10: BT.2020 chromaticity, ST2084 (PQ) EOTF, static luminance metadata
  • HDMI audio: stereo, 5.1 and 7.1 surround (LPCM) with speaker allocation
  • HDMI 2.1: Fixed Rate Link (FRL) up to 48 Gbps, Display Stream Compression (DSC 1.2), ALLM
  • Native CVT Reduced Blanking v1 timing calculation with no external dependencies
  • Optional validation via edid-decode (if installed)

Installation

Requirements: Node.js (version with ES modules support).

npm install

Usage

npm run generate

The wizard will guide you through the configuration:

  1. Display name (max 13 characters)
  2. Manufacturer ID (3 uppercase letters, e.g. DEL, SAM, ACR)
  3. Interface: HDMI or DisplayPort
  4. Color depth: 6, 8, 10, or 12 bpc
  5. HDR: available when color depth >= 10 bpc
  6. Audio: none, stereo, 5.1, or 7.1 (HDMI only)
  7. DPI: used to compute the physical display dimensions
  8. Resolutions and refresh rates: selectable from VIC presets or entered manually
  9. Preferred mode: the primary resolution/refresh rate for the display
  10. Output file: path of the .bin file to generate

Upon completion, the command to load the EDID into the Linux kernel is displayed:

sudo cp output.bin /usr/lib/firmware/edid/
# In /etc/default/grub or your bootloader configuration:
# drm_kms_helper.edid_firmware=HDMI-A-1:edid/output.bin

Testing

npm test

Tests verify the correctness of EDID generation, checksum conformance, and (if edid-decode is installed) validation with the reference tool.

How the generated EDID is structured

An EDID file is composed of one or more 128-byte blocks. The first block is mandatory and contains the display's basic information; subsequent blocks are extensions that add advanced capabilities.

Base block (128 bytes)

The base block follows the EDID 1.3 (for HDMI) or EDID 1.4 (for DisplayPort) standard and contains:

  • Fixed 8-byte header that identifies the file as a valid EDID
  • Manufacturer and product ID: 3-letter manufacturer code and device identifier
  • Week and year of manufacture
  • EDID version: 1.3 or 1.4 depending on the interface (the HDMI specification requires 1.3)
  • Basic video parameters: signal type (digital), color depth, interface type
  • Physical display dimensions in centimeters, computed from DPI and resolution
  • Chromaticity: sRGB color coordinates (or BT.2020 for HDR) describing the display's color gamut
  • Established and standard timings: bitmap of supported classic video modes (640x480, 800x600, etc.)
  • Descriptors (4 slots of 18 bytes each):
    • Preferred DTD: the Detailed Timing Descriptor of the primary resolution/refresh rate, encoding pixel clock, active area, blanking, and sync signals
    • Range limits: supported horizontal and vertical frequency range, maximum pixel clock
    • Display name: ASCII string up to 13 characters
    • Serial number (or an additional DTD)
  • Checksum: the last byte is computed so that the sum of all 128 bytes equals 0 modulo 256

CTA-861 extension (128-byte blocks, tag 0x02)

The CTA-861 extension (also known as CEA extension) is the standard format for declaring advanced capabilities of HDMI and modern displays. It contains:

  • Short Video Descriptor (SVD): a list of VICs (Video Identification Codes), standardized numeric codes from CTA-861 that uniquely identify well-known combinations of resolution, refresh rate, and aspect ratio (e.g. VIC 16 = 1920x1080@60Hz 16:9). Up to 31 VICs per EDID.
  • HDMI data block (HDMI Vendor Specific Data Block): declares HDMI-specific capabilities such as Deep Color support (10/12 bit) and maximum TMDS clock.
  • HDMI Forum data block (HDMI 2.1): declares Fixed Rate Link (FRL) support with the appropriate bandwidth level, Display Stream Compression (DSC), and Auto Low Latency Mode (ALLM).
  • Audio Data Block: supported codecs (LPCM), channel count, sample rates (32/44.1/48 kHz), and bit depths (16/20/24 bit).
  • Speaker Allocation: speaker channel map (front, surround, subwoofer, etc.).
  • Video Capability Data Block (VCDB): declares underscan and basic audio support.
  • Colorimetry Data Block: supported color spaces (sRGB, BT.2020 for HDR).
  • HDR Static Metadata: supported EOTFs (SDR, ST2084/PQ), maximum/minimum luminance values.
  • VFPDB and NVRDB: blocks declaring the preferred video format and native resolution, used for 4K and higher resolutions.
  • Additional DTDs: detailed timings for video modes that lack a standard VIC, with pixel clocks up to 655.35 MHz.

When more DTDs or data are needed than fit in a single block, additional chained CTA-861 blocks are generated.

DisplayID 2.0 extension (128-byte blocks, tag 0x70)

For ultra-high-bandwidth video modes whose pixel clock exceeds 655.35 MHz (the limit of the traditional DTD format), the generator uses DisplayID 2.0 blocks containing:

  • Display Parameters Data Block: resolution, physical size, chromaticity, luminance, and color depth.
  • Type VII Detailed Timing: an extended timing format supporting pixel clocks up to 16+ GHz with 1 kHz resolution, sufficient for any high-refresh-rate 8K mode.

Each DisplayID block can hold multiple timings (3 in the first block, 5 in subsequent ones). If there are many high-bandwidth modes, multiple chained DisplayID blocks are generated.

Block Map (EDID 1.3 only)

When the EDID contains more than one data extension and the version is 1.3, a block map (tag 0xF0) is inserted that lists the types of all extensions present, as required by the specification.

Structure overview

+-------------------+
|  Base Block       |  128 bytes - EDID 1.3 or 1.4
|  (header, DTD,    |  Basic info, preferred timing,
|   range, name)    |  range limits, display name
+-------------------+
|  Block Map        |  128 bytes - EDID 1.3 with 2+ extensions only
|  (optional)       |  Extension block map
+-------------------+
|  CTA-861 #1       |  128 bytes - SVD, HDMI VSDB, audio,
|                   |  HDR, colorimetry, additional DTDs
+-------------------+
|  CTA-861 #2..N    |  128 bytes - Additional DTDs (if needed)
|  (optional)       |
+-------------------+
|  DisplayID #1     |  128 bytes - Display params + Type VII timing
|  (optional)       |  For modes with pixel clock > 655.35 MHz
+-------------------+
|  DisplayID #2..N  |  128 bytes - Additional Type VII timings
|  (optional)       |
+-------------------+

The total number of blocks varies depending on the complexity of the configuration: a 1080p@60Hz HDMI display typically produces 2 blocks (256 bytes), while a 4K display with multiple refresh rates, HDR, and audio can reach 6 or more blocks (768+ bytes).

Motivation: remote gaming on Hyprland with Sunshine and a dummy plug

This project was born out of a specific use case: remote desktop streaming on a Wayland/Hyprland setup with an Nvidia GPU.

The setup consists of 3 physical monitors connected to the GPU plus a DisplayPort dummy plug. When working remotely, the physical monitors are disabled and the dummy plug output is enabled, then streamed to a client via Moonlight + Sunshine.

The reason for the dummy plug is the capture method. On Wayland with Nvidia, the available options are:

  • NvFBC — Nvidia's frame buffer capture API, fast and efficient, but not compatible with Wayland.
  • wlroots — can capture virtual outputs (no physical connection needed), but in practice caused GPU memory leaks, XWayland breakage, and frequent system crashes.
  • KMS — kernel-level capture, stable and reliable, but it can only capture outputs that are physically connected to the GPU. It cannot see virtual outputs.

KMS is the only stable capture method on this setup, but it requires a real signal path from the GPU to a physical connector. A dummy plug satisfies this requirement: the GPU treats it as a real monitor, KMS can capture its framebuffer, and Sunshine streams it to Moonlight. The custom EDID loaded onto the dummy plug output controls what resolutions, refresh rates, and color capabilities are available for the remote session.

Known limitations

DisplayPort bandwidth filtering (Linux)

When using a DisplayPort connection on Linux, the GPU negotiates the actual link parameters with the receiving device through a process called link training. During this negotiation, the GPU and the device agree on two physical characteristics of the connection: the number of lanes (1, 2, or 4) and the link rate per lane (1.62, 2.7, 5.4, or 8.1 Gbps). The product of these two values determines the total available bandwidth.

Cheap DP dummy plugs, adapters, and some KVM switches often support only a subset of lanes or lower link rates. For instance, a device limited to 2 lanes at 2.7 Gbps provides roughly 5.4 Gbps of total bandwidth — far less than the ~12.5 Gbps required for 4K@60Hz at 8 bpc.

The Nvidia driver compares each mode declared in the EDID against the bandwidth actually available on the link. Any mode that exceeds the negotiated bandwidth is silently discarded, regardless of what the EDID says. This means that loading a custom EDID with 4K@60Hz will have no effect if the physical link can only carry 4K@30Hz worth of data: the mode simply won't appear in the list of available resolutions.

This is not an EDID or a driver bug — it is the expected behavior of the DisplayPort standard, which unlike HDMI does not allow a source to send more data than the link can physically carry.

This behavior has been observed with Nvidia proprietary drivers. Whether Intel or AMD GPUs apply the same kind of filtering is unknown — it may depend on the driver implementation.

Possible workarounds:

  • Use a dummy plug or adapter that supports 4 lanes at HBR2 (5.4 Gbps/lane) or higher — this provides ~21.6 Gbps, enough for 4K@120Hz at 8 bpc.
  • If the target resolution is not bandwidth-critical, try lowering the refresh rate or color depth to fit within the available link capacity.
  • Switch to an HDMI dummy plug if the GPU has an HDMI output: HDMI does not perform this kind of pre-filtering, and the EDID modes will be accepted as declared.

Project structure

generate-edid.mjs          CLI wizard (entry point)
lib/
  edid-builder.mjs          Full EDID binary assembly
  cea-extension.mjs         CTA-861 extension block builder
  displayid.mjs             DisplayID 2.0 extension block builder
  timing.mjs                DTD encoding, standard timings, range limits
  cvt.mjs                   CVT Reduced Blanking v1 timing calculation
  constants.mjs             VIC table, audio configurations, FRL levels
tests/
  edid.test.mjs             Test suite
  helpers.mjs               Test utilities and edid-decode integration

Disclaimer

This software is provided as-is, with no warranty of any kind. Use it at your own risk.

The generated EDID binaries are validated with a test suite and checked against edid-decode where possible, and they have worked correctly in every configuration I have personally tested. That said, this is a side project built to solve a specific personal need — it is not continuously exercised across a wide range of hardware and configurations. Unusual or untested combinations of options may produce malformed EDIDs. If you encounter issues, bug reports and pull requests are welcome.

Thanks to

License

MIT

About

Interactive CLI tool that creates EDID binary files for virtual and physical displays. Supports HDMI and DisplayPort from VGA to 8K, with multi-resolution profiles combining any number of modes and refresh rates in a single file. Includes HDR, surround audio, and automatic validation.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors