freebsd / drm-kmod

drm driver for FreeBSD
157 stars 68 forks source link

No sound over HDMI #187

Open Jocala opened 2 years ago

Jocala commented 2 years ago

No sound over HDMI

FreeBSD bsd 13.1-RELEASE FreeBSD 13.1-RELEASE releng/13.1-n250148-fc952ac2212 GENERIC amd64 cat /etc/rc.conf hostname="bsd" wlans_iwm0="wlan0" ifconfig_wlan0="WPA DHCP" create_args_wlan0="country US regdomain FCC" sshd_enable="YES" moused_enable="YES" ntpdate_enable="YES" ntpd_enable="YES" dumpdev="AUTO" dbus_enable="YES" hald_enable="YES" kld_list="i915kms" nfs_client_enable="YES" sddm_enable="YES" linux_enable="YES"

cat /etc/sysctl.conf hw.snd.default_unit=0

cat /boot/loader.conf kern.vty=vt compat.linuxkpi.i915_disable_power_well="0"

dmesg | grep pcm pcm0: <Intel Broadwell (HDMI/DP 8ch)> at nid 3 on hdaa0 pcm1: <Realtek ALC283 (Left Analog)> at nid 33 and 25 on hdaa1 pcm0: <Intel Broadwell (HDMI/DP 8ch)> at nid 3 on hdaa0 pcm1: <Realtek ALC283 (Left Analog)> at nid 33 and 25 on hdaa1 pcm0: <Intel Broadwell (HDMI/DP 8ch)> at nid 3 on hdaa0 pcm1: <Realtek ALC283 (Left Analog)> at nid 33 and 25 on hdaa1 pcm0: <Intel Broadwell (HDMI/DP 8ch)> at nid 3 on hdaa0 pcm1: <Realtek ALC283 (Left Analog)> at nid 33 and 25 on hdaa1

cat /dev/sndstat Installed devices: pcm0: <Intel Broadwell (HDMI/DP 8ch)> (play) pcm1: <Realtek ALC283 (Left Analog)> (play/rec) default No devices installed from userspace.

evadot commented 2 years ago

HDMI seems to be detected fine ? What's the problem exactly ?

shkhln commented 2 years ago

No, the audio device that the GPU presents to the system was detected fine. As I said elsewhere HDMI is actually very suspect. Also see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237340.

evadot commented 2 years ago

"HDMI is actually very suspect." What does that mean ? I have no problems on all my intel machines here (sandybridge, skylake, kabylake and coffelake) and this is the first time that I heard that someone is having sound problem.

evadot commented 2 years ago

So I was sure that I did tested my kabylake laptop but I guess I didn't because indeed it doesn't work. From what I could see when digging into this last friday drm is only needed to apply the power for the hda codec that lives in the graphics area and we seems to do this correctly. I'm a bit lost right now and do not understand if this is a drm-kmod problem or a snd_hda one ...

russor commented 2 years ago

This may be more of a snd_hda issue. I'm having the same problem on my Broadwell system. Comparing with Linux on the same hardware, Linux finds three outputs on hdaa0 and FreeBSD only sees one. On my system, my display is the second output.

Poking around, the Linux HDA driver does some things the FreeBSD doesn't

a) for many Intel GPU Codecs, it sends a command to enable all outputs (and Display port 1.2 features, whatever that is) during the probing process b) there's interaction between the HDA driver and the DRM driver that seems to manage the power well stuff as well as making sure the audio framing size is sufficient c) there's a fair amount of other stuff marked as haswell fixups that may be useful

On my hardware, if I add the command to enable all outputs in hdac.c, after Found CODEC at address, FreeBSD will see three outputs, if I also enable DP 1.2 features, I only get pcm0. Playing audio to dsp1 (when there are three) or dsp0 results in sound coming out, but there's an apparent sample rate issue, the audio is very slow and time mpg123 ... shows 2x the real time as the length of the file.

russor commented 2 years ago

The sample rate issue is related to the lack of communication between the hda and i915 drivers. On Haswell and Broadwell, it looks like the B Clock divider network needs to be set based on the Core Display clock . There's a way to get that from the i915 driver (i915_audio_component_get_cdclk_freq after binding), but I'm out of my depth trying to make that happen properly.

Setting the clock divider network with hardcoded code during codec initialization works, but is clearly fragile.

evadot commented 2 years ago

Could you share your patches for hda ? I'll try to take some time to dig more. Thanks.

russor commented 2 years ago

This is hacky --- I did not check for matching hardware, etc, I just go and poke things. This is OK on my test system, because I disabled the analog sound interface in firmware (I'm not using it), so the only HDA is the HDMI attached codec.

From what I can tell, the HDA_CMD bit should be pretty safe to run on all intel hdmi codecs past haswell (I've found an intel documentation that lists these values, but isn't super explicit about what it does), but the BCLK is only appropriate for haswell and broadwell. #define names, variable names, and the shape of the code are taken from the Linux driver, in case that matters (INTEL_FEATS is my own, Linux enables the flags one at a time, I do both at once)

patched against releng/13.1, but I didn't see major differences in HEAD.

--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -1588,6 +1588,35 @@ hdac_attach2(void *arg)
                                    "CODEC at address %d not responding!\n", i);
                                continue;
                        }
+
+       #define INTEL_GET_VENDOR_VERB 0xf81
+       #define INTEL_SET_VENDOR_VERB 0x781
+       #define INTEL_BDW_VENDOR_NID 0x08
+       #define INTEL_EN_ALL_PIN_CVTS      0x01    /* enable 2nd & 3rd pins and convertors */
+       #define INTEL_EN_DP12                   0x02 /* enable DP 1.2 features */
+       #define INTEL_FEATS (INTEL_EN_ALL_PIN_CVTS|INTEL_EN_DP12)
+
+       #define HSW_EM4 0x100c
+       #define HSW_EM5 0x1010
+
+                       unsigned int vendor_param;
+                       vendor_param = hdac_send_command(sc, i,
+                               HDA_CMD_12BIT(0, INTEL_BDW_VENDOR_NID, INTEL_GET_VENDOR_VERB, 0));
+                       if (!(vendor_param == -1 || (vendor_param & INTEL_FEATS) == INTEL_FEATS)) {
+                               vendor_param |= INTEL_FEATS;
+                               vendor_param = hdac_send_command(sc, i,
+                                       HDA_CMD_12BIT(0, INTEL_BDW_VENDOR_NID, INTEL_SET_VENDOR_VERB, vendor_param));
+                       }
+
+                       unsigned int bclk_m, bclk_n;
+                       bclk_m = 16;
+                       bclk_n = 225;
+
+                       HDAC_WRITE_4(&sc->mem, HSW_EM4, bclk_m);
+                       HDAC_WRITE_4(&sc->mem, HSW_EM5, bclk_n);
+
+                       device_printf(sc->dev, "bclk M %d, N %d\n", bclk_m, bclk_n);
+
                        sc->codecs[i].vendor_id =
                            HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid);
                        sc->codecs[i].device_id =
russor commented 2 years ago

So, I've been running this patch on my HTPC, and it works, but when the screen goes away and comes back, video works, but audio doesn't. I struggled with this on Linux as well, and ended up with forcing static EDID. IMHO, it's a deficiency of my receiver/TV that the EDID changes when those devices turn off or don't have the computer set as the input, but fixing them is obviously out of scope ;). I haven't checked to see if that's an option here as well, but if I have time, I will.

Edit: I got an external EDID fixer as I wasn't able to figure out how to force edid, but that didn't fix the audio issues anyway, so my understanding of the problem is wrong. Either way, after some time unused, the audio device becomes unusable until a reboot; i have compat.linuxkpi.i915_disable_power_well=1, but maybe there's something else I'm missing that's letting the audio device power save and not come back in the right shape.

charan-sai-k commented 1 year ago

sone hda verbs wrt to display audio have not been implemented