Part 1 / 6: Why an HDMI Analyzer
This series of posts is about an FPGA-based HDMI analyzer I made recently while working on HDMI-related issues for Linaro. It discusses why you might want one, exactly how HDMI works at the wire level and above, and how the analyzer works, and how to build one yourself for ~US$150. And the fpga vhdl (minus the Xilinx pieces), the kernel pieces and the userland pieces are available in git under gpl2.
Here's what the browser-based UI looks like in use on a real 720p HDMI source.
Brief Detour on Hikey
Linaro have recently started making low-ish cost credit-card sized boards for various SoC, 96boards.
It's a very crowded market, but since Linaro have access to their members at a high level, their first one, Hisilicon 'Hikey' 96board is quite interesting, it's a proper 64-bit ARM SoC on there.
Note 1: I do work for Linaro almost since they began, and so have an indirect interest in Hikey/96boards. But this is not actually the subject of these posts as you'll see.
Note 2: The HDMICAP design described here was paid for by Linaro.
It's still difficult to buy the cheapo *pi type boards with 64-bit. At any rate since its launch in Feb, although it's pretty usable there are still some software deficits. Actually by now anyway, these are rather less than have been typical in this market, for example it has working Mali. And because they base on Linaro's maintained LSK kernel, there are some other synergies there, like various things backported.
HDMI on Hikey and other 96boards
Some months ago I was asked to look at the HDMI situation on it, although it had working hdmi since Feb, in fact that was fixed to 720p and had various compatibility issues. I had worked on hdmi and hdmi audio drivers for a couple of other SoC already, but the setup on Hikey and other 96boards was different and as it went on, quite interesting.
Hi6220 on Hikey like several other SoC on 96boards doesn't have onchip hdmi IP, so the scheme used was onchip DSI IP is sent to a DSI-HDMI encoder IC, ADV7533 (unfortunately the useful datasheet is not public, but kernel drivers are on the way). Sounds simple, right?
Well the DSI unit as really a kind of 'pixel bus encoder' IP, it doesn't know itself how to create the basic raster (VSYNC, HSYNC, DE) timimg or do the DMA to get the pixel data. So it relies on a generic CRTC also in the SoC to take care of that. Then the whole system overview is like this:
Improving Hikey HDMI kernel code
After some debugging and general orientation I succeeded to improve the situation, supporting 1080p and other modes using the EDID returned from the monitor. And those patches are now on the main hikey branch. There are still issues though
made 1080p work by increasing the number of usable DSI lanes to 4
compatibility with various monitors and TVs differs according to the mode. 1080p is pretty good, so we are lucky there since that'll be the default mode in probably most cases nowadays. These are basically the same compatibility problems found on the original "720p" that was the only mode supported (it's timing was completely unrelated to the standard 720p modes).
Generally compatibility is better on monitors, rather than TVs. On some modes TVs will show the picture correctly, then blank and reacquire the image briefly before repeating that endlessly
Hotplug is forced to appear to always be present at ADV7533 (mainly because ADV7533 likes to reset half the chip if he sees hotplug go away)
To make this remaining compatibility situation a bit more surviveable I came up with and implemented two hacks
Alt-Gr SysRq G will make DRM cycle through the modes. So if you are confronted with a non-workable default mode, you can try other modes from your EDID "blind" via the keyboard. (You can force the mode from the kernel commandline once you know what works).
If you boot with the hdmi connector out, and no EDID appears, a canned mode of 720p60 is used. You can then plug the connector after kernel boot and always get 720p.
However these are basically palliative hacks, and I was very curious what the exact problem was.
Difficulties working blind with HDMI
Basically your TV or monitor is your debugger when it comes to getting HDMI working. If it displays something, you can often get a clue, but more often than not it will just go blank if there's something wrong.
Unlike a traditional system where you basically program the CRTC and see the output directly, in this system the data is only visible after it has been though two separate protocol encoders. So if something is broken, it becomes very hard to be sure where the problem was introduced.
Part of the problem with getting the output modes to bear some relationship with the correct timing was DSI introducing additional delays going to low power mode at different places in the blanking... that was only found by trial and error since there's no way anyone in Linaro has the tools to look at the DSI or HDMI stream.
You can use inferences like measure VSYNC IRQ period as exactly as possible, and even to some extent get a little idea by looking at the HDMI differential data with a 'scope. However you can't get hard data like the exact timings or semantic information that may be encoded in the non-active part of the raster.
So during the weeks I was working blind on it I was increasingly motivated to design something that would get around these problems and let me know what was happening on the wire. Finally since I had some spare time on my main job, I decided to build it. And that's the subject of this and future articles.
You can buy HDMI analyzers, but there are basically two kinds, very expensive, presumably nice ones, and ones re-using existing HDMI decoder chips with an MPU to control and read out info from registers in the HDMI decoder chip. Often they just put this info on OSD overlay on the video. Linaro doesn't have a budget for this kind of development hardware.
However what I was looking for was anyway something a bit different, basically 100% wire capture at wire speed. So every bit that is transferred on the HDMI cable should be available in capture memory, not just the active area but the blanking too, where HDMI sends data islands and control periods. For convenience, rather than parse the stream in software, hardware should perform summary measurements on the same data so we can have the data quickly and without effort at the same time.
And although HDMI is today's problem, since it looks like Linaro will be involved with many SoC designs with 96boards, probably another protocol like DSI or something else will be tomorrow's problem, so it should be flexible.
Since I have a long experience with Xilinx FPGAs (going back to XC2064s in the late 1980s...) I chose a Xilnx Zynq FPGA, these are cheap and include deal Cortex A9s. There are a few ready-made boards around with them, I chose Z-turn from MYIR, since it's only US$119 for the larger 7Z020 version.
FPGA design 2015-style
It was a few years since I last used an FPGA, since I have mainly been working on Linux kernel. Although I learned VHDL a decade ago, and that's still the same, the density and capability of the programmable logic fabric has really matured since I last used it.
Xilinx offer their Java-based tools that will work on Linux natively for free (although they are not Free) and the standard basis for app IP design is the AXI bus, same as it is in real SoC design. In fact the general level of IPs available is the same as midrange SoC designers use. Again Xilinx offer free (but not Free) sophisticated enabling IPs such as scatter-gather DMAs, that you can just instantiate how you like. And even the low-end FPGAs have enough gates and assets in the programmable logic fabric that you can make serious digital designs that work at respectable clock rates (this was not always the case, the further back you go the more tricks were needed).
At any rate the cost of entry into using FPGA designs is less than US$120 now, the tools come for free for lowend devices.
In the next part I'll discuss exactly how HDMI works on the wire. I thought I knew enough about it before I started this but the details are quite interesting and since you don't need to know most of them from the software point of view, not that widely known.