Hi everybody.
I’ve gotten the zcu104 board and are trying to establish a hdmi passthrough at 1920x1080@~120Hz using the base overlay on pynq 3.0.1. This have shown to be more difficult than I thought it would be - I have not succeeded (yet) and hope to hear some of your thoughts on the problems I am facing here.
I am using a ASUS PG27AQDP 480 Hz OLED monitor ( ASUS ROG Swift OLED PG27AQDP Review - RTINGS.com ). Before connecting it to the HDMI out port of the zcu104 - I’ve connected the monitor directly to my ubuntu PC. On the PC I have set the display settings on the monitor to be the 1920x1080 @119.88Hz option. I’ve then run the command “xvidtune -show” to get the timing information:
“1920x1080“ 296.70 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
With a pixel clock of 296.70 MHz it should be well under the 300 Mhz with 2 ppc that the zcu104 has capabilities to handle. I’ve used wxEDID to make a EDID block that sets this resolution as the preferred resolution.
I have tested both HDMI cables for the passthrough setup between the PC and the monitor running this resolution. Now I setup the monitor, the zcu104, and the PC in a passthrough setup where I use the one HDMI cables to connect from the PC to the zcu104 HDMI-in port and the other to connect the zcu104 HDMI-out port to the monitor HDMI in.
I then use the following python/pynq code to setup the hdmi passthrough:
from pynq.overlays.base import BaseOverlay
from pynq.lib.video import *
base = BaseOverlay("self_base.bit")
hdmi_in = base.video.hdmi_in
hdmi_out = base.video.hdmi_out
import time
# EDID that I created used xvidtune and wxEDID
EDID_HEX = """00FFFFFFFFFFFF0006B34027FFFFFFFF
30220103803B21782A5420AD523FAF25
0C5054254A00814081808100A940D1C0
010101010101E673801871382D40582C
45004B4A2100001A000000FD0A28E11E
FFFC000A202020202020000000FC0050
473237415144500A20202020000000FF
0053424C4D52533034303938390A0154
020367F1E27802550413101F61607675
3F402221205F5E5D0312021101230907
07830100006D030C0020003844200060
0302016DD85DC40178806B0268E0C364
1DE20FF0E200EAE305C301E606050197
4C03741A0000030328F0F08497034C04
E00100000000006FC200A0A0A0555030
2035004B4A2100001A00000000000000"""
edid_data = bytes.fromhex(''.join(EDID_HEX.split())) # removes whitespace/newlines
if not (128 <= len(edid_data) <= 256):
raise ValueError("EDID must be between 128 and 256 bytes long")
# Load EDID into the rx submodule
hdmi_in.frontend.load_edid(edid_data)
hdmi_in.configure()
print(hdmi_in.mode)
hdmi_out.configure(hdmi_in.mode)
print(hdmi_out.mode)
hdmi_out.cacheable_frames = False
hdmi_in.cacheable_frames = False
hdmi_out.start()
hdmi_in.start()
hdmi_in.tie(hdmi_out)
try:
hdmi_out._hdmi.report()
except Exception as e:
print("hdmi_out.report() raised:", e)
try:
hdmi_in._hdmi.report()
except Exception as e:
print("hdmi_in.report() raised:", e)
Running this will yield the following output to the terminal:
Successfully loaded edid.
Successfully loaded edid.
VideoMode: width=1920 height=1080 bpp=24 fps=120
VideoMode: width=1920 height=1080 bpp=24 fps=120
------------
HDMI TX SubSystem
------------
->HDMI TX Subsystem Cores
: HDMI TX
: VTC Core
HDMI TX version : 03.00 (0400)
VTC version : 06.02 (000c)
HDMI TX timing
------------
HDMI TX Mode - HDMI
HDMI Video Mask is Disabled
Color Format: RGB
Color Depth: 8
Pixels Per Clock: 2
Mode: Progressive
DSC Status: Uncompressed
Frame Rate: 120Hz
Resolution: 1920x1080@120Hz
Pixel Clock: 297000 kHz
HSYNC Timing: hav=1920, hfp=88, hsw=44(hsp=1), hbp=148, htot=2200
VSYNC Timing: vav=1080, vfp=04, vsw=05(vsp=1), vbp=036, vtot=1125
Scrambled: 0
Sample rate: 1
Audio
---------
Format : L-PCM
Channels : 0
DRM info frame
--------------
No DRM info
------------
HDMI RX SubSystem
------------
->HDMI RX Subsystem Cores
: HDMI RX
HDMI RX version : 03.00 (0460)
HDMI RX Mode - HDMI
------------
HDMI RX timing
------------
Color Format: RGB
Color Depth: 8
Pixels Per Clock: 2
Mode: Progressive
DSC Status: Uncompressed
Frame Rate: 120Hz
Resolution: 1920x1080 [Custom Mode]
Pixel Clock: 297000 kHz
HSYNC Timing: hav=1920, hfp=88, hsw=44(hsp=1), hbp=148, htot=2200
VSYNC Timing: vav=1080, vfp=04, vsw=05(vsp=0), vbp=036, vtot=1125
VIC: 0
Scrambled: 0
Link quality
---------
Link quality channel 0 : bad (65535)
Link quality channel 1 : bad (65535)
Link quality channel 2 : bad (65535)
Audio
---------
Format : L-PCM
Channels : 2
ACR CTS : 329666
ACR N : 6272
DRM info frame
--------------
eotf: 0
DRM IF info:
desc id: 0
display primaries x0, y0, x1, y1, x2, y2: 0 0 0 0 0 0
white point x, y: 0 0
min/max display mastering luminance: 0 0
Max_CLL: 0
max_fall: 0
Infoframe
---------
RX header: 271a0187
But the monitor will just remain black…
One thing that I noted is that it appears that the frame rate is interpreted as an integer 119.88Hz != 120 Hz. This then appears to result in a wrong pixelclock 296700 kHz != 297000 kHz. Could this be the reason? Looking through some of the source code of libxhdmi it looks like framerates are consistently treated as integers ( https://github.com/Xilinx/PYNQ/blob/master/pynq/lib/\_pynq/\_xhdmi/hdmi_functions.c and the embeddedsw) - how can this be? Can this be circumvented somehow? or are we locked to resolutions with fixed integer framerates? Or am I overseeing something obvious here?