Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/macppc/dev add basic support for iMac G5 audio:
details: https://anonhg.NetBSD.org/src/rev/446a8b0150c5
branches: trunk
changeset: 953530:446a8b0150c5
user: macallan <macallan%NetBSD.org@localhost>
date: Thu Mar 11 19:36:11 2021 +0000
description:
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
diffstat:
sys/arch/macppc/dev/snapper.c | 121 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 105 insertions(+), 16 deletions(-)
diffs (264 lines):
diff -r 970ee75e6ba3 -r 446a8b0150c5 sys/arch/macppc/dev/snapper.c
--- a/sys/arch/macppc/dev/snapper.c Thu Mar 11 19:34:11 2021 +0000
+++ b/sys/arch/macppc/dev/snapper.c Thu Mar 11 19:36:11 2021 +0000
@@ -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 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 @@
#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 @@
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 @@
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_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 @@
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 @@
}
#define headphone_active 0 /* XXX OF */
+#define lineout_active 0 /* XXX OF */
#define amp_active 0 /* XXX OF */
static void
@@ -1977,30 +1999,68 @@
}
}
+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 @@
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 @@
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 @@
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 @@
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_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 @@
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;
Home |
Main Index |
Thread Index |
Old Index