Custom Low-Resolution Modelines over DVI on Linux

Modern Linux distributions can output custom low-resolution modelines over DVI, but the implementation depends heavily on whether the connection uses analog or digital DVI, GPU hardware limits, and the choice between X11 and Wayland. While native low resolutions like 240p or 480i are achievable for retro gaming or CRT monitors, overcoming driver-level pixel clock minimums and modern display server restrictions requires specific configuration methods such as custom EDID overrides or horizontal super-resolutions.

DVI-I (Analog) vs. DVI-D (Digital) Limitations

The physical interface dictates what signals the graphics card can send:

  • DVI-I (Integrated Analog and Digital): When paired with a passive DVI-to-VGA adapter, DVI-I functions as an analog RGB source. Analog signals have no strict lower limit on pixel clocks, allowing true low native resolutions (e.g., 320x240 at 15 kHz or 60 Hz) commonly used for CRT monitors and arcade setups.
  • DVI-D (Digital Only): Digital DVI operates via Transition-Minimized Differential Signaling (TMDS). The TMDS specification and modern GPU transmitters enforce a minimum pixel clock—typically around 25 MHz. Because a standard resolution like 320x240 @ 60 Hz requires a pixel clock of only ~6.4 MHz, modern graphics drivers will reject the mode over a digital link.

Bypassing Digital Limits with Super-Resolutions

To display a low vertical resolution over digital DVI without falling below the 25 MHz hardware clock floor, you must use "super-resolutions."

By dramatically expanding the horizontal resolution while keeping the vertical line count low (for example, 2560x240 @ 60 Hz), the pixel clock rises above 30 MHz. The monitor processes the image as a valid high-frequency digital signal, while the vertical refresh and line count remain low enough to match 240p timing characteristics without downscaling artifacts.

X11 Implementation via XRandR

Under the traditional X11 display server, custom modelines can be injected dynamically at runtime:

  1. Generate the Modeline: Use utilities like cvt or gtf with the --reduced blanking flag, or use arcade-oriented calculators to define precise timings.
  2. Register the Mode: Add the calculated modeline to X11 using xrandr --newmode.
  3. Assign to Output: Associate the mode with the target DVI port using xrandr --addmode <Output-Name> <Mode-Name>.
  4. Apply the Resolution: Switch to the target resolution using xrandr --output <Output-Name> --mode <Mode-Name>.

If the driver's Kernel Mode Setting (KMS) layer deems the pixel clock invalid for that specific port, the xrandr command will return an error, necessitating an EDID-level workaround.

Wayland and Kernel-Level Configuration (KMS)

Modern distributions increasingly default to Wayland, which does not support dynamic runtime mode injection via tools like xrandr. Instead, custom resolutions must be defined at the Linux kernel level via Direct Rendering Manager (DRM) and Kernel Mode Setting (KMS):

  • Custom EDID Injection: Generate a custom binary EDID containing the required low-resolution timing using tools like Custom Resolution Utility (CRU) or edid-generator. Place the .bin file in /lib/firmware/edid/.
  • Kernel Parameters: Instruct the kernel to force the custom EDID on boot by adding parameters to your bootloader (e.g., GRUB): drm.edid_firmware=DVI-I-1:edid/custom_240p.bin video=DVI-I-1:e
  • Video Command Line Overrides: In some setups, basic mode forcing can be declared directly using video=DVI-I-1:640x480@60 in the kernel parameters, though custom arbitrary timings still require a full EDID profile.

GPU Driver Considerations

  • Open-Source AMD/Intel Drivers (amdgpu, radeon, i915): These drivers offer the highest flexibility for custom modes and 15 kHz output, especially when patched with community retro-gaming kernels (such as the Linux CRT Emudriver forks).
  • NVIDIA Proprietary Drivers: NVIDIA's proprietary driver uses its own internal mode validation engine and often ignores standard KMS EDID overrides, requiring configuration via custom xorg.conf blocks with ModeValidation flags set to disable clock and frequency checks.