Lines Matching +full:pcm +full:- +full:clock +full:- +full:mode

1 /*-
2 * Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
42 #include <dev/sound/pcm/sound.h>
84 #define AC_DAC_DPC(_sc) ((_sc)->cfg->DPC)
86 #define AC_DAC_FIFOC(_sc) ((_sc)->cfg->DAC_FIFOC)
110 #define AC_DAC_FIFOS(_sc) ((_sc)->cfg->DAC_FIFOS)
111 #define AC_DAC_TXDATA(_sc) ((_sc)->cfg->DAC_TXDATA)
112 #define AC_ADC_FIFOC(_sc) ((_sc)->cfg->ADC_FIFOC)
124 #define AC_ADC_FIFOS(_sc) ((_sc)->cfg->ADC_FIFOS)
125 #define AC_ADC_RXDATA(_sc) ((_sc)->cfg->ADC_RXDATA)
126 #define AC_DAC_CNT(_sc) ((_sc)->cfg->DAC_CNT)
127 #define AC_ADC_CNT(_sc) ((_sc)->cfg->ADC_CNT)
175 { -1, 0 }
178 #define CODEC_ANALOG_READ(sc, reg) bus_read_4((sc)->res[1], (reg))
179 #define CODEC_ANALOG_WRITE(sc, reg, val) bus_write_4((sc)->res[1], (reg), (val))
181 #define CODEC_READ(sc, reg) bus_read_4((sc)->res[0], (reg))
182 #define CODEC_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
284 case SOUND_MASK_LINE: /* line-in */
423 /* De-assert reset */
427 /* Read mode */
448 /* De-assert reset */
462 /* Write mode */
485 if (OF_getencprop(ofw_bus_get_node(sc->dev), "allwinner,codec-analog-controls",
495 sc->res[1] = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &rid, reg[0],
498 if (sc->res[1] == NULL) {
507 pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL);
561 if ((src & SOUND_MASK_LINE) != 0) /* line-in */
628 ch->physaddr = segs[0].ds_addr;
637 if (ch->dir == PCMDIR_PLAY) {
638 src = ch->physaddr + ch->pos;
639 dst = ch->fifo;
641 src = ch->fifo;
642 dst = ch->physaddr + ch->pos;
645 error = SUNXI_DMA_TRANSFER(ch->dmac, ch->dmachan, src, dst,
646 ch->blocksize);
648 ch->run = 0;
649 device_printf(ch->parent->dev, "DMA transfer failed: %d\n",
657 struct a10codec_info *sc = ch->parent;
664 if (ch->dir == PCMDIR_PLAY) {
666 conf.src_drqtype = sc->cfg->drqtype_sdram;
667 conf.dst_drqtype = sc->cfg->drqtype_codec;
670 conf.src_drqtype = sc->cfg->drqtype_codec;
671 conf.dst_drqtype = sc->cfg->drqtype_sdram;
674 SUNXI_DMA_SET_CONFIG(ch->dmac, ch->dmachan, &conf);
683 bufsize = sndbuf_getsize(ch->buffer);
685 ch->pos += ch->blocksize;
686 if (ch->pos >= bufsize)
687 ch->pos -= bufsize;
689 if (ch->run) {
690 chn_intr(ch->channel);
698 switch (ch->speed) {
723 struct a10codec_info *sc = ch->parent;
726 ch->pos = 0;
728 if (ch->dir == PCMDIR_PLAY) {
737 sc->cfg->mute(sc, 0, ch->dir);
744 (AFMT_CHANNEL(ch->format) == 1 ? DAC_FIFOC_MONO_EN : 0) |
763 sc->cfg->mute(sc, 0, ch->dir);
772 (AFMT_CHANNEL(ch->format) == 1 ? ADC_FIFOC_MONO_EN : 0) |
789 struct a10codec_info *sc = ch->parent;
792 SUNXI_DMA_HALT(ch->dmac, ch->dmachan);
794 sc->cfg->mute(sc, 1, ch->dir);
796 if (ch->dir == PCMDIR_PLAY) {
810 struct a10codec_chinfo *ch = dir == PCMDIR_PLAY ? &sc->play : &sc->rec;
815 error = ofw_bus_parse_xref_list_alloc(ofw_bus_get_node(sc->dev),
816 "dmas", "#dma-cells", dir == PCMDIR_PLAY ? 1 : 0,
819 device_printf(sc->dev, "cannot parse 'dmas' property\n");
824 ch->parent = sc;
825 ch->channel = c;
826 ch->buffer = b;
827 ch->dir = dir;
828 ch->fifo = rman_get_start(sc->res[0]) +
831 ch->dmac = OF_device_from_xref(xref);
832 if (ch->dmac == NULL) {
833 device_printf(sc->dev, "cannot find DMA controller\n");
834 device_printf(sc->dev, "xref = 0x%x\n", (u_int)xref);
837 ch->dmachan = SUNXI_DMA_ALLOC(ch->dmac, false, a10codec_dmaintr, ch);
838 if (ch->dmachan == NULL) {
839 device_printf(sc->dev, "cannot allocate DMA channel\n");
843 error = bus_dmamem_alloc(sc->dmat, &ch->dmaaddr,
844 BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &ch->dmamap);
846 device_printf(sc->dev, "cannot allocate channel buffer\n");
849 error = bus_dmamap_load(sc->dmat, ch->dmamap, ch->dmaaddr,
850 sc->dmasize, a10codec_dmamap_cb, ch, BUS_DMA_NOWAIT);
852 device_printf(sc->dev, "cannot load DMA map\n");
855 memset(ch->dmaaddr, 0, sc->dmasize);
857 if (sndbuf_setup(ch->buffer, ch->dmaaddr, sc->dmasize) != 0) {
858 device_printf(sc->dev, "cannot setup sndbuf\n");
869 struct a10codec_info *sc = ch->parent;
871 SUNXI_DMA_FREE(ch->dmac, ch->dmachan);
872 bus_dmamap_unload(sc->dmat, ch->dmamap);
873 bus_dmamem_free(sc->dmat, ch->dmaaddr, ch->dmamap);
883 ch->format = format;
895 * use the same source clock (PLL2). Limit the available speeds to
905 ch->speed = speed;
909 /* 96 KHz / 192 KHz mode only supported for playback */
910 if (ch->dir == PCMDIR_PLAY) {
911 ch->speed = speed;
913 ch->speed = 48000;
917 ch->speed = 48000;
920 ch->speed = 24000;
923 ch->speed = 12000;
926 ch->speed = 48000;
930 return (ch->speed);
938 ch->blocksize = blocksize & ~3;
940 return (ch->blocksize);
947 struct a10codec_info *sc = ch->parent;
952 snd_mtxlock(sc->lock);
955 ch->run = 1;
961 ch->run = 0;
967 snd_mtxunlock(sc->lock);
977 return (ch->pos);
985 if (ch->dir == PCMDIR_PLAY) {
1042 { "allwinner,sun4i-a10-codec", (uintptr_t)&a10_config },
1043 { "allwinner,sun7i-a20-codec", (uintptr_t)&a10_config },
1044 { "allwinner,sun8i-h3-codec", (uintptr_t)&h3_config },
1054 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
1076 sc->cfg = (void *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
1077 sc->dev = dev;
1078 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "a10codec softc");
1080 if (bus_alloc_resources(dev, a10codec_spec, sc->res)) {
1086 sc->dmasize = 131072;
1089 4, sc->dmasize, /* alignment, boundary */
1093 sc->dmasize, 1, /* maxsize, nsegs */
1094 sc->dmasize, 0, /* maxsegsize, flags */
1096 &sc->dmat);
1105 device_printf(dev, "cannot find bus clock\n");
1109 device_printf(dev, "cannot find codec clock\n");
1113 /* Gating bus clock for codec */
1115 device_printf(dev, "cannot enable bus clock\n");
1118 /* Activate audio codec clock. According to the A10 and A20 user
1120 * audio sampling rates require an 24.576MHz input clock with the
1122 * both capture and playback use the same clock source so to
1124 * 24.576MHz clock source and don't advertise native support for
1129 device_printf(dev, "cannot set codec clock frequency\n");
1132 /* Enable audio codec clock */
1135 device_printf(dev, "cannot enable codec clock\n");
1139 /* De-assert hwreset */
1143 device_printf(dev, "cannot de-assert reset\n");
1153 if (mixer_init(dev, sc->cfg->mixer_class, sc)) {
1159 if (gpio_pin_get_by_ofw_property(dev, node, "allwinner,pa-gpios",
1182 bus_release_resources(dev, a10codec_spec, sc->res);
1183 snd_mtxfree(sc->lock);
1198 "pcm",