Eric Anholt (anholt) wrote,
Eric Anholt

This week in vc4 (2016-10-31): HDMI audio

Last week was spent almost entirely on HDMI audio support.

I had started the VC4-side HDMI setup last week, and got the rest of the stubbed bits filled out this week.

Next was starting to get the audio side connected.  I had originally derived my VC4 side from the Mediatek driver, which makes a child device for the generic "hdmi-codec" DAI codec to attach to.  HDMI-codec is a shared implementation for HDMI encoders that take I2S input, which basically just passes audio setup params into the DRM HDMI encoder, whose job is to actually make I2S signals on wires get routed into HDMI audio packets.  They also have a CPU DAI registered through device tree that moves PCM data from memory onto wires, and a machine driver registered through devicetree that connects the CPU DAI's wires to the HDMI codec DAI's wires.  This is apparently how SoC audio is usually structured.

VC4, on the other hand, doesn't have a separate hardware block for moving PCM data from memory onto wires, it just has the MAI_DATA register in the HDMI block that you put S/PDIF (IEC958) data into using the SoC's generic DMA engine.  So I made VC4's HDMI driver register another a child device with the MAI_DATA register's address passed in, and that child device gets bound by the CPU DAI driver and uses the ASoC generic DMA engine support.  That CPU DAI driver also ends up setting up the machine driver, since I didn't have any other reference to the CPU DAI anywhere.  The glue here is all based on static strings I can't rely on, and is a complete hack for now.

Last, notice how I've used "PCM" talking about a working implementation's audio data and "S/PDIF" data for the thing I have to take in?  That's the sticking point.  The MAI_DATA register wants things that look like the AES3 frames description you can find on wikipedia.  I think the HW is generating my preamble.  In the firmware's HDMI audio implementation, they go through the unpacked PCM data and set the channel status bit in each sample according to the S/PDIF channel status word (the first 2 bytes of which are also documented on wikipedia).   At the same time that they're doing that, they also set the parity bit.

My first thought was "Hey, look, ALSA has SNDRV_PCM_FORMAT_IEC958_SUBFRAME, maybe my codec can say it only takes these S/PDIF frames and everything will work out."  No.  It turns out aplay won't generate them and neither will gstreamer.  To make a usable HDMI audio driver, I'm going to need to generate my IEC958 myself.

Linux is happy to generate my channel status word in memory.  I think the hardware is happy to generate my parity bit.  That just leaves making the CPU DAI write the bits of the channel status word into the subframes as PCM samples come in to the driver, and making sure that the MSB of the PCM audio data is bit 27.  I haven't figured out how to do that quite yet, which is the project for this week.

Work-in-progress, completely non-functional code is here.
Tags: vc4
  • Post a new comment


    default userpic

    Your IP address will be recorded