Index: sys/arm/allwinner/a10_codec.c =================================================================== --- sys/arm/allwinner/a10_codec.c +++ sys/arm/allwinner/a10_codec.c @@ -67,6 +67,12 @@ /* toggle DAC/ADC mute */ void (*mute)(struct a10codec_info *, int, int); + /* handle extra resource */ + int (*setup_analog)(struct a10codec_info *, phandle_t); + + /* extra resource for analog register */ + struct resource* res; + /* DRQ types */ u_int drqtype_codec; u_int drqtype_sdram; @@ -164,7 +170,7 @@ struct a10codec_info { device_t dev; - struct resource *res[3]; + struct resource *res[2]; struct mtx *lock; bus_dma_tag_t dmat; unsigned dmasize; @@ -178,11 +184,13 @@ static struct resource_spec a10codec_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_OPTIONAL }, { SYS_RES_IRQ, 0, RF_ACTIVE }, { -1, 0 } }; +#define CODEC_ANALOG_READ(sc, reg) bus_read_4((sc)->cfg->res, (reg)) +#define CODEC_ANALOG_WRITE(sc, reg, val) bus_write_4((sc)->cfg->res, (reg), (val)) + #define CODEC_READ(sc, reg) bus_read_4((sc)->res[0], (reg)) #define CODEC_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val)) @@ -222,6 +230,9 @@ #define A10_PA_EN (1U << 4) #define A10_DDE (1U << 3) +static void +a10codec_stop(struct a10codec_chinfo *ch); + static int a10_mixer_init(struct snd_mixer *m) { @@ -372,7 +383,7 @@ */ #define H3_PR_CFG 0x00 -#define H3_AC_PR_RST (1 << 18) +#define H3_AC_PR_RST (1 << 28) #define H3_AC_PR_RW (1 << 24) #define H3_AC_PR_ADDR_SHIFT 16 #define H3_AC_PR_ADDR_MASK (0x1f << H3_AC_PR_ADDR_SHIFT) @@ -424,23 +435,23 @@ uint32_t val; /* Read current value */ - val = bus_read_4(sc->res[1], H3_PR_CFG); + val = CODEC_ANALOG_READ(sc, H3_PR_CFG); /* De-assert reset */ val |= H3_AC_PR_RST; - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Read mode */ val &= ~H3_AC_PR_RW; - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Set address */ val &= ~H3_AC_PR_ADDR_MASK; val |= (addr << H3_AC_PR_ADDR_SHIFT); - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Read data */ - return (bus_read_4(sc->res[1], H3_PR_CFG) & H3_ACDA_PR_RDAT_MASK); + return (CODEC_ANALOG_READ(sc , H3_PR_CFG) & H3_ACDA_PR_RDAT_MASK); } static void @@ -449,25 +460,25 @@ uint32_t val; /* Read current value */ - val = bus_read_4(sc->res[1], H3_PR_CFG); + val = CODEC_ANALOG_READ(sc, H3_PR_CFG); /* De-assert reset */ val |= H3_AC_PR_RST; - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Set address */ val &= ~H3_AC_PR_ADDR_MASK; val |= (addr << H3_AC_PR_ADDR_SHIFT); - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Write data */ val &= ~H3_ACDA_PR_WDAT_MASK; val |= (data << H3_ACDA_PR_WDAT_SHIFT); - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); /* Write mode */ val |= H3_AC_PR_RW; - bus_write_4(sc->res[1], H3_PR_CFG, val); + CODEC_ANALOG_WRITE(sc, H3_PR_CFG, val); } static void @@ -591,6 +602,31 @@ } } +static int +h3_setup_analog(struct a10codec_info *sc, phandle_t node) +{ + int rid=1; + pcell_t reg[2]; + phandle_t analogref; + + if (OF_getencprop(node, "allwinner,codec-analog-controls", &analogref, sizeof(analogref)) <= 0) { + return (ENXIO); + } + + if (OF_getencprop(OF_node_from_xref(analogref), "reg", reg, sizeof(reg)) <= 0) { + return (ENXIO); + } + + sc->cfg->res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &rid, reg[0], + ~0ul, reg[1], RF_ACTIVE ); + + if (sc->cfg->res == NULL) { + return (ENXIO); + } + + return (0); +} + static kobj_method_t h3_mixer_methods[] = { KOBJMETHOD(mixer_init, h3_mixer_init), KOBJMETHOD(mixer_set, h3_mixer_set), @@ -712,6 +748,8 @@ ch->pos = 0; + a10codec_stop(ch); + if (ch->dir == PCMDIR_PLAY) { /* Flush DAC FIFO */ CODEC_WRITE(sc, AC_DAC_FIFOC(sc), DAC_FIFOC_FIFO_FLUSH); @@ -996,6 +1034,8 @@ static const struct a10codec_config a10_config = { .mixer_class = &a10_mixer_class, .mute = a10_mute, + .setup_analog = NULL, + .res = NULL, .drqtype_codec = 19, .drqtype_sdram = 22, .DPC = 0x00, @@ -1012,6 +1052,8 @@ static const struct a10codec_config h3_config = { .mixer_class = &h3_mixer_class, .mute = h3_mute, + .setup_analog = h3_setup_analog, + .res = NULL, .drqtype_codec = 15, .drqtype_sdram = 1, .DPC = 0x00, @@ -1070,6 +1112,13 @@ goto fail; } + if (sc->cfg->setup_analog != NULL) { + if (sc->cfg->setup_analog(sc, node) != 0) { + error = ENXIO; + goto fail; + } + } + sc->dmasize = 131072; error = bus_dma_tag_create( bus_get_dma_tag(dev), @@ -1124,8 +1173,7 @@ } /* De-assert hwreset */ - if (hwreset_get_by_ofw_name(dev, 0, "apb", &rst) == 0 || - hwreset_get_by_ofw_name(dev, 0, "ahb", &rst) == 0) { + if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) { error = hwreset_deassert(rst); if (error != 0) { device_printf(dev, "cannot de-assert reset\n");