64#include <sys/kernel.h>
65#include <sys/module.h>
67#include <sys/malloc.h>
70#include <machine/dbdma.h>
71#include <machine/intr_machdep.h>
72#include <machine/resource.h>
73#include <machine/bus.h>
74#include <machine/pio.h>
76#include <dev/ofw/ofw_bus.h>
78#ifdef HAVE_KERNEL_OPTION_HEADERS
85#include <powerpc/powermac/macgpiovar.h>
161 char subchildname[255];
163 name = ofw_bus_get_name(self);
167 if (strcmp(
name,
"i2s") != 0)
175 subchild = OF_child(OF_child(ofw_bus_get_node(self)));
176 if (subchild != 0 && OF_getprop(subchild,
"name", subchildname,
177 sizeof(subchildname)) > 0 && strcmp(subchildname,
"lightshow") == 0)
180 device_set_desc(self,
"Apple I2S Audio Controller");
191 struct resource *dbdma_irq;
196 sc = malloc(
sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
199 sc->
node = ofw_bus_get_node(self);
208 mtx_init(&sc->
port_mtx,
"port_mtx", NULL, MTX_DEF);
212 sc->
reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &
rid, RF_ACTIVE);
218 sc->
aoa.
sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, &
rid,
225 dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ,
226 &
rid, RF_SHAREABLE | RF_ACTIVE);
227 if (dbdma_irq == NULL)
238 oirq = rman_get_start(dbdma_irq);
239 err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
248 M_TEMP, M_WAITOK | M_ZERO)) == NULL)
274#define GPIO_CTRL_EXTINT_SET \
275 ((1 << HEADPHONE_DETECT) | \
276 (1 << LINEOUT_DETECT))
279 {NULL, NULL, NULL, NULL, NULL, NULL};
301 device_t self = cookie;
304 sc = device_get_softc(self);
306 if (macgpio_read(self) & GPIO_LEVEL_RO)
324 node = ofw_bus_get_node(
gpio);
325 if (node == 0 || node == -1)
328 bzero(bname,
sizeof(bname));
329 if (OF_getprop(node,
"audio-gpio", bname,
sizeof(bname)) > 2)
336 if (strcmp(
name,
m->name) == 0) {
337 sc = device_get_softc(
gpio);
345 OF_getprop(node,
"audio-gpio-active-state",
351 device_set_desc(
gpio,
m->name);
368 sc = device_get_softc(
gpio);
371 r = bus_alloc_resource_any(
gpio, SYS_RES_IRQ, &
rid, RF_ACTIVE);
375 irq = rman_get_start(
r);
378 if (powerpc_config_intr(
irq, INTR_TRIGGER_EDGE,
379 INTR_POLARITY_LOW) != 0)
382 bus_setup_intr(
gpio,
r, INTR_TYPE_MISC | INTR_MPSAFE |
393#define I2S_FORMAT 0x10
394#define I2S_FRAMECOUNT 0x40
395#define I2S_FRAMEMATCH 0x50
396#define I2S_WORDSIZE 0x60
399#define I2S_INT_CLKSTOPPEND 0x01000000
402#define CLKSRC_49MHz 0x80000000
403#define CLKSRC_45MHz 0x40000000
404#define CLKSRC_18MHz 0x00000000
405#define MCLK_DIV_MASK 0x1f000000
406#define SCLK_DIV_MASK 0x00f00000
407#define SCLK_MASTER 0x00080000
408#define SCLK_SLAVE 0x00000000
409#define SERIAL_FORMAT 0x00070000
410#define SERIAL_SONY 0x00000000
411#define SERIAL_64x 0x00010000
412#define SERIAL_32x 0x00020000
413#define SERIAL_DAV 0x00040000
414#define SERIAL_SILICON 0x00050000
417#define INPUT_STEREO (2 << 24)
418#define INPUT_MONO (1 << 24)
419#define INPUT_16BIT (0 << 16)
420#define INPUT_24BIT (3 << 16)
421#define OUTPUT_STEREO (2 << 8)
422#define OUTPUT_MONO (1 << 8)
423#define OUTPUT_16BIT (0 << 0)
424#define OUTPUT_24BIT (3 << 0)
450 u_int mclk, mdiv, sdiv;
451 u_int
reg = 0, x, wordformat;
455 if ((wordsize * 2) > sclk_fs)
458 if (sclk_fs != 32 && sclk_fs != 64)
469 for (i = 0; i <
NCLKS; ++i) {
470 if ((
clksrc[i].cs_clock % mclk) == 0) {
549 printf(
"i2s_setup: changing format not supported yet.\n");
553 if (obio_fcr_isset(OBIO_FCR1, I2S0CLKEN)) {
555 bus_space_write_4(sc->sc_tag, sc->sc_bsh,
I2S_INT,
558 obio_fcr_clear(OBIO_FCR1, I2S0CLKEN);
560 for (timo = 1000; timo > 0; timo--) {
561 if (bus_space_read_4(sc->sc_tag, sc->sc_bsh,
569 printf(
"%s: timeout waiting for clock to stop\n",
570 sc->sc_dev.dv_xname);
575 obio_fcr_set(OBIO_FCR1, I2S0CLKEN);
589 for (
n = OF_child(node);
n != -1;
n = OF_peer(
n)) {
591 OF_getprop(
n,
"name",
name,
sizeof(
name));
593 if (strcmp(
name, req_name) == 0)
620 reg = GPIO_DDR_OUTPUT;
624 macgpio_write(sc->
dev,
reg);
646#define reset_active 0
649#define RESET_SETUP_TIME 5000
650#define RESET_HOLD_TIME 20000
651#define RESET_RELEASE_TIME 10000
657 DPRINTF((
"resetting codec\n"));
669 DPRINTF((
"no audio_hw_reset\n"));
674#define HEADPHONE_ACTIVE 0
675#define LINEOUT_ACTIVE 0
677#define MUTE_CONTROL(xxx, yyy) \
679i2s_mute_##xxx(struct i2s_softc *sc, int mute) \
683 if (gpio_ctrls[yyy##_MUTE] == NULL) \
688 x = ! yyy##_ACTIVE; \
690 if (x != gpio_read(yyy##_MUTE)) \
691 gpio_write(yyy##_MUTE, x); \
712 DPRINTF((
"enabled outputs: "));
714 if (
mask & (1 << 0)) {
718 if (
mask & (1 << 1)) {
722 if (
mask & (1 << 2)) {
void aoa_interrupt(void *xsc)
int aoa_attach(void *xsc)
struct pcmchan_matrix * m
static driver_t aoagpio_driver
static devclass_t aoagpio_devclass
static phandle_t of_find_firstchild_byname(phandle_t, const char *)
static const struct i2s_clksrc clksrc[NCLKS]
static driver_t pcm_i2s_driver
static u_int gpio_read(enum gpio_ctrl ctrl)
#define I2S_INT_CLKSTOPPEND
static int aoagpio_attach(device_t)
static int i2s_probe(device_t)
static device_method_t pcm_i2s_methods[]
#define MUTE_CONTROL(xxx, yyy)
static int i2s_attach(device_t)
static struct gpio_match gpio_controls[]
static void i2s_postattach(void *)
MODULE_DEPEND(pcm_i2s, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
static void i2s_audio_hw_reset(struct i2s_softc *sc)
static device_method_t aoagpio_methods[]
static void i2s_mute_headphone(struct i2s_softc *, int)
static void i2s_set_outputs(void *, u_int)
#define RESET_RELEASE_TIME
static void gpio_write(enum gpio_ctrl ctrl, u_int x)
static struct aoagpio_softc * gpio_ctrls[GPIO_CTRL_NUM]
static void i2s_mute_speaker(struct i2s_softc *, int)
static struct intr_config_hook * i2s_delayed_attach
kobj_class_t i2s_mixer_class
#define GPIO_CTRL_EXTINT_SET
static void aoagpio_int(void *cookie)
static int aoagpio_probe(device_t)
static void i2s_cint(struct i2s_softc *)
DRIVER_MODULE(pcm_i2s, macio, pcm_i2s_driver, pcm_devclass, 0, 0)
static int i2s_setup(struct i2s_softc *, u_int, u_int, u_int)
static void i2s_mute_lineout(struct i2s_softc *, int)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
struct resource * sc_odma