diff options
-rw-r--r-- | sys/arch/macppc/dev/i2s.c | 326 | ||||
-rw-r--r-- | sys/arch/macppc/dev/i2sreg.h | 6 | ||||
-rw-r--r-- | sys/arch/macppc/dev/i2svar.h | 12 |
3 files changed, 127 insertions, 217 deletions
diff --git a/sys/arch/macppc/dev/i2s.c b/sys/arch/macppc/dev/i2s.c index 40774112d96..a5f18639fae 100644 --- a/sys/arch/macppc/dev/i2s.c +++ b/sys/arch/macppc/dev/i2s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i2s.c,v 1.21 2011/05/15 09:10:26 mpi Exp $ */ +/* $OpenBSD: i2s.c,v 1.22 2011/06/07 16:29:51 mpi Exp $ */ /* $NetBSD: i2s.c,v 1.1 2003/12/27 02:19:34 grant Exp $ */ /*- @@ -67,31 +67,18 @@ struct audio_params i2s_audio_default = { struct i2s_mode *i2s_find_mode(u_int, u_int, u_int); -static int gpio_read(char *); -static void gpio_write(char *, int); -void i2s_mute_speaker(struct i2s_softc *, int); -void i2s_mute_headphone(struct i2s_softc *, int); -void i2s_mute_lineout(struct i2s_softc *, int); -int i2s_cint(void *); -u_char *i2s_gpio_map(struct i2s_softc *, char *, int *); -void i2s_init(struct i2s_softc *, int); +void i2s_mute(u_int, int); +int i2s_cint(void *); +u_int i2s_gpio_offset(struct i2s_softc *, char *, int *); +void i2s_init(struct i2s_softc *, int); -int i2s_intr(void *); -int i2s_iintr(void *); +int i2s_intr(void *); +int i2s_iintr(void *); struct cfdriver i2s_cd = { NULL, "i2s", DV_DULL }; -static u_char *amp_mute; -static u_char *headphone_mute; -static u_char *lineout_mute; -static u_char *audio_hw_reset; -static u_char *headphone_detect; -static int headphone_detect_active; -static u_char *lineout_detect; -static int lineout_detect_active; - void i2s_attach(struct device *parent, struct i2s_softc *sc, struct confargs *ca) { @@ -514,15 +501,15 @@ i2s_set_port(void *h, mixer_ctrl_t *mc) if (mc->un.mask == sc->sc_output_mask) return 0; - i2s_mute_speaker(sc, 1); - i2s_mute_headphone(sc, 1); - i2s_mute_lineout(sc, 1); - if (mc->un.mask & 1 << 0) - i2s_mute_speaker(sc, 0); - if (mc->un.mask & 1 << 1) - i2s_mute_headphone(sc, 0); - if (mc->un.mask & 1 << 2) - i2s_mute_lineout(sc, 0); + i2s_mute(sc->sc_spkr, 1); + i2s_mute(sc->sc_hp, 1); + i2s_mute(sc->sc_line, 1); + if (mc->un.mask & I2S_SELECT_SPEAKER) + i2s_mute(sc->sc_spkr, 0); + if (mc->un.mask & I2S_SELECT_HEADPHONE) + i2s_mute(sc->sc_hp, 0); + if (mc->un.mask & I2S_SELECT_LINEOUT) + i2s_mute(sc->sc_line, 0); sc->sc_output_mask = mc->un.mask; return 0; @@ -538,19 +525,19 @@ i2s_set_port(void *h, mixer_ctrl_t *mc) sc->sc_mute = (mc->un.ord != 0); if (sc->sc_mute) { - if (sc->sc_output_mask & 1 << 0) - i2s_mute_speaker(sc, 1); - if (sc->sc_output_mask & 1 << 1) - i2s_mute_headphone(sc, 1); - if (sc->sc_output_mask & 1 << 2) - i2s_mute_lineout(sc, 1); + if (sc->sc_output_mask & I2S_SELECT_SPEAKER) + i2s_mute(sc->sc_spkr, 1); + if (sc->sc_output_mask & I2S_SELECT_HEADPHONE) + i2s_mute(sc->sc_hp, 1); + if (sc->sc_output_mask & I2S_SELECT_LINEOUT) + i2s_mute(sc->sc_line, 1); } else { - if (sc->sc_output_mask & 1 << 0) - i2s_mute_speaker(sc, 0); - if (sc->sc_output_mask & 1 << 1) - i2s_mute_headphone(sc, 0); - if (sc->sc_output_mask & 1 << 2) - i2s_mute_lineout(sc, 0); + if (sc->sc_output_mask & I2S_SELECT_SPEAKER) + i2s_mute(sc->sc_spkr, 0); + if (sc->sc_output_mask & I2S_SELECT_HEADPHONE) + i2s_mute(sc->sc_hp, 0); + if (sc->sc_output_mask & I2S_SELECT_LINEOUT) + i2s_mute(sc->sc_line, 0); } return (0); @@ -570,8 +557,8 @@ i2s_set_port(void *h, mixer_ctrl_t *mc) if (mc->un.mask == sc->sc_record_source) return 0; switch (mc->un.mask) { - case 1 << 0: /* microphone */ - case 1 << 1: /* line in */ + case I2S_SELECT_SPEAKER: + case I2S_SELECT_HEADPHONE: /* XXX TO BE DONE */ break; default: /* invalid argument */ @@ -655,17 +642,17 @@ i2s_query_devinfo(void *h, mixer_devinfo_t *dip) dip->prev = dip->next = AUDIO_MIXER_LAST; strlcpy(dip->un.s.member[n].label.name, AudioNspeaker, sizeof(dip->un.s.member[n].label.name)); - dip->un.s.member[n++].mask = 1 << 0; - if (headphone_mute) { + dip->un.s.member[n++].mask = I2S_SELECT_SPEAKER; + if (sc->sc_hp) { strlcpy(dip->un.s.member[n].label.name, AudioNheadphone, sizeof(dip->un.s.member[n].label.name)); - dip->un.s.member[n++].mask = 1 << 1; + dip->un.s.member[n++].mask = I2S_SELECT_HEADPHONE; } - if (lineout_mute) { + if (sc->sc_line) { strlcpy(dip->un.s.member[n].label.name, AudioNline, sizeof(dip->un.s.member[n].label.name)); - dip->un.s.member[n++].mask = 1 << 2; + dip->un.s.member[n++].mask = I2S_SELECT_LINEOUT; } dip->un.s.num_mem = n; return 0; @@ -705,10 +692,10 @@ i2s_query_devinfo(void *h, mixer_devinfo_t *dip) dip->un.s.num_mem = 2; strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone, sizeof(dip->un.s.member[0].label.name)); - dip->un.s.member[0].mask = 1 << 0; + dip->un.s.member[0].mask = I2S_SELECT_SPEAKER; strlcpy(dip->un.s.member[1].label.name, AudioNline, sizeof(dip->un.s.member[1].label.name)); - dip->un.s.member[1].mask = 1 << 1; + dip->un.s.member[1].mask = I2S_SELECT_HEADPHONE; return 0; case I2S_VOL_INPUT: @@ -993,151 +980,73 @@ done: return 0; } -int -gpio_read(addr) - char *addr; -{ - if (*addr & GPIO_DATA) - return 1; - return 0; -} - -void -gpio_write(addr, val) - char *addr; - int val; -{ - u_int data = GPIO_DDR_OUTPUT; - - if (val) - data |= GPIO_DATA; - *addr = data; - asm volatile ("eieio" ::: "memory"); -} - -#define amp_active 0 /* XXX OF */ -#define headphone_active 0 /* XXX OF */ -#define lineout_active 0 /* XXX OF */ - void -i2s_mute_speaker(sc, mute) - struct i2s_softc *sc; - int mute; +i2s_mute(u_int offset, int mute) { - u_int x; - - if (amp_mute == NULL) + if (offset == 0) return; - DPRINTF(("ampmute %d --> ", gpio_read(amp_mute))); + DPRINTF(("gpio: %x, %d -> ", offset, macobio_read(offset) & GPIO_DATA)); - if (mute) - x = amp_active; /* mute */ - else - x = !amp_active; /* unmute */ - if (x != gpio_read(amp_mute)) - gpio_write(amp_mute, x); + /* 0 means mute */ + if (mute == (macobio_read(offset) & GPIO_DATA)) + macobio_write(offset, !mute | GPIO_DDR_OUTPUT); - DPRINTF(("%d\n", gpio_read(amp_mute))); -} - -void -i2s_mute_headphone(sc, mute) - struct i2s_softc *sc; - int mute; -{ - u_int x; - - if (headphone_mute == NULL) - return; - - DPRINTF(("headphonemute %d --> ", gpio_read(headphone_mute))); - - if (mute) - x = headphone_active; /* mute */ - else - x = !headphone_active; /* unmute */ - if (x != gpio_read(headphone_mute)) - gpio_write(headphone_mute, x); - - DPRINTF(("%d\n", gpio_read(headphone_mute))); -} - -void -i2s_mute_lineout(sc, mute) - struct i2s_softc *sc; - int mute; -{ - u_int x; - - if (lineout_mute == NULL) - return; - - DPRINTF(("lineout %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))); + DPRINTF(("%d\n", macobio_read(offset) & GPIO_DATA)); } int -i2s_cint(v) - void *v; +i2s_cint(void *v) { struct i2s_softc *sc = v; u_int sense; sc->sc_output_mask = 0; - i2s_mute_speaker(sc, 1); - i2s_mute_headphone(sc, 1); - i2s_mute_lineout(sc, 1); + i2s_mute(sc->sc_spkr, 1); + i2s_mute(sc->sc_hp, 1); + i2s_mute(sc->sc_line, 1); - if (headphone_detect) - sense = *headphone_detect; + if (sc->sc_hp_detect) + sense = macobio_read(sc->sc_hp_detect); else - sense = !headphone_detect_active << 1; + sense = !sc->sc_hp_active << 1; DPRINTF(("headphone detect = 0x%x\n", sense)); - if (((sense & 0x02) >> 1) == headphone_detect_active) { + if (((sense & 0x02) >> 1) == sc->sc_hp_active) { DPRINTF(("headphone is inserted\n")); - sc->sc_output_mask |= 1 << 1; + sc->sc_output_mask |= I2S_SELECT_HEADPHONE; if (!sc->sc_mute) - i2s_mute_headphone(sc, 0); + i2s_mute(sc->sc_hp, 0); } else { DPRINTF(("headphone is NOT inserted\n")); } - if (lineout_detect) - sense = *lineout_detect; + if (sc->sc_line_detect) + sense = macobio_read(sc->sc_line_detect); else - sense = !lineout_detect_active << 1; + sense = !sc->sc_line_active << 1; DPRINTF(("lineout detect = 0x%x\n", sense)); - if (((sense & 0x02) >> 1) == lineout_detect_active) { + if (((sense & 0x02) >> 1) == sc->sc_line_active) { DPRINTF(("lineout is inserted\n")); - sc->sc_output_mask |= 1 << 2; + sc->sc_output_mask |= I2S_SELECT_LINEOUT; if (!sc->sc_mute) - i2s_mute_lineout(sc, 0); + i2s_mute(sc->sc_line, 0); } else { DPRINTF(("lineout is NOT inserted\n")); } if (sc->sc_output_mask == 0) { - sc->sc_output_mask |= 1 << 0; + sc->sc_output_mask |= I2S_SELECT_SPEAKER; if (!sc->sc_mute) - i2s_mute_speaker(sc, 0); + i2s_mute(sc->sc_spkr, 0); } return 1; } -u_char * -i2s_gpio_map(struct i2s_softc *sc, char *name, int *irq) +u_int +i2s_gpio_offset(struct i2s_softc *sc, char *name, int *irq) { u_int32_t reg[2]; u_int32_t intr[2]; @@ -1149,102 +1058,89 @@ i2s_gpio_map(struct i2s_softc *sc, char *name, int *irq) sizeof(reg[0])) != sizeof(reg[0]) || OF_getprop(OF_parent(gpio), "reg", ®[1], sizeof(reg[1])) != sizeof(reg[1])) - return NULL; + return (0); if (irq && OF_getprop(gpio, "interrupts", intr, sizeof(intr)) == sizeof(intr)) { *irq = intr[0]; } - return mapiodev(sc->sc_baseaddr + reg[0] + reg[1], 1); + return (reg[0] + reg[1]); } void -i2s_gpio_init(sc, node, parent) - struct i2s_softc *sc; - int node; - struct device *parent; +i2s_gpio_init(struct i2s_softc *sc, int node, struct device *parent) { int gpio; - int headphone_detect_intr = -1, headphone_detect_intrtype; - int lineout_detect_intr = -1; - - /* Map gpios. */ - amp_mute = i2s_gpio_map(sc, "platform-amp-mute", NULL); - headphone_mute = i2s_gpio_map(sc, "platform-headphone-mute", NULL); - headphone_detect = i2s_gpio_map(sc, "platform-headphone-detect", - &headphone_detect_intr); - lineout_mute = i2s_gpio_map(sc, "platform-lineout-mute", NULL); - lineout_detect = i2s_gpio_map(sc, "platform-lineout-detect", - &lineout_detect_intr); - audio_hw_reset = i2s_gpio_map(sc, "platform-hw-reset", NULL); + int hp_detect_intr = -1, line_detect_intr = -1; + + sc->sc_spkr = i2s_gpio_offset(sc, "platform-amp-mute", NULL); + sc->sc_hp = i2s_gpio_offset(sc, "platform-headphone-mute", NULL); + sc->sc_hp_detect = i2s_gpio_offset(sc, "platform-headphone-detect", + &hp_detect_intr); + sc->sc_line = i2s_gpio_offset(sc, "platform-lineout-mute", NULL); + sc->sc_line_detect = i2s_gpio_offset(sc, "platform-lineout-detect", + &line_detect_intr); + sc->sc_hw_reset = i2s_gpio_offset(sc, "platform-hw-reset", NULL); gpio = OF_getnodebyname(OF_parent(node), "gpio"); DPRINTF((" /gpio 0x%x\n", gpio)); - gpio = OF_child(gpio); - while (gpio) { + for (gpio = OF_child(gpio); gpio; gpio = OF_peer(gpio)) { char name[64], audio_gpio[64]; int intr[2]; - paddr_t addr; + uint32_t reg; + reg = 0; bzero(name, sizeof name); bzero(audio_gpio, sizeof audio_gpio); - addr = 0; OF_getprop(gpio, "name", name, sizeof name); OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio); - OF_getprop(gpio, "AAPL,address", &addr, sizeof addr); - /* printf("0x%x %s %s\n", gpio, name, audio_gpio); */ + OF_getprop(gpio, "reg", ®, sizeof(reg)); /* gpio5 */ - if (headphone_mute == NULL && - strcmp(audio_gpio, "headphone-mute") == 0) - headphone_mute = mapiodev(addr,1); + if (sc->sc_hp == 0 && strcmp(audio_gpio, "headphone-mute") == 0) + sc->sc_hp = reg; /* gpio6 */ - if (amp_mute == NULL && - strcmp(audio_gpio, "amp-mute") == 0) - amp_mute = mapiodev(addr,1); + if (sc->sc_spkr == 0 && strcmp(audio_gpio, "amp-mute") == 0) + sc->sc_spkr = reg; /* extint-gpio15 */ - if (headphone_detect == NULL && + if (sc->sc_hp_detect == 0 && strcmp(audio_gpio, "headphone-detect") == 0) { - headphone_detect = mapiodev(addr,1); + sc->sc_hp_detect = reg; OF_getprop(gpio, "audio-gpio-active-state", - &headphone_detect_active, 4); + &sc->sc_hp_active, 4); OF_getprop(gpio, "interrupts", intr, 8); - headphone_detect_intr = intr[0]; - headphone_detect_intrtype = intr[1]; + hp_detect_intr = intr[0]; } /* gpio11 (keywest-11) */ - if (audio_hw_reset == NULL && + if (sc->sc_hw_reset == 0 && strcmp(audio_gpio, "audio-hw-reset") == 0) - audio_hw_reset = mapiodev(addr,1); - - gpio = OF_peer(gpio); + sc->sc_hw_reset = reg; } - DPRINTF((" amp-mute %p\n", amp_mute)); - DPRINTF((" headphone-mute %p\n", headphone_mute)); - DPRINTF((" headphone-detect %p\n", headphone_detect)); - DPRINTF((" headphone-detect active %x\n", headphone_detect_active)); - DPRINTF((" headphone-detect intr %x\n", headphone_detect_intr)); - DPRINTF((" lineout-mute %p\n", lineout_mute)); - DPRINTF((" lineout-detect %p\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 %p\n", audio_hw_reset)); - - if (headphone_detect_intr != -1) - mac_intr_establish(parent, headphone_detect_intr, IST_EDGE, + DPRINTF((" amp-mute 0x%x\n", sc->sc_spkr)); + DPRINTF((" headphone-mute 0x%x\n", sc->sc_hp)); + DPRINTF((" headphone-detect 0x%x\n", sc->sc_hp_detect)); + DPRINTF((" headphone-detect active %x\n", sc->sc_hp_active)); + DPRINTF((" headphone-detect intr %x\n", hp_detect_intr)); + DPRINTF((" lineout-mute 0x%x\n", sc->sc_line)); + DPRINTF((" lineout-detect 0x%x\n", sc->sc_line_detect)); + DPRINTF((" lineout-detect active 0x%x\n", sc->sc_line_active)); + DPRINTF((" lineout-detect intr 0x%x\n", line_detect_intr)); + DPRINTF((" audio-hw-reset 0x%x\n", sc->sc_hw_reset)); + + if (hp_detect_intr != -1) + mac_intr_establish(parent, hp_detect_intr, IST_EDGE, IPL_AUDIO, i2s_cint, sc, sc->sc_dev.dv_xname); - if (lineout_detect_intr != -1) - mac_intr_establish(parent, lineout_detect_intr, IST_EDGE, + if (line_detect_intr != -1) + mac_intr_establish(parent, line_detect_intr, IST_EDGE, IPL_AUDIO, i2s_cint, sc, sc->sc_dev.dv_xname); /* Enable headphone interrupt? */ - *headphone_detect |= 0x80; - asm volatile("eieio"); + macobio_write(sc->sc_hp_detect, 0x80); /* Update headphone status. */ i2s_cint(sc); @@ -1318,16 +1214,16 @@ i2s_allocm(void *h, int dir, size_t size, int type, int flags) int deq_reset(struct i2s_softc *sc) { - if (audio_hw_reset == NULL) + if (sc->sc_hw_reset == 0) return (-1); - gpio_write(audio_hw_reset, !reset_active); + macobio_write(sc->sc_hw_reset, !reset_active | GPIO_DDR_OUTPUT); delay(1000000); - gpio_write(audio_hw_reset, reset_active); + macobio_write(sc->sc_hw_reset, reset_active | GPIO_DDR_OUTPUT); delay(1); - gpio_write(audio_hw_reset, !reset_active); + macobio_write(sc->sc_hw_reset, !reset_active | GPIO_DDR_OUTPUT); delay(10000); return (0); diff --git a/sys/arch/macppc/dev/i2sreg.h b/sys/arch/macppc/dev/i2sreg.h index 4dd8237c343..0ad9a890d32 100644 --- a/sys/arch/macppc/dev/i2sreg.h +++ b/sys/arch/macppc/dev/i2sreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i2sreg.h,v 1.2 2007/04/21 15:48:22 gwk Exp $ */ +/* $OpenBSD: i2sreg.h,v 1.3 2011/06/07 16:29:51 mpi Exp $ */ /*- * Copyright (c) 2002 Tsubai Masanari. All rights reserved. * @@ -36,6 +36,10 @@ #define I2SClockOffset 0x3c #define I2S_INT_CLKSTOPPEND 0x01000000 +#define I2S_SELECT_SPEAKER 1 << 0 +#define I2S_SELECT_HEADPHONE 1 << 1 +#define I2S_SELECT_LINEOUT 1 << 2 + /* FCR(0x3c) bits */ #define I2S0CLKEN 0x1000 #define I2S0EN 0x2000 diff --git a/sys/arch/macppc/dev/i2svar.h b/sys/arch/macppc/dev/i2svar.h index ff4dc25b909..8c4701fdb87 100644 --- a/sys/arch/macppc/dev/i2svar.h +++ b/sys/arch/macppc/dev/i2svar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i2svar.h,v 1.7 2011/05/05 18:54:23 jasper Exp $ */ +/* $OpenBSD: i2svar.h,v 1.8 2011/06/07 16:29:51 mpi Exp $ */ /*- * Copyright (c) 2001,2003 Tsubai Masanari. All rights reserved. @@ -72,6 +72,16 @@ struct i2s_softc { u_int sc_treble; u_int sc_mute; + u_int sc_spkr; /* amp mute gpio offset */ + u_int sc_hp; /* headphone mute gpio offset */ + u_int sc_hp_detect; /* headphone detect gpio */ + u_int sc_hp_active; + u_int sc_line; /* line out mute gpio offset */ + u_int sc_line_detect; /* line detect gpio */ + u_int sc_line_active; + u_int sc_hw_reset; /* hw reset gpio */ + + bus_dma_tag_t sc_dmat; dbdma_regmap_t *sc_odma; dbdma_regmap_t *sc_idma; |