While in my case the HDMI audio control register does respond, my configuration is either incomplete or wrong, because the HDMI audio data register is consuming SPDIF frames way too fast.
The following bare metal code contains the VC6 addresses of the HDMI audio registers from Linux [1] (0x2000000 is a virtual address that maps to 0xfe000000 on the Raspberry Pi 4):
And the following bare metal code is how I'm trying to produce audio:
The HDMI audio device does respond to the code above but consumes over 2000000 subframes per second when I expected it to only consume 96000 and actually produce audio. I also tried doing this through the DMA controller but then realized that I don't know the DREQ for the HDMI audio device, and I can't seem to be able to access the DMA controller's registers to read that information on Linux possibly because the stock kernel has CONFIG_STRICT_DEVMEM set to its safe default value. The magic values in my code come from my interpretation of the kernel source [2][3], and roughly match the values wile playing audio through HDMI on Linux. The value in the clock register matches exactly the value on Linux which makes sense to me.
The code above outputs the following debug message:
My next step will be to recompile the kernel with CONFIG_STRICT_DEVMEM explicitly disabled to make sure that it's not getting in the way of my attempts to read hardware registers as well as the DMA control blocks.
[1]: https://github.com/raspberrypi/linux/bl ... dmi_regs.h
[2]: https://github.com/raspberrypi/linux/bl ... vc4_hdmi.h
[3]: https://github.com/raspberrypi/linux/bl ... vc4_regs.h
The following bare metal code contains the VC6 addresses of the HDMI audio registers from Linux [1] (0x2000000 is a virtual address that maps to 0xfe000000 on the Raspberry Pi 4):
Code:
/// HDMI base.#[cfg(hdmi)]const HDMI_BASE: usize = PERRY_RANGE.start + 0x2f20000;/// HDMI control register.#[cfg(hdmi)]const HDMI_CTL: *mut u32 = (HDMI_BASE + 0x10) as _;/// HDMI DREQ configuration register (not sure what THR means).#[cfg(hdmi)]const HDMI_THR: *mut u32 = (HDMI_BASE + 0x14) as _;/// HDMI format register.#[cfg(hdmi)]const HDMI_FMT: *mut u32 = (HDMI_BASE + 0x18) as _;/// HDMI clock divisor register.#[cfg(hdmi)]const HDMI_SMP: *mut u32 = (HDMI_BASE + 0x20) as _;/// HDMI packet configuration register.#[cfg(hdmi)]const HDMI_PACKET: *mut u32 = (HDMI_BASE + 0xc0) as _;/// HDMI channel map.#[cfg(hdmi)]const HDMI_CHMAP: *mut u32 = (HDMI_BASE + 0xa4) as _;/// HDMI config register.#[cfg(hdmi)]const HDMI_CFG: *mut u32 = (HDMI_BASE + 0xa8) as _;/// Hardware FIFO register.#[cfg(hdmi)]const HW_FIFO: *mut u32 = (HDMI_BASE + 0x1c) as _;
Code:
unsafe { HDMI_CTL.write_volatile(0x1); HDMI_FMT.write_volatile(0x20900); HDMI_PACKET.write_volatile(0x3d00); HDMI_THR.write_volatile(0x10101c1c); HDMI_SMP.write_volatile((CLOCK_RATE / SMPL_RATE) << 9); HDMI_CFG.write_volatile(0xc000003); HDMI_CHMAP.write_volatile(0x8); HDMI_CTL.write_volatile(0xb32e); fence(Ordering::Release); fence(Ordering::Acquire); crate::debug!("HDMI_CTL: {:X}", HDMI_CTL.read_volatile()); let mut cs = [0x0; 24]; cs[0 .. 5].copy_from_slice(&[0x4, 0x50, 0x0, 0x22, 0xd2]); for frame in 0 .. { let mut val0 = if (frame / 120) & 0x1 == 1 {0x3fff << 12} else {0xc000 << 12}; let mut val1 = if (frame / 80) & 0x1 == 1 {0x3fff << 12} else {0xc000 << 12}; let frame = frame % 192; if frame == 0 { // Send the synchronization marker configured earlier. val0 |= 0xf; } let byte = frame >> 3; let bit = frame & 0x7; let cs = (cs[byte] >> bit) & 0x1; val0 |= cs << 30; val1 |= cs << 30; if frame == 16 || frame == 20 { // Set the channel bits for the second channel. val1 |= 1 << 30; } // Add the parity bit. for bit in 4 .. 31 { val0 ^= ((val0 >> bit) & 0x1) << 31; val1 ^= ((val1 >> bit) & 0x1) << 31; } HW_FIFO.write_volatile(val0); HW_FIFO.write_volatile(val1); fence(Ordering::AcqRel); while HDMI_CTL.read_volatile() & 0x800 != 0 { core::hint::spin_loop(); } } }
The code above outputs the following debug message:
Code:
HDMI_CTL: 3528
[1]: https://github.com/raspberrypi/linux/bl ... dmi_regs.h
[2]: https://github.com/raspberrypi/linux/bl ... vc4_hdmi.h
[3]: https://github.com/raspberrypi/linux/bl ... vc4_regs.h
Statistics: Posted by Fridux — Sat Apr 20, 2024 10:11 pm