(TL;DR: Had to fix some of the code, explanation follows see bottom of post for change I made to make it work)
After getting the cross compilation working quake 3 was still not working. It started up and you could hear the intro movie sound and press arrow keys to hear the menu sounds as you moved around it but the display was just a straight gradient pattern. I enabled the debug output of the dmaer module and you could see that V3D was receiving jobs and happily processing things just nothing was appearing on the screen.
Eventually I tracked down the problem to init_dispmanx in dispman_connection.c. This sends mailbox messages to the GPU to allocate a framebuffer. At the end of the file it mmaps physical memory to write 0xFF to the framebuffer memory. There is a comment saying that we need to touch all the pixels before anything appears on screen.
Given I saw a gradient pattern rather than a white screen it looked like this final bit of code wasn't doing anything, looking at the address it was using it had received an address 0xd8402260 from the GPU for the framebuffer and writing directly to that. This was a bit suspicious as it looks like a bus address rather than an ARM physical address. I added an & ~0xC0000000 to turn it into an ARM physical address and now everything works (see an initial white screen as expected and then Q3 actually displays).
My question is why did this work in the first place? Has there been a recent firmware change? Perhaps that mailbox message which allocates the buffer used to return ARM physical addresses rather than bus addresses?
Line 225 of dispman_connection.c should be changed from
Code: Select all
unsigned int pa = ((unsigned int)gRectVars.buffers.m_pMemory);
Code: Select all
unsigned int pa = ((unsigned int)gRectVars.buffers.m_pMemory) & ~0xC0000000;