f_ changed the topic of ##raspberrypi-internals to: The inner workings of the Raspberry Pi (Low level VPU/HW) -- for general queries please visit #raspberrypi -- open firmware: https://librerpi.github.io/ -- VC4 VPU Programmers Manual: https://github.com/hermanhermitage/videocoreiv/wiki -- chat logs: https://libera.irclog.whitequark.org/~h~raspberrypi-internals -- bridged to matrix and discord
bob_x2 has quit [Remote host closed the connection]
bob_x2 has joined ##raspberrypi-internals
jn has quit [Ping timeout: 256 seconds]
jn has joined ##raspberrypi-internals
jn has joined ##raspberrypi-internals
jn has quit [Changing host]
f_ridge has quit [Remote host closed the connection]
f_ridge has joined ##raspberrypi-internals
Bitweasil has quit [*.net *.split]
NightMonkey has quit [*.net *.split]
Bitweasil has joined ##raspberrypi-internals
NightMonkey has joined ##raspberrypi-internals
kbingham_ is now known as kbingham
jcea has joined ##raspberrypi-internals
Guest92 has joined ##raspberrypi-internals
<Guest92> Hi. I have recently been doing some reverse engineering work on the SMI and GPIO hardware on the RPI Zero 2 w, and was hoping to find others to compare notes with
<clever> Guest92: *waves*
<clever> Guest92: ive mostly used SMI with the existing linux driver
<Guest92> I can make some contributions/correction to https://github.com/librerpi/rpi-open-firmware/blob/master/docs/smi.txt if that is helpful
<clever> but these guys also RE'd it more, and wrote some proper docs
<Guest92> I looked at the linux driver, the lean2 blog/code and the caribouLite code/design
<clever> ah, nice
<Guest92> and then did experiments with Circle lib and 1GHz logic analyzer
<clever> ahhh nice, my 100mhz scope is a bit limiting
<Guest92> things I have not seen documented by other devs:
<Guest92> 1) REQ line (SD16) is used to device-pace both reads and writes from the device
<Guest92> 2) WrREQ (SD17) is an <output> from the PI, not an input
<Guest92> WrREQ goes high when the PI has data in the SMI write FIFO and the device deasserts REQ (ie, looks like SD17 allows SMI to request that device assert REQ to receive data)
<Guest92> latency between device asserting REQ and SMI asserting SE is 16ns (with 500MHz SMI clock)
<clever> i heard from one of the pistorm guys, that i think the raw data register, will stall the axi bus when in dreq mode
<clever> so you dont have to poll a fifo status reg
<Guest92> yes, I was trying to get the CPU to be a 'smart DMA controller', feeding the SMI fifo instead of DMA
<Guest92> But I can only write the SMI data reg with SMI disabled. Attempting to write to SMI_D with the SMI subsystem enabled causes an error and SMI to halt
<clever> do you have a name or github acct, so i can add credit to the txt file?
<clever> there is also a sort of concurrent access i theorized is possible, but ive not figured out the details
<clever> the 2d core supports an SMI based video mode
<clever> my rough understanding, is that you just configure the device timings and address, and the 2d subsystem will just dump pixel data into the fifo
<clever> and ive seen hints, that you can use SMI_D to talk to a second device at the same time
<Guest92> SMI reg setup is time consuming, so I was unable to switch between read & write every ~400ns which was a design requirement
<clever> thats why there is a SMI_A and SMI_DA
<Guest92> My github name is JohnMBrooks, but I don't use github much. I primarily do low-level dev for videogame consoles (day job), and retro dev for Apple II (hobby)
<clever> ahhh
<clever> your probably aware of the pistorm guys then?
<Guest92> no, what are they doing?
<clever> emulating an m68k cpu in aarch64 with a JIT
<clever> then capturing all access to a 4gig window, and bit-banging the m68k cpu socket on an amiga motherboard
<clever> so you can just shove an entire rpi-zero2 into the m68k cpu socket, and boot the stock amiga os/kernel
<Guest92> lol, cool
<clever> and with the power of JIT and a modern cpu, its just screaming along
<clever> until it has to hit slow ram or mmio
<clever> in amiga terms, fastram is ram on the accelerator card, and chipram is on the motherboard
<clever> and dma can only reach chipram
<Guest92> I made a 1080p display card for retro AppleII 5 years ago, but the pandemic chip shortage killed the parts I use, so I am trying to see if RPIZ2W can work
<clever> and even back in the day, they had accelerator cards, which was basically just some ram and a cpu, that ran at a higher clock
<Guest92> But the timing is tight, with the card emulating a CRT beam at 980ns intervals (1mil FPS)
<clever> and by making the fastram private to the cpu, they dont have to obey the same clock specs
<Guest92> Yeah, need private CPU and ram for any modern accelerator/accesory
<clever> for pistorm, they didnt isolate the m68k "guest"
<clever> the amiga kernel has unrestricted access to the rpi hw registers
<clever> this would be running over the hdmi port on the pi
<Guest92> Apple did something similar in 1986 with the Apple IIGS, and then a few years later with the Apple IIc+, put a faster-clocked CPU and RAM/cache alongside the legacy low-clocked video & IO
<clever> and just because they can, here is amiga running at 4k: https://www.youtube.com/watch?v=-MAnG86SmUk
Guest92 has quit [Quit: Client closed]
Guest92 has joined ##raspberrypi-internals
<clever> wb
<clever> did you catch the 4k link?
<Guest92> yes. thanks
<clever> i also have some other news that might help your round-trip times
<clever> ive got PIO working on the pi5's PIO block
<Guest92> PIO is great tech, but I am on RPIZ2W for size & power
<clever> ah
<clever> tried using the VPU to side-step some of the latencies?
<Guest92> that is my next step, but seems harsh
<Guest92> was going to try booting without firmware which is how I found the open firmware github
<clever> ah
<clever> due to how the pi boots, thats not really possible, but you can replace the firmware and customize the replacement
<Guest92> when bitbanging gpio, I can do <200ns access for over 4 seconds, then GPIO suddenly goes away for 750ns
<clever> this was a 96kb bootcode.bin test i did, it boots in just 0.61 seconds
<clever> this build has a command prompt, sd, ext4, and ntsc drivers
<clever> so you can then mount a card and read files
<Guest92> That relates to my interests.  :)
<clever> no usb however, so i had to type to it over uart
<clever> but i have since made progress with usb drivers
<clever> and that is entirely without turning on the arm cores
<Guest92> I only need low-latency I/O and HDMI video
<clever> hdmi video is an issue
<clever> i have yet to figure out how to initialize hdmi from scratch
<clever> so if you switch to the open firmware, then your limited to just DPI and composite
<Guest92> doesn't linux driver do init-from-scratch?
<clever> nope
<clever> linux relies on the firmware to turn several things on
<clever> and with the open firmware, linux just immediately dies to async external abort
<Guest92> ah, so open-firmware doc talking about linux boot is headless? or non-HDMI video?
<clever> most of my demos are in ntsc/composite mode
<clever> but i do have dpi/vga working as well
<clever> but dpi also obviously cuts into your gpio
<clever> https://www.youtube.com/watch?v=BQyyVtmmVg8 this is one of my most advanced demos
<Guest92> yeah, I need HDMI, so maybe RPI is still a no-go for me, sadly.
<clever> the top half of the screen is the VPU framebuffer
<clever> the bottom half of the screen is /dev/fb0
<clever> the bouncing rpi logo is a sprite with XY animated
<Guest92> I tried to use RPI2 in 2017, but had to switch to Cypress PSOC for 6502-bus interface an Orange Pi for SBC due to RPI perf problems
<clever> and the triangle is a fullscreen 3d render, with alpha for the background clear color
<clever> for hdmi, i think i'm just 1 control register away from making it work
<clever> and maybe you could help out?
<Guest92> looks cool on NTSC
<Guest92> sure, what is the plan/strategy for HDMI
<clever> https://i.imgur.com/0doKSWG.jpg and a second ntsc example
<clever> this time, full xfce, and working usb keyboard/mouse
<Guest92> can you observe the registers after firmware sets them?
<Guest92> or is there a setup sequence/timing constraint that is unknown?
<clever> the problem is more, i dont know which registers to observe
<clever> let me get the code and hexdumps...
<Guest92> what about JTAG watching the VPU during startup?
<clever> there is no public documentation on how to use the VPU jtag
<Guest92> ouch
<clever> here is my hdmi init code
<clever> and the hexdump in the 2 posts here
<clever> you can see that one peripheral range has "hdmi" repeating in all of the undefined registers, and "dbus" in the other
<clever> but when i boot under the closed firmware, that "dbus" region turns into mostly nulls
<clever> my theory, is that half of the hdmi peripheral is just disabled entirely, and not responding to any r/w actions
<Guest92> so if linux w/firmware is booted with no HDMI active, and then HDMI is hotplugged, can linux setup HDMI, or does it ask broadcom firmware to do it?
<clever> i think the hdmi is already enabled, before linux even starts booting
<clever> but i didnt actually check that
<Guest92> even if no HDMI display is present and no EDID query?
<clever> let me dig out a pi and see.....
<clever> grabbed a random 02 off a shelf, its already got an sd card in it, and i think its booting....
<clever> waiting to see if anything appears on the wifi....
<clever> hmmm, let me pop in hdmi to see why its not booting
<clever> i see a login prompt!, so why is it not on wifi.....
<clever> rfkill: WLAN soft blocked
<clever> CTRL: Invalid group 'wheel'
<clever> Failed to initialize control interface 'DIR=/var/run/wpa_supplicant GROUP=wheel'.
<clever> its a borked install, due to copying the wpa config from another machine
<clever> Guest92: related to your VidHD, pistorm has 3 ways of getting HDMI out
<Guest92> Took a look at the pistorm github. Looks like they are bitbanging GPIO (pistorm/gpio
<clever> the main one, is to just use the rpi's internal hdmi, via the RTG driver stack, but a lot of games dont support RTG
<Guest92> unsigned int ps_read_16(unsigned int address) {
<Guest92>   *(gpio + 0) = GPFSEL0_OUTPUT;
<Guest92>   *(gpio + 1) = GPFSEL1_OUTPUT;
<Guest92>   *(gpio + 2) = GPFSEL2_OUTPUT;
<Guest92>   *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0);
<Guest92>   *(gpio + 7) = 1 << PIN_WR;
<Guest92>   *(gpio + 10) = 1 << PIN_WR;
<Guest92>   *(gpio + 10) = 0xffffec;
<Guest92>   *(gpio + 7) = ((0x0200 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0);
<Guest92>   *(gpio + 7) = 1 << PIN_WR;
<Guest92>   *(gpio + 10) = 1 << PIN_WR;
<Guest92>   *(gpio + 10) = 0xffffec;
<Guest92>   *(gpio + 0) = GPFSEL0_INPUT;
<Guest92>   *(gpio + 1) = GPFSEL1_INPUT;
<Guest92>   *(gpio + 2) = GPFSEL2_INPUT;
<Guest92>   *(gpio + 7) = (REG_DATA << PIN_A0);
<Guest92>   *(gpio + 7) = 1 << PIN_RD;
<Guest92>   while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) {}
<clever> yeah, but they did look into SMI at one point, not sure why they arent using SMI currently
<clever> the second option is just rgb2hdmi
<Guest92> I would expect the above to take about 500ns, so bus speed would be slower than real Amiga hardware
<clever> and the 3rd is a custom rgb2csi adapter, so the pistorm pi can then capture it, and re-output it over hdmi
<clever> i'm not sure what tricks they are pulling off, but emu68 is able to do that entire dance within a single bus transaction on the amiga motherboard
<Guest92> ah, the good old Amiga genlock, toaster
<Guest92> I suspect they are rarely on the bus given the slow GPIO time
<clever> and thats part of why the pi5 isnt pistorm friendly
<clever> the pcie bus transfers just add too much latency
<Guest92> if the emu68 is almost always accessing internal mem, then having the bus run at 1Mhz or less may be acceptable
<clever> one sort of ugly trick they have, there is an fpga acting as glue between the gpio and bus socket
<clever> the fpga is clocked by the pi, via a GPCLK channel
<clever> and i think the gpio and GPCLK are on the same clock parent
<clever> so the edges all line up nicely
<Guest92> Is there a way to send a screen capture on here?
<clever> irc doesnt really support that, discord or a custom rtsp stream would work
<clever> and after much searching, i found an OTG adapter, now i can control this zero2
<clever> now to brute-force my own pw!
<clever> hmmm, weird, /etc/shadow is identical between my laptop and pi, for that user, let me try that user again.....
<Guest92> I sent the logic analyzer screenshot of 700+ns GPIO stall to you via email
<clever> yep, i see that
<clever> have you done anything with cpufreq?
<Guest92> I set Turbo in the firmware, then set the ARM freq to 1000MHz
<clever> but linux is still free to change the clocks
<Guest92> I dedicate ARM core 1 to GPIO handling, idling cores 0,2,3
<clever> based on cpu usage
<clever> echo userspace > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
<Guest92> no linux
<clever> try running this and oh
<Guest92> Circle bare-metal OS
<clever> ahhh
<clever> i would assume that lacks cpufreq then
<Guest92> yes, tho who knows what firmware does behind the scenes
<Guest92> which is why I want to try without firmware running if possible
<clever> the only time it should change the freq, is when its doing thermal or undervoltage throttling
<clever> and on that subject, i have some good news for extending circle
<clever> do you know the old vcgencmd?
<Guest92> not very well
<clever> its a way to send commands off to the firmware, and get text replies back
<clever> for the pi0-pi4, it was done over the vchiq protocol, a complex message passing thing, meant for video encode/decode and camera
<clever> pi5 just deleted vchiq entirely
<clever> so RPT re-implemented vcgencmd as a mailbox property
<Guest92> RPT?
<clever> raspberry pi trading
<clever> i dont see any backwards compatability code for vchiq stuff
<clever> i assume the mailbox property works on older models as well
<clever> so in theory, circle can just implement the mailbox code i just linked, and then you can run `vcgencmd get_throttled` and `vcgencmd measure_clock arm` from circle
<clever> assuming you have a more recent start.elf
<clever> oh, and i just had a thought, can you try measuring the interval between each 700ns stall?
<clever> how far apart are they?
<Guest92> Yeah, I plan to do that test tonight. The stall didn't happen for 3-4 seconds, so my guess is that the firmware wakes up and does something that interferes with GPIO access
<clever> ah, its unlikely to be hsync then
<clever> clever@raspberrypi:~ $ git clone https://github.com/librerpi/rpi-tools
<Guest92> yeah, too slow for hsync or vsync. more likely a temp/throttle check, or hdmi hotplug
<clever> ah, i need to fix rpi-tools, one min
<clever> clever@raspberrypi:~/rpi-tools/utils $ make ramdumper
<clever> clever@raspberrypi:~/rpi-tools/utils $ sudo ./ramdumper -m -a 0x3f808000 -l 128
<clever> 0x3f808000 69 6d 64 68 69 6d 64 68 69 6d 64 68 01 02 00 00 |imdhimdhimdh....|
<clever> clever@raspberrypi:~/rpi-tools/utils $ sudo ./ramdumper -m -a 0x3f902000 -l 128
<clever> 0x3f902040 00 00 00 00 00 00 00 00 00 00 00 80 00 10 00 50 |...............P|
<clever> 0x3f902050 00 10 00 00 80 00 13 00 00 00 00 00 41 40 00 00 |............A@..|
<clever> Guest92: and with this, i can see all of the hdmi regs, as i showed in that old forum post, but reproduced on a new install
<clever> now to unplug hdmi, and repeat...
<Guest92> can you do those reads after booting headless, then plug in HDMI and dump?
<clever> yep, thats why ive unplugged and rebooted
<clever> i can see a few bytes differing, but its all readable
<Guest92> Ok, so firmware brings up HDMI hardware, even if no display connected
<clever> and if i hotplug an hdmi display, the bytes revert to the previous configuration
<Guest92> that is good news (probably), as it means that all the HW init is together before KERNEL load/launch
<clever> unplugging does not reverse that
<clever> oh wait
<clever> it was delayed, but it did reverse
<Guest92> ok, so there may be a clock domain being brought up and then shut down if not used
<clever> there are 2 critical problems ive confirmed in the past
<clever> first, the 2d core (called the HVS) has some undocumented security around it
<clever> any attempt to write to any register, kills the arm with external async abort
<clever> but as you can see from all of my YT vids and screenshots, the VPU is perfectly capable of driving the HVS with full 3d animations
<clever> its definitely on (several rpi engineers claimed it wasnt), and fully working
<clever> second, a chunk of the hdmi registers are just not responding
<clever> the 1st problem means linux cant use the existing hw accel drivers
<Guest92> sounds like a power/clock or bringup/init fail
<clever> currently, ive just been rigging /dev/fb0 to a static region of ram, via the simple-framebuffer entry in device-tree
<clever> no pageflips or resolution changes, but it works
<Guest92> yeah, I used /dev/fb0 for VidHD on Orange Pi, but linux was a pain for low-latency embedded use
<Guest92> and I had to mod drivers and display select/init for my use-case, as well as buildroot to reduce slow startup
<clever> i think linux usually maps fb0 as write-combined, so writes can merge, but reads are never cached
<clever> and for certain access patterns, that can kill performance
<Guest92> hoping to avoid that for the next go-around
<clever> when driving the 2d core on the rpi, from the VPU, you can entirely ignore the cache issues
<clever> the VPU and HVS can both access the same L2 cache
<clever> and page flipping is more flexible
<clever> scrolling and hw scaling is also on your side
<clever> this would be the stock gfxconsole that little-kernel comes with
<clever> it implements scrolling by just memcpy()'ing the entire framebuffer up a few lines
<clever> this would be a custom gfx console, that takes advantage of the 2d core
<clever> it basically treats the framebuffer as a ringbuffer, and just wraps within the buffer and never scrolls
<clever> it then slices that ringbuffer into 2 sprites, and has the 2d core render each slice seperately
<clever> for debug, there is an obvious seam between the 2 slices, but that can be closed up
<Guest92> so HVS == 2nd VPU core?
<clever> the HVS is the dedicated 2d scaling engine
<clever> you can think of it as like a sprite only gpu (think c64 or (s)nes)
<clever> but without any limitations on sprite size
<Guest92> k
<Guest92> UI overlay
<clever> for each sprite, you generate a 7 x 32bit structure in a special region of ram
<clever> less of an overlay, and more, the only way to do any video output
<clever> the hardware kinda doesnt support a framebuffer
<clever> what you think is a framebuffer, is just a sprite covering the entire screen
<Guest92> I thought there were multiple vram DMA sources that could be merged for video output
<clever> nope, just 3 channels on the HVS
<clever> there is a shared `uint32_t[4096]` that contains all of the display lists
<clever> for each sprite, you write a 7 x 32bit entry to that memory, and cap it off with a 32bit termination code
<clever> then you just tell the hardware what index each channel begins at
<clever> internally, the HVS has 3 FIFO's that hold composited pixel streams
<clever> when a FIFO has room for a scanline, the HVS will re-parse the entire display list, fetch image data from ram, composite it directly into the FIFO, and then go back to idle
<Guest92> cool
<clever> during that process, it can do pixel format conversions (565, 888, yuv), alpha blending, scaling, and mirroring
<clever> the pixel valves then read that fifo, at a defined pixel clock, and turn the flow off during blanking periods
Guest92 has quit [Quit: Client closed]
<clever> and then the PHY's take that throttled stream of pixels and hsync/vsync, and turn it into something usable
Guest92 has joined ##raspberrypi-internals
<Guest92> I seem to get auto-logged-out periodically
<clever> it may help if you install an irc client
<clever> 2024-02-12 18:32:06 < Guest92> cool
<clever> 2024-02-12 18:32:26 < clever> during that process, it can do pixel format conversions (565, 888, yuv), alpha blending, scaling, and mirroring
<clever> 2024-02-12 18:32:43 < clever> the pixel valves then read that fifo, at a defined pixel clock, and turn the flow off during blanking periods
<clever> 2024-02-12 18:33:07 -!- Guest92 [~Guest92@ip-67-215-32-70.syringanetworks.net] has quit [Quit: Client closed]
<clever> 2024-02-12 18:37:18 < clever> and then the PHY's take that throttled stream of pixels and hsync/vsync, and turn it into something usable
<clever> the last few things i said
<Guest92> k. thx
<clever> for some PHY's like DPI, its barely even a PHY
<clever> it just exposes the hsync/vsync/data-valid/rgb888 raw on the gpio
Guest92 has quit [Client Quit]
<clever> for other PHY's like hdmi and vec(ntsc/pal), it has its own view of the video timing parameters, and you get rolling artifacts (like a lost vsync) if the pixel-valve and hdmi/vec dont agree
Guest92 has joined ##raspberrypi-internals
<clever> for other PHY's like hdmi and vec(ntsc/pal), it has its own view of the video timing parameters, and you get rolling artifacts (like a lost vsync) if the pixel-valve and hdmi/vec dont agree
<clever> Guest92: at some point, i need to re-open ghidra, and go over the debug build with a fine toothed comb.....
<clever> commit 4f63c3bdd4d9ca4f308e683fe7e70501b4ac3232
<clever> Author: popcornmix <popcornmix@gmail.com>
<clever> Date: Thu Jun 26 17:57:25 2014 +0100
<clever> Guest92: in this commit of the official firmware, they messed up, and published a binary with all of the symbols present
<clever> -rw-r--r-- 1 clever users 870K Feb 12 19:22 start_cd-4f63c3bdd4d9ca4f308e683fe7e70501b4ac3232-unstripped.elf
<clever> this would be the "cut down" build from that leak, it lacks a large number of optional things
<clever> ideally, less hay to comb thru.....
<clever> interesting, i found an aes_run_round() function
<clever> ah, thats why, hdcp_aes_run()
<clever> but that leads right to a relevant function, hdmi_init()!
<clever> at offset gp + 0x87e28, is the hdmi state...
<clever> so i can then just search for 0x87e28 and fnd everything using hdmi state
<clever> and i see an hdmi_close() function, that is writing to registers in the dead region!
<Guest92> wow, nice find
<clever> 2 ways for you to view the assembly
<clever> 2 is a full binutils/gcc fork, that supports the VPU
<clever> you can just `objdump -d` the elf, to get assembly listings
<clever> Guest92: but if you use ghidra, then youll get https://gist.github.com/cleverca22/2f443a175ba76c6b12d636c0c74b8c15
<clever> which is far more readable
<clever> and ctrl+f'ing more, i found hdmi_open()
<clever> which even has a handy debug statement, declaring that its on like 567 of hdmi.c
<clever> vcfw/drivers/chip/vciv/2708/hdmi.c specifically
<clever> and yep, hdmi_open is writing to the other hdmi bank, the one that is always present
<clever> ok, so what is this function doing...
<clever> it reads HD_HDM_CTRL, OR's a 4 into it, and writes it back, then delays for 10 units of time
<clever> that would be writing bit 2
<clever> it then reads the register, clears bit 2, and writes it back
<clever> then it clears bits 4/5
<Guest92> sounds promising
<clever> then it clears bits 6/7
<clever> then it sets bit 1
<clever> then it does something with the pixel valve
<clever> and begins writing to the dead region
<clever> so by this point, the dead block is online
<clever> either because of what this just did, or something before it
<clever> and this would be the header, saying what those bits mean
<clever> so first, it set SW_RST, waited 10 units of time, and cleared SW_RST
<clever> then it sets PDSTBY to 0
<clever> and RFSTBY to 0
<clever> then ENABLE = 1
<clever> Guest92: that does sound promising!!
<Guest92> !!!
<clever> and this would be what i wrote, based on linux
<clever> it sets SW_RST, waits 1 usec, sets everything to 0, then sets enable
<clever> that should be functionally identical?
<Guest92> unlikely
<clever> and this is how linux did it
<clever> HDMI_SW_RESET_CONTROL is in the dead half of the peripheral, and that write has no effect in my code
<Guest92> what you described waits longer and clears standby
<clever> linux is clearing standby, by just writing the entire register with a 0
<clever> so all sub-fields are zeroed in one shot
<Guest92> but will fail if subsystem is coming out of reset
<clever> i could try sleeping longer...
<clever> but its also likely, that this isnt the key
<clever> and something else enabled it, before calling hdmi_open
<Guest92> could be
<Guest92> but if standby and enable are set too early, that would do it
<clever> except that is how linux did things....
<Guest92> but linux may have always been incorrect, but didn't matter since firmware enabled HDMI at boot
<Guest92> although if linux was doing a reset, and disabled hdmi, then I would expect the re-enable to be correct
<Guest92> but first-time reset+enable may need a longer delay than a later soft reset
<clever> could be
<clever> let me track down how hdmi_open is called first....
<clever> its in a big table of function pointers, the firmware likes doing that