Module Name:    src
Committed By:   jmcneill
Date:           Mon Mar 21 09:12:10 UTC 2022

Modified Files:
        src/sys/dev/hdaudio: hdaudioreg.h
        src/sys/dev/pci: hdaudio_pci.c hdaudio_pci.h

Log Message:
hdaudio: pci: PCIe config space fixes and Intel PCH snoop support

The HD audio specification does not cover PCI config space, and this
driver was unconditionally writing to a vendor specific register. Reduce
scope of config space accesses based on PCI IDs.

With this cleaned up, add support for Intel PCH devices which require
some additional vendor specific configuration to bypass no snoop mode.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/hdaudio/hdaudioreg.h
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/pci/hdaudio_pci.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/hdaudio_pci.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/hdaudio/hdaudioreg.h
diff -u src/sys/dev/hdaudio/hdaudioreg.h:1.3 src/sys/dev/hdaudio/hdaudioreg.h:1.4
--- src/sys/dev/hdaudio/hdaudioreg.h:1.3	Mon Jan  7 01:03:05 2019
+++ src/sys/dev/hdaudio/hdaudioreg.h	Mon Mar 21 09:12:10 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudioreg.h,v 1.3 2019/01/07 01:03:05 mrg Exp $ */
+/* $NetBSD: hdaudioreg.h,v 1.4 2022/03/21 09:12:10 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -36,14 +36,6 @@
 #include <sys/types.h>
 
 /*
- * High Definition Audio Audio PCI Configuration Space
- */
-#define	HDAUDIO_PCI_AZBARL	0x10
-#define	HDAUDIO_PCI_AZBARU	0x14
-#define	HDAUDIO_PCI_AZCTL	0x40
-#define	HDAUDIO_PCI_TCSEL	0x44
-
-/*
  * High Definition Audio Memory Mapped Configuration Registers
  */
 #define	HDAUDIO_MMIO_GCAP	0x000

Index: src/sys/dev/pci/hdaudio_pci.c
diff -u src/sys/dev/pci/hdaudio_pci.c:1.11 src/sys/dev/pci/hdaudio_pci.c:1.12
--- src/sys/dev/pci/hdaudio_pci.c:1.11	Thu Oct 28 09:15:35 2021
+++ src/sys/dev/pci/hdaudio_pci.c	Mon Mar 21 09:12:09 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_pci.c,v 1.11 2021/10/28 09:15:35 msaitoh Exp $ */
+/* $NetBSD: hdaudio_pci.c,v 1.12 2022/03/21 09:12:09 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.11 2021/10/28 09:15:35 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.12 2022/03/21 09:12:09 jmcneill Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -61,6 +61,11 @@ struct hdaudio_pci_softc {
 	pci_intr_handle_t	*sc_pihp;
 };
 
+#define	HDAUDIO_PCI_IS_INTEL(sc)	\
+	(PCI_VENDOR(sc->sc_id) == PCI_VENDOR_INTEL)
+#define	HDAUDIO_PCI_IS_NVIDIA(sc)	\
+	(PCI_VENDOR(sc->sc_id) == PCI_VENDOR_NVIDIA)
+
 static int	hdaudio_pci_match(device_t, cfdata_t, void *);
 static void	hdaudio_pci_attach(device_t, device_t, void *);
 static int	hdaudio_pci_detach(device_t, int);
@@ -68,7 +73,7 @@ static int	hdaudio_pci_rescan(device_t, 
 static void	hdaudio_pci_childdet(device_t, device_t);
 
 static int	hdaudio_pci_intr(void *);
-static void	hdaudio_pci_reinit(struct hdaudio_pci_softc *);
+static void	hdaudio_pci_init(struct hdaudio_pci_softc *);
 
 /* power management */
 static bool	hdaudio_pci_resume(device_t, const pmf_qual_t *);
@@ -139,7 +144,7 @@ hdaudio_pci_attach(device_t parent, devi
 	pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, csr);
 
 	/* Map MMIO registers */
-	reg = HDAUDIO_PCI_AZBARL;
+	reg = PCI_BAR0;
 	maptype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, reg);
 	err = pci_mapreg_map(pa, reg, maptype, 0,
 			     &sc->sc_hdaudio.sc_memt,
@@ -174,7 +179,7 @@ hdaudio_pci_attach(device_t parent, devi
 	}
 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
 
-	hdaudio_pci_reinit(sc);
+	hdaudio_pci_init(sc);
 
 	/* Attach bus-independent HD audio layer */
 	if (hdaudio_attach(self, &sc->sc_hdaudio)) {
@@ -187,15 +192,18 @@ hdaudio_pci_attach(device_t parent, devi
 		sc->sc_hdaudio.sc_memvalid = false;
 		csr = pci_conf_read(sc->sc_pc, sc->sc_tag,
 		    PCI_COMMAND_STATUS_REG);
-		csr &= ~(PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE);
+		csr &= ~(PCI_COMMAND_MASTER_ENABLE |
+			 PCI_COMMAND_BACKTOBACK_ENABLE);
 		pci_conf_write(sc->sc_pc, sc->sc_tag,
 		    PCI_COMMAND_STATUS_REG, csr);
 
-		if (!pmf_device_register(self, NULL, NULL))
-			aprint_error_dev(self, "couldn't establish power handler\n");
-	}
-	else if (!pmf_device_register(self, NULL, hdaudio_pci_resume))
+		if (!pmf_device_register(self, NULL, NULL)) {
+			aprint_error_dev(self,
+			    "couldn't establish power handler\n");
+		}
+	} else if (!pmf_device_register(self, NULL, hdaudio_pci_resume)) {
 		aprint_error_dev(self, "couldn't establish power handler\n");
+	}
 }
 
 static int
@@ -252,28 +260,51 @@ hdaudio_pci_intr(void *opaque)
 	return hdaudio_intr(&sc->sc_hdaudio);
 }
 
-
 static void
-hdaudio_pci_reinit(struct hdaudio_pci_softc *sc)
+hdaudio_pci_init(struct hdaudio_pci_softc *sc)
 {
 	pcireg_t val;
 
-	/* stops playback static */
-	val = pci_conf_read(sc->sc_pc, sc->sc_tag, HDAUDIO_PCI_TCSEL);
-	val &= ~7;
-	val |= 0;
-	pci_conf_write(sc->sc_pc, sc->sc_tag, HDAUDIO_PCI_TCSEL, val);
-
-	switch (PCI_VENDOR(sc->sc_id)) {
-	case PCI_VENDOR_NVIDIA:
-		/* enable snooping */
+	if (HDAUDIO_PCI_IS_INTEL(sc)) {
+		/*
+		 * ICH: Set traffic class for input/output/buf descriptors
+		 * to TC0. For PCH without a TCSEL register, PGCTL is in
+		 * the same location and clearing these bits is harmless.
+		 */
+		val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_ICH_TCSEL);
+		val &= ~HDAUDIO_INTEL_ICH_TCSEL_MASK;
+		val |= HDAUDIO_INTEL_ICH_TCSEL_TC0;
+		pci_conf_write(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_ICH_TCSEL, val);
+
+		/*
+		 * PCH: Disable dynamic clock gating logic. Implementations
+		 * without a CGCTL register do not appear to have anything
+		 * else in its place.
+		 */
+		val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_PCH_CGCTL);
+		val &= ~HDAUDIO_INTEL_PCH_CGCTL_MISCBDCGE;
+		pci_conf_write(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_PCH_CGCTL, val);
+
+		/* ICH/PCH: Enable snooping. */
+		val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_PCH_DEVC);
+		val &= ~HDAUDIO_INTEL_PCH_DEVC_NSNPEN;
+		pci_conf_write(sc->sc_pc, sc->sc_tag,
+		    HDAUDIO_INTEL_REG_PCH_DEVC, val);
+	}
+
+	if (HDAUDIO_PCI_IS_NVIDIA(sc)) {
+		/* Enable snooping. */
 		val = pci_conf_read(sc->sc_pc, sc->sc_tag,
 		    HDAUDIO_NV_REG_SNOOP);
 		val &= ~HDAUDIO_NV_SNOOP_MASK;
 		val |= HDAUDIO_NV_SNOOP_ENABLE;
 		pci_conf_write(sc->sc_pc, sc->sc_tag,
 		    HDAUDIO_NV_REG_SNOOP, val);
-		break;
 	}
 }
 
@@ -282,7 +313,8 @@ hdaudio_pci_resume(device_t self, const 
 {
 	struct hdaudio_pci_softc *sc = device_private(self);
 
-	hdaudio_pci_reinit(sc);
+	hdaudio_pci_init(sc);
+
 	return hdaudio_resume(&sc->sc_hdaudio);
 }
 

Index: src/sys/dev/pci/hdaudio_pci.h
diff -u src/sys/dev/pci/hdaudio_pci.h:1.1 src/sys/dev/pci/hdaudio_pci.h:1.2
--- src/sys/dev/pci/hdaudio_pci.h:1.1	Sat Mar 28 14:09:59 2015
+++ src/sys/dev/pci/hdaudio_pci.h	Mon Mar 21 09:12:09 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_pci.h,v 1.1 2015/03/28 14:09:59 jmcneill Exp $ */
+/* $NetBSD: hdaudio_pci.h,v 1.2 2022/03/21 09:12:09 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2010 Jared D. McNeill <jmcne...@invisible.ca>
@@ -31,8 +31,20 @@
 #ifndef _HDAUDIO_PCI_H
 #define _HDAUDIO_PCI_H
 
-#define	HDAUDIO_NV_REG_SNOOP	0x4c
-#define	  HDAUDIO_NV_SNOOP_MASK		0x00ff0000
-#define	  HDAUDIO_NV_SNOOP_ENABLE	0x000f0000
+/* NVIDIA specific registers */
+#define	HDAUDIO_NV_REG_SNOOP		0x4c
+#define	  HDAUDIO_NV_SNOOP_MASK			0x00ff0000
+#define	  HDAUDIO_NV_SNOOP_ENABLE		0x000f0000
+
+/* Intel ICH specific registers */
+#define	HDAUDIO_INTEL_REG_ICH_TCSEL	0x44
+#define	 HDAUDIO_INTEL_ICH_TCSEL_MASK		__BITS(2,0)
+#define	 HDAUDIO_INTEL_ICH_TCSEL_TC0		0
+
+/* Intel 100 Series Chipset Family Platform Controller Hub (PCH) */
+#define	HDAUDIO_INTEL_REG_PCH_CGCTL	0x48
+#define	  HDAUDIO_INTEL_PCH_CGCTL_MISCBDCGE	__BIT(6)
+#define	HDAUDIO_INTEL_REG_PCH_DEVC	0x78
+#define	  HDAUDIO_INTEL_PCH_DEVC_NSNPEN		__BIT(11)
 
 #endif /* !_HDAUDIO_PCI_H */

Reply via email to