X11 Configuration / xrandr / Refresh Rates

Turns out the modes available can be edited in the kernel source, then compiled.

[JetPack Install Dir]/64_TX1/Linux_for_Tegra_64_tx1/sources/kernel_source/drivers/video/modedb.c contains the definitions of the modes used by the framebuffer and X11 in const struct fb_videomode cea_modes. In my specific example:

/* 97: 3840x2160p @ 60Hz */
	{.refresh = 60, .xres = 3840, .yres = 2160, .pixclock = 1683,
	 .left_margin = 296, .right_margin = 176,
	 .upper_margin = 72, .lower_margin = 8,
	 .hsync_len = 88, .vsync_len = 10,
	 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
	 .flag = FB_FLAG_RATIO_16_9,
	 .vmode = FB_VMODE_NONINTERLACED},

This defines the 4K UHD @ 60fps mode. While modeline calculators and EDID editors alter the pixel clock in terms of MHz, the way they are defined in modedb.c is as a picosecond divisor. As seen above, the pixclock is set to 1683. 1000000/pixclock = the value in MHz for a modeline (e.g. 1683 → 1000000/1683 → 594.18).

The main problem is that this way of defining the pixel clock has a different granularity than the modelines and EDID definitions. While this is one is the closest match for the desired MHz, it creates a rounding error that leads to the 60.02Hz refresh rate (that then gets rejected by devices that have strict allowances).

So, the solution is:

  1. Use a tool that creates modes based off of the modedb.c pixclock format, rather than a "close enough" calculation based on a MHz format.
  2. Alter [JetPack Install Dir]/64_TX1/Linux_for_Tegra_64_tx1/sources/kernel_source/drivers/video/modedb.c -> const struct fb_videomode cea_modes to use the new mode.
  3. Compile the kernel.
  4. Either move the required files (zImage, Image, device tree binaries, modules) to the TX1 and restart, or to the JetPack locaions and flash the TX1.
  5. Configure X11 (/etc/X11/xorg.conf) to use the altered mode.