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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 */