diff options
| author | Orion Hodson <orion@FreeBSD.org> | 2001-12-18 03:29:31 +0000 |
|---|---|---|
| committer | Orion Hodson <orion@FreeBSD.org> | 2001-12-18 03:29:31 +0000 |
| commit | 0225c5ac86a9dd10f91c347bc42c82dc64ca9933 (patch) | |
| tree | e07e4be5f0df9e347395e8710c857ba61e38d272 /sys/dev/sound | |
| parent | 99364715f765e34621643adc9d81d4c515884b5a (diff) | |
Notes
Diffstat (limited to 'sys/dev/sound')
| -rw-r--r-- | sys/dev/sound/pci/ich.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c index 328540c6b6e3c..2da31502832e8 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; |
