Some broken codecs don't release the CAS on reads to AC97_REG_GPIO_STATUS.

In auich_read_codec, do a dummy read to the RESET register if we're
reading GPIO_STATUS to be safe.
This commit is contained in:
jmcneill 2005-04-12 17:30:51 +00:00
parent 4f351ce9a0
commit eddca7ac5f
1 changed files with 33 additions and 4 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: auich.c,v 1.94 2005/04/11 11:20:45 jmcneill Exp $ */
/* $NetBSD: auich.c,v 1.95 2005/04/12 17:30:51 jmcneill Exp $ */
/*-
* Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.94 2005/04/11 11:20:45 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.95 2005/04/12 17:30:51 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -288,6 +288,7 @@ static int auich_set_rate(struct auich_softc *, int, u_long);
static int auich_sysctl_verify(SYSCTLFN_ARGS);
static void auich_finish_attach(struct device *);
static void auich_calibrate(struct auich_softc *);
static void auich_clear_cas(struct auich_softc *);
static int auich_attach_codec(void *, struct ac97_codec_if *);
static int auich_read_codec(void *, uint8_t, uint16_t *);
@ -756,11 +757,17 @@ auich_read_codec(void *v, uint8_t reg, uint16_t *val)
*val = 0xffff;
DPRINTF(ICH_DEBUG_CODECIO,
("%s: read_codec error\n", sc->sc_dev.dv_xname));
if (reg == AC97_REG_GPIO_STATUS)
auich_clear_cas(sc);
return -1;
}
if (reg == AC97_REG_GPIO_STATUS)
auich_clear_cas(sc);
return 0;
} else {
aprint_normal("%s: read_codec timeout\n", sc->sc_dev.dv_xname);
if (reg == AC97_REG_GPIO_STATUS)
auich_clear_cas(sc);
return -1;
}
}
@ -810,10 +817,12 @@ auich_reset_codec(void *v)
sc = v;
control = bus_space_read_4(sc->iot, sc->aud_ioh,
ICH_GCTRL + sc->sc_modem_offset);
if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO)
if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
control &= ~(ICH_ACLSO | ICH_PCM246_MASK);
else
} else {
control &= ~ICH_ACLSO;
control |= ICH_GIE;
}
control |= (control & ICH_CRESET) ? ICH_WRESET : ICH_CRESET;
bus_space_write_4(sc->iot, sc->aud_ioh,
ICH_GCTRL + sc->sc_modem_offset, control);
@ -1226,6 +1235,16 @@ auich_intr(void *v)
ret++;
}
#ifdef AUICH_MODEM_DEBUG
if (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_GSCI) {
printf("%s: gsts=0x%x\n", sc->sc_dev.dv_xname, gsts);
/* int ack */
bus_space_write_4(sc->iot, sc->aud_ioh,
ICH_GSTS + sc->sc_modem_offset, ICH_GSCI);
ret++;
}
#endif
return ret;
}
@ -1613,3 +1632,13 @@ auich_calibrate(struct auich_softc *sc)
sc->sc_ac97_clock = ac97rate;
}
static void
auich_clear_cas(struct auich_softc *sc)
{
/* Clear the codec access semaphore */
(void)bus_space_read_2(sc->iot, sc->mix_ioh,
AC97_REG_RESET * (sc->sc_codecnum * ICH_CODEC_OFFSET));
return;
}