git: 65341ec31729 - main - snd_hda: Reassign duplicate HDMI/DP pin sequences instead of disabling

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Tue, 19 May 2026 12:26:04 UTC
The branch main has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=65341ec3172936804b081c8ceca9bae88f5c7192

commit 65341ec3172936804b081c8ceca9bae88f5c7192
Author:     Abdelkader Boudih <freebsd@seuros.com>
AuthorDate: 2026-05-19 12:24:14 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2026-05-19 12:25:51 +0000

    snd_hda: Reassign duplicate HDMI/DP pin sequences instead of disabling
    
    Some firmware (e.g. Apple EFI on Sandy Bridge Mac hardware) programs all
    HDMI/DP output pins in an association with identical sequence numbers.
    
    The existing code disables the entire association on the first
    duplicate, leaving HDMI/DP audio non-functional.
    
    For digital output pins (HDMI/DP) with seq=0 duplicates, search for the
    next free sequence slot and reassign the duplicate rather than
    disabling.
    
    The seq=0 restriction targets the known Apple firmware pattern; any
    other duplicate sequence is more likely a genuine firmware error and the
    association is still disabled.
    
    Update first after reassignment so that hpredir is not left pointing at
    a stale sequence. Non-digital and input associations retain the existing
    disable behaviour.
    
    MFC after:      1 week
    Reviewed by:    christos
    Differential Revision:  https://reviews.freebsd.org/D55473
---
 sys/dev/sound/pci/hda/hdaa.c | 49 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c
index 7dec437de944..8add23217d1b 100644
--- a/sys/dev/sound/pci/hda/hdaa.c
+++ b/sys/dev/sound/pci/hda/hdaa.c
@@ -3268,10 +3268,51 @@ hdaa_audio_as_parse(struct hdaa_devinfo *devinfo)
 				first = seq;
 			/* Check association correctness. */
 			if (as[cnt].pins[seq] != 0) {
-				device_printf(devinfo->dev, "%s: Duplicate pin %d (%d) "
-				    "in association %d! Disabling association.\n",
-				    __func__, seq, w->nid, j);
-				as[cnt].enable = 0;
+				int newseq = -1;
+
+				/*
+				 * Some firmware (e.g. Apple EFI on Mac hardware)
+				 * assigns seq=0 to all HDMI/DP output pins in
+				 * an association.  Reassign the duplicate to
+				 * the next free slot rather than disabling the
+				 * whole association.  Limit to seq=0 duplicates:
+				 * any other duplicate sequence is more likely a
+				 * genuine firmware error and should still disable.
+				 */
+				if (seq == 0 && dir == HDAA_CTL_OUT &&
+				    HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(
+				    w->param.widget_cap) &&
+				    (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap) ||
+				    HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap))) {
+					int cand;
+
+					for (cand = 1; cand < 16; cand++) {
+						if (as[cnt].pins[cand] == 0) {
+							newseq = cand;
+							break;
+						}
+					}
+				}
+				if (newseq >= 0) {
+					HDA_BOOTVERBOSE(
+						device_printf(devinfo->dev,
+						    "%s: Duplicate pin %d (%d) "
+						    "in association %d, "
+						    "reassigning to seq %d.\n",
+						    __func__, seq, w->nid,
+						    j, newseq);
+					);
+					seq = newseq;
+					/* Update hpredir anchor to lowest seq. */
+					first = min(first, newseq);
+				} else {
+					device_printf(devinfo->dev,
+					    "%s: Duplicate pin %d (%d) "
+					    "in association %d! "
+					    "Disabling association.\n",
+					    __func__, seq, w->nid, j);
+					as[cnt].enable = 0;
+				}
 			}
 			if (dir != as[cnt].dir) {
 				device_printf(devinfo->dev, "%s: Pin %d has wrong "