summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2001-06-17 03:42:01 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2001-06-17 03:42:01 +0000
commit555ddb02b45e7136508eddc4826dcf96773cc6e6 (patch)
tree05aaaa547bcb4e667f1c298727166c7323bad330 /sys/arch
parent3c48d6f2837b3a20783d5c56bd69bcf331c50949 (diff)
Significant improvement on awacs driver.
Interrupts dealt with better, edge/level information used (from netbsd) The device does not cause interrupt storm anymore. Port change interrupt handled correctly now, audio automatically switches from speaker to headphone and back when headphone is inserted. If headphone is present on boot, audio automatically configures to headphone output. Audio level now defaults to decent, low level by default.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/powerpc/mac/awacs.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/sys/arch/powerpc/mac/awacs.c b/sys/arch/powerpc/mac/awacs.c
index c9ba2562e61..a1f99c20589 100644
--- a/sys/arch/powerpc/mac/awacs.c
+++ b/sys/arch/powerpc/mac/awacs.c
@@ -245,6 +245,8 @@ awacs_attach(parent, self, aux)
{
struct awacs_softc *sc = (struct awacs_softc *)self;
struct confargs *ca = aux;
+ int cirq, oirq, iirq;
+ int cirq_type, oirq_type, iirq_type;
ca->ca_reg[0] += ca->ca_baseaddr;
ca->ca_reg[2] += ca->ca_baseaddr;
@@ -257,21 +259,34 @@ awacs_attach(parent, self, aux)
sc->sc_odmacmd = dbdma_alloc(20 * sizeof(struct dbdma_command));
sc->sc_idmacmd = dbdma_alloc(20 * sizeof(struct dbdma_command));
- mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_AUDIO, awacs_intr,
+ if (ca->ca_nintr == 24) {
+ cirq = ca->ca_intr[0];
+ oirq = ca->ca_intr[2];
+ iirq = ca->ca_intr[4];
+ cirq_type = ca->ca_intr[1] ? IST_LEVEL : IST_EDGE;
+ oirq_type = ca->ca_intr[3] ? IST_LEVEL : IST_EDGE;
+ iirq_type = ca->ca_intr[5] ? IST_LEVEL : IST_EDGE;
+ } else {
+ cirq = ca->ca_intr[0];
+ oirq = ca->ca_intr[1];
+ iirq = ca->ca_intr[2];
+ cirq_type = oirq_type = iirq_type = IST_LEVEL;
+ }
+ mac_intr_establish(parent, cirq, cirq_type, IPL_AUDIO, awacs_intr,
sc, "awacs");
- mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_AUDIO, awacs_tx_intr,
+ mac_intr_establish(parent, oirq, oirq_type, IPL_AUDIO, awacs_tx_intr,
sc, "awacs/tx");
#if 0
/* do not use this for now, since both are tied to same freq
* we can service both in the same interrupt, lowering
* interrupt load by half
*/
- mac_intr_establish(parent, ca->ca_intr[4], IST_LEVEL, IPL_AUDIO, awacs_intr,
+ mac_intr_establish(parent, iirq, irq_type, IPL_AUDIO, awacs_intr,
sc, "awacs/rx");
#endif
- printf(": irq %d,%d,%d\n",
- ca->ca_intr[0], ca->ca_intr[2], ca->ca_intr[4]);
+ printf(": irq %d,%d,%d",
+ cirq, oirq, iirq);
sc->sc_soundctl = AWACS_INPUT_SUBFRAME0 | AWACS_OUTPUT_SUBFRAME0 |
AWACS_RATE_44100 | AWACS_INT_PORTCHG;
@@ -287,17 +302,29 @@ awacs_attach(parent, self, aux)
/* Set initial volume[s] */
awacs_set_speaker_volume(sc, 80, 80);
+ awacs_set_ext_volume(sc, 80, 80);
/* Set loopback (for CD?) */
/* sc->sc_codecctl1 |= 0x440; */
sc->sc_codecctl1 |= 0x40;
awacs_write_codec(sc, sc->sc_codecctl1);
- /* default output to speakers */
- sc->sc_output_mask = 1 << 0;
- sc->sc_codecctl1 &= ~AWACS_MUTE_SPEAKER;
- sc->sc_codecctl1 |= AWACS_MUTE_HEADPHONE;
- awacs_write_codec(sc, sc->sc_codecctl1);
+ /* check for headphone present */
+ if (awacs_read_reg(sc, AWACS_CODEC_STATUS) & 0x8) {
+ /* default output to speakers */
+ printf(" headphones");
+ sc->sc_output_mask = 1 << 1;
+ sc->sc_codecctl1 &= ~AWACS_MUTE_HEADPHONE;
+ sc->sc_codecctl1 |= AWACS_MUTE_SPEAKER;
+ awacs_write_codec(sc, sc->sc_codecctl1);
+ } else {
+ /* default output to speakers */
+ printf(" speaker");
+ sc->sc_output_mask = 1 << 0;
+ sc->sc_codecctl1 &= ~AWACS_MUTE_SPEAKER;
+ sc->sc_codecctl1 |= AWACS_MUTE_HEADPHONE;
+ awacs_write_codec(sc, sc->sc_codecctl1);
+ }
/* default input from CD */
sc->sc_record_source = 1 << 0;
@@ -309,6 +336,7 @@ awacs_attach(parent, self, aux)
/* XXX ... */
awacs_halt_output(sc);
awacs_halt_input(sc);
+ printf("\n");
audio_attach_mi(&awacs_hw_if, sc, &sc->sc_dev);
}
@@ -356,12 +384,23 @@ awacs_intr(v)
printf("should change inputs\n");
}
if (reason & AWACS_CTL_PORTCHG) {
- error = (awacs_read_reg(sc, AWACS_CODEC_STATUS) >> 16) && 0xf;
- if (error != 0) {
- printf("AWACS error 0x%x\n", error);
+ if (awacs_read_reg(sc, AWACS_CODEC_STATUS) & 0x8) {
+ /* default output to speakers */
+ printf(" headphones");
+ sc->sc_output_mask = 1 << 1;
+ sc->sc_codecctl1 &= ~AWACS_MUTE_HEADPHONE;
+ sc->sc_codecctl1 |= AWACS_MUTE_SPEAKER;
+ awacs_write_codec(sc, sc->sc_codecctl1);
+ } else {
+ /* default output to speakers */
+ printf(" speaker");
+ sc->sc_output_mask = 1 << 0;
+ sc->sc_codecctl1 &= ~AWACS_MUTE_SPEAKER;
+ sc->sc_codecctl1 |= AWACS_MUTE_HEADPHONE;
+ awacs_write_codec(sc, sc->sc_codecctl1);
}
-
}
+
awacs_write_reg(sc, AWACS_SOUND_CTRL, reason); /* clear interrupt */
return 1;
}
@@ -573,6 +612,8 @@ awacs_round_blocksize(h, size)
void *h;
int size;
{
+ if (size < NBPG)
+ size = NBPG;
return size & ~PGOFSET;
}