Home | History | Annotate | Line # | Download | only in imx
imx23_digfilt.c revision 1.1.2.2
      1  1.1.2.2  skrll /* $Id: imx23_digfilt.c,v 1.1.2.2 2015/04/06 15:17:52 skrll Exp $ */
      2  1.1.2.2  skrll 
      3  1.1.2.2  skrll /*
      4  1.1.2.2  skrll  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      5  1.1.2.2  skrll  * All rights reserved.
      6  1.1.2.2  skrll  *
      7  1.1.2.2  skrll  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1.2.2  skrll  * by Petri Laakso.
      9  1.1.2.2  skrll  *
     10  1.1.2.2  skrll  * Redistribution and use in source and binary forms, with or without
     11  1.1.2.2  skrll  * modification, are permitted provided that the following conditions
     12  1.1.2.2  skrll  * are met:
     13  1.1.2.2  skrll  * 1. Redistributions of source code must retain the above copyright
     14  1.1.2.2  skrll  *    notice, this list of conditions and the following disclaimer.
     15  1.1.2.2  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1.2.2  skrll  *    notice, this list of conditions and the following disclaimer in the
     17  1.1.2.2  skrll  *    documentation and/or other materials provided with the distribution.
     18  1.1.2.2  skrll  *
     19  1.1.2.2  skrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1.2.2  skrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1.2.2  skrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1.2.2  skrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1.2.2  skrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1.2.2  skrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1.2.2  skrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1.2.2  skrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1.2.2  skrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1.2.2  skrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1.2.2  skrll  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1.2.2  skrll  */
     31  1.1.2.2  skrll 
     32  1.1.2.2  skrll #include <sys/param.h>
     33  1.1.2.2  skrll #include <sys/cdefs.h>
     34  1.1.2.2  skrll #include <sys/types.h>
     35  1.1.2.2  skrll #include <sys/device.h>
     36  1.1.2.2  skrll #include <sys/errno.h>
     37  1.1.2.2  skrll #include <sys/systm.h>
     38  1.1.2.2  skrll #include <sys/bus.h>
     39  1.1.2.2  skrll #include <sys/mutex.h>
     40  1.1.2.2  skrll #include <sys/audioio.h>
     41  1.1.2.2  skrll #include <dev/audio_if.h>
     42  1.1.2.2  skrll #include <dev/auconv.h>
     43  1.1.2.2  skrll #include <sys/mallocvar.h>
     44  1.1.2.2  skrll #include <arm/imx/imx23_digfiltreg.h>
     45  1.1.2.2  skrll #include <arm/imx/imx23_rtcvar.h>
     46  1.1.2.2  skrll #include <arm/imx/imx23_clkctrlvar.h>
     47  1.1.2.2  skrll #include <arm/imx/imx23_apbdmavar.h>
     48  1.1.2.2  skrll #include <arm/imx/imx23_icollreg.h>
     49  1.1.2.2  skrll #include <arm/imx/imx23var.h>
     50  1.1.2.2  skrll 
     51  1.1.2.2  skrll #include <arm/pic/picvar.h>
     52  1.1.2.2  skrll 
     53  1.1.2.2  skrll /* Autoconf. */
     54  1.1.2.2  skrll static int digfilt_match(device_t, cfdata_t, void *);
     55  1.1.2.2  skrll static void digfilt_attach(device_t, device_t, void *);
     56  1.1.2.2  skrll static int digfilt_activate(device_t, enum devact);
     57  1.1.2.2  skrll 
     58  1.1.2.2  skrll /* Audio driver interface. */
     59  1.1.2.2  skrll static int digfilt_drain(void *);
     60  1.1.2.2  skrll static int digfilt_query_encoding(void *, struct audio_encoding *);
     61  1.1.2.2  skrll static int digfilt_set_params(void *, int, int, audio_params_t *,
     62  1.1.2.2  skrll     audio_params_t *, stream_filter_list_t *,
     63  1.1.2.2  skrll     stream_filter_list_t *);
     64  1.1.2.2  skrll static int digfilt_round_blocksize(void *, int, int, const audio_params_t *);
     65  1.1.2.2  skrll static int digfilt_init_output(void *, void *, int );
     66  1.1.2.2  skrll static int digfilt_start_output(void *, void *, int, void (*)(void *), void *);
     67  1.1.2.2  skrll static int digfilt_halt_output(void *);
     68  1.1.2.2  skrll static int digfilt_getdev(void *, struct audio_device *);
     69  1.1.2.2  skrll static int digfilt_set_port(void *, mixer_ctrl_t *);
     70  1.1.2.2  skrll static int digfilt_get_port(void *, mixer_ctrl_t *);
     71  1.1.2.2  skrll static int digfilt_query_devinfo(void *, mixer_devinfo_t *);
     72  1.1.2.2  skrll static void *digfilt_allocm(void *, int, size_t);
     73  1.1.2.2  skrll static void digfilt_freem(void *, void *, size_t);
     74  1.1.2.2  skrll static size_t digfilt_round_buffersize(void *, int, size_t);
     75  1.1.2.2  skrll static int digfilt_get_props(void *);
     76  1.1.2.2  skrll static void digfilt_get_locks(void *, kmutex_t **, kmutex_t **);
     77  1.1.2.2  skrll 
     78  1.1.2.2  skrll /* IRQs */
     79  1.1.2.2  skrll static int dac_error_intr(void *);
     80  1.1.2.2  skrll static int dac_dma_intr(void *);
     81  1.1.2.2  skrll 
     82  1.1.2.2  skrll struct digfilt_softc;
     83  1.1.2.2  skrll 
     84  1.1.2.2  skrll /* Audio out. */
     85  1.1.2.2  skrll static void *digfilt_ao_alloc_dmachain(void *, size_t);
     86  1.1.2.2  skrll static void digfilt_ao_apply_mutes(struct digfilt_softc *);
     87  1.1.2.2  skrll static void digfilt_ao_init(struct digfilt_softc *);
     88  1.1.2.2  skrll static void digfilt_ao_reset(struct digfilt_softc *);
     89  1.1.2.2  skrll static void digfilt_ao_set_rate(struct digfilt_softc *, int);
     90  1.1.2.2  skrll 
     91  1.1.2.2  skrll /* Audio in. */
     92  1.1.2.2  skrll #if 0
     93  1.1.2.2  skrll static void digfilt_ai_reset(struct digfilt_softc *);
     94  1.1.2.2  skrll #endif
     95  1.1.2.2  skrll 
     96  1.1.2.2  skrll #define DIGFILT_DMA_NSEGS 1
     97  1.1.2.2  skrll #define DIGFILT_BLOCKSIZE_MAX 4096
     98  1.1.2.2  skrll #define DIGFILT_BLOCKSIZE_ROUND 512
     99  1.1.2.2  skrll #define DIGFILT_DMA_CHAIN_LENGTH 3
    100  1.1.2.2  skrll #define DIGFILT_DMA_CHANNEL 1
    101  1.1.2.2  skrll #define DIGFILT_MUTE_DAC 1
    102  1.1.2.2  skrll #define DIGFILT_MUTE_HP 2
    103  1.1.2.2  skrll #define DIGFILT_MUTE_LINE 4
    104  1.1.2.2  skrll #define DIGFILT_SOFT_RST_LOOP 455	/* At least 1 us. */
    105  1.1.2.2  skrll 
    106  1.1.2.2  skrll #define AO_RD(sc, reg)							\
    107  1.1.2.2  skrll 	bus_space_read_4(sc->sc_iot, sc->sc_aohdl, (reg))
    108  1.1.2.2  skrll #define AO_WR(sc, reg, val)						\
    109  1.1.2.2  skrll 	bus_space_write_4(sc->sc_iot, sc->sc_aohdl, (reg), (val))
    110  1.1.2.2  skrll #define AI_RD(sc, reg)							\
    111  1.1.2.2  skrll 	bus_space_read_4(sc->sc_iot, sc->sc_aihdl, (reg))
    112  1.1.2.2  skrll #define AI_WR(sc, reg, val)						\
    113  1.1.2.2  skrll 	bus_space_write_4(sc->sc_iot, sc->sc_aihdl, (reg), (val))
    114  1.1.2.2  skrll 
    115  1.1.2.2  skrll struct digfilt_softc {
    116  1.1.2.2  skrll 	device_t sc_dev;
    117  1.1.2.2  skrll 	device_t sc_audiodev;
    118  1.1.2.2  skrll 	struct audio_format sc_format;
    119  1.1.2.2  skrll 	struct audio_encoding_set *sc_encodings;
    120  1.1.2.2  skrll 	bus_space_handle_t sc_aihdl;
    121  1.1.2.2  skrll 	bus_space_handle_t sc_aohdl;
    122  1.1.2.2  skrll 	apbdma_softc_t sc_dmac;
    123  1.1.2.2  skrll 	bus_dma_tag_t sc_dmat;
    124  1.1.2.2  skrll 	bus_dmamap_t sc_dmamp;
    125  1.1.2.2  skrll 	bus_dmamap_t sc_c_dmamp;
    126  1.1.2.2  skrll 	bus_dma_segment_t sc_ds[DIGFILT_DMA_NSEGS];
    127  1.1.2.2  skrll 	bus_dma_segment_t sc_c_ds[DIGFILT_DMA_NSEGS];
    128  1.1.2.2  skrll 	bus_space_handle_t sc_hdl;
    129  1.1.2.2  skrll 	kmutex_t sc_intr_lock;
    130  1.1.2.2  skrll 	bus_space_tag_t	sc_iot;
    131  1.1.2.2  skrll 	kmutex_t sc_lock;
    132  1.1.2.2  skrll 	audio_params_t sc_pparam;
    133  1.1.2.2  skrll 	void *sc_buffer;
    134  1.1.2.2  skrll 	void *sc_dmachain;
    135  1.1.2.2  skrll 	void *sc_intarg;
    136  1.1.2.2  skrll 	void (*sc_intr)(void*);
    137  1.1.2.2  skrll 	uint8_t sc_mute;
    138  1.1.2.2  skrll 	uint8_t sc_cmd_index;
    139  1.1.2.2  skrll };
    140  1.1.2.2  skrll 
    141  1.1.2.2  skrll CFATTACH_DECL3_NEW(digfilt,
    142  1.1.2.2  skrll 	sizeof(struct digfilt_softc),
    143  1.1.2.2  skrll 	digfilt_match,
    144  1.1.2.2  skrll 	digfilt_attach,
    145  1.1.2.2  skrll 	NULL,
    146  1.1.2.2  skrll 	digfilt_activate,
    147  1.1.2.2  skrll 	NULL,
    148  1.1.2.2  skrll 	NULL,
    149  1.1.2.2  skrll 	0);
    150  1.1.2.2  skrll 
    151  1.1.2.2  skrll static const struct audio_hw_if digfilt_hw_if = {
    152  1.1.2.2  skrll 	.open = NULL,
    153  1.1.2.2  skrll 	.close = NULL,
    154  1.1.2.2  skrll 	.drain = digfilt_drain,
    155  1.1.2.2  skrll 	.query_encoding = digfilt_query_encoding,
    156  1.1.2.2  skrll 	.set_params = digfilt_set_params,
    157  1.1.2.2  skrll 	.round_blocksize = digfilt_round_blocksize,
    158  1.1.2.2  skrll 	.commit_settings = NULL,
    159  1.1.2.2  skrll 	.init_output = digfilt_init_output,
    160  1.1.2.2  skrll 	.init_input = NULL,
    161  1.1.2.2  skrll 	.start_output = digfilt_start_output,
    162  1.1.2.2  skrll 	.start_input = NULL,
    163  1.1.2.2  skrll 	.halt_output = digfilt_halt_output,
    164  1.1.2.2  skrll 	.speaker_ctl = NULL,
    165  1.1.2.2  skrll 	.getdev = digfilt_getdev,
    166  1.1.2.2  skrll 	.setfd = NULL,
    167  1.1.2.2  skrll 	.set_port = digfilt_set_port,
    168  1.1.2.2  skrll 	.get_port = digfilt_get_port,
    169  1.1.2.2  skrll 	.query_devinfo = digfilt_query_devinfo,
    170  1.1.2.2  skrll 	.allocm = digfilt_allocm,
    171  1.1.2.2  skrll 	.freem = digfilt_freem,
    172  1.1.2.2  skrll 	.round_buffersize = digfilt_round_buffersize,
    173  1.1.2.2  skrll 	.mappage = NULL,
    174  1.1.2.2  skrll 	.get_props = digfilt_get_props,
    175  1.1.2.2  skrll 	.trigger_output = NULL,
    176  1.1.2.2  skrll 	.trigger_input = NULL,
    177  1.1.2.2  skrll 	.dev_ioctl = NULL,
    178  1.1.2.2  skrll 	.get_locks = digfilt_get_locks
    179  1.1.2.2  skrll };
    180  1.1.2.2  skrll 
    181  1.1.2.2  skrll enum {
    182  1.1.2.2  skrll 	DIGFILT_OUTPUT_CLASS,
    183  1.1.2.2  skrll 	DIGFILT_OUTPUT_DAC_VOLUME,
    184  1.1.2.2  skrll 	DIGFILT_OUTPUT_DAC_MUTE,
    185  1.1.2.2  skrll 	DIGFILT_OUTPUT_HP_VOLUME,
    186  1.1.2.2  skrll 	DIGFILT_OUTPUT_HP_MUTE,
    187  1.1.2.2  skrll 	DIGFILT_OUTPUT_LINE_VOLUME,
    188  1.1.2.2  skrll 	DIGFILT_OUTPUT_LINE_MUTE,
    189  1.1.2.2  skrll 	DIGFILT_ENUM_LAST
    190  1.1.2.2  skrll };
    191  1.1.2.2  skrll 
    192  1.1.2.2  skrll static int
    193  1.1.2.2  skrll digfilt_match(device_t parent, cfdata_t match, void *aux)
    194  1.1.2.2  skrll {
    195  1.1.2.2  skrll 	struct apb_attach_args *aa = aux;
    196  1.1.2.2  skrll 
    197  1.1.2.2  skrll 	if (aa->aa_addr == HW_DIGFILT_BASE && aa->aa_size == HW_DIGFILT_SIZE)
    198  1.1.2.2  skrll 		return 1;
    199  1.1.2.2  skrll 	else
    200  1.1.2.2  skrll 		return 0;
    201  1.1.2.2  skrll }
    202  1.1.2.2  skrll 
    203  1.1.2.2  skrll static void
    204  1.1.2.2  skrll digfilt_attach(device_t parent, device_t self, void *aux)
    205  1.1.2.2  skrll {
    206  1.1.2.2  skrll 	struct apb_softc *sc_parent = device_private(parent);
    207  1.1.2.2  skrll 	struct digfilt_softc *sc = device_private(self);
    208  1.1.2.2  skrll 	struct apb_attach_args *aa = aux;
    209  1.1.2.2  skrll 	static int digfilt_attached = 0;
    210  1.1.2.2  skrll 	int error;
    211  1.1.2.2  skrll 	uint32_t v;
    212  1.1.2.2  skrll 	void *intr;
    213  1.1.2.2  skrll 
    214  1.1.2.2  skrll 	sc->sc_dev = self;
    215  1.1.2.2  skrll 	sc->sc_iot = aa->aa_iot;
    216  1.1.2.2  skrll 	sc->sc_dmat = aa->aa_dmat;
    217  1.1.2.2  skrll 
    218  1.1.2.2  skrll 	/* This driver requires DMA functionality from the bus.
    219  1.1.2.2  skrll 	 * Parent bus passes handle to the DMA controller instance. */
    220  1.1.2.2  skrll 	if (sc_parent->dmac == NULL) {
    221  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "DMA functionality missing\n");
    222  1.1.2.2  skrll 		return;
    223  1.1.2.2  skrll 	}
    224  1.1.2.2  skrll 	sc->sc_dmac = device_private(sc_parent->dmac);
    225  1.1.2.2  skrll 
    226  1.1.2.2  skrll 	if (aa->aa_addr == HW_DIGFILT_BASE && digfilt_attached) {
    227  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "DIGFILT already attached\n");
    228  1.1.2.2  skrll 		return;
    229  1.1.2.2  skrll 	}
    230  1.1.2.2  skrll 
    231  1.1.2.2  skrll 	/* Allocate DMA for audio buffer. */
    232  1.1.2.2  skrll 	error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS,
    233  1.1.2.2  skrll 		MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp);
    234  1.1.2.2  skrll 	if (error) {
    235  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    236  1.1.2.2  skrll 		    "Unable to allocate DMA handle\n");
    237  1.1.2.2  skrll 		return;
    238  1.1.2.2  skrll 	}
    239  1.1.2.2  skrll 
    240  1.1.2.2  skrll 	/* Allocate for DMA chain. */
    241  1.1.2.2  skrll 	error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS,
    242  1.1.2.2  skrll 		MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_c_dmamp);
    243  1.1.2.2  skrll 	if (error) {
    244  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    245  1.1.2.2  skrll 		    "Unable to allocate DMA handle\n");
    246  1.1.2.2  skrll 		return;
    247  1.1.2.2  skrll 	}
    248  1.1.2.2  skrll 
    249  1.1.2.2  skrll 	/* Map DIGFILT bus space. */
    250  1.1.2.2  skrll 	if (bus_space_map(sc->sc_iot, HW_DIGFILT_BASE, HW_DIGFILT_SIZE, 0,
    251  1.1.2.2  skrll 	    &sc->sc_hdl)) {
    252  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    253  1.1.2.2  skrll 		    "Unable to map DIGFILT bus space\n");
    254  1.1.2.2  skrll 		return;
    255  1.1.2.2  skrll 	}
    256  1.1.2.2  skrll 
    257  1.1.2.2  skrll 	/* Map AUDIOOUT subregion from parent bus space. */
    258  1.1.2.2  skrll 	if (bus_space_subregion(sc->sc_iot, sc->sc_hdl,
    259  1.1.2.2  skrll 	    (HW_AUDIOOUT_BASE - HW_DIGFILT_BASE), HW_AUDIOOUT_SIZE,
    260  1.1.2.2  skrll 	    &sc->sc_aohdl)) {
    261  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    262  1.1.2.2  skrll 			"Unable to submap AUDIOOUT bus space\n");
    263  1.1.2.2  skrll 		return;
    264  1.1.2.2  skrll 	}
    265  1.1.2.2  skrll 
    266  1.1.2.2  skrll 	/* Map AUDIOIN subregion from parent bus space. */
    267  1.1.2.2  skrll 	if (bus_space_subregion(sc->sc_iot, sc->sc_hdl,
    268  1.1.2.2  skrll 	    (HW_AUDIOIN_BASE - HW_DIGFILT_BASE), HW_AUDIOIN_SIZE,
    269  1.1.2.2  skrll 	    &sc->sc_aihdl)) {
    270  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    271  1.1.2.2  skrll 			"Unable to submap AUDIOIN bus space\n");
    272  1.1.2.2  skrll 		return;
    273  1.1.2.2  skrll 	}
    274  1.1.2.2  skrll 
    275  1.1.2.2  skrll 	/* Enable clocks to the DIGFILT block. */
    276  1.1.2.2  skrll 	clkctrl_en_filtclk();
    277  1.1.2.2  skrll 	delay(10);
    278  1.1.2.2  skrll 
    279  1.1.2.2  skrll 	digfilt_ao_reset(sc);	/* Reset AUDIOOUT. */
    280  1.1.2.2  skrll 	/* Not yet: digfilt_ai_reset(sc); */
    281  1.1.2.2  skrll 
    282  1.1.2.2  skrll 	v = AO_RD(sc, HW_AUDIOOUT_VERSION);
    283  1.1.2.2  skrll 	aprint_normal(": DIGFILT Block v%" __PRIuBIT ".%" __PRIuBIT
    284  1.1.2.2  skrll 		".%" __PRIuBIT "\n",
    285  1.1.2.2  skrll 		__SHIFTOUT(v, HW_AUDIOOUT_VERSION_MAJOR),
    286  1.1.2.2  skrll 		__SHIFTOUT(v, HW_AUDIOOUT_VERSION_MINOR),
    287  1.1.2.2  skrll 		__SHIFTOUT(v, HW_AUDIOOUT_VERSION_STEP));
    288  1.1.2.2  skrll 
    289  1.1.2.2  skrll 	digfilt_ao_init(sc);
    290  1.1.2.2  skrll 	digfilt_ao_set_rate(sc, 44100);	/* Default sample rate 44.1 kHz. */
    291  1.1.2.2  skrll 
    292  1.1.2.2  skrll 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    293  1.1.2.2  skrll 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    294  1.1.2.2  skrll 
    295  1.1.2.2  skrll 	/* HW supported formats. */
    296  1.1.2.2  skrll 	sc->sc_format.mode = AUMODE_PLAY|AUMODE_RECORD;
    297  1.1.2.2  skrll 	sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_LE;
    298  1.1.2.2  skrll 	sc->sc_format.validbits = 16;
    299  1.1.2.2  skrll 	sc->sc_format.precision = 16;
    300  1.1.2.2  skrll 	sc->sc_format.channels = 2;
    301  1.1.2.2  skrll 	sc->sc_format.channel_mask = AUFMT_STEREO;
    302  1.1.2.2  skrll 	sc->sc_format.frequency_type = 8;
    303  1.1.2.2  skrll 	sc->sc_format.frequency[0] = 8000;
    304  1.1.2.2  skrll 	sc->sc_format.frequency[1] = 11025;
    305  1.1.2.2  skrll 	sc->sc_format.frequency[2] = 12000;
    306  1.1.2.2  skrll 	sc->sc_format.frequency[3] = 16000;
    307  1.1.2.2  skrll 	sc->sc_format.frequency[4] = 22050;
    308  1.1.2.2  skrll 	sc->sc_format.frequency[5] = 24000;
    309  1.1.2.2  skrll 	sc->sc_format.frequency[6] = 32000;
    310  1.1.2.2  skrll 	sc->sc_format.frequency[7] = 44100;
    311  1.1.2.2  skrll 
    312  1.1.2.2  skrll 	if (auconv_create_encodings(&sc->sc_format, 1, &sc->sc_encodings)) {
    313  1.1.2.2  skrll 		aprint_error_dev(self, "could not create encodings\n");
    314  1.1.2.2  skrll 		return;
    315  1.1.2.2  skrll 	}
    316  1.1.2.2  skrll 
    317  1.1.2.2  skrll 	sc->sc_audiodev = audio_attach_mi(&digfilt_hw_if, sc, sc->sc_dev);
    318  1.1.2.2  skrll 
    319  1.1.2.2  skrll 	/* Default mutes. */
    320  1.1.2.2  skrll 	sc->sc_mute = DIGFILT_MUTE_LINE;
    321  1.1.2.2  skrll 	digfilt_ao_apply_mutes(sc);
    322  1.1.2.2  skrll 
    323  1.1.2.2  skrll 	/* Allocate DMA safe memory for the DMA chain. */
    324  1.1.2.2  skrll 	sc->sc_dmachain = digfilt_ao_alloc_dmachain(sc,
    325  1.1.2.2  skrll 		sizeof(struct apbdma_command) * DIGFILT_DMA_CHAIN_LENGTH);
    326  1.1.2.2  skrll 	if (sc->sc_dmachain == NULL) {
    327  1.1.2.2  skrll 		aprint_error_dev(self, "digfilt_ao_alloc_dmachain failed\n");
    328  1.1.2.2  skrll 		return;
    329  1.1.2.2  skrll 	}
    330  1.1.2.2  skrll 
    331  1.1.2.2  skrll 	intr = intr_establish(IRQ_DAC_DMA, IPL_SCHED, IST_LEVEL, dac_dma_intr,
    332  1.1.2.2  skrll 			sc);
    333  1.1.2.2  skrll 	if (intr == NULL) {
    334  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    335  1.1.2.2  skrll 			"Unable to establish IRQ for DAC_DMA\n");
    336  1.1.2.2  skrll 		return;
    337  1.1.2.2  skrll 	}
    338  1.1.2.2  skrll 
    339  1.1.2.2  skrll 	intr = intr_establish(IRQ_DAC_ERROR, IPL_SCHED, IST_LEVEL,
    340  1.1.2.2  skrll 		dac_error_intr, sc);
    341  1.1.2.2  skrll 	if (intr == NULL) {
    342  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    343  1.1.2.2  skrll 			"Unable to establish IRQ for DAC_ERROR\n");
    344  1.1.2.2  skrll 		return;
    345  1.1.2.2  skrll 	}
    346  1.1.2.2  skrll 
    347  1.1.2.2  skrll 	/* Initialize DMA channel. */
    348  1.1.2.2  skrll 	apbdma_chan_init(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
    349  1.1.2.2  skrll 
    350  1.1.2.2  skrll 	digfilt_attached = 1;
    351  1.1.2.2  skrll 
    352  1.1.2.2  skrll 	return;
    353  1.1.2.2  skrll }
    354  1.1.2.2  skrll 
    355  1.1.2.2  skrll static int
    356  1.1.2.2  skrll digfilt_activate(device_t self, enum devact act)
    357  1.1.2.2  skrll {
    358  1.1.2.2  skrll 	return EOPNOTSUPP;
    359  1.1.2.2  skrll }
    360  1.1.2.2  skrll 
    361  1.1.2.2  skrll static int
    362  1.1.2.2  skrll digfilt_drain(void *priv)
    363  1.1.2.2  skrll {
    364  1.1.2.2  skrll 
    365  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    366  1.1.2.2  skrll 
    367  1.1.2.2  skrll 	apbdma_wait(sc->sc_dmac, 1);
    368  1.1.2.2  skrll 	sc->sc_cmd_index = 0;
    369  1.1.2.2  skrll 
    370  1.1.2.2  skrll 	return 0;
    371  1.1.2.2  skrll }
    372  1.1.2.2  skrll 
    373  1.1.2.2  skrll static int
    374  1.1.2.2  skrll digfilt_query_encoding(void *priv, struct audio_encoding *ae)
    375  1.1.2.2  skrll {
    376  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    377  1.1.2.2  skrll 	return auconv_query_encoding(sc->sc_encodings, ae);
    378  1.1.2.2  skrll }
    379  1.1.2.2  skrll 
    380  1.1.2.2  skrll static int
    381  1.1.2.2  skrll digfilt_set_params(void *priv, int setmode, int usemode,
    382  1.1.2.2  skrll     audio_params_t *play, audio_params_t *rec,
    383  1.1.2.2  skrll     stream_filter_list_t *pfil, stream_filter_list_t *rfil)
    384  1.1.2.2  skrll {
    385  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    386  1.1.2.2  skrll 	int index;
    387  1.1.2.2  skrll 
    388  1.1.2.2  skrll 	if (play && (setmode & AUMODE_PLAY)) {
    389  1.1.2.2  skrll 		index = auconv_set_converter(&sc->sc_format, 1,
    390  1.1.2.2  skrll 		    AUMODE_PLAY, play, true, pfil);
    391  1.1.2.2  skrll 		if (index < 0)
    392  1.1.2.2  skrll 			return EINVAL;
    393  1.1.2.2  skrll 		sc->sc_pparam = pfil->req_size > 0 ?
    394  1.1.2.2  skrll 		    pfil->filters[0].param :
    395  1.1.2.2  skrll 		    *play;
    396  1.1.2.2  skrll 
    397  1.1.2.2  skrll 		/* At this point bitrate should be figured out. */
    398  1.1.2.2  skrll 		digfilt_ao_set_rate(sc, sc->sc_pparam.sample_rate);
    399  1.1.2.2  skrll 	}
    400  1.1.2.2  skrll 
    401  1.1.2.2  skrll 	return 0;
    402  1.1.2.2  skrll }
    403  1.1.2.2  skrll 
    404  1.1.2.2  skrll static int
    405  1.1.2.2  skrll digfilt_round_blocksize(void *priv, int bs, int mode,
    406  1.1.2.2  skrll const audio_params_t *param)
    407  1.1.2.2  skrll {
    408  1.1.2.2  skrll 	int blocksize;
    409  1.1.2.2  skrll 
    410  1.1.2.2  skrll 	if (bs > DIGFILT_BLOCKSIZE_MAX)
    411  1.1.2.2  skrll 		blocksize = DIGFILT_BLOCKSIZE_MAX;
    412  1.1.2.2  skrll 	else
    413  1.1.2.2  skrll 		blocksize = bs & ~(DIGFILT_BLOCKSIZE_ROUND-1);
    414  1.1.2.2  skrll 
    415  1.1.2.2  skrll 	return blocksize;
    416  1.1.2.2  skrll }
    417  1.1.2.2  skrll 
    418  1.1.2.2  skrll static int
    419  1.1.2.2  skrll digfilt_init_output(void *priv, void *buffer, int size)
    420  1.1.2.2  skrll {
    421  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    422  1.1.2.2  skrll 	apbdma_command_t dma_cmd;
    423  1.1.2.2  skrll 	int i;
    424  1.1.2.2  skrll 	dma_cmd = sc->sc_dmachain;
    425  1.1.2.2  skrll 	sc->sc_cmd_index = 0;
    426  1.1.2.2  skrll 
    427  1.1.2.2  skrll 	/*
    428  1.1.2.2  skrll 	 * Build circular DMA command chain template for later use.
    429  1.1.2.2  skrll 	 */
    430  1.1.2.2  skrll 	for (i = 0; i < DIGFILT_DMA_CHAIN_LENGTH; i++) {
    431  1.1.2.2  skrll 		/* Last entry loops back to first. */
    432  1.1.2.2  skrll 		if (i == DIGFILT_DMA_CHAIN_LENGTH - 1)
    433  1.1.2.2  skrll 			dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr);
    434  1.1.2.2  skrll 		else
    435  1.1.2.2  skrll 			dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr + (sizeof(struct apbdma_command) * (1 + i)));
    436  1.1.2.2  skrll 
    437  1.1.2.2  skrll 		dma_cmd[i].control = __SHIFTIN(DIGFILT_BLOCKSIZE_MAX,  APBDMA_CMD_XFER_COUNT) |
    438  1.1.2.2  skrll 		    __SHIFTIN(1, APBDMA_CMD_CMDPIOWORDS) |
    439  1.1.2.2  skrll 		    APBDMA_CMD_SEMAPHORE |
    440  1.1.2.2  skrll 		    APBDMA_CMD_IRQONCMPLT |
    441  1.1.2.2  skrll 		    APBDMA_CMD_CHAIN |
    442  1.1.2.2  skrll 		    __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND);
    443  1.1.2.2  skrll 
    444  1.1.2.2  skrll 		dma_cmd[i].buffer = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr);
    445  1.1.2.2  skrll 
    446  1.1.2.2  skrll 		dma_cmd[i].pio_words[0] = HW_AUDIOOUT_CTRL_WORD_LENGTH |
    447  1.1.2.2  skrll 		    HW_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN |
    448  1.1.2.2  skrll 		    HW_AUDIOOUT_CTRL_RUN;
    449  1.1.2.2  skrll 
    450  1.1.2.2  skrll 	}
    451  1.1.2.2  skrll 
    452  1.1.2.2  skrll 	apbdma_chan_set_chain(sc->sc_dmac, DIGFILT_DMA_CHANNEL, sc->sc_c_dmamp);
    453  1.1.2.2  skrll 
    454  1.1.2.2  skrll 	return 0;
    455  1.1.2.2  skrll }
    456  1.1.2.2  skrll 
    457  1.1.2.2  skrll static int
    458  1.1.2.2  skrll digfilt_start_output(void *priv, void *start, int bs, void (*intr)(void*), void *intarg)
    459  1.1.2.2  skrll {
    460  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    461  1.1.2.2  skrll 	apbdma_command_t dma_cmd;
    462  1.1.2.2  skrll 	bus_addr_t offset;
    463  1.1.2.2  skrll 
    464  1.1.2.2  skrll 	sc->sc_intr = intr;
    465  1.1.2.2  skrll 	sc->sc_intarg = intarg;
    466  1.1.2.2  skrll 	dma_cmd = sc->sc_dmachain;
    467  1.1.2.2  skrll 
    468  1.1.2.2  skrll 	offset = (bus_addr_t)start - (bus_addr_t)sc->sc_buffer;
    469  1.1.2.2  skrll 
    470  1.1.2.2  skrll 	dma_cmd[sc->sc_cmd_index].buffer =
    471  1.1.2.2  skrll 	    (void *)((bus_addr_t)sc->sc_dmamp->dm_segs[0].ds_addr + offset);
    472  1.1.2.2  skrll 
    473  1.1.2.2  skrll 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, offset, bs, BUS_DMASYNC_PREWRITE);
    474  1.1.2.2  skrll 	bus_dmamap_sync(sc->sc_dmat, sc->sc_c_dmamp,
    475  1.1.2.2  skrll 	    sizeof(struct apbdma_command) * sc->sc_cmd_index, sizeof(struct apbdma_command), BUS_DMASYNC_PREWRITE);
    476  1.1.2.2  skrll 
    477  1.1.2.2  skrll 	sc->sc_cmd_index++;
    478  1.1.2.2  skrll 	if (sc->sc_cmd_index > DIGFILT_DMA_CHAIN_LENGTH - 1)
    479  1.1.2.2  skrll 		sc->sc_cmd_index = 0;
    480  1.1.2.2  skrll 
    481  1.1.2.2  skrll 	apbdma_run(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
    482  1.1.2.2  skrll 
    483  1.1.2.2  skrll 	return 0;
    484  1.1.2.2  skrll }
    485  1.1.2.2  skrll 
    486  1.1.2.2  skrll static int
    487  1.1.2.2  skrll digfilt_halt_output(void *priv)
    488  1.1.2.2  skrll {
    489  1.1.2.2  skrll 	return 0;
    490  1.1.2.2  skrll }
    491  1.1.2.2  skrll 
    492  1.1.2.2  skrll static int
    493  1.1.2.2  skrll digfilt_getdev(void *priv, struct audio_device *ad)
    494  1.1.2.2  skrll {
    495  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    496  1.1.2.2  skrll 
    497  1.1.2.2  skrll 	strncpy(ad->name, device_xname(sc->sc_dev), MAX_AUDIO_DEV_LEN);
    498  1.1.2.2  skrll 	strncpy(ad->version, "", MAX_AUDIO_DEV_LEN);
    499  1.1.2.2  skrll 	strncpy(ad->config, "", MAX_AUDIO_DEV_LEN);
    500  1.1.2.2  skrll 
    501  1.1.2.2  skrll 	return 0;
    502  1.1.2.2  skrll }
    503  1.1.2.2  skrll 
    504  1.1.2.2  skrll static int
    505  1.1.2.2  skrll digfilt_set_port(void *priv, mixer_ctrl_t *mc)
    506  1.1.2.2  skrll {
    507  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    508  1.1.2.2  skrll 	uint32_t val;
    509  1.1.2.2  skrll 	uint8_t nvol;
    510  1.1.2.2  skrll 
    511  1.1.2.2  skrll 	switch (mc->dev) {
    512  1.1.2.2  skrll 	case DIGFILT_OUTPUT_DAC_VOLUME:
    513  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
    514  1.1.2.2  skrll 		val &= ~(HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT |
    515  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
    516  1.1.2.2  skrll 
    517  1.1.2.2  skrll 		/* DAC volume field is 8 bits. */
    518  1.1.2.2  skrll 		nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    519  1.1.2.2  skrll 		if (nvol > 0xff)
    520  1.1.2.2  skrll 			nvol = 0xff;
    521  1.1.2.2  skrll 
    522  1.1.2.2  skrll 		val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT);
    523  1.1.2.2  skrll 
    524  1.1.2.2  skrll 		nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    525  1.1.2.2  skrll 		if (nvol > 0xff)
    526  1.1.2.2  skrll 			nvol = 0xff;
    527  1.1.2.2  skrll 
    528  1.1.2.2  skrll 		val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
    529  1.1.2.2  skrll 
    530  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_DACVOLUME, val);
    531  1.1.2.2  skrll 
    532  1.1.2.2  skrll 		return 0;
    533  1.1.2.2  skrll 
    534  1.1.2.2  skrll 	case DIGFILT_OUTPUT_HP_VOLUME:
    535  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
    536  1.1.2.2  skrll 		val &= ~(HW_AUDIOOUT_HPVOL_VOL_LEFT |
    537  1.1.2.2  skrll 		    HW_AUDIOOUT_HPVOL_VOL_RIGHT);
    538  1.1.2.2  skrll 
    539  1.1.2.2  skrll 		/* HP volume field is 7 bits. */
    540  1.1.2.2  skrll 		nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    541  1.1.2.2  skrll 		if (nvol > 0x7f)
    542  1.1.2.2  skrll 			nvol = 0x7f;
    543  1.1.2.2  skrll 
    544  1.1.2.2  skrll 		nvol = ~nvol;
    545  1.1.2.2  skrll 		val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_LEFT);
    546  1.1.2.2  skrll 
    547  1.1.2.2  skrll 		nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    548  1.1.2.2  skrll 		if (nvol > 0x7f)
    549  1.1.2.2  skrll 			nvol = 0x7f;
    550  1.1.2.2  skrll 
    551  1.1.2.2  skrll 		nvol = ~nvol;
    552  1.1.2.2  skrll 		val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_RIGHT);
    553  1.1.2.2  skrll 
    554  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_HPVOL, val);
    555  1.1.2.2  skrll 
    556  1.1.2.2  skrll 		return 0;
    557  1.1.2.2  skrll 
    558  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_VOLUME:
    559  1.1.2.2  skrll 		return 1;
    560  1.1.2.2  skrll 
    561  1.1.2.2  skrll 	case DIGFILT_OUTPUT_DAC_MUTE:
    562  1.1.2.2  skrll 		if (mc->un.ord)
    563  1.1.2.2  skrll 			sc->sc_mute |= DIGFILT_MUTE_DAC;
    564  1.1.2.2  skrll 		else
    565  1.1.2.2  skrll 			sc->sc_mute &= ~DIGFILT_MUTE_DAC;
    566  1.1.2.2  skrll 
    567  1.1.2.2  skrll 		digfilt_ao_apply_mutes(sc);
    568  1.1.2.2  skrll 
    569  1.1.2.2  skrll 		return 0;
    570  1.1.2.2  skrll 
    571  1.1.2.2  skrll 	case DIGFILT_OUTPUT_HP_MUTE:
    572  1.1.2.2  skrll 		if (mc->un.ord)
    573  1.1.2.2  skrll 			sc->sc_mute |= DIGFILT_MUTE_HP;
    574  1.1.2.2  skrll 		else
    575  1.1.2.2  skrll 			sc->sc_mute &= ~DIGFILT_MUTE_HP;
    576  1.1.2.2  skrll 
    577  1.1.2.2  skrll 		digfilt_ao_apply_mutes(sc);
    578  1.1.2.2  skrll 
    579  1.1.2.2  skrll 		return 0;
    580  1.1.2.2  skrll 
    581  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_MUTE:
    582  1.1.2.2  skrll 		if (mc->un.ord)
    583  1.1.2.2  skrll 			sc->sc_mute |= DIGFILT_MUTE_LINE;
    584  1.1.2.2  skrll 		else
    585  1.1.2.2  skrll 			sc->sc_mute &= ~DIGFILT_MUTE_LINE;
    586  1.1.2.2  skrll 
    587  1.1.2.2  skrll 		digfilt_ao_apply_mutes(sc);
    588  1.1.2.2  skrll 
    589  1.1.2.2  skrll 		return 0;
    590  1.1.2.2  skrll 	}
    591  1.1.2.2  skrll 
    592  1.1.2.2  skrll 	return ENXIO;
    593  1.1.2.2  skrll }
    594  1.1.2.2  skrll 
    595  1.1.2.2  skrll static int
    596  1.1.2.2  skrll digfilt_get_port(void *priv, mixer_ctrl_t *mc)
    597  1.1.2.2  skrll {
    598  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    599  1.1.2.2  skrll 	uint32_t val;
    600  1.1.2.2  skrll 	uint8_t nvol;
    601  1.1.2.2  skrll 
    602  1.1.2.2  skrll         switch (mc->dev) {
    603  1.1.2.2  skrll         case DIGFILT_OUTPUT_DAC_VOLUME:
    604  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
    605  1.1.2.2  skrll 
    606  1.1.2.2  skrll 		nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT);
    607  1.1.2.2  skrll                 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = nvol;
    608  1.1.2.2  skrll 
    609  1.1.2.2  skrll 		nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
    610  1.1.2.2  skrll                 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = nvol;
    611  1.1.2.2  skrll 
    612  1.1.2.2  skrll                 return 0;
    613  1.1.2.2  skrll 
    614  1.1.2.2  skrll         case DIGFILT_OUTPUT_HP_VOLUME:
    615  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
    616  1.1.2.2  skrll 
    617  1.1.2.2  skrll 		nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_LEFT);
    618  1.1.2.2  skrll 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ~nvol & 0x7f;
    619  1.1.2.2  skrll 
    620  1.1.2.2  skrll 		nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_RIGHT);
    621  1.1.2.2  skrll 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ~nvol & 0x7f;
    622  1.1.2.2  skrll 
    623  1.1.2.2  skrll 		return 0;
    624  1.1.2.2  skrll 
    625  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_VOLUME:
    626  1.1.2.2  skrll 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 255;
    627  1.1.2.2  skrll 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 255;
    628  1.1.2.2  skrll 
    629  1.1.2.2  skrll 		return 0;
    630  1.1.2.2  skrll 
    631  1.1.2.2  skrll 	case DIGFILT_OUTPUT_DAC_MUTE:
    632  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
    633  1.1.2.2  skrll 
    634  1.1.2.2  skrll 		mc->un.ord = (val & (HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
    635  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT)) ? 1 : 0;
    636  1.1.2.2  skrll 
    637  1.1.2.2  skrll 		return 0;
    638  1.1.2.2  skrll 
    639  1.1.2.2  skrll 	case DIGFILT_OUTPUT_HP_MUTE:
    640  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
    641  1.1.2.2  skrll 
    642  1.1.2.2  skrll 		mc->un.ord = (val & HW_AUDIOOUT_HPVOL_MUTE) ? 1 : 0;
    643  1.1.2.2  skrll 
    644  1.1.2.2  skrll 		return 0;
    645  1.1.2.2  skrll 
    646  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_MUTE:
    647  1.1.2.2  skrll 		val = AO_RD(sc, HW_AUDIOOUT_SPEAKERCTRL);
    648  1.1.2.2  skrll 
    649  1.1.2.2  skrll 		mc->un.ord = (val & HW_AUDIOOUT_SPEAKERCTRL_MUTE) ? 1 : 0;
    650  1.1.2.2  skrll 
    651  1.1.2.2  skrll 		return 0;
    652  1.1.2.2  skrll         }
    653  1.1.2.2  skrll 
    654  1.1.2.2  skrll         return ENXIO;
    655  1.1.2.2  skrll }
    656  1.1.2.2  skrll 
    657  1.1.2.2  skrll static int
    658  1.1.2.2  skrll digfilt_query_devinfo(void *priv, mixer_devinfo_t *di)
    659  1.1.2.2  skrll {
    660  1.1.2.2  skrll 
    661  1.1.2.2  skrll 	switch (di->index) {
    662  1.1.2.2  skrll 	case DIGFILT_OUTPUT_CLASS:
    663  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    664  1.1.2.2  skrll 		strcpy(di->label.name, AudioCoutputs);
    665  1.1.2.2  skrll 		di->type = AUDIO_MIXER_CLASS;
    666  1.1.2.2  skrll 		di->next = di->prev = AUDIO_MIXER_LAST;
    667  1.1.2.2  skrll 		return 0;
    668  1.1.2.2  skrll 
    669  1.1.2.2  skrll 	case DIGFILT_OUTPUT_DAC_VOLUME:
    670  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    671  1.1.2.2  skrll 		strcpy(di->label.name, AudioNdac);
    672  1.1.2.2  skrll 		di->type = AUDIO_MIXER_VALUE;
    673  1.1.2.2  skrll 		di->prev = AUDIO_MIXER_LAST;
    674  1.1.2.2  skrll 		di->next = DIGFILT_OUTPUT_DAC_MUTE;
    675  1.1.2.2  skrll 		di->un.v.num_channels = 2;
    676  1.1.2.2  skrll 		strcpy(di->un.v.units.name, AudioNvolume);
    677  1.1.2.2  skrll 		return 0;
    678  1.1.2.2  skrll 
    679  1.1.2.2  skrll 	case DIGFILT_OUTPUT_DAC_MUTE:
    680  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    681  1.1.2.2  skrll 		di->type = AUDIO_MIXER_ENUM;
    682  1.1.2.2  skrll 		di->prev = DIGFILT_OUTPUT_DAC_VOLUME;
    683  1.1.2.2  skrll 		di->next = AUDIO_MIXER_LAST;
    684  1.1.2.2  skrll mute:
    685  1.1.2.2  skrll 		strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
    686  1.1.2.2  skrll 		di->un.e.num_mem = 2;
    687  1.1.2.2  skrll 		strlcpy(di->un.e.member[0].label.name, AudioNon,
    688  1.1.2.2  skrll 		    sizeof(di->un.e.member[0].label.name));
    689  1.1.2.2  skrll 		di->un.e.member[0].ord = 1;
    690  1.1.2.2  skrll 		strlcpy(di->un.e.member[1].label.name, AudioNoff,
    691  1.1.2.2  skrll 		    sizeof(di->un.e.member[1].label.name));
    692  1.1.2.2  skrll 		di->un.e.member[1].ord = 0;
    693  1.1.2.2  skrll 		return 0;
    694  1.1.2.2  skrll 
    695  1.1.2.2  skrll 	case DIGFILT_OUTPUT_HP_VOLUME:
    696  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    697  1.1.2.2  skrll 		strcpy(di->label.name, AudioNheadphone);
    698  1.1.2.2  skrll 		di->type = AUDIO_MIXER_VALUE;
    699  1.1.2.2  skrll 		di->prev = AUDIO_MIXER_LAST;
    700  1.1.2.2  skrll 		di->next = DIGFILT_OUTPUT_HP_MUTE;
    701  1.1.2.2  skrll 		di->un.v.num_channels = 2;
    702  1.1.2.2  skrll 		strcpy(di->un.v.units.name, AudioNvolume);
    703  1.1.2.2  skrll 		return 0;
    704  1.1.2.2  skrll 
    705  1.1.2.2  skrll 	case DIGFILT_OUTPUT_HP_MUTE:
    706  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    707  1.1.2.2  skrll 		di->type = AUDIO_MIXER_ENUM;
    708  1.1.2.2  skrll 		di->prev = DIGFILT_OUTPUT_HP_VOLUME;
    709  1.1.2.2  skrll 		di->next = AUDIO_MIXER_LAST;
    710  1.1.2.2  skrll 		goto mute;
    711  1.1.2.2  skrll 
    712  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_VOLUME:
    713  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    714  1.1.2.2  skrll 		strcpy(di->label.name, AudioNline);
    715  1.1.2.2  skrll 		di->type = AUDIO_MIXER_VALUE;
    716  1.1.2.2  skrll 		di->prev = AUDIO_MIXER_LAST;
    717  1.1.2.2  skrll 		di->next = DIGFILT_OUTPUT_LINE_MUTE;
    718  1.1.2.2  skrll 		di->un.v.num_channels = 2;
    719  1.1.2.2  skrll 		strcpy(di->un.v.units.name, AudioNvolume);
    720  1.1.2.2  skrll 		return 0;
    721  1.1.2.2  skrll 
    722  1.1.2.2  skrll 	case DIGFILT_OUTPUT_LINE_MUTE:
    723  1.1.2.2  skrll 		di->mixer_class = DIGFILT_OUTPUT_CLASS;
    724  1.1.2.2  skrll 		di->type = AUDIO_MIXER_ENUM;
    725  1.1.2.2  skrll 		di->prev = DIGFILT_OUTPUT_LINE_VOLUME;
    726  1.1.2.2  skrll 		di->next = AUDIO_MIXER_LAST;
    727  1.1.2.2  skrll 		goto mute;
    728  1.1.2.2  skrll 	}
    729  1.1.2.2  skrll 
    730  1.1.2.2  skrll         return ENXIO;
    731  1.1.2.2  skrll }
    732  1.1.2.2  skrll 
    733  1.1.2.2  skrll static void *
    734  1.1.2.2  skrll digfilt_allocm(void *priv, int direction, size_t size)
    735  1.1.2.2  skrll {
    736  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    737  1.1.2.2  skrll 	int rsegs;
    738  1.1.2.2  skrll 	int error;
    739  1.1.2.2  skrll 
    740  1.1.2.2  skrll 	sc->sc_buffer = NULL;
    741  1.1.2.2  skrll 
    742  1.1.2.2  skrll 	/*
    743  1.1.2.2  skrll 	 * AUMODE_PLAY is DMA from memory to device.
    744  1.1.2.2  skrll 	 */
    745  1.1.2.2  skrll 	if (direction != AUMODE_PLAY)
    746  1.1.2.2  skrll 		return NULL;
    747  1.1.2.2  skrll 
    748  1.1.2.2  skrll 	error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT);
    749  1.1.2.2  skrll 	if (error) {
    750  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    751  1.1.2.2  skrll 		    "bus_dmamem_alloc: %d\n", error);
    752  1.1.2.2  skrll 		goto out;
    753  1.1.2.2  skrll 	}
    754  1.1.2.2  skrll 
    755  1.1.2.2  skrll 	error = bus_dmamem_map(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS, size, &sc->sc_buffer, BUS_DMA_NOWAIT);
    756  1.1.2.2  skrll 	if (error) {
    757  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error);
    758  1.1.2.2  skrll 		goto dmamem_free;
    759  1.1.2.2  skrll 	}
    760  1.1.2.2  skrll 
    761  1.1.2.2  skrll 	/* After load sc_dmamp is valid. */
    762  1.1.2.2  skrll 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamp, sc->sc_buffer, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
    763  1.1.2.2  skrll 	if (error) {
    764  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error);
    765  1.1.2.2  skrll 		goto dmamem_unmap;
    766  1.1.2.2  skrll 	}
    767  1.1.2.2  skrll 
    768  1.1.2.2  skrll 	memset(sc->sc_buffer, 0x00, size);
    769  1.1.2.2  skrll 
    770  1.1.2.2  skrll 	return sc->sc_buffer;
    771  1.1.2.2  skrll 
    772  1.1.2.2  skrll dmamem_unmap:
    773  1.1.2.2  skrll 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_buffer, size);
    774  1.1.2.2  skrll dmamem_free:
    775  1.1.2.2  skrll 	bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS);
    776  1.1.2.2  skrll out:
    777  1.1.2.2  skrll 	return NULL;
    778  1.1.2.2  skrll }
    779  1.1.2.2  skrll 
    780  1.1.2.2  skrll static void
    781  1.1.2.2  skrll digfilt_freem(void *priv, void *kvap, size_t size)
    782  1.1.2.2  skrll {
    783  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    784  1.1.2.2  skrll 
    785  1.1.2.2  skrll 	bus_dmamem_unmap(sc->sc_dmat, kvap, size);
    786  1.1.2.2  skrll 	bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS);
    787  1.1.2.2  skrll 
    788  1.1.2.2  skrll 	return;
    789  1.1.2.2  skrll }
    790  1.1.2.2  skrll 
    791  1.1.2.2  skrll static size_t
    792  1.1.2.2  skrll digfilt_round_buffersize(void *hdl, int direction, size_t bs)
    793  1.1.2.2  skrll {
    794  1.1.2.2  skrll 	int bufsize;
    795  1.1.2.2  skrll 
    796  1.1.2.2  skrll 	bufsize = bs & ~(DIGFILT_BLOCKSIZE_MAX-1);
    797  1.1.2.2  skrll 
    798  1.1.2.2  skrll 	return bufsize;
    799  1.1.2.2  skrll }
    800  1.1.2.2  skrll 
    801  1.1.2.2  skrll static int
    802  1.1.2.2  skrll digfilt_get_props(void *sc)
    803  1.1.2.2  skrll {
    804  1.1.2.2  skrll 	return (AUDIO_PROP_PLAYBACK | AUDIO_PROP_INDEPENDENT);
    805  1.1.2.2  skrll }
    806  1.1.2.2  skrll 
    807  1.1.2.2  skrll static void
    808  1.1.2.2  skrll digfilt_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread)
    809  1.1.2.2  skrll {
    810  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    811  1.1.2.2  skrll 
    812  1.1.2.2  skrll 	*intr = &sc->sc_intr_lock;
    813  1.1.2.2  skrll 	*thread = &sc->sc_lock;
    814  1.1.2.2  skrll 
    815  1.1.2.2  skrll 	return;
    816  1.1.2.2  skrll }
    817  1.1.2.2  skrll 
    818  1.1.2.2  skrll /*
    819  1.1.2.2  skrll  * IRQ for DAC error.
    820  1.1.2.2  skrll  */
    821  1.1.2.2  skrll static int
    822  1.1.2.2  skrll dac_error_intr(void *arg)
    823  1.1.2.2  skrll {
    824  1.1.2.2  skrll 	struct digfilt_softc *sc = arg;
    825  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ);
    826  1.1.2.2  skrll 	return 1;
    827  1.1.2.2  skrll }
    828  1.1.2.2  skrll 
    829  1.1.2.2  skrll /*
    830  1.1.2.2  skrll  * IRQ from DMA.
    831  1.1.2.2  skrll  */
    832  1.1.2.2  skrll static int
    833  1.1.2.2  skrll dac_dma_intr(void *arg)
    834  1.1.2.2  skrll {
    835  1.1.2.2  skrll 	struct digfilt_softc *sc = arg;
    836  1.1.2.2  skrll 
    837  1.1.2.2  skrll 	unsigned int dma_err;
    838  1.1.2.2  skrll 
    839  1.1.2.2  skrll 	mutex_enter(&sc->sc_intr_lock);
    840  1.1.2.2  skrll 
    841  1.1.2.2  skrll 	dma_err = apbdma_intr_status(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
    842  1.1.2.2  skrll 
    843  1.1.2.2  skrll 	if (dma_err) {
    844  1.1.2.2  skrll 		apbdma_ack_error_intr(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
    845  1.1.2.2  skrll 	}
    846  1.1.2.2  skrll 
    847  1.1.2.2  skrll 	sc->sc_intr(sc->sc_intarg);
    848  1.1.2.2  skrll 	apbdma_ack_intr(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
    849  1.1.2.2  skrll 
    850  1.1.2.2  skrll 	mutex_exit(&sc->sc_intr_lock);
    851  1.1.2.2  skrll 
    852  1.1.2.2  skrll 	/* Return 1 to acknowledge IRQ. */
    853  1.1.2.2  skrll 	return 1;
    854  1.1.2.2  skrll }
    855  1.1.2.2  skrll 
    856  1.1.2.2  skrll static void *
    857  1.1.2.2  skrll digfilt_ao_alloc_dmachain(void *priv, size_t size)
    858  1.1.2.2  skrll {
    859  1.1.2.2  skrll 	struct digfilt_softc *sc = priv;
    860  1.1.2.2  skrll 	int rsegs;
    861  1.1.2.2  skrll 	int error;
    862  1.1.2.2  skrll 	void *kvap;
    863  1.1.2.2  skrll 
    864  1.1.2.2  skrll 	kvap = NULL;
    865  1.1.2.2  skrll 
    866  1.1.2.2  skrll 	error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_c_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT);
    867  1.1.2.2  skrll 	if (error) {
    868  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev,
    869  1.1.2.2  skrll 		    "bus_dmamem_alloc: %d\n", error);
    870  1.1.2.2  skrll 		goto out;
    871  1.1.2.2  skrll 	}
    872  1.1.2.2  skrll 
    873  1.1.2.2  skrll 	error = bus_dmamem_map(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS, size, &kvap, BUS_DMA_NOWAIT);
    874  1.1.2.2  skrll 	if (error) {
    875  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error);
    876  1.1.2.2  skrll 		goto dmamem_free;
    877  1.1.2.2  skrll 	}
    878  1.1.2.2  skrll 
    879  1.1.2.2  skrll 	/* After load sc_c_dmamp is valid. */
    880  1.1.2.2  skrll 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_c_dmamp, kvap, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
    881  1.1.2.2  skrll 	if (error) {
    882  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error);
    883  1.1.2.2  skrll 		goto dmamem_unmap;
    884  1.1.2.2  skrll 	}
    885  1.1.2.2  skrll 
    886  1.1.2.2  skrll 	memset(kvap, 0x00, size);
    887  1.1.2.2  skrll 
    888  1.1.2.2  skrll 	return kvap;
    889  1.1.2.2  skrll 
    890  1.1.2.2  skrll dmamem_unmap:
    891  1.1.2.2  skrll 	bus_dmamem_unmap(sc->sc_dmat, kvap, size);
    892  1.1.2.2  skrll dmamem_free:
    893  1.1.2.2  skrll 	bus_dmamem_free(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS);
    894  1.1.2.2  skrll out:
    895  1.1.2.2  skrll 
    896  1.1.2.2  skrll 	return kvap;
    897  1.1.2.2  skrll }
    898  1.1.2.2  skrll 
    899  1.1.2.2  skrll static void
    900  1.1.2.2  skrll digfilt_ao_apply_mutes(struct digfilt_softc *sc)
    901  1.1.2.2  skrll {
    902  1.1.2.2  skrll 
    903  1.1.2.2  skrll 	/* DAC. */
    904  1.1.2.2  skrll 	if (sc->sc_mute & DIGFILT_MUTE_DAC) {
    905  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_DACVOLUME_SET,
    906  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
    907  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT
    908  1.1.2.2  skrll 		);
    909  1.1.2.2  skrll 
    910  1.1.2.2  skrll 	} else {
    911  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_DACVOLUME_CLR,
    912  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
    913  1.1.2.2  skrll 		    HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT
    914  1.1.2.2  skrll 		);
    915  1.1.2.2  skrll 	}
    916  1.1.2.2  skrll 
    917  1.1.2.2  skrll 	/* HP. */
    918  1.1.2.2  skrll 	if (sc->sc_mute & DIGFILT_MUTE_HP)
    919  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_HPVOL_SET, HW_AUDIOOUT_HPVOL_MUTE);
    920  1.1.2.2  skrll 	else
    921  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_HPVOL_CLR, HW_AUDIOOUT_HPVOL_MUTE);
    922  1.1.2.2  skrll 
    923  1.1.2.2  skrll 	/* Line. */
    924  1.1.2.2  skrll 	if (sc->sc_mute & DIGFILT_MUTE_LINE)
    925  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_SET,
    926  1.1.2.2  skrll 		    HW_AUDIOOUT_SPEAKERCTRL_MUTE);
    927  1.1.2.2  skrll 	else
    928  1.1.2.2  skrll 		AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_CLR,
    929  1.1.2.2  skrll 		    HW_AUDIOOUT_SPEAKERCTRL_MUTE);
    930  1.1.2.2  skrll 
    931  1.1.2.2  skrll 	return;
    932  1.1.2.2  skrll }
    933  1.1.2.2  skrll 
    934  1.1.2.2  skrll /*
    935  1.1.2.2  skrll  * Initialize audio system.
    936  1.1.2.2  skrll  */
    937  1.1.2.2  skrll static void
    938  1.1.2.2  skrll digfilt_ao_init(struct digfilt_softc *sc)
    939  1.1.2.2  skrll {
    940  1.1.2.2  skrll 
    941  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_ANACLKCTRL_CLR, HW_AUDIOOUT_ANACLKCTRL_CLKGATE);
    942  1.1.2.2  skrll 	while ((AO_RD(sc, HW_AUDIOOUT_ANACLKCTRL) &
    943  1.1.2.2  skrll 	    HW_AUDIOOUT_ANACLKCTRL_CLKGATE));
    944  1.1.2.2  skrll 
    945  1.1.2.2  skrll 	/* Hold headphones outputs at ground. */
    946  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND);
    947  1.1.2.2  skrll 
    948  1.1.2.2  skrll 	/* Remove pulldown resistors on headphone outputs. */
    949  1.1.2.2  skrll 	rtc_release_gnd(1);
    950  1.1.2.2  skrll 
    951  1.1.2.2  skrll 	/* Release pull down */
    952  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_ANACTRL_CLR, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND);
    953  1.1.2.2  skrll 
    954  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_CLASSAB);
    955  1.1.2.2  skrll 
    956  1.1.2.2  skrll 	/* Enable Modules. */
    957  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_PWRDN_CLR,
    958  1.1.2.2  skrll 	    HW_AUDIOOUT_PWRDN_RIGHT_ADC |
    959  1.1.2.2  skrll 	    HW_AUDIOOUT_PWRDN_DAC |
    960  1.1.2.2  skrll 	    HW_AUDIOOUT_PWRDN_CAPLESS |
    961  1.1.2.2  skrll 	    HW_AUDIOOUT_PWRDN_HEADPHONE
    962  1.1.2.2  skrll 	);
    963  1.1.2.2  skrll 
    964  1.1.2.2  skrll 	return;
    965  1.1.2.2  skrll }
    966  1.1.2.2  skrll 
    967  1.1.2.2  skrll /*
    968  1.1.2.2  skrll  * Reset the AUDIOOUT block.
    969  1.1.2.2  skrll  *
    970  1.1.2.2  skrll  * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
    971  1.1.2.2  skrll  */
    972  1.1.2.2  skrll static void
    973  1.1.2.2  skrll digfilt_ao_reset(struct digfilt_softc *sc)
    974  1.1.2.2  skrll {
    975  1.1.2.2  skrll 	unsigned int loop;
    976  1.1.2.2  skrll 
    977  1.1.2.2  skrll 	/* Prepare for soft-reset by making sure that SFTRST is not currently
    978  1.1.2.2  skrll 	* asserted. Also clear CLKGATE so we can wait for its assertion below.
    979  1.1.2.2  skrll 	*/
    980  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST);
    981  1.1.2.2  skrll 
    982  1.1.2.2  skrll 	/* Wait at least a microsecond for SFTRST to deassert. */
    983  1.1.2.2  skrll 	loop = 0;
    984  1.1.2.2  skrll 	while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) ||
    985  1.1.2.2  skrll 	    (loop < DIGFILT_SOFT_RST_LOOP))
    986  1.1.2.2  skrll 		loop++;
    987  1.1.2.2  skrll 
    988  1.1.2.2  skrll 	/* Clear CLKGATE so we can wait for its assertion below. */
    989  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE);
    990  1.1.2.2  skrll 
    991  1.1.2.2  skrll 	/* Soft-reset the block. */
    992  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_SET, HW_AUDIOOUT_CTRL_SFTRST);
    993  1.1.2.2  skrll 
    994  1.1.2.2  skrll 	/* Wait until clock is in the gated state. */
    995  1.1.2.2  skrll 	while (!(AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE));
    996  1.1.2.2  skrll 
    997  1.1.2.2  skrll 	/* Bring block out of reset. */
    998  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST);
    999  1.1.2.2  skrll 
   1000  1.1.2.2  skrll 	loop = 0;
   1001  1.1.2.2  skrll 	while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) ||
   1002  1.1.2.2  skrll 	    (loop < DIGFILT_SOFT_RST_LOOP))
   1003  1.1.2.2  skrll 		loop++;
   1004  1.1.2.2  skrll 
   1005  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE);
   1006  1.1.2.2  skrll 
   1007  1.1.2.2  skrll 	/* Wait until clock is in the NON-gated state. */
   1008  1.1.2.2  skrll 	while (AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE);
   1009  1.1.2.2  skrll 
   1010  1.1.2.2  skrll 	return;
   1011  1.1.2.2  skrll }
   1012  1.1.2.2  skrll 
   1013  1.1.2.2  skrll static void
   1014  1.1.2.2  skrll digfilt_ao_set_rate(struct digfilt_softc *sc, int sr)
   1015  1.1.2.2  skrll {
   1016  1.1.2.2  skrll 	uint32_t val;
   1017  1.1.2.2  skrll 
   1018  1.1.2.2  skrll 
   1019  1.1.2.2  skrll 	val = AO_RD(sc, HW_AUDIOOUT_DACSRR);
   1020  1.1.2.2  skrll 
   1021  1.1.2.2  skrll 
   1022  1.1.2.2  skrll 	val &= ~(HW_AUDIOOUT_DACSRR_BASEMULT | HW_AUDIOOUT_DACSRR_SRC_HOLD |
   1023  1.1.2.2  skrll 	    HW_AUDIOOUT_DACSRR_SRC_INT | HW_AUDIOOUT_DACSRR_SRC_FRAC);
   1024  1.1.2.2  skrll 
   1025  1.1.2.2  skrll 	switch(sr) {
   1026  1.1.2.2  skrll 	case 8000:
   1027  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1028  1.1.2.2  skrll 		    __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1029  1.1.2.2  skrll 		    __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1030  1.1.2.2  skrll 		    __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1031  1.1.2.2  skrll 		break;
   1032  1.1.2.2  skrll 	case 11025:
   1033  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1034  1.1.2.2  skrll 		    __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1035  1.1.2.2  skrll 		    __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1036  1.1.2.2  skrll 		    __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1037  1.1.2.2  skrll 		break;
   1038  1.1.2.2  skrll 	case 12000:
   1039  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1040  1.1.2.2  skrll 		    __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1041  1.1.2.2  skrll 		    __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1042  1.1.2.2  skrll 		    __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1043  1.1.2.2  skrll 		break;
   1044  1.1.2.2  skrll 	case 16000:
   1045  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1046  1.1.2.2  skrll 		    __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1047  1.1.2.2  skrll 		    __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1048  1.1.2.2  skrll 		    __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1049  1.1.2.2  skrll 		break;
   1050  1.1.2.2  skrll 	case 22050:
   1051  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1052  1.1.2.2  skrll 		    __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1053  1.1.2.2  skrll 		    __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1054  1.1.2.2  skrll 		    __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1055  1.1.2.2  skrll 		break;
   1056  1.1.2.2  skrll 	case 24000:
   1057  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1058  1.1.2.2  skrll 		    __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1059  1.1.2.2  skrll 		    __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1060  1.1.2.2  skrll 		    __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1061  1.1.2.2  skrll 		break;
   1062  1.1.2.2  skrll 	case 32000:
   1063  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1064  1.1.2.2  skrll 		    __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1065  1.1.2.2  skrll 		    __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1066  1.1.2.2  skrll 		    __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1067  1.1.2.2  skrll 		break;
   1068  1.1.2.2  skrll 	default:
   1069  1.1.2.2  skrll 		aprint_error_dev(sc->sc_dev, "uknown sample rate: %d\n", sr);
   1070  1.1.2.2  skrll 	case 44100:
   1071  1.1.2.2  skrll 		val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
   1072  1.1.2.2  skrll 		    __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
   1073  1.1.2.2  skrll 		    __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
   1074  1.1.2.2  skrll 		    __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
   1075  1.1.2.2  skrll 		break;
   1076  1.1.2.2  skrll 	}
   1077  1.1.2.2  skrll 
   1078  1.1.2.2  skrll 	AO_WR(sc, HW_AUDIOOUT_DACSRR, val);
   1079  1.1.2.2  skrll 
   1080  1.1.2.2  skrll 	val = AO_RD(sc, HW_AUDIOOUT_DACSRR);
   1081  1.1.2.2  skrll 
   1082  1.1.2.2  skrll 	return;
   1083  1.1.2.2  skrll }
   1084  1.1.2.2  skrll #if 0
   1085  1.1.2.2  skrll /*
   1086  1.1.2.2  skrll  * Reset the AUDIOIN block.
   1087  1.1.2.2  skrll  *
   1088  1.1.2.2  skrll  * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
   1089  1.1.2.2  skrll  */
   1090  1.1.2.2  skrll static void
   1091  1.1.2.2  skrll digfilt_ai_reset(struct digfilt_softc *sc)
   1092  1.1.2.2  skrll {
   1093  1.1.2.2  skrll 	unsigned int loop;
   1094  1.1.2.2  skrll 
   1095  1.1.2.2  skrll 	/* Prepare for soft-reset by making sure that SFTRST is not currently
   1096  1.1.2.2  skrll 	* asserted. Also clear CLKGATE so we can wait for its assertion below.
   1097  1.1.2.2  skrll 	*/
   1098  1.1.2.2  skrll 	AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST);
   1099  1.1.2.2  skrll 
   1100  1.1.2.2  skrll 	/* Wait at least a microsecond for SFTRST to deassert. */
   1101  1.1.2.2  skrll 	loop = 0;
   1102  1.1.2.2  skrll 	while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) ||
   1103  1.1.2.2  skrll 	    (loop < DIGFILT_SOFT_RST_LOOP))
   1104  1.1.2.2  skrll 		loop++;
   1105  1.1.2.2  skrll 
   1106  1.1.2.2  skrll 	/* Clear CLKGATE so we can wait for its assertion below. */
   1107  1.1.2.2  skrll 	AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE);
   1108  1.1.2.2  skrll 
   1109  1.1.2.2  skrll 	/* Soft-reset the block. */
   1110  1.1.2.2  skrll 	AI_WR(sc, HW_AUDIOIN_CTRL_SET, HW_AUDIOIN_CTRL_SFTRST);
   1111  1.1.2.2  skrll 
   1112  1.1.2.2  skrll 	/* Wait until clock is in the gated state. */
   1113  1.1.2.2  skrll 	while (!(AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE));
   1114  1.1.2.2  skrll 
   1115  1.1.2.2  skrll 	/* Bring block out of reset. */
   1116  1.1.2.2  skrll 	AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST);
   1117  1.1.2.2  skrll 
   1118  1.1.2.2  skrll 	loop = 0;
   1119  1.1.2.2  skrll 	while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) ||
   1120  1.1.2.2  skrll 	    (loop < DIGFILT_SOFT_RST_LOOP))
   1121  1.1.2.2  skrll 		loop++;
   1122  1.1.2.2  skrll 
   1123  1.1.2.2  skrll 	AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE);
   1124  1.1.2.2  skrll 
   1125  1.1.2.2  skrll 	/* Wait until clock is in the NON-gated state. */
   1126  1.1.2.2  skrll 	while (AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE);
   1127  1.1.2.2  skrll 
   1128  1.1.2.2  skrll 	return;
   1129  1.1.2.2  skrll }
   1130  1.1.2.2  skrll #endif
   1131