Module Name: src Committed By: macallan Date: Thu Mar 11 19:36:11 UTC 2021
Modified Files: src/sys/arch/macppc/dev: snapper.c Log Message: add basic support for iMac G5 audio: - match AOAShasta - deal with headphone gpios labeled as lineout in OF - set sc_mode to SNAPPER_IS_PCM3052 - OF makes it look like an unlabeled TAS3004 TODO: - actually support pcm3052 instead of treating it like a sw codec To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.57 src/sys/arch/macppc/dev/snapper.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/macppc/dev/snapper.c diff -u src/sys/arch/macppc/dev/snapper.c:1.56 src/sys/arch/macppc/dev/snapper.c:1.57 --- src/sys/arch/macppc/dev/snapper.c:1.56 Fri Mar 5 07:15:53 2021 +++ src/sys/arch/macppc/dev/snapper.c Thu Mar 11 19:36:11 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: snapper.c,v 1.56 2021/03/05 07:15:53 rin Exp $ */ +/* $NetBSD: snapper.c,v 1.57 2021/03/11 19:36:11 macallan Exp $ */ /* Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp */ /* Id: i2s.c,v 1.12 2005/01/15 14:32:35 tsubai Exp */ @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: snapper.c,v 1.56 2021/03/05 07:15:53 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: snapper.c,v 1.57 2021/03/11 19:36:11 macallan Exp $"); #include <sys/param.h> #include <sys/audioio.h> @@ -158,6 +158,7 @@ static int gpio_read(bus_size_t); static void gpio_write(bus_size_t, int); static void snapper_mute_speaker(struct snapper_softc *, int); static void snapper_mute_headphone(struct snapper_softc *, int); +static void snapper_mute_lineout(struct snapper_softc *, int); static int snapper_cint(void *); static int tas3004_init(struct snapper_softc *); static void snapper_init(struct snapper_softc *, int); @@ -519,11 +520,14 @@ static const struct audio_format onyx_fo #define ONYX_NFORMATS __arraycount(onyx_formats) static bus_size_t amp_mute; -static bus_size_t headphone_mute; +static bus_size_t headphone_mute = 0; static bus_size_t audio_hw_reset; -static bus_size_t headphone_detect; +static bus_size_t headphone_detect = 0; +static bus_size_t lineout_detect = 0; +static bus_size_t lineout_mute= 0; static bus_size_t owaddr = -1; -static uint8_t headphone_detect_active; +static uint8_t headphone_detect_active = 0; +static uint8_t lineout_detect_active = 0; /* I2S registers */ @@ -692,6 +696,9 @@ snapper_match(device_t parent, struct cf if (strcmp(compat, "AOAK2") == 0) return 1; + + if (strcmp(compat, "AOAShasta") == 0) + return 1; if (strcmp(compat, "AOAbase") == 0) return 1; @@ -870,8 +877,17 @@ snapper_defer(device_t dev) if (codec[0] == 0) { if (sc->sc_deqaddr == 0x34) { sc->sc_mode = SNAPPER_IS_TAS3001; - } else + } else { + int root = OF_finddevice("/"); + char model[32]; sc->sc_mode = SNAPPER_IS_TAS3004; + if (OF_getprop(root, "model", model, 32) > 0) { + printf("model %s\n", model); + if (strcmp(model, "PowerMac8,1") == 0) { + sc->sc_mode = SNAPPER_IS_PCM3052; + } + } + } } else if (strcmp(codec, "tas3004") == 0) { sc->sc_mode = SNAPPER_IS_TAS3004; } else if (strcmp(codec, "pcm3052") == 0) { @@ -1077,10 +1093,13 @@ snapper_set_port(void *h, mixer_ctrl_t * snapper_mute_speaker(sc, 1); snapper_mute_headphone(sc, 1); + snapper_mute_lineout(sc, 1); if (mc->un.mask & 1 << 0) snapper_mute_speaker(sc, 0); if (mc->un.mask & 1 << 1) snapper_mute_headphone(sc, 0); + if (mc->un.mask & 1 << 2) + snapper_mute_lineout(sc, 0); sc->sc_output_mask = mc->un.mask; return 0; @@ -1240,11 +1259,13 @@ snapper_query_devinfo(void *h, mixer_dev strcpy(dip->label.name, AudioNoutput); dip->type = AUDIO_MIXER_SET; dip->prev = dip->next = AUDIO_MIXER_LAST; - dip->un.s.num_mem = 2; + dip->un.s.num_mem = 3; strcpy(dip->un.s.member[0].label.name, AudioNspeaker); dip->un.s.member[0].mask = 1 << 0; strcpy(dip->un.s.member[1].label.name, AudioNheadphone); dip->un.s.member[1].mask = 1 << 1; + strcpy(dip->un.s.member[2].label.name, AudioNline); + dip->un.s.member[2].mask = 1 << 2; return 0; case SNAPPER_VOL_OUTPUT: @@ -1937,6 +1958,7 @@ gpio_write(bus_size_t addr, int val) } #define headphone_active 0 /* XXX OF */ +#define lineout_active 0 /* XXX OF */ #define amp_active 0 /* XXX OF */ static void @@ -1977,30 +1999,68 @@ snapper_mute_headphone(struct snapper_so } } +static void +snapper_mute_lineout(struct snapper_softc *sc, int mute) +{ + u_int x; + + if (lineout_mute != 0) { + DPRINTF("lineoutmute %d --> ", gpio_read(lineout_mute)); + + if (mute) + x = lineout_active; /* mute */ + else + x = !lineout_active; /* unmute */ + if (x != gpio_read(lineout_mute)) + gpio_write(lineout_mute, x); + + DPRINTF("%d\n", gpio_read(lineout_mute)); + } +} + static int snapper_cint(void *v) { - struct snapper_softc *sc; + struct snapper_softc *sc = v; u_int sense; + int mask = 1 << 0; if (headphone_detect != 0) { - sc = v; sense = obio_read_1(headphone_detect); DPRINTF("headphone detect = 0x%x\n", sense); if (((sense & 0x02) >> 1) == headphone_detect_active) { DPRINTF("headphone is inserted\n"); - snapper_mute_speaker(sc, 1); - snapper_mute_headphone(sc, 0); - sc->sc_output_mask = 1 << 1; + mask |= 1 << 1; + mask &= ~(1 << 0); } else { DPRINTF("headphone is NOT inserted\n"); - snapper_mute_speaker(sc, 0); - snapper_mute_headphone(sc, 1); - sc->sc_output_mask = 1 << 0; } } - + if (lineout_detect != 0) { + sense = obio_read_1(lineout_detect); + DPRINTF("lineout detect = 0x%x\n", sense); + + if (((sense & 0x02) >> 1) == lineout_detect_active) { + DPRINTF("lineout is inserted\n"); + mask |= 1 << 2; + mask &= ~(1 << 0); + } else { + DPRINTF("lineout is NOT inserted\n"); + } + } + if (mask != sc->sc_output_mask) { + sc->sc_output_mask = mask; + if (mask & (1 << 0)) { + snapper_mute_speaker(sc, 0); + } else snapper_mute_speaker(sc, 1); + if (mask & (1 << 1)) { + snapper_mute_headphone(sc, 0); + } else snapper_mute_headphone(sc, 1); + if (mask & (1 << 2)) { + snapper_mute_lineout(sc, 0); + } else snapper_mute_lineout(sc, 1); + } return 1; } @@ -2068,7 +2128,7 @@ static void snapper_init(struct snapper_softc *sc, int node) { int gpio; - int headphone_detect_intr; + int headphone_detect_intr, lineout_detect_intr; uint32_t gpio_base, reg[1], fcreg; char intr_xname[INTRDEVNAMEBUF]; #ifdef SNAPPER_DEBUG @@ -2082,6 +2142,7 @@ snapper_init(struct snapper_softc *sc, i obio_write_4(KEYLARGO_FCR1, fcreg); headphone_detect_intr = -1; + lineout_detect_intr = -1; gpio = of_getnode_byname(OF_parent(node), "gpio"); if (OF_getprop(gpio, "reg", reg, sizeof(reg)) == sizeof(reg)) @@ -2133,6 +2194,19 @@ snapper_init(struct snapper_softc *sc, i headphone_detect_intr = intr[0]; } } + if (strcmp(audio_gpio, "lineout-mute") == 0 || + strcmp(name, "lineout-mute") == 0) + lineout_mute = addr; + if (strcmp(audio_gpio, "lineout-detect") == 0 || + strcmp(name, "lineout-detect") == 0) { + uint32_t act = 0; + lineout_detect = addr; + OF_getprop(gpio, "audio-gpio-active-state", &act, 4); + lineout_detect_active = act; + if (OF_getprop(gpio, "interrupts", intr, 8) == 8) { + lineout_detect_intr = intr[0]; + } + } /* extint-gpio16 on Quicksilver */ if (strcmp(sid, "speaker-id") == 0) { owaddr = addr; @@ -2148,10 +2222,14 @@ snapper_init(struct snapper_softc *sc, i if (owaddr != -1) snapper_setup_ow(sc); DPRINTF(" headphone-mute %x\n", headphone_mute); + DPRINTF(" lineout-mute %x\n", lineout_mute); DPRINTF(" amp-mute %x\n", amp_mute); DPRINTF(" headphone-detect %x\n", headphone_detect); DPRINTF(" headphone-detect active %x\n", headphone_detect_active); DPRINTF(" headphone-detect intr %x\n", headphone_detect_intr); + DPRINTF(" lineout-detect %x\n", lineout_detect); + DPRINTF(" lineout-detect active %x\n", lineout_detect_active); + DPRINTF(" lineout-detect intr %x\n", lineout_detect_intr); DPRINTF(" audio-hw-reset %x\n", audio_hw_reset); if (headphone_detect_intr != -1) { @@ -2161,6 +2239,13 @@ snapper_init(struct snapper_softc *sc, i snapper_cint, sc, intr_xname); } + if (lineout_detect_intr != -1) { + snprintf(intr_xname, sizeof(intr_xname), "%s line out", + device_xname(sc->sc_dev)); + intr_establish_xname(lineout_detect_intr, IST_EDGE, IPL_AUDIO, + snapper_cint, sc, intr_xname); + } + sc->sc_rate = 44100; /* default rate */ sc->sc_bitspersample = 16; @@ -2169,6 +2254,10 @@ snapper_init(struct snapper_softc *sc, i obio_write_1(headphone_detect, obio_read_1(headphone_detect) | 0x80); } + if (lineout_detect != 0) { + obio_write_1(lineout_detect, + obio_read_1(lineout_detect) | 0x80); + } if (tas3004_init(sc)) return;