summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authororion <orion@FreeBSD.org>2001-12-18 03:29:31 +0000
committerorion <orion@FreeBSD.org>2001-12-18 03:29:31 +0000
commit96b6116d6eb2970f9c11711ff24c9b26f90a7b0e (patch)
treee07e4be5f0df9e347395e8710c857ba61e38d272
parent7bdd95a9ab45ef5b5f86c31655bd16aeb5877423 (diff)
downloadFreeBSD-src-96b6116d6eb2970f9c11711ff24c9b26f90a7b0e.zip
FreeBSD-src-96b6116d6eb2970f9c11711ff24c9b26f90a7b0e.tar.gz
Add calibration test to determine extent of AC97 overclocking (if any).
-rw-r--r--sys/dev/sound/pci/ich.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c
index 328540c..2da3150 100644
--- a/sys/dev/sound/pci/ich.c
+++ b/sys/dev/sound/pci/ich.c
@@ -423,6 +423,55 @@ ich_initsys(struct sc_info* sc)
}
/* -------------------------------------------------------------------- */
+/* Calibrate card (some boards are overclocked and need scaling) */
+
+static
+unsigned int ich_calibrate(struct sc_info *sc)
+{
+ /* Grab audio from input for fixed interval and compare how
+ * much we actually get with what we expect. Interval needs
+ * to be sufficiently short that no interrupts are
+ * generated. */
+ struct sc_chinfo *ch = &sc->ch[1];
+ u_int16_t target_picb, actual_picb;
+ u_int32_t wait_us;
+ int32_t actual_48k_rate;
+
+ KASSERT(ch->regbase == ICH_REG_PI_BASE, ("wrong direction"));
+
+ ichchan_setspeed(0, ch, 48000);
+ ichchan_setblocksize(0, ch, ICH_DEFAULT_BUFSZ);
+
+ target_picb = ch->dtbl[0].length / 2; /* half interrupt interval */
+ wait_us = target_picb * 1000 / (2 * 48); /* (2 == stereo -> mono) */
+
+ if (bootverbose)
+ device_printf(sc->dev, "Calibration interval %d us\n",
+ wait_us);
+
+ ichchan_trigger(0, ch, PCMTRIG_START);
+ DELAY(wait_us);
+ actual_picb = ich_rd(sc, ch->regbase + ICH_REG_X_PICB, 2);
+ ichchan_trigger(0, ch, PCMTRIG_ABORT);
+
+ actual_48k_rate = 48000 * (2 * target_picb - actual_picb) /
+ (target_picb);
+
+ if (bootverbose)
+ device_printf(sc->dev,
+ "Tgt PICB %d, Act PICB %d, 48k rate %d\n",
+ target_picb, actual_picb, actual_48k_rate);
+
+ if ((actual_48k_rate - 48000) > 500 ||
+ (actual_48k_rate - 48000) < -500) {
+ sc->ac97rate = actual_48k_rate;
+ } else {
+ sc->ac97rate = 48000;
+ }
+ return sc->ac97rate;
+}
+
+/* -------------------------------------------------------------------- */
/* Probe and attach the card */
static void
@@ -573,6 +622,7 @@ ich_pci_attach(device_t dev)
pcm_setstatus(dev, status);
ich_initsys(sc);
+ ich_calibrate(sc);
return 0;
OpenPOWER on IntegriCloud