Part 6 / 6: HDMICAP vs Hikey HDMI

Recap on Hikey video flow

If you recall, hikey has a bit of a complex video output path.

Hikey video path

In this system, the CRTC part is ultimately resposible for generating the video timings, and he is driven by a clock we will call the "pixel clock". So ultimately the time allotted for one frame is decided in units of the CRTC's pixel clock

Hikey video path

CRTC VSYNC is the boss

Everything else that happens to the video stream in the processing scheme, turns out to be secondary to that fact,

Just before I decided to build hdmicap, I found a clue about the video modes that had a lot of incompatibilities with TVs, that they VSYNC was not aligned with their HSYNC.

Broken HSYNC to VSYNC relationship

However nobody understood why this should be so, there are no registers in hikey that allow offsetting of VSYNC horizontally.

Debugging the VSYNC offset

As you can see in the picture, the DSI + HDMI parts of the processing take a different clock than the CRTC part.

In the modes where the VSYNC is offset, a different clock is used for each part, eg, on 576p the CRTC gets 26.66MHz, but the DSI part gets 8 x 26.8MHz (in DSI it sends a byte per lane, so this translates to whole pixels at a rate of 26.8MHz. And the HDMI clock is directly derived from the DSI clock, so that too is 26.8MHz (with data coming at 10 x that as explained before).

The existing code in hikey video stack sets the intended timing exactly at the CRTC, and modifies the blanking numbers at the DSI IP to take account of the difference in clocks... it computes the absolute time in pixel clocks and the divides that by the period of the DSI byte lane clock.

This gives the output timing shown below

Output timing with CRTC set correctly and DSI adaptively

Basically the timing is all slightly off from the correct, official CEA numbers on the left (hdmicap has acquired the VIC sent by the ADV7533 and automatically shown the correct numbers there).

I assumed that this was the basic problem, so I altered the video stack code so that it sets the DSI timing registers with the canonical, CEA numbers, and adaptively computes the timing numbers for the CRTC part, taking into account the different clock rates. That got me a "working" result, with perfect timing numbers coming through DSI and the HDMI encoder chip...

Output timing with DSI set correctly and CRTC adaptively

... but it did not eliminate the horizontal offset of the VSYNC.

Fudging by one pixel per line

I also tried fudging the blanking by one pixel more or less per line, that did not solve the VSYNC offset problem either, just moved it around by some amount.

Finally after some consideration I realized... the VSYNC is effectively asynchronous to whatever happens on the DSI clock domain: the VSYNC is coming directly from the CRTC pixel clock domain.

If it wasn't like that, because the clocks in the two domains are different, over time the DSI side would slip further and further away from matching the CRTC timing, until we are having to buffer whole frames, and there'd be no end to it as it kept going.

As it is, in the DSI and / or HDMI encoder there is at least one line buffer of pixels kept in a FIFO, to hide the accumulating small differences in line time between the two clock domains. Here is a capture of what happens when I fudged an extra DSI pixel time in the blanking as as test, as mentioned above...

Excessive drift exceeds DSI line buffer

Partway through the raster, the CRTC's opinion on where it is in the raster, using the pixel clock and CRTC timings, and the DSI + HDMI side's opinion of where it is in the raster, using the DSI clock and DSI timings (fudged to use an extra DSI clock time in HBP), got so far out of whack that the pixel FIFO could no longer cover for the difference.

Realization about retimed HSYNCs

I could get rid of this by removing the extra fudged pixel time, but after thinking about it, this has another very important implication. We know with that set of timings on CRTC and DSI sides, that during the frame the timing is drifting further and further apart, the FIFO does its best to cover for it but eventually it runs out. But generally... for the top 1/3rd before it breaks down, the left edge of the active region is a straight line.

However we KNOW that our DSI hsync is drifting by one or more pixels per line, it was already inexact due to the different clocks involved, and we added one more fudge DSI pixel time. The fact that it comes out of HDMI aligned with the pixels from the start of the original CRTC HSYNC, means that DSI is issuing retimed HSYNCs, as well as getting pxel data shifted in time thanks to the FIFO - it's not trying to stay consistent with the original CRTC HSYNC time.

In other words, after DSI, we are issuing retimed, DSI-originated HSYNCS and pixel data delayed to match, but original, CRTC-originated VSYNCS.

Effect on VSYNC relationship to HSYNC

The original CRTC-originated VSYNC has no clue later IPs retimed HSYNC, he just does his thing. That is why we see VSYNC coming partway through a line, we have "bulged" our retimed frame due to there being no way to express the same period exactly using integer amounts of CRTC clocks (26.66MHz) and DSI clocks (26.8MHz).

HSYNC drift during frame

The end result is the original VSYNC comes at his original time and chops off part of the last line. Since VSYNC is defined to be an integer number of HSYNCs, this fatally confuses some TVs.

The only tool to affect it is add or remove one pixel per line in blanking... but it's a very blunt instrument, if there are 625 lines in the mode, you can only affect it in units of 625 pixel-times, so actually there is no chance to do anything.


The end result of all this was I could finally understand what was going on leading to the offset VSYNC problem. But having understood it, there was nothing I could see to do about it. It is possible to retime syncs in ADV7533 but whatever we do there cannot hide the timing of the original CRTC frame sync, because DSI itself gets reset to that each frame, which means there is a discontiguity in HSYNC timing each new frame.

Serveral modes on Hikey seem unaffected and have much better compatibility, such as 1080p and 800x600... these happen to have the same clock on both CRTC and DSI sides. So it's recommended by Linaro now that if using this video output scheme, to try to arrange that the same clock source is providing the clock for both CRTC and DSI / HDMI sides.

I hoped you enjoyed reading about hdmicap and the debugging adventures with it ^ ^