The diff below makes use of the macobio_* methods to manage the i2s
GPIOs. In order to achieve this goal, instead of reading the gpio
address from the openfirmware, it now retrieves the offsets from the
base bus address. The result is that we don't need to re-map the GPIOs.
It also removes the customs gpio_* methods and move all the remaining
global variables in the i2s softc.
The next work will be to have a working line in/out. Please test this
diff an report any regression. So far I haven't seen any problem on my
machines.
Martin
Index: dev/i2s.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/i2s.c,v
retrieving revision 1.21
diff -u -p -r1.21 i2s.c
--- dev/i2s.c 15 May 2011 09:10:26 -0000 1.21
+++ dev/i2s.c 23 May 2011 15:22:44 -0000
@@ -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
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
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;
-{
- u_int x;
-
- if (amp_mute == NULL)
- return;
-
- DPRINTF(("ampmute %d --> ", gpio_read(amp_mute)));
-
- if (mute)
- x = amp_active; /* mute */
- else
- x = !amp_active; /* unmute */
- if (x != gpio_read(amp_mute))
- gpio_write(amp_mute, x);
-
- DPRINTF(("%d\n", gpio_read(amp_mute)));
-}
-
void
-i2s_mute_headphone(sc, mute)
- struct i2s_softc *sc;
- int mute;
+i2s_mute(u_int offset, int mute)
{
- u_int x;
-
- if (headphone_mute == NULL)
+ if (offset == 0)
return;
- DPRINTF(("headphonemute %d --> ", gpio_read(headphone_mute)));
+ DPRINTF(("gpio: %x, %d -> ", offset, macobio_read(offset) & GPIO_DATA));
- if (mute)
- x = headphone_active; /* mute */
- else
- x = !headphone_active; /* unmute */
- if (x != gpio_read(headphone_mute))
- gpio_write(headphone_mute, x);
+ /* 0 means mute */
+ if (mute == (macobio_read(offset) & GPIO_DATA))
+ macobio_write(offset, !mute | GPIO_DDR_OUTPUT);
- 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
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;
+ int hp_detect_intr = -1, line_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);
+ 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));
+ 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 (headphone_detect_intr != -1)
- mac_intr_establish(parent, headphone_detect_intr, IST_EDGE,
+ 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
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);
Index: dev/i2sreg.h
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/i2sreg.h,v
retrieving revision 1.2
diff -u -p -r1.2 i2sreg.h
--- dev/i2sreg.h 21 Apr 2007 15:48:22 -0000 1.2
+++ dev/i2sreg.h 23 May 2011 15:22:44 -0000
@@ -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
Index: dev/i2svar.h
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/i2svar.h,v
retrieving revision 1.7
diff -u -p -r1.7 i2svar.h
--- dev/i2svar.h 5 May 2011 18:54:23 -0000 1.7
+++ dev/i2svar.h 23 May 2011 15:22:44 -0000
@@ -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;