-
Multichannel audio problem with AMD GPUs (over HDMI)
From time to time that question reappears: what about multichannel audio with AMD/ATI GPU? I wanted to share that short summary on the current state and the lacking parts.
First of all, alsa driver needs to know audio-related capabilites of a receiver. That includes supported formats, channels and frequencies, all of that is available in CEA extension of an EDID (CEA is just a part of EDID). The problem is that the EDID is received by GPU, and it is GPU driver that has access to it, not the audio one.
So how it's usually solved? It's handled with the special connection between GPU and audio. That way GPU driver can pass some data to the audio card and audio driver can read it. There are 2 important formats:
1) SAD (Short Audio Descriptor) is a 3 bytes struct used in CEA. It carries info about format, channels, frequencies and bitrate. CEA usually has many SAD blocks.
2) ELD (EDID-Like Data) is a bigger struct containing name, information about speakrs and SADs.
Usually GPU driver's role is to read EDID, extract audio related info from it, build ELD struct and write it to the GPU. Thanks to the GPU←→audio connection that becomes available for in the audio card. It's nicely implemented in i915: they read EDID, use drm_edid_to_eld to construct ELD, and write it to the GPU in intel_write_eld function.
In case of Radeon hardware it seems slightly different. Driver doesn't build ELD struct, but it just fills proper registers with SADs data (see AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0 up to AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13). It doesn't sound like a big difference, but it causes some implementation/RE problems actually. My first idea was that it's firmware that builds ELD from the passed values and audio driver can just reads the ELD in a standard way. Unfortunately it doesn't seem to be so easy. When using fglrx I can clearly see that the registers are correctly filled, but alsa driver still complains with all that:
ALSA hda_eld.c:337 HDMI: ELD buf size is 0, force 128
ALSA hda_eld.c:356 HDMI: invalid ELD data byte 0
As I don't suspect bugs in fglrx regarding that part of audio support, I believe we are doing something wrong in audio driver. As reading ELD in a standard way doesn't seem to work, I think we should look for something else. The problem is I'm not sure if AMD uses ELD format at all. I got an idea that maybe we should look for the SADs in a vendor-specific verbs (on the audio side). I've installed "hda-verb" and wrote a trivial PHP script to read all possible vendor-specific verbs (starting from 0xF70 to 0xFFF and params from 0 to 0xFFFF). Unfortunately I didn't get anything interesting.
I don't really have any other ideas how to read SADs/ELD in the audio driver at this point. Kind of workaround would be to pass that info in a software way (just export a simple function in the alsa driver). However I don't think this hack would be accepted in a kernel. So right now I'm out of ideas and until someone figures it out, we won't really have a multichannel audio support in the alsa driver :(
One more extra problem is that "radeon" driver currently doesn't fill that AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0 ... AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13 registers at all. It blocks multichannel audio support, however there is no rush in implementing this, as alsa driver can read that anyway.
I've mailed some summary to alsa-devel as well, to see if someone has any idea: hda: sink info in case of AMD Radeon GPU card (no ELD?) -
Reverse engineering fglrx and HDMI audio
So this time instead of just improving HDMI audio support I've decided to also describe that RE process. I hope it may help some hacker who would like to help but doesn't know where to start.
First of all, I assume we want to include out work in Linux kernel, so we're interested only in clean room reverse engineering. It means we can't disassemble binary, but we are allowed to observe closed source driver behaviour. There are two methods left in this case: reading registers values or watching regs operations. -
Northern Islands HDMI audio support
Good news Northern Islands users!
Today Linus pulled Dave's drm-fixes tree with one (interesting?) patch from me:
drm/radeon: enable HDMI on DCE5 (AKA NI excluding Aruba)
Unless something really bad happens, starting with kernel 3.5-rc4 you will have NI HDMI audio support in radeon KMS driver :) -
Santa doesn't forget about old cards (R6xx/R7xx HDMI audio)
Since ever few radeon HDMI audio testers were reporting problems with their TVs not displaying anything at all. Enabling audio support resulted in invalid signal or similar error.
Thanks to great help from Nirbheek Chauhan, I've finally found the source of this issue. It appears we calculate checksum of HDMI infoframe incorrectly. Some TVs don't care about this, but others really do, refusing to display or play anything.
I've just posted:
[PATCH] drm/radeon/kms: workaround invalid AVI infoframe checksum
with suggestion of backporting this patch to stable releases. Just a one another Christmas gift from me.
Merry Christmas everyone who celebrate it :) -
Evergreen HDMI audio ready!
Few days ago I've managed to hack radeon to play audio over HDMI on my Evergreen card. At first I just forced radeon to use single hardcoded HDMI block I've discovered on my card.
Then I started looking for universal (general) solution. I was trying to do HDMI block mapping based on crtc offset, but it failed. Trying to use encoder type (which is really a transmitter in Radeon hardware) also didn't work out.
Finally, after analyzing dumps I've received from people, I found out the real solution. HDMI block mapping has to be based on DIG encoder.
I want to help the community for helping me with the dumps. Without them I wouldn't write really-working code so fast. Sometimes you don't have to known ANSI C and hardware programming to help in development :)
The patches will be released in minutes, I hope every Evergreen card will be supported now. They hopefully will hit Dave's tree soon and kernel 3.3 as the result.
P.S.
List of patches:
[PATCH] drm/radeon/kms: minor HDMI audio cleanups
[PATCH 1/3] drm/radeon/kms: one more HDMI cleanup (in disabling code)
[PATCH 2/3] drm/radeon/kms: support for audio on Evergreen
[PATCH V2 3/3] drm/radeon/kms: enable HDMI mode on Evergreen encoders
[PATCH V2] drm/radeon/kms: do not force DVI mode on DCE4 if audio is on