Home | History | Annotate | Line # | Download | only in sbus
dbri.c revision 1.41.2.1
      1  1.41.2.1    martin /*	$NetBSD: dbri.c,v 1.41.2.1 2020/03/21 15:31:51 martin Exp $	*/
      2       1.1  macallan 
      3       1.1  macallan /*
      4       1.2  macallan  * Copyright (C) 1997 Rudolf Koenig (rfkoenig (at) immd4.informatik.uni-erlangen.de)
      5       1.2  macallan  * Copyright (c) 1998, 1999 Brent Baccala (baccala (at) freesoft.org)
      6       1.2  macallan  * Copyright (c) 2001, 2002 Jared D. McNeill <jmcneill (at) netbsd.org>
      7      1.19  macallan  * Copyright (c) 2005 Michael Lorenz <macallan (at) netbsd.org>
      8       1.1  macallan  * All rights reserved.
      9       1.1  macallan  *
     10      1.19  macallan  * This driver is losely based on a Linux driver written by Rudolf Koenig and
     11      1.19  macallan  * Brent Baccala who kindly gave their permission to use their code in a
     12       1.2  macallan  * BSD-licensed driver.
     13       1.2  macallan  *
     14       1.1  macallan  * Redistribution and use in source and binary forms, with or without
     15       1.1  macallan  * modification, are permitted provided that the following conditions
     16       1.1  macallan  * are met:
     17       1.1  macallan  * 1. Redistributions of source code must retain the above copyright
     18       1.1  macallan  *    notice, this list of conditions and the following disclaimer.
     19       1.1  macallan  * 2. Redistributions in binary form must reproduce the above copyright
     20       1.1  macallan  *    notice, this list of conditions and the following disclaimer in the
     21       1.1  macallan  *    documentation and/or other materials provided with the distribution.
     22       1.1  macallan  *
     23      1.19  macallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
     24      1.19  macallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25      1.19  macallan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26      1.19  macallan  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     27      1.19  macallan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     28      1.19  macallan  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
     29      1.19  macallan  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30      1.19  macallan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31      1.19  macallan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32      1.19  macallan  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33       1.1  macallan  *
     34       1.1  macallan  */
     35       1.1  macallan 
     36       1.1  macallan #include <sys/cdefs.h>
     37  1.41.2.1    martin __KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.41.2.1 2020/03/21 15:31:51 martin Exp $");
     38       1.1  macallan 
     39       1.1  macallan #include "audio.h"
     40       1.1  macallan #if NAUDIO > 0
     41       1.1  macallan 
     42       1.1  macallan #include <sys/param.h>
     43       1.1  macallan #include <sys/systm.h>
     44       1.1  macallan #include <sys/errno.h>
     45       1.1  macallan #include <sys/device.h>
     46       1.1  macallan #include <sys/proc.h>
     47      1.15  macallan #include <sys/kernel.h>
     48      1.16        ad #include <sys/bus.h>
     49      1.16        ad #include <sys/intr.h>
     50      1.34  jmcneill #include <sys/kmem.h>
     51       1.1  macallan 
     52       1.1  macallan #include <dev/sbus/sbusvar.h>
     53       1.1  macallan #include <sparc/sparc/auxreg.h>
     54       1.1  macallan #include <machine/autoconf.h>
     55       1.1  macallan 
     56       1.1  macallan #include <sys/audioio.h>
     57      1.40     isaki #include <dev/audio/audio_if.h>
     58       1.1  macallan 
     59       1.1  macallan #include <dev/ic/cs4215reg.h>
     60       1.1  macallan #include <dev/ic/cs4215var.h>
     61       1.1  macallan #include <dev/sbus/dbrireg.h>
     62       1.1  macallan #include <dev/sbus/dbrivar.h>
     63       1.1  macallan 
     64       1.4  macallan #include "opt_sbus_dbri.h"
     65       1.4  macallan 
     66       1.1  macallan #define DBRI_ROM_NAME_PREFIX		"SUNW,DBRI"
     67       1.1  macallan 
     68       1.4  macallan #ifdef DBRI_DEBUG
     69      1.11  macallan # define DPRINTF aprint_normal
     70       1.4  macallan #else
     71      1.10  macallan # define DPRINTF while (0) printf
     72       1.4  macallan #endif
     73       1.1  macallan 
     74       1.1  macallan static const char *dbri_supported[] = {
     75       1.1  macallan 	"e",
     76       1.1  macallan 	"s3",
     77       1.1  macallan 	""
     78       1.1  macallan };
     79       1.1  macallan 
     80       1.1  macallan enum ms {
     81       1.1  macallan 	CHImaster,
     82       1.1  macallan 	CHIslave
     83       1.1  macallan };
     84       1.1  macallan 
     85       1.1  macallan enum io {
     86       1.1  macallan 	PIPEinput,
     87       1.1  macallan 	PIPEoutput
     88       1.1  macallan };
     89       1.1  macallan 
     90       1.1  macallan /*
     91       1.1  macallan  * Function prototypes
     92       1.1  macallan  */
     93       1.1  macallan 
     94       1.1  macallan /* softc stuff */
     95      1.20  macallan static void	dbri_attach_sbus(device_t, device_t, void *);
     96      1.22    cegger static int	dbri_match_sbus(device_t, cfdata_t, void *);
     97       1.1  macallan 
     98      1.32  macallan static int	dbri_config_interrupts(device_t);
     99       1.1  macallan 
    100       1.1  macallan /* interrupt handler */
    101       1.1  macallan static int	dbri_intr(void *);
    102      1.17        ad static void	dbri_softint(void *);
    103       1.1  macallan 
    104       1.1  macallan /* supporting subroutines */
    105       1.1  macallan static int	dbri_init(struct dbri_softc *);
    106       1.1  macallan static int	dbri_reset(struct dbri_softc *);
    107      1.25   tsutsui static volatile uint32_t *dbri_command_lock(struct dbri_softc *);
    108      1.25   tsutsui static void	dbri_command_send(struct dbri_softc *, volatile uint32_t *);
    109       1.1  macallan static void	dbri_process_interrupt_buffer(struct dbri_softc *);
    110       1.1  macallan static void	dbri_process_interrupt(struct dbri_softc *, int32_t);
    111       1.1  macallan 
    112       1.1  macallan /* mmcodec subroutines */
    113       1.1  macallan static int	mmcodec_init(struct dbri_softc *);
    114       1.1  macallan static void	mmcodec_init_data(struct dbri_softc *);
    115       1.1  macallan static void	mmcodec_pipe_init(struct dbri_softc *);
    116       1.1  macallan static void	mmcodec_default(struct dbri_softc *);
    117       1.1  macallan static void	mmcodec_setgain(struct dbri_softc *, int);
    118       1.1  macallan static int	mmcodec_setcontrol(struct dbri_softc *);
    119       1.1  macallan 
    120       1.1  macallan /* chi subroutines */
    121       1.1  macallan static void	chi_reset(struct dbri_softc *, enum ms, int);
    122       1.1  macallan 
    123       1.1  macallan /* pipe subroutines */
    124       1.1  macallan static void	pipe_setup(struct dbri_softc *, int, int);
    125       1.1  macallan static void	pipe_reset(struct dbri_softc *, int);
    126       1.5     blymn static void	pipe_receive_fixed(struct dbri_softc *, int,
    127      1.25   tsutsui     volatile uint32_t *);
    128      1.25   tsutsui static void	pipe_transmit_fixed(struct dbri_softc *, int, uint32_t);
    129       1.1  macallan 
    130       1.1  macallan static void	pipe_ts_link(struct dbri_softc *, int, enum io, int, int, int);
    131       1.1  macallan static int	pipe_active(struct dbri_softc *, int);
    132       1.1  macallan 
    133       1.1  macallan /* audio(9) stuff */
    134      1.40     isaki static int	dbri_query_format(void *, audio_format_query_t *);
    135      1.40     isaki static int	dbri_set_format(void *, int,
    136      1.40     isaki     const audio_params_t *, const audio_params_t *,
    137      1.40     isaki     audio_filter_reg_t *, audio_filter_reg_t *);
    138       1.1  macallan static int	dbri_round_blocksize(void *, int, int, const audio_params_t *);
    139       1.1  macallan static int	dbri_halt_output(void *);
    140      1.13  macallan static int	dbri_halt_input(void *);
    141       1.1  macallan static int	dbri_getdev(void *, struct audio_device *);
    142       1.1  macallan static int	dbri_set_port(void *, mixer_ctrl_t *);
    143       1.1  macallan static int	dbri_get_port(void *, mixer_ctrl_t *);
    144       1.1  macallan static int	dbri_query_devinfo(void *, mixer_devinfo_t *);
    145       1.1  macallan static int	dbri_get_props(void *);
    146       1.4  macallan static int	dbri_open(void *, int);
    147       1.4  macallan static void	dbri_close(void *);
    148       1.1  macallan 
    149      1.14  macallan static void	setup_ring_xmit(struct dbri_softc *, int, int, int, int,
    150      1.14  macallan     void (*)(void *), void *);
    151      1.14  macallan static void	setup_ring_recv(struct dbri_softc *, int, int, int, int,
    152      1.11  macallan     void (*)(void *), void *);
    153       1.1  macallan 
    154       1.5     blymn static int	dbri_trigger_output(void *, void *, void *, int,
    155       1.1  macallan     void (*)(void *), void *, const struct audio_params *);
    156      1.13  macallan static int	dbri_trigger_input(void *, void *, void *, int,
    157      1.13  macallan     void (*)(void *), void *, const struct audio_params *);
    158      1.34  jmcneill static void	dbri_get_locks(void *, kmutex_t **, kmutex_t **);
    159       1.1  macallan 
    160      1.34  jmcneill static void	*dbri_malloc(void *, int, size_t);
    161      1.34  jmcneill static void	dbri_free(void *, void *, size_t);
    162       1.4  macallan static void	dbri_set_power(struct dbri_softc *, int);
    163       1.4  macallan static void	dbri_bring_up(struct dbri_softc *);
    164      1.31    dyoung static bool	dbri_suspend(device_t, const pmf_qual_t *);
    165      1.31    dyoung static bool	dbri_resume(device_t, const pmf_qual_t *);
    166      1.37  macallan static int	dbri_commit(void *);
    167       1.1  macallan 
    168       1.1  macallan /* stupid support routines */
    169      1.25   tsutsui static uint32_t	reverse_bytes(uint32_t, int);
    170       1.1  macallan 
    171       1.1  macallan struct audio_device dbri_device = {
    172       1.1  macallan 	"CS4215",
    173       1.1  macallan 	"",
    174       1.1  macallan 	"dbri"
    175       1.1  macallan };
    176       1.1  macallan 
    177       1.1  macallan struct audio_hw_if dbri_hw_if = {
    178      1.34  jmcneill 	.open			= dbri_open,
    179      1.34  jmcneill 	.close			= dbri_close,
    180      1.40     isaki 	.query_format		= dbri_query_format,
    181      1.40     isaki 	.set_format		= dbri_set_format,
    182      1.34  jmcneill 	.round_blocksize	= dbri_round_blocksize,
    183      1.34  jmcneill 	.halt_output		= dbri_halt_output,
    184      1.34  jmcneill 	.halt_input		= dbri_halt_input,
    185      1.34  jmcneill 	.getdev			= dbri_getdev,
    186      1.34  jmcneill 	.set_port		= dbri_set_port,
    187      1.34  jmcneill 	.get_port		= dbri_get_port,
    188      1.34  jmcneill 	.query_devinfo		= dbri_query_devinfo,
    189      1.34  jmcneill 	.allocm			= dbri_malloc,
    190      1.34  jmcneill 	.freem			= dbri_free,
    191      1.34  jmcneill 	.get_props		= dbri_get_props,
    192      1.34  jmcneill 	.trigger_output		= dbri_trigger_output,
    193      1.34  jmcneill 	.trigger_input		= dbri_trigger_input,
    194      1.34  jmcneill 	.get_locks		= dbri_get_locks,
    195      1.37  macallan 	.commit_settings	= dbri_commit,
    196       1.1  macallan };
    197       1.1  macallan 
    198      1.20  macallan CFATTACH_DECL_NEW(dbri, sizeof(struct dbri_softc),
    199       1.1  macallan     dbri_match_sbus, dbri_attach_sbus, NULL, NULL);
    200       1.1  macallan 
    201      1.40     isaki /* The HW actually supports more encodings/frequencies, but it's enough. */
    202      1.40     isaki static const struct audio_format dbri_formats[] = {
    203      1.40     isaki 	{
    204      1.40     isaki 		.mode		= AUMODE_PLAY | AUMODE_RECORD,
    205      1.40     isaki 		.encoding	= AUDIO_ENCODING_SLINEAR_BE,
    206      1.40     isaki 		.validbits	= 16,
    207      1.40     isaki 		.precision	= 16,
    208      1.40     isaki 		.channels	= 2,
    209      1.40     isaki 		.channel_mask	= AUFMT_STEREO,
    210      1.40     isaki 		.frequency_type	= 8,
    211      1.40     isaki 		.frequency	=
    212      1.40     isaki 		    { 8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000 },
    213      1.40     isaki 	},
    214      1.11  macallan };
    215      1.40     isaki #define DBRI_NFORMATS	__arraycount(dbri_formats)
    216      1.11  macallan 
    217       1.1  macallan enum {
    218      1.13  macallan 	DBRI_OUTPUT_CLASS,
    219       1.1  macallan 	DBRI_VOL_OUTPUT,
    220       1.1  macallan 	DBRI_ENABLE_MONO,
    221       1.1  macallan 	DBRI_ENABLE_HEADPHONE,
    222      1.13  macallan 	DBRI_ENABLE_LINE,
    223      1.13  macallan 	DBRI_MONITOR_CLASS,
    224      1.13  macallan 	DBRI_VOL_MONITOR,
    225       1.1  macallan 	DBRI_INPUT_CLASS,
    226       1.1  macallan 	DBRI_INPUT_GAIN,
    227       1.1  macallan 	DBRI_INPUT_SELECT,
    228      1.13  macallan 	DBRI_RECORD_CLASS,
    229       1.1  macallan 	DBRI_ENUM_LAST
    230       1.1  macallan };
    231       1.1  macallan 
    232       1.1  macallan /*
    233       1.1  macallan  * Autoconfig routines
    234       1.1  macallan  */
    235      1.11  macallan static int
    236      1.22    cegger dbri_match_sbus(device_t parent, cfdata_t match, void *aux)
    237       1.1  macallan {
    238       1.1  macallan 	struct sbus_attach_args *sa = aux;
    239       1.1  macallan 	char *ver;
    240       1.1  macallan 	int i;
    241       1.1  macallan 
    242       1.1  macallan 	if (strncmp(DBRI_ROM_NAME_PREFIX, sa->sa_name, 9))
    243       1.1  macallan 		return (0);
    244       1.1  macallan 
    245       1.1  macallan 	ver = &sa->sa_name[9];
    246       1.1  macallan 
    247       1.1  macallan 	for (i = 0; dbri_supported[i][0] != '\0'; i++)
    248       1.1  macallan 		if (strcmp(dbri_supported[i], ver) == 0)
    249       1.1  macallan 			return (1);
    250       1.1  macallan 
    251       1.1  macallan 	return (0);
    252       1.1  macallan }
    253       1.1  macallan 
    254      1.11  macallan static void
    255      1.20  macallan dbri_attach_sbus(device_t parent, device_t self, void *aux)
    256       1.1  macallan {
    257      1.20  macallan 	struct dbri_softc *sc = device_private(self);
    258       1.1  macallan 	struct sbus_attach_args *sa = aux;
    259       1.1  macallan 	bus_space_handle_t ioh;
    260       1.1  macallan 	bus_size_t size;
    261      1.17        ad 	int error, rseg, pwr, i;
    262       1.1  macallan 	char *ver = &sa->sa_name[9];
    263       1.1  macallan 
    264      1.20  macallan 	sc->sc_dev = self;
    265       1.1  macallan 	sc->sc_iot = sa->sa_bustag;
    266       1.1  macallan 	sc->sc_dmat = sa->sa_dmatag;
    267      1.15  macallan 	sc->sc_powerstate = 1;
    268       1.5     blymn 
    269      1.37  macallan 	sc->sc_whack_codec = 0;
    270      1.37  macallan 
    271       1.4  macallan 	pwr = prom_getpropint(sa->sa_node,"pwr-on-auxio",0);
    272      1.13  macallan 	aprint_normal(": rev %s\n", ver);
    273      1.10  macallan 
    274      1.12  macallan 	if (pwr) {
    275       1.5     blymn 		/*
    276       1.4  macallan 		 * we can control DBRI power via auxio and we're initially
    277       1.4  macallan 		 * powered down
    278       1.4  macallan 		 */
    279       1.5     blymn 
    280       1.4  macallan 		sc->sc_have_powerctl = 1;
    281       1.4  macallan 		sc->sc_powerstate = 0;
    282       1.4  macallan 		dbri_set_power(sc, 1);
    283      1.26  christos 		if (!pmf_device_register(self, dbri_suspend, dbri_resume)) {
    284      1.26  christos 			aprint_error_dev(self,
    285      1.26  christos 			    "cannot set power mgmt handler\n");
    286      1.26  christos 		}
    287       1.4  macallan 	} else {
    288       1.4  macallan 		/* we can't control power so we're always up */
    289       1.4  macallan 		sc->sc_have_powerctl = 0;
    290       1.4  macallan 		sc->sc_powerstate = 1;
    291       1.4  macallan 	}
    292       1.5     blymn 
    293      1.17        ad 	for (i = 0; i < DBRI_NUM_DESCRIPTORS; i++) {
    294      1.17        ad 		sc->sc_desc[i].softint = softint_establish(SOFTINT_SERIAL,
    295      1.17        ad 		    dbri_softint, &sc->sc_desc[i]);
    296      1.40     isaki 		sc->sc_desc[i].sc = sc;
    297      1.17        ad 	}
    298      1.17        ad 
    299       1.1  macallan 	if (sa->sa_npromvaddrs)
    300       1.1  macallan 		ioh = (bus_space_handle_t)sa->sa_promvaddrs[0];
    301       1.1  macallan 	else {
    302       1.1  macallan 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
    303       1.1  macallan 				 sa->sa_offset, sa->sa_size,
    304       1.1  macallan 				 BUS_SPACE_MAP_LINEAR, /*0,*/ &ioh) != 0) {
    305      1.10  macallan 			aprint_error("%s @ sbus: cannot map registers\n",
    306      1.18    cegger 				device_xname(self));
    307       1.1  macallan 			return;
    308       1.1  macallan 		}
    309       1.1  macallan 	}
    310       1.1  macallan 
    311       1.1  macallan 	sc->sc_ioh = ioh;
    312       1.1  macallan 
    313       1.1  macallan 	size = sizeof(struct dbri_dma);
    314       1.1  macallan 
    315       1.1  macallan 	/* get a DMA handle */
    316       1.1  macallan 	if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    317       1.1  macallan 				       BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
    318      1.18    cegger 		aprint_error_dev(self, "DMA map create error %d\n",
    319      1.14  macallan 		    error);
    320       1.1  macallan 		return;
    321       1.1  macallan 	}
    322       1.1  macallan 
    323       1.1  macallan 	/* allocate DMA buffer */
    324       1.1  macallan 	if ((error = bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_dmaseg,
    325       1.1  macallan 				      1, &rseg, BUS_DMA_NOWAIT)) != 0) {
    326      1.18    cegger 		aprint_error_dev(self, "DMA buffer alloc error %d\n",
    327      1.18    cegger 		    error);
    328       1.1  macallan 		return;
    329       1.1  macallan 	}
    330       1.1  macallan 
    331       1.1  macallan 	/* map DMA buffer into CPU addressable space */
    332       1.1  macallan 	if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dmaseg, rseg, size,
    333       1.1  macallan 				    &sc->sc_membase,
    334       1.1  macallan 				    BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
    335      1.18    cegger 		aprint_error_dev(self, "DMA buffer map error %d\n",
    336      1.18    cegger 		    error);
    337       1.1  macallan 		return;
    338       1.1  macallan 	}
    339       1.1  macallan 
    340       1.1  macallan 	/* load the buffer */
    341       1.1  macallan 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
    342       1.1  macallan 				     sc->sc_membase, size, NULL,
    343       1.1  macallan 				     BUS_DMA_NOWAIT)) != 0) {
    344      1.18    cegger 		aprint_error_dev(self, "DMA buffer map load error %d\n",
    345      1.18    cegger 		    error);
    346       1.1  macallan 		bus_dmamem_unmap(sc->sc_dmat, sc->sc_membase, size);
    347       1.1  macallan 		bus_dmamem_free(sc->sc_dmat, &sc->sc_dmaseg, rseg);
    348       1.1  macallan 		return;
    349       1.1  macallan 	}
    350       1.1  macallan 
    351       1.1  macallan 	/* map the registers into memory */
    352       1.1  macallan 
    353       1.9  macallan 	/* kernel virtual address of DMA buffer */
    354       1.9  macallan 	sc->sc_dma = (struct dbri_dma *)sc->sc_membase;
    355       1.9  macallan 	/* physical address of DMA buffer */
    356       1.9  macallan 	sc->sc_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
    357       1.1  macallan 	sc->sc_bufsiz = size;
    358       1.1  macallan 
    359      1.34  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    360      1.37  macallan 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    361      1.34  jmcneill 
    362      1.36       mrg #ifndef DBRI_SPIN
    363      1.36       mrg 	cv_init(&sc->sc_cv, "dbricv");
    364      1.36       mrg #endif
    365      1.36       mrg 
    366      1.37  macallan 	bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, dbri_intr,
    367      1.12  macallan 	    sc);
    368       1.1  macallan 
    369       1.1  macallan 	sc->sc_locked = 0;
    370       1.1  macallan 	sc->sc_desc_used = 0;
    371      1.14  macallan 	sc->sc_refcount = 0;
    372      1.13  macallan 	sc->sc_playing = 0;
    373      1.14  macallan 	sc->sc_recording = 0;
    374      1.32  macallan 	sc->sc_init_done = 0;
    375      1.32  macallan 	config_finalize_register(self, &dbri_config_interrupts);
    376       1.1  macallan 
    377       1.1  macallan 	return;
    378       1.1  macallan }
    379       1.1  macallan 
    380       1.4  macallan /*
    381       1.4  macallan  * lowlevel routine to switch power for the DBRI chip
    382       1.4  macallan  */
    383       1.4  macallan static void
    384       1.4  macallan dbri_set_power(struct dbri_softc *sc, int state)
    385       1.4  macallan {
    386       1.4  macallan 	int s;
    387       1.5     blymn 
    388       1.4  macallan 	if (sc->sc_have_powerctl == 0)
    389       1.4  macallan 		return;
    390       1.4  macallan 	if (sc->sc_powerstate == state)
    391       1.4  macallan 		return;
    392       1.5     blymn 
    393       1.4  macallan 	if (state) {
    394      1.20  macallan 		DPRINTF("%s: waiting to power up... ",
    395      1.20  macallan 		    device_xname(sc->sc_dev));
    396       1.4  macallan 		s = splhigh();
    397       1.4  macallan 		*AUXIO4M_REG |= (AUXIO4M_MMX);
    398       1.4  macallan 		splx(s);
    399       1.9  macallan 		delay(10000);
    400      1.13  macallan 		DPRINTF("done (%02x)\n", *AUXIO4M_REG);
    401       1.4  macallan 	} else {
    402      1.20  macallan 		DPRINTF("%s: powering down\n", device_xname(sc->sc_dev));
    403       1.4  macallan 		s = splhigh();
    404       1.4  macallan 		*AUXIO4M_REG &= ~AUXIO4M_MMX;
    405       1.4  macallan 		splx(s);
    406      1.10  macallan 		DPRINTF("done (%02x})\n", *AUXIO4M_REG);
    407       1.4  macallan 	}
    408       1.4  macallan 	sc->sc_powerstate = state;
    409       1.4  macallan }
    410       1.4  macallan 
    411       1.4  macallan /*
    412       1.4  macallan  * power up and re-initialize the chip
    413       1.4  macallan  */
    414       1.4  macallan static void
    415       1.4  macallan dbri_bring_up(struct dbri_softc *sc)
    416       1.4  macallan {
    417       1.4  macallan 
    418       1.4  macallan 	if (sc->sc_have_powerctl == 0)
    419       1.4  macallan 		return;
    420      1.15  macallan 
    421       1.4  macallan 	if (sc->sc_powerstate == 1)
    422       1.4  macallan 		return;
    423       1.5     blymn 
    424       1.4  macallan 	/* ok, we really need to do something */
    425       1.4  macallan 	dbri_set_power(sc, 1);
    426       1.4  macallan 
    427       1.4  macallan 	/*
    428       1.4  macallan 	 * re-initialize the chip but skip all the probing, don't overwrite
    429       1.4  macallan 	 * any other settings either
    430       1.4  macallan 	 */
    431       1.4  macallan 	dbri_init(sc);
    432       1.4  macallan 	mmcodec_setgain(sc, 1);
    433       1.4  macallan 	mmcodec_pipe_init(sc);
    434       1.4  macallan 	mmcodec_init_data(sc);
    435       1.4  macallan 	mmcodec_setgain(sc, 0);
    436       1.4  macallan }
    437       1.4  macallan 
    438      1.32  macallan static int
    439      1.20  macallan dbri_config_interrupts(device_t dev)
    440       1.1  macallan {
    441      1.20  macallan 	struct dbri_softc *sc = device_private(dev);
    442       1.9  macallan 
    443      1.36       mrg 	mutex_spin_enter(&sc->sc_intr_lock);
    444      1.36       mrg 	if (sc->sc_init_done != 0) {
    445      1.36       mrg 		mutex_spin_exit(&sc->sc_intr_lock);
    446      1.32  macallan 		return 0;
    447      1.36       mrg 	}
    448      1.32  macallan 	sc->sc_init_done = 1;
    449      1.32  macallan 
    450       1.1  macallan 	dbri_init(sc);
    451      1.37  macallan 
    452      1.37  macallan 	/* talking to the codec needs working interrupts */
    453      1.30  macallan 	if (mmcodec_init(sc) == -1) {
    454      1.38       mrg 		mutex_spin_exit(&sc->sc_intr_lock);
    455      1.30  macallan 		printf("%s: no codec detected, aborting\n",
    456      1.30  macallan 		    device_xname(dev));
    457      1.32  macallan 		return 0;
    458      1.30  macallan 	}
    459      1.38       mrg 	mutex_spin_exit(&sc->sc_intr_lock);
    460      1.30  macallan 
    461       1.1  macallan 	/* Attach ourselves to the high level audio interface */
    462      1.20  macallan 	audio_attach_mi(&dbri_hw_if, sc, sc->sc_dev);
    463       1.5     blymn 
    464       1.4  macallan 	/* power down until open() */
    465      1.36       mrg 	mutex_spin_enter(&sc->sc_intr_lock);
    466       1.4  macallan 	dbri_set_power(sc, 0);
    467      1.36       mrg 	mutex_spin_exit(&sc->sc_intr_lock);
    468      1.36       mrg 
    469      1.32  macallan 	return 0;
    470       1.1  macallan }
    471       1.1  macallan 
    472      1.11  macallan static int
    473       1.1  macallan dbri_intr(void *hdl)
    474       1.1  macallan {
    475       1.1  macallan 	struct dbri_softc *sc = hdl;
    476       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    477       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    478       1.1  macallan 	int x;
    479       1.1  macallan 
    480      1.34  jmcneill 	mutex_spin_enter(&sc->sc_intr_lock);
    481      1.34  jmcneill 
    482       1.1  macallan 	/* clear interrupt */
    483       1.1  macallan 	x = bus_space_read_4(iot, ioh, DBRI_REG1);
    484       1.1  macallan 	if (x & (DBRI_MRR | DBRI_MLE | DBRI_LBG | DBRI_MBE)) {
    485      1.25   tsutsui 		uint32_t tmp;
    486       1.1  macallan 
    487       1.1  macallan 		if (x & DBRI_MRR)
    488      1.20  macallan 			aprint_debug_dev(sc->sc_dev,
    489      1.20  macallan 			     "multiple ack error on sbus\n");
    490       1.1  macallan 		if (x & DBRI_MLE)
    491      1.20  macallan 			aprint_debug_dev(sc->sc_dev,
    492      1.20  macallan 			    "multiple late error on sbus\n");
    493       1.1  macallan 		if (x & DBRI_LBG)
    494      1.20  macallan 			aprint_debug_dev(sc->sc_dev,
    495      1.20  macallan 			    "lost bus grant on sbus\n");
    496       1.1  macallan 		if (x & DBRI_MBE)
    497      1.20  macallan 			aprint_debug_dev(sc->sc_dev, "burst error on sbus\n");
    498       1.1  macallan 
    499       1.1  macallan 		/*
    500       1.1  macallan 		 * Some of these errors disable the chip's circuitry.
    501       1.1  macallan 		 * Re-enable the circuitry and keep on going.
    502       1.1  macallan 		 */
    503       1.1  macallan 
    504       1.1  macallan 		tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
    505       1.1  macallan 		tmp &= ~(DBRI_DISABLE_MASTER);
    506       1.1  macallan 		bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
    507       1.1  macallan 	}
    508       1.1  macallan 
    509       1.1  macallan #if 0
    510       1.1  macallan 	if (!x & 1)	/* XXX: DBRI_INTR_REQ */
    511       1.1  macallan 		return (1);
    512       1.1  macallan #endif
    513       1.1  macallan 
    514       1.1  macallan 	dbri_process_interrupt_buffer(sc);
    515       1.1  macallan 
    516      1.34  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
    517      1.34  jmcneill 
    518       1.1  macallan 	return (1);
    519       1.1  macallan }
    520       1.1  macallan 
    521      1.17        ad static void
    522      1.17        ad dbri_softint(void *cookie)
    523      1.17        ad {
    524      1.17        ad 	struct dbri_desc *dd = cookie;
    525      1.40     isaki 	struct dbri_softc *sc = dd->sc;
    526      1.17        ad 
    527      1.40     isaki 	mutex_spin_enter(&sc->sc_intr_lock);
    528      1.17        ad 	if (dd->callback != NULL)
    529      1.17        ad 		dd->callback(dd->callback_args);
    530      1.40     isaki 	mutex_spin_exit(&sc->sc_intr_lock);
    531      1.17        ad }
    532      1.17        ad 
    533      1.11  macallan static int
    534       1.1  macallan dbri_init(struct dbri_softc *sc)
    535       1.1  macallan {
    536       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    537       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    538      1.25   tsutsui 	uint32_t reg;
    539      1.25   tsutsui 	volatile uint32_t *cmd;
    540       1.1  macallan 	bus_addr_t dmaaddr;
    541       1.1  macallan 	int n;
    542       1.1  macallan 
    543      1.38       mrg 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    544      1.36       mrg 
    545       1.1  macallan 	dbri_reset(sc);
    546      1.37  macallan 	sc->sc_mm.status = 0;
    547       1.1  macallan 
    548       1.1  macallan 	cmd = dbri_command_lock(sc);
    549       1.1  macallan 
    550       1.1  macallan 	/* XXX: Initialize interrupt ring buffer */
    551      1.25   tsutsui 	sc->sc_dma->intr[0] = (uint32_t)sc->sc_dmabase + dbri_dma_off(intr, 0);
    552       1.1  macallan 	sc->sc_irqp = 1;
    553       1.5     blymn 
    554       1.1  macallan 	/* Initialize pipes */
    555       1.1  macallan 	for (n = 0; n < DBRI_PIPE_MAX; n++)
    556       1.1  macallan 		sc->sc_pipe[n].desc = sc->sc_pipe[n].next = -1;
    557       1.5     blymn 
    558      1.12  macallan 	for (n = 1; n < DBRI_INT_BLOCKS; n++) {
    559      1.12  macallan 		sc->sc_dma->intr[n] = 0;
    560       1.1  macallan 	}
    561       1.5     blymn 
    562       1.1  macallan 	/* XXX 16 byte bursts cause errors, the rest works */
    563       1.1  macallan 	reg = bus_space_read_4(iot, ioh, DBRI_REG0);
    564       1.9  macallan 
    565       1.1  macallan 	/*reg &= ~(DBRI_BURST_4 | DBRI_BURST_8 | DBRI_BURST_16);*/
    566       1.1  macallan 	reg |= (DBRI_BURST_4 | DBRI_BURST_8);
    567       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, reg);
    568       1.5     blymn 
    569       1.1  macallan 	/* setup interrupt queue */
    570      1.25   tsutsui 	dmaaddr = (uint32_t)sc->sc_dmabase + dbri_dma_off(intr, 0);
    571       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_IIQ, 0, 0);
    572       1.1  macallan 	*(cmd++) = dmaaddr;
    573       1.5     blymn 
    574       1.1  macallan 	dbri_command_send(sc, cmd);
    575      1.36       mrg 
    576       1.1  macallan 	return (0);
    577       1.1  macallan }
    578       1.1  macallan 
    579      1.11  macallan static int
    580       1.1  macallan dbri_reset(struct dbri_softc *sc)
    581       1.1  macallan {
    582      1.12  macallan 	int bail = 0;
    583      1.12  macallan 
    584       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    585       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    586       1.1  macallan 
    587       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, DBRI_SOFT_RESET);
    588       1.5     blymn 	while ((bus_space_read_4(iot, ioh, DBRI_REG0) & DBRI_SOFT_RESET) &&
    589       1.5     blymn 	    (bail < 100000)) {
    590       1.1  macallan 		bail++;
    591       1.1  macallan 		delay(10);
    592       1.1  macallan 	}
    593      1.18    cegger 	if (bail == 100000)
    594      1.20  macallan 		aprint_error_dev(sc->sc_dev, "reset timed out\n");
    595       1.1  macallan 	return (0);
    596       1.1  macallan }
    597       1.1  macallan 
    598      1.25   tsutsui static volatile uint32_t *
    599       1.1  macallan dbri_command_lock(struct dbri_softc *sc)
    600       1.1  macallan {
    601       1.1  macallan 
    602       1.1  macallan 	if (sc->sc_locked)
    603      1.20  macallan 		aprint_debug_dev(sc->sc_dev, "command buffer locked\n");
    604       1.1  macallan 
    605       1.1  macallan 	sc->sc_locked++;
    606       1.1  macallan 
    607       1.1  macallan 	return (&sc->sc_dma->command[0]);
    608       1.1  macallan }
    609       1.1  macallan 
    610      1.11  macallan static void
    611      1.25   tsutsui dbri_command_send(struct dbri_softc *sc, volatile uint32_t *cmd)
    612       1.1  macallan {
    613       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    614       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    615       1.1  macallan 	int maxloops = 1000000;
    616       1.1  macallan 
    617      1.38       mrg 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    618       1.1  macallan 
    619       1.1  macallan 	sc->sc_locked--;
    620       1.1  macallan 
    621       1.1  macallan 	if (sc->sc_locked != 0) {
    622      1.20  macallan 		aprint_error_dev(sc->sc_dev,
    623      1.20  macallan 		    "command buffer improperly locked\n");
    624       1.1  macallan 	} else if ((cmd - &sc->sc_dma->command[0]) >= DBRI_NUM_COMMANDS - 1) {
    625      1.20  macallan 		aprint_error_dev(sc->sc_dev, "command buffer overflow\n");
    626       1.1  macallan 	} else {
    627       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_PAUSE, 0, 0);
    628       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_WAIT, 1, 0);
    629       1.1  macallan 		sc->sc_waitseen = 0;
    630       1.1  macallan 		bus_space_write_4(iot, ioh, DBRI_REG8, sc->sc_dmabase);
    631       1.1  macallan 		while ((--maxloops) > 0 &&
    632       1.1  macallan 		    (bus_space_read_4(iot, ioh, DBRI_REG0)
    633       1.1  macallan 		     & DBRI_COMMAND_VALID)) {
    634       1.1  macallan 			bus_space_barrier(iot, ioh, DBRI_REG0, 4,
    635       1.1  macallan 					  BUS_SPACE_BARRIER_READ);
    636       1.1  macallan 			delay(1000);
    637       1.1  macallan 		}
    638       1.1  macallan 
    639       1.1  macallan 		if (maxloops == 0) {
    640      1.20  macallan 			aprint_error_dev(sc->sc_dev,
    641      1.18    cegger 			    "chip never completed command buffer\n");
    642       1.1  macallan 		} else {
    643       1.9  macallan 
    644      1.10  macallan 			DPRINTF("%s: command completed\n",
    645      1.20  macallan 			    device_xname(sc->sc_dev));
    646       1.9  macallan 
    647       1.1  macallan 			while ((--maxloops) > 0 && (!sc->sc_waitseen))
    648       1.1  macallan 				dbri_process_interrupt_buffer(sc);
    649       1.1  macallan 			if (maxloops == 0) {
    650      1.20  macallan 				aprint_error_dev(sc->sc_dev, "chip never acked WAIT\n");
    651       1.1  macallan 			}
    652       1.1  macallan 		}
    653       1.1  macallan 	}
    654       1.1  macallan 
    655       1.1  macallan 	return;
    656       1.1  macallan }
    657       1.1  macallan 
    658      1.11  macallan static void
    659       1.1  macallan dbri_process_interrupt_buffer(struct dbri_softc *sc)
    660       1.1  macallan {
    661       1.1  macallan 	int32_t i;
    662      1.36       mrg 	int orig_irqp = sc->sc_irqp;
    663      1.36       mrg 
    664      1.38       mrg 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    665       1.1  macallan 
    666       1.1  macallan 	while ((i = sc->sc_dma->intr[sc->sc_irqp]) != 0) {
    667       1.1  macallan 		sc->sc_dma->intr[sc->sc_irqp] = 0;
    668       1.1  macallan 		sc->sc_irqp++;
    669       1.1  macallan 
    670       1.1  macallan 		if (sc->sc_irqp == DBRI_INT_BLOCKS)
    671       1.1  macallan 			sc->sc_irqp = 1;
    672       1.1  macallan 		else if ((sc->sc_irqp & (DBRI_INT_BLOCKS - 1)) == 0)
    673       1.1  macallan 			sc->sc_irqp++;
    674       1.1  macallan 
    675       1.1  macallan 		dbri_process_interrupt(sc, i);
    676      1.36       mrg 
    677      1.36       mrg 		/* don't loop more than once. */
    678      1.36       mrg 		if (orig_irqp == sc->sc_irqp)
    679      1.36       mrg 			break;
    680       1.1  macallan 	}
    681       1.1  macallan 
    682       1.1  macallan 	return;
    683       1.1  macallan }
    684       1.1  macallan 
    685      1.11  macallan static void
    686       1.1  macallan dbri_process_interrupt(struct dbri_softc *sc, int32_t i)
    687       1.1  macallan {
    688       1.1  macallan #if 0
    689       1.1  macallan 	const int liu_states[] = { 1, 0, 8, 3, 4, 5, 6, 7 };
    690       1.1  macallan #endif
    691       1.1  macallan 	int val = DBRI_INTR_GETVAL(i);
    692       1.1  macallan 	int channel = DBRI_INTR_GETCHAN(i);
    693       1.1  macallan 	int command = DBRI_INTR_GETCMD(i);
    694       1.1  macallan 	int code = DBRI_INTR_GETCODE(i);
    695       1.1  macallan #if 0
    696       1.1  macallan 	int rval = DBRI_INTR_GETRVAL(i);
    697       1.1  macallan #endif
    698       1.1  macallan 	if (channel == DBRI_INTR_CMD && command == DBRI_COMMAND_WAIT)
    699       1.1  macallan 		sc->sc_waitseen++;
    700       1.1  macallan 
    701       1.1  macallan 	switch (code) {
    702       1.1  macallan 	case DBRI_INTR_XCMP:	/* transmission complete */
    703       1.1  macallan 	{
    704       1.1  macallan 		int td;
    705       1.1  macallan 		struct dbri_desc *dd;
    706       1.1  macallan 
    707      1.36       mrg 		DPRINTF("%s:%d tx complete\n", __func__, channel);
    708       1.1  macallan 		td = sc->sc_pipe[channel].desc;
    709       1.1  macallan 		dd = &sc->sc_desc[td];
    710       1.5     blymn 
    711      1.17        ad 		if (dd->callback != NULL)
    712      1.17        ad 			softint_schedule(dd->softint);
    713       1.1  macallan 		break;
    714       1.1  macallan 	}
    715       1.1  macallan 	case DBRI_INTR_FXDT:		/* fixed data change */
    716      1.36       mrg 		DPRINTF("%s:%d: Fixed data change: %x\n", __func__, channel,
    717      1.10  macallan 		    val);
    718       1.1  macallan 		if (sc->sc_pipe[channel].sdp & DBRI_SDP_MSB)
    719       1.1  macallan 			val = reverse_bytes(val, sc->sc_pipe[channel].length);
    720       1.1  macallan 		if (sc->sc_pipe[channel].prec)
    721       1.1  macallan 			*(sc->sc_pipe[channel].prec) = val;
    722      1.13  macallan #ifndef DBRI_SPIN
    723      1.36       mrg 		DPRINTF("%s: cv_broadcast %p\n", device_xname(sc->sc_dev), sc);
    724      1.36       mrg 		cv_broadcast(&sc->sc_cv);
    725       1.1  macallan #endif
    726       1.1  macallan 		break;
    727       1.1  macallan 	case DBRI_INTR_SBRI:
    728      1.10  macallan 		DPRINTF("dbri_intr: SBRI\n");
    729       1.1  macallan 		break;
    730       1.1  macallan 	case DBRI_INTR_BRDY:
    731       1.1  macallan 	{
    732      1.14  macallan 		int td;
    733      1.14  macallan 		struct dbri_desc *dd;
    734       1.1  macallan 
    735      1.36       mrg 		DPRINTF("dbri_intr: buffer ready (%d)\n", channel);
    736      1.14  macallan 		td = sc->sc_pipe[channel].desc;
    737      1.14  macallan 		dd = &sc->sc_desc[td];
    738       1.1  macallan 
    739      1.14  macallan 		if (dd->callback != NULL)
    740      1.17        ad 			softint_schedule(dd->softint);
    741       1.1  macallan 		break;
    742       1.1  macallan 	}
    743       1.1  macallan 	case DBRI_INTR_UNDR:
    744       1.1  macallan 	{
    745      1.25   tsutsui 		volatile uint32_t *cmd;
    746       1.1  macallan 		int td = sc->sc_pipe[channel].desc;
    747       1.1  macallan 
    748      1.20  macallan 		DPRINTF("%s: DBRI_INTR_UNDR\n", device_xname(sc->sc_dev));
    749       1.1  macallan 
    750      1.14  macallan 		sc->sc_dma->xmit[td].status = 0;
    751       1.1  macallan 
    752       1.1  macallan 		cmd = dbri_command_lock(sc);
    753       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
    754       1.1  macallan 				    sc->sc_pipe[channel].sdp |
    755       1.1  macallan 				    DBRI_SDP_VALID_POINTER |
    756       1.1  macallan 				    DBRI_SDP_CLEAR |
    757       1.1  macallan 				    DBRI_SDP_2SAME);
    758      1.14  macallan 		*(cmd++) = sc->sc_dmabase + dbri_dma_off(xmit, td);
    759       1.1  macallan 		dbri_command_send(sc, cmd);
    760       1.1  macallan 		break;
    761       1.1  macallan 	}
    762       1.9  macallan 	case DBRI_INTR_CMDI:
    763      1.14  macallan 		DPRINTF("ok");
    764       1.9  macallan 		break;
    765       1.1  macallan 	default:
    766       1.9  macallan 
    767      1.20  macallan 		aprint_error_dev(sc->sc_dev, "unknown interrupt code %d\n",
    768      1.18    cegger 		    code);
    769       1.1  macallan 		break;
    770       1.1  macallan 	}
    771       1.1  macallan 
    772       1.1  macallan 	return;
    773       1.1  macallan }
    774       1.1  macallan 
    775       1.1  macallan /*
    776       1.1  macallan  * mmcodec stuff
    777       1.1  macallan  */
    778       1.1  macallan 
    779      1.11  macallan static int
    780       1.1  macallan mmcodec_init(struct dbri_softc *sc)
    781       1.1  macallan {
    782       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    783       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    784      1.25   tsutsui 	uint32_t reg2;
    785       1.9  macallan 	int bail;
    786       1.1  macallan 
    787       1.1  macallan 	reg2 = bus_space_read_4(iot, ioh, DBRI_REG2);
    788      1.10  macallan 	DPRINTF("mmcodec_init: PIO reads %x\n", reg2);
    789       1.5     blymn 
    790       1.1  macallan 	if (reg2 & DBRI_PIO2) {
    791      1.20  macallan 		aprint_normal_dev(sc->sc_dev, " onboard CS4215 detected\n");
    792       1.1  macallan 		sc->sc_mm.onboard = 1;
    793       1.1  macallan 	}
    794       1.1  macallan 
    795       1.1  macallan 	if (reg2 & DBRI_PIO0) {
    796      1.20  macallan 		aprint_normal_dev(sc->sc_dev, "speakerbox detected\n");
    797      1.15  macallan 		bus_space_write_4(iot, ioh, DBRI_REG2, DBRI_PIO2_ENABLE);
    798       1.1  macallan 		sc->sc_mm.onboard = 0;
    799       1.1  macallan 	}
    800       1.1  macallan 
    801       1.1  macallan 	if ((reg2 & DBRI_PIO2) && (reg2 & DBRI_PIO0)) {
    802      1.20  macallan 		aprint_normal_dev(sc->sc_dev, "using speakerbox\n");
    803       1.1  macallan 		bus_space_write_4(iot, ioh, DBRI_REG2, DBRI_PIO2_ENABLE);
    804       1.1  macallan 		sc->sc_mm.onboard = 0;
    805       1.1  macallan 	}
    806       1.1  macallan 
    807       1.1  macallan 	if (!(reg2 & (DBRI_PIO0|DBRI_PIO2))) {
    808      1.20  macallan 		aprint_normal_dev(sc->sc_dev, "no mmcodec found\n");
    809       1.1  macallan 		return -1;
    810       1.1  macallan 	}
    811       1.1  macallan 
    812       1.1  macallan 	sc->sc_version = 0xff;
    813       1.1  macallan 
    814       1.1  macallan 	mmcodec_pipe_init(sc);
    815       1.1  macallan 	mmcodec_default(sc);
    816       1.1  macallan 
    817       1.1  macallan 	sc->sc_mm.offset = sc->sc_mm.onboard ? 0 : 8;
    818       1.1  macallan 
    819       1.9  macallan 	/*
    820       1.9  macallan 	 * mmcodec_setcontrol() sometimes fails right after powerup
    821       1.9  macallan 	 * so we just try again until we either get a useful response or run
    822       1.9  macallan 	 * out of time
    823       1.9  macallan 	 */
    824       1.9  macallan 	bail = 0;
    825       1.9  macallan 	while (mmcodec_setcontrol(sc) == -1 || sc->sc_version == 0xff) {
    826       1.9  macallan 
    827       1.9  macallan 		bail++;
    828       1.9  macallan 		if (bail > 100) {
    829      1.10  macallan 			DPRINTF("%s: cs4215 probe failed at offset %d\n",
    830      1.20  macallan 		    	    device_xname(sc->sc_dev), sc->sc_mm.offset);
    831       1.9  macallan 			return (-1);
    832       1.9  macallan 		}
    833       1.9  macallan 		delay(10000);
    834       1.1  macallan 	}
    835       1.1  macallan 
    836      1.20  macallan 	aprint_normal_dev(sc->sc_dev, "cs4215 rev %c found at offset %d\n",
    837      1.18    cegger 	    0x43 + (sc->sc_version & 0xf), sc->sc_mm.offset);
    838       1.1  macallan 
    839       1.1  macallan 	/* set some sane defaults for mmcodec_init_data */
    840       1.1  macallan 	sc->sc_params.channels = 2;
    841       1.1  macallan 	sc->sc_params.precision = 16;
    842       1.1  macallan 
    843       1.1  macallan 	mmcodec_init_data(sc);
    844       1.1  macallan 
    845       1.1  macallan 	return (0);
    846       1.1  macallan }
    847       1.1  macallan 
    848      1.11  macallan static void
    849       1.1  macallan mmcodec_init_data(struct dbri_softc *sc)
    850       1.1  macallan {
    851       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    852       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    853      1.25   tsutsui 	uint32_t tmp;
    854       1.1  macallan 	int data_width;
    855       1.1  macallan 
    856       1.1  macallan 	tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
    857       1.1  macallan 	tmp &= ~(DBRI_CHI_ACTIVATE);	/* disable CHI */
    858       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
    859       1.1  macallan 
    860       1.1  macallan 	/* switch CS4215 to data mode - set PIO3 to 1 */
    861       1.1  macallan 	tmp = DBRI_PIO_ENABLE_ALL | DBRI_PIO1 | DBRI_PIO3;
    862      1.12  macallan 
    863      1.12  macallan 	/* XXX */
    864       1.1  macallan 	tmp |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
    865       1.5     blymn 
    866       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG2, tmp);
    867       1.1  macallan 	chi_reset(sc, CHIslave, 128);
    868       1.1  macallan 
    869      1.12  macallan 	data_width = sc->sc_params.channels * sc->sc_params.precision;
    870      1.14  macallan 
    871      1.14  macallan 	if ((data_width != 32) && (data_width != 8))
    872      1.14  macallan 		aprint_error("%s: data_width is %d\n", __func__, data_width);
    873      1.14  macallan 
    874       1.1  macallan 	pipe_ts_link(sc, 20, PIPEoutput, 16, 32, sc->sc_mm.offset + 32);
    875       1.1  macallan 	pipe_ts_link(sc, 4, PIPEoutput, 16, data_width, sc->sc_mm.offset);
    876       1.1  macallan 	pipe_ts_link(sc, 6, PIPEinput, 16, data_width, sc->sc_mm.offset);
    877      1.37  macallan #if 0
    878      1.37  macallan 	/* readback for the mixer registers - we don't use that */
    879      1.14  macallan 	pipe_ts_link(sc, 21, PIPEinput, 16, 32, sc->sc_mm.offset + 32);
    880      1.14  macallan 
    881      1.37  macallan 	pipe_receive_fixed(sc, 21, &sc->sc_mm.d.ldata);
    882      1.37  macallan #endif
    883       1.1  macallan 	mmcodec_setgain(sc, 0);
    884       1.1  macallan 
    885       1.1  macallan 	tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
    886       1.1  macallan 	tmp |= DBRI_CHI_ACTIVATE;
    887       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
    888       1.1  macallan 
    889       1.1  macallan 	return;
    890       1.1  macallan }
    891       1.1  macallan 
    892      1.11  macallan static void
    893       1.1  macallan mmcodec_pipe_init(struct dbri_softc *sc)
    894       1.1  macallan {
    895       1.1  macallan 
    896       1.1  macallan 	pipe_setup(sc, 4, DBRI_SDP_MEM | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
    897       1.1  macallan 	pipe_setup(sc, 20, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
    898       1.1  macallan 	pipe_setup(sc, 6, DBRI_SDP_MEM | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
    899      1.37  macallan #if 0
    900       1.1  macallan 	pipe_setup(sc, 21, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
    901      1.37  macallan #endif
    902       1.1  macallan 	pipe_setup(sc, 17, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
    903       1.1  macallan 	pipe_setup(sc, 18, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
    904       1.1  macallan 	pipe_setup(sc, 19, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
    905       1.1  macallan 
    906       1.1  macallan 	pipe_receive_fixed(sc, 18, &sc->sc_mm.status);
    907       1.1  macallan 	pipe_receive_fixed(sc, 19, &sc->sc_mm.version);
    908       1.1  macallan 
    909       1.1  macallan 	return;
    910       1.1  macallan }
    911       1.1  macallan 
    912      1.11  macallan static void
    913       1.1  macallan mmcodec_default(struct dbri_softc *sc)
    914       1.1  macallan {
    915       1.1  macallan 	struct cs4215_state *mm = &sc->sc_mm;
    916       1.1  macallan 
    917       1.1  macallan 	/*
    918       1.1  macallan 	 * no action, memory resetting only
    919       1.1  macallan 	 *
    920       1.1  macallan 	 * data time slots 5-8
    921       1.1  macallan 	 * speaker, line and headphone enable. set gain to half.
    922      1.14  macallan 	 * input is line
    923       1.1  macallan 	 */
    924       1.9  macallan 	mm->d.bdata[0] = sc->sc_latt = 0x20 | CS4215_HE | CS4215_LE;
    925       1.9  macallan 	mm->d.bdata[1] = sc->sc_ratt = 0x20 | CS4215_SE;
    926      1.13  macallan 	sc->sc_linp = 128;
    927      1.13  macallan 	sc->sc_rinp = 128;
    928      1.13  macallan 	sc->sc_monitor = 0;
    929      1.13  macallan 	sc->sc_input = 1;	/* line */
    930      1.13  macallan 	mm->d.bdata[2] = (CS4215_LG((sc->sc_linp >> 4)) & 0x0f) |
    931      1.13  macallan 	    ((sc->sc_input == 2) ? CS4215_IS : 0) | CS4215_PIO0 | CS4215_PIO1;
    932      1.13  macallan 	mm->d.bdata[3] = (CS4215_RG((sc->sc_rinp >> 4) & 0x0f)) |
    933      1.13  macallan 	    CS4215_MA(15 - ((sc->sc_monitor >> 4) & 0x0f));
    934      1.13  macallan 
    935       1.1  macallan 
    936       1.1  macallan 	/*
    937       1.1  macallan 	 * control time slots 1-4
    938       1.1  macallan 	 *
    939       1.1  macallan 	 * 0: default I/O voltage scale
    940       1.1  macallan 	 * 1: 8 bit ulaw, 8kHz, mono, high pass filter disabled
    941       1.1  macallan 	 * 2: serial enable, CHI master, 128 bits per frame, clock 1
    942       1.1  macallan 	 * 3: tests disabled
    943       1.1  macallan 	 */
    944      1.37  macallan 	mm->c.bcontrol[0] = CS4215_ONE | CS4215_MLB;
    945       1.9  macallan 	mm->c.bcontrol[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval;
    946       1.9  macallan 	mm->c.bcontrol[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal;
    947       1.9  macallan 	mm->c.bcontrol[3] = 0;
    948       1.1  macallan 
    949       1.1  macallan 	return;
    950       1.1  macallan }
    951       1.1  macallan 
    952      1.11  macallan static void
    953       1.1  macallan mmcodec_setgain(struct dbri_softc *sc, int mute)
    954       1.1  macallan {
    955       1.1  macallan 	if (mute) {
    956       1.1  macallan 		/* disable all outputs, max. attenuation */
    957       1.9  macallan 		sc->sc_mm.d.bdata[0] = sc->sc_latt | 63;
    958       1.9  macallan 		sc->sc_mm.d.bdata[1] = sc->sc_ratt | 63;
    959       1.1  macallan 	} else {
    960      1.13  macallan 
    961       1.9  macallan 		sc->sc_mm.d.bdata[0] = sc->sc_latt;
    962       1.9  macallan 		sc->sc_mm.d.bdata[1] = sc->sc_ratt;
    963       1.1  macallan 	}
    964       1.1  macallan 
    965      1.13  macallan 	/* input stuff */
    966      1.13  macallan 	sc->sc_mm.d.bdata[2] = CS4215_LG((sc->sc_linp >> 4) & 0x0f) |
    967      1.13  macallan 	    ((sc->sc_input == 2) ? CS4215_IS : 0) | CS4215_PIO0 | CS4215_PIO1;
    968      1.13  macallan 	sc->sc_mm.d.bdata[3] = (CS4215_RG((sc->sc_rinp >> 4)) & 0x0f) |
    969      1.13  macallan 	    (CS4215_MA(15 - ((sc->sc_monitor >> 4) & 0x0f)));
    970      1.13  macallan 
    971       1.4  macallan 	if (sc->sc_powerstate == 0)
    972       1.4  macallan 		return;
    973       1.9  macallan 	pipe_transmit_fixed(sc, 20, sc->sc_mm.d.ldata);
    974       1.5     blymn 
    975      1.13  macallan 	DPRINTF("mmcodec_setgain: %08x\n", sc->sc_mm.d.ldata);
    976      1.13  macallan 	/* give the chip some time to execute the command */
    977       1.1  macallan 	delay(250);
    978       1.5     blymn 
    979       1.1  macallan 	return;
    980       1.1  macallan }
    981       1.1  macallan 
    982      1.11  macallan static int
    983       1.1  macallan mmcodec_setcontrol(struct dbri_softc *sc)
    984       1.1  macallan {
    985       1.1  macallan 	bus_space_tag_t iot = sc->sc_iot;
    986       1.1  macallan 	bus_space_handle_t ioh = sc->sc_ioh;
    987      1.25   tsutsui 	uint32_t val;
    988      1.25   tsutsui 	uint32_t tmp;
    989      1.37  macallan 	int ret = 0;
    990      1.37  macallan #ifdef DBRI_SPIN
    991       1.1  macallan 	int i;
    992      1.36       mrg #else
    993      1.37  macallan 	int error, bail = 0;
    994       1.1  macallan #endif
    995       1.1  macallan 
    996      1.38       mrg 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    997      1.38       mrg 
    998       1.1  macallan 	/*
    999       1.1  macallan 	 * Temporarily mute outputs and wait 125 us to make sure that it
   1000       1.1  macallan 	 * happens. This avoids clicking noises.
   1001       1.1  macallan 	 */
   1002       1.1  macallan 	mmcodec_setgain(sc, 1);
   1003       1.9  macallan 	delay(125);
   1004       1.1  macallan 
   1005      1.37  macallan 	tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
   1006      1.37  macallan 	tmp &= ~(DBRI_CHI_ACTIVATE);	/* disable CHI */
   1007      1.37  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
   1008      1.37  macallan 
   1009      1.15  macallan 	bus_space_write_4(iot, ioh, DBRI_REG2, 0);
   1010      1.15  macallan 	delay(125);
   1011      1.15  macallan 
   1012       1.1  macallan 	/* enable control mode */
   1013       1.1  macallan 	val = DBRI_PIO_ENABLE_ALL | DBRI_PIO1;	/* was PIO1 */
   1014       1.1  macallan 
   1015      1.12  macallan 	/* XXX */
   1016       1.1  macallan 	val |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
   1017       1.1  macallan 
   1018       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG2, val);
   1019       1.9  macallan 	delay(34);
   1020       1.1  macallan 
   1021       1.1  macallan 	/*
   1022       1.1  macallan 	 * in control mode, the cs4215 is the slave device, so the
   1023       1.1  macallan 	 * DBRI must act as the CHI master.
   1024       1.1  macallan 	 *
   1025       1.1  macallan 	 * in data mode, the cs4215 must be the CHI master to insure
   1026       1.1  macallan 	 * that the data stream is in sync with its codec
   1027       1.1  macallan 	 */
   1028       1.1  macallan 	tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
   1029       1.1  macallan 	tmp &= ~DBRI_COMMAND_CHI;
   1030       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
   1031       1.1  macallan 
   1032       1.1  macallan 	chi_reset(sc, CHImaster, 128);
   1033       1.1  macallan 
   1034       1.1  macallan 	/* control mode */
   1035       1.1  macallan 	pipe_ts_link(sc, 17, PIPEoutput, 16, 32, sc->sc_mm.offset);
   1036       1.1  macallan 	pipe_ts_link(sc, 18, PIPEinput, 16, 8, sc->sc_mm.offset);
   1037       1.1  macallan 	pipe_ts_link(sc, 19, PIPEinput, 16, 8, sc->sc_mm.offset + 48);
   1038       1.1  macallan 
   1039      1.37  macallan 	pipe_receive_fixed(sc, 18, &sc->sc_mm.status);
   1040      1.37  macallan 
   1041       1.1  macallan 	/* wait for the chip to echo back CLB as zero */
   1042       1.9  macallan 	sc->sc_mm.c.bcontrol[0] &= ~CS4215_CLB;
   1043       1.9  macallan 	pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
   1044       1.1  macallan 
   1045       1.1  macallan 	tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
   1046       1.1  macallan 	tmp |= DBRI_CHI_ACTIVATE;
   1047       1.1  macallan 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
   1048       1.5     blymn 
   1049      1.37  macallan #ifdef DBRI_SPIN
   1050       1.1  macallan 	i = 1024;
   1051      1.37  macallan 	while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (i > 0)) {
   1052      1.37  macallan 		i--;
   1053       1.1  macallan 		delay(125);
   1054       1.1  macallan 	}
   1055       1.1  macallan 
   1056       1.1  macallan 	if (i == 0) {
   1057      1.10  macallan 		DPRINTF("%s: cs4215 didn't respond to CLB (0x%02x)\n",
   1058      1.20  macallan 		    device_xname(sc->sc_dev), sc->sc_mm.status);
   1059      1.37  macallan 		ret = -1;
   1060      1.37  macallan 		goto fail;
   1061       1.1  macallan 	}
   1062       1.1  macallan #else
   1063      1.37  macallan 	while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (bail < 10)) {
   1064      1.36       mrg 		DPRINTF("%s: cv_wait_sig %p\n", device_xname(sc->sc_dev), sc);
   1065      1.36       mrg 		error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_intr_lock, hz);
   1066      1.36       mrg 		if (error == EINTR) {
   1067      1.36       mrg 			DPRINTF("%s: interrupted\n", device_xname(sc->sc_dev));
   1068      1.37  macallan 			ret = -1;
   1069      1.37  macallan 			mutex_spin_exit(&sc->sc_intr_lock);
   1070      1.37  macallan 			goto fail;
   1071      1.36       mrg 		}
   1072      1.15  macallan 		bail++;
   1073       1.1  macallan 	}
   1074      1.15  macallan 	if (bail >= 10) {
   1075      1.37  macallan 		aprint_error("%s: switching to control mode timed out (%x %x)\n",
   1076      1.20  macallan 		    device_xname(sc->sc_dev), sc->sc_mm.status,
   1077      1.15  macallan 		    bus_space_read_4(iot, ioh, DBRI_REG2));
   1078      1.37  macallan 		ret = -1;
   1079      1.37  macallan 		goto fail;
   1080      1.15  macallan 	}
   1081      1.37  macallan #endif
   1082       1.5     blymn 
   1083       1.1  macallan 	/* copy the version information before it becomes unreadable again */
   1084       1.9  macallan 	sc->sc_version = sc->sc_mm.version;
   1085      1.37  macallan 	sc->sc_whack_codec = 0;
   1086       1.1  macallan 
   1087      1.37  macallan fail:
   1088       1.1  macallan 	/* terminate cs4215 control mode */
   1089       1.9  macallan 	sc->sc_mm.c.bcontrol[0] |= CS4215_CLB;
   1090       1.9  macallan 	pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
   1091       1.1  macallan 
   1092       1.1  macallan 	/* two frames of control info @ 8kHz frame rate = 250us delay */
   1093       1.9  macallan 	delay(250);
   1094       1.1  macallan 
   1095       1.1  macallan 	mmcodec_setgain(sc, 0);
   1096       1.1  macallan 
   1097      1.37  macallan 	return ret;
   1098       1.5     blymn 
   1099       1.1  macallan }
   1100       1.1  macallan 
   1101       1.1  macallan /*
   1102       1.1  macallan  * CHI combo
   1103       1.1  macallan  */
   1104      1.11  macallan static void
   1105       1.1  macallan chi_reset(struct dbri_softc *sc, enum ms ms, int bpf)
   1106       1.1  macallan {
   1107      1.25   tsutsui 	volatile uint32_t *cmd;
   1108       1.1  macallan 	int val;
   1109       1.1  macallan 	int clockrate, divisor;
   1110       1.1  macallan 
   1111       1.1  macallan 	cmd = dbri_command_lock(sc);
   1112       1.1  macallan 
   1113       1.1  macallan 	/* set CHI anchor: pipe 16 */
   1114       1.1  macallan 	val = DBRI_DTS_VI | DBRI_DTS_INS | DBRI_DTS_PRVIN(16) | DBRI_PIPE(16);
   1115       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
   1116       1.1  macallan 	*(cmd++) = DBRI_TS_ANCHOR | DBRI_TS_NEXT(16);
   1117       1.1  macallan 	*(cmd++) = 0;
   1118       1.1  macallan 
   1119       1.1  macallan 	val = DBRI_DTS_VO | DBRI_DTS_INS | DBRI_DTS_PRVOUT(16) | DBRI_PIPE(16);
   1120       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
   1121       1.1  macallan 	*(cmd++) = 0;
   1122       1.1  macallan 	*(cmd++) = DBRI_TS_ANCHOR | DBRI_TS_NEXT(16);
   1123       1.1  macallan 
   1124       1.1  macallan 	sc->sc_pipe[16].sdp = 1;
   1125       1.1  macallan 	sc->sc_pipe[16].next = 16;
   1126       1.1  macallan 	sc->sc_chi_pipe_in = 16;
   1127       1.1  macallan 	sc->sc_chi_pipe_out = 16;
   1128       1.1  macallan 
   1129       1.1  macallan 	switch (ms) {
   1130       1.1  macallan 	case CHIslave:
   1131       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_CHI, 0, DBRI_CHI_CHICM(0));
   1132       1.1  macallan 		break;
   1133       1.1  macallan 	case CHImaster:
   1134       1.1  macallan 		clockrate = bpf * 8;
   1135       1.1  macallan 		divisor = 12288 / clockrate;
   1136       1.1  macallan 
   1137       1.1  macallan 		if (divisor > 255 || divisor * clockrate != 12288)
   1138      1.20  macallan 			aprint_error_dev(sc->sc_dev,
   1139      1.20  macallan 			    "illegal bits-per-frame %d\n", bpf);
   1140       1.1  macallan 
   1141       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_CHI, 0,
   1142       1.1  macallan 		    DBRI_CHI_CHICM(divisor) | DBRI_CHI_FD | DBRI_CHI_BPF(bpf));
   1143       1.1  macallan 		break;
   1144       1.1  macallan 	default:
   1145      1.20  macallan 		aprint_error_dev(sc->sc_dev, "unknown value for ms!\n");
   1146       1.1  macallan 		break;
   1147       1.1  macallan 	}
   1148       1.1  macallan 
   1149       1.1  macallan 	sc->sc_chi_bpf = bpf;
   1150       1.1  macallan 
   1151       1.1  macallan 	/* CHI data mode */
   1152       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_PAUSE, 0, 0);
   1153       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_CDM, 0,
   1154       1.1  macallan 	    DBRI_CDM_XCE | DBRI_CDM_XEN | DBRI_CDM_REN);
   1155       1.1  macallan 
   1156       1.1  macallan 	dbri_command_send(sc, cmd);
   1157       1.1  macallan 
   1158       1.1  macallan 	return;
   1159       1.1  macallan }
   1160       1.1  macallan 
   1161       1.1  macallan /*
   1162       1.1  macallan  * pipe stuff
   1163       1.1  macallan  */
   1164      1.11  macallan static void
   1165       1.1  macallan pipe_setup(struct dbri_softc *sc, int pipe, int sdp)
   1166       1.1  macallan {
   1167      1.10  macallan 	DPRINTF("pipe setup: %d\n", pipe);
   1168       1.1  macallan 	if (pipe < 0 || pipe >= DBRI_PIPE_MAX) {
   1169      1.20  macallan 		aprint_error_dev(sc->sc_dev, "illegal pipe number %d\n",
   1170      1.18    cegger 		    pipe);
   1171       1.1  macallan 		return;
   1172       1.1  macallan 	}
   1173       1.1  macallan 
   1174       1.1  macallan 	if ((sdp & 0xf800) != sdp)
   1175      1.20  macallan 		aprint_error_dev(sc->sc_dev, "strange SDP value %d\n",
   1176      1.14  macallan 		    sdp);
   1177       1.1  macallan 
   1178       1.1  macallan 	if (DBRI_SDP_MODE(sdp) == DBRI_SDP_FIXED &&
   1179       1.1  macallan 	    !(sdp & DBRI_SDP_TO_SER))
   1180       1.1  macallan 		sdp |= DBRI_SDP_CHANGE;
   1181       1.1  macallan 
   1182       1.1  macallan 	sdp |= DBRI_PIPE(pipe);
   1183       1.1  macallan 
   1184       1.1  macallan 	sc->sc_pipe[pipe].sdp = sdp;
   1185       1.1  macallan 	sc->sc_pipe[pipe].desc = -1;
   1186       1.1  macallan 
   1187       1.1  macallan 	pipe_reset(sc, pipe);
   1188       1.1  macallan 
   1189       1.1  macallan 	return;
   1190       1.1  macallan }
   1191       1.1  macallan 
   1192      1.11  macallan static void
   1193       1.1  macallan pipe_reset(struct dbri_softc *sc, int pipe)
   1194       1.1  macallan {
   1195       1.1  macallan 	struct dbri_desc *dd;
   1196       1.1  macallan 	int sdp;
   1197       1.1  macallan 	int desc;
   1198      1.25   tsutsui 	volatile uint32_t *cmd;
   1199       1.1  macallan 
   1200       1.1  macallan 	if (pipe < 0 || pipe >= DBRI_PIPE_MAX) {
   1201      1.20  macallan 		aprint_error_dev(sc->sc_dev, "illegal pipe number %d\n",
   1202      1.18    cegger 		    pipe);
   1203       1.1  macallan 		return;
   1204       1.1  macallan 	}
   1205       1.1  macallan 
   1206       1.1  macallan 	sdp = sc->sc_pipe[pipe].sdp;
   1207       1.1  macallan 	if (sdp == 0) {
   1208      1.20  macallan 		aprint_error_dev(sc->sc_dev, "can not reset uninitialized pipe %d\n",
   1209      1.18    cegger 		    pipe);
   1210       1.1  macallan 		return;
   1211       1.1  macallan 	}
   1212       1.1  macallan 
   1213       1.1  macallan 	cmd = dbri_command_lock(sc);
   1214       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
   1215       1.1  macallan 	    sdp | DBRI_SDP_CLEAR | DBRI_SDP_VALID_POINTER);
   1216       1.1  macallan 	*(cmd++) = 0;
   1217       1.1  macallan 	dbri_command_send(sc, cmd);
   1218       1.1  macallan 
   1219       1.1  macallan 	desc = sc->sc_pipe[pipe].desc;
   1220       1.1  macallan 
   1221       1.1  macallan 	dd = &sc->sc_desc[desc];
   1222       1.5     blymn 
   1223       1.1  macallan 	dd->busy = 0;
   1224       1.1  macallan 
   1225      1.12  macallan #if 0
   1226       1.1  macallan 	if (dd->callback)
   1227      1.17        ad 		softint_schedule(dd->softint);
   1228      1.12  macallan #endif
   1229       1.1  macallan 
   1230       1.1  macallan 	sc->sc_pipe[pipe].desc = -1;
   1231       1.1  macallan 
   1232       1.1  macallan 	return;
   1233       1.1  macallan }
   1234       1.1  macallan 
   1235      1.11  macallan static void
   1236      1.25   tsutsui pipe_receive_fixed(struct dbri_softc *sc, int pipe, volatile uint32_t *prec)
   1237       1.1  macallan {
   1238       1.1  macallan 
   1239       1.1  macallan 	if (pipe < DBRI_PIPE_MAX / 2 || pipe >= DBRI_PIPE_MAX) {
   1240      1.20  macallan 		aprint_error_dev(sc->sc_dev, "illegal pipe number %d\n",
   1241      1.18    cegger 		    pipe);
   1242       1.1  macallan 		return;
   1243       1.1  macallan 	}
   1244       1.1  macallan 
   1245       1.1  macallan 	if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) != DBRI_SDP_FIXED) {
   1246      1.20  macallan 		aprint_error_dev(sc->sc_dev, "non-fixed pipe %d\n",
   1247       1.1  macallan 		    pipe);
   1248       1.1  macallan 		return;
   1249       1.1  macallan 	}
   1250       1.1  macallan 
   1251       1.1  macallan 	if (sc->sc_pipe[pipe].sdp & DBRI_SDP_TO_SER) {
   1252      1.20  macallan 		aprint_error_dev(sc->sc_dev, "can not receive on transmit pipe %d\b",
   1253      1.18    cegger 		    pipe);
   1254       1.1  macallan 		return;
   1255       1.1  macallan 	}
   1256       1.1  macallan 
   1257       1.1  macallan 	sc->sc_pipe[pipe].prec = prec;
   1258       1.1  macallan 
   1259       1.1  macallan 	return;
   1260       1.1  macallan }
   1261       1.1  macallan 
   1262      1.11  macallan static void
   1263      1.25   tsutsui pipe_transmit_fixed(struct dbri_softc *sc, int pipe, uint32_t data)
   1264       1.1  macallan {
   1265      1.25   tsutsui 	volatile uint32_t *cmd;
   1266       1.1  macallan 
   1267       1.1  macallan 	if (pipe < DBRI_PIPE_MAX / 2 || pipe >= DBRI_PIPE_MAX) {
   1268      1.20  macallan 		aprint_error_dev(sc->sc_dev, "illegal pipe number %d\n",
   1269      1.18    cegger 		    pipe);
   1270       1.1  macallan 		return;
   1271       1.1  macallan 	}
   1272       1.1  macallan 
   1273       1.1  macallan 	if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) == 0) {
   1274      1.20  macallan 		aprint_error_dev(sc->sc_dev, "uninitialized pipe %d\n",
   1275      1.18    cegger 		    pipe);
   1276       1.1  macallan 		return;
   1277       1.1  macallan 	}
   1278       1.1  macallan 
   1279       1.1  macallan 	if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) != DBRI_SDP_FIXED) {
   1280      1.20  macallan 		aprint_error_dev(sc->sc_dev, "non-fixed pipe %d\n",
   1281      1.12  macallan 		    pipe);
   1282       1.1  macallan 		return;
   1283       1.1  macallan 	}
   1284       1.1  macallan 
   1285       1.1  macallan 	if (!(sc->sc_pipe[pipe].sdp & DBRI_SDP_TO_SER)) {
   1286      1.20  macallan 		aprint_error_dev(sc->sc_dev, "called on receive pipe %d\n",
   1287      1.18    cegger 		    pipe);
   1288       1.1  macallan 		return;
   1289       1.1  macallan 	}
   1290       1.1  macallan 
   1291       1.1  macallan 	if (sc->sc_pipe[pipe].sdp & DBRI_SDP_MSB)
   1292       1.1  macallan 		data = reverse_bytes(data, sc->sc_pipe[pipe].length);
   1293       1.1  macallan 
   1294       1.1  macallan 	cmd = dbri_command_lock(sc);
   1295       1.1  macallan 	*(cmd++) = DBRI_CMD(DBRI_COMMAND_SSP, 0, pipe);
   1296       1.1  macallan 	*(cmd++) = data;
   1297       1.1  macallan 
   1298       1.1  macallan 	dbri_command_send(sc, cmd);
   1299       1.1  macallan 
   1300       1.1  macallan 	return;
   1301       1.1  macallan }
   1302       1.1  macallan 
   1303      1.11  macallan static void
   1304      1.14  macallan setup_ring_xmit(struct dbri_softc *sc, int pipe, int which, int num, int blksz,
   1305       1.1  macallan 		void (*callback)(void *), void *callback_args)
   1306       1.1  macallan {
   1307      1.25   tsutsui 	volatile uint32_t *cmd;
   1308      1.34  jmcneill 	int i;
   1309      1.35       mrg #if 0
   1310       1.1  macallan 	int td;
   1311       1.1  macallan 	int td_first, td_last;
   1312      1.35       mrg #endif
   1313       1.1  macallan 	bus_addr_t dmabuf, dmabase;
   1314       1.1  macallan 	struct dbri_desc *dd = &sc->sc_desc[which];
   1315       1.1  macallan 
   1316      1.14  macallan 	switch (pipe) {
   1317      1.14  macallan 		case 4:
   1318      1.14  macallan 			/* output, offset 0 */
   1319      1.14  macallan 			break;
   1320      1.14  macallan 		default:
   1321      1.14  macallan 			aprint_error("%s: illegal pipe number (%d)\n",
   1322      1.14  macallan 			    __func__, pipe);
   1323      1.14  macallan 			return;
   1324      1.14  macallan 	}
   1325      1.14  macallan 
   1326      1.35       mrg #if 0
   1327       1.1  macallan 	td = 0;
   1328       1.1  macallan 	td_first = td_last = -1;
   1329      1.35       mrg #endif
   1330       1.1  macallan 
   1331      1.14  macallan 	if (sc->sc_pipe[pipe].sdp == 0) {
   1332      1.20  macallan 		aprint_error_dev(sc->sc_dev, "uninitialized pipe %d\n",
   1333      1.18    cegger 		    pipe);
   1334       1.1  macallan 		return;
   1335       1.1  macallan 	}
   1336       1.1  macallan 
   1337      1.14  macallan 	dmabuf = dd->dmabase;
   1338      1.14  macallan 	dmabase = sc->sc_dmabase;
   1339      1.14  macallan 
   1340      1.14  macallan 	for (i = 0; i < (num - 1); i++) {
   1341      1.14  macallan 
   1342      1.14  macallan 		sc->sc_dma->xmit[i].flags = TX_BCNT(blksz)
   1343      1.14  macallan 		    | TX_EOF | TX_BINT;
   1344      1.14  macallan 		sc->sc_dma->xmit[i].ba = dmabuf;
   1345      1.14  macallan 		sc->sc_dma->xmit[i].nda = dmabase + dbri_dma_off(xmit, i + 1);
   1346      1.14  macallan 		sc->sc_dma->xmit[i].status = 0;
   1347      1.14  macallan 
   1348      1.35       mrg #if 0
   1349      1.14  macallan 		td_last = td;
   1350      1.35       mrg #endif
   1351      1.14  macallan 		dmabuf += blksz;
   1352      1.14  macallan 	}
   1353      1.14  macallan 
   1354      1.14  macallan 	sc->sc_dma->xmit[i].flags = TX_BCNT(blksz) | TX_EOF | TX_BINT;
   1355      1.14  macallan 
   1356      1.14  macallan 	sc->sc_dma->xmit[i].ba = dmabuf;
   1357      1.14  macallan 	sc->sc_dma->xmit[i].nda = dmabase + dbri_dma_off(xmit, 0);
   1358      1.14  macallan 	sc->sc_dma->xmit[i].status = 0;
   1359      1.14  macallan 
   1360      1.14  macallan 	dd->callback = callback;
   1361      1.14  macallan 	dd->callback_args = callback_args;
   1362      1.14  macallan 
   1363      1.14  macallan 	/* the pipe shouldn't be active */
   1364      1.14  macallan 	if (pipe_active(sc, pipe)) {
   1365      1.14  macallan 		aprint_error("pipe active (CDP)\n");
   1366      1.14  macallan 		/* pipe is already active */
   1367      1.14  macallan #if 0
   1368      1.14  macallan 		td_last = sc->sc_pipe[pipe].desc;
   1369      1.14  macallan 		while (sc->sc_desc[td_last].next != -1)
   1370      1.14  macallan 			td_last = sc->sc_desc[td_last].next;
   1371      1.14  macallan 
   1372      1.14  macallan 		sc->sc_desc[td_last].next = td_first;
   1373      1.14  macallan 		sc->sc_dma->desc[td_last].nda =
   1374      1.14  macallan 		    sc->sc_dmabase + dbri_dma_off(desc, td_first);
   1375      1.14  macallan 
   1376      1.14  macallan 		cmd = dbri_command_lock(sc);
   1377      1.14  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_CDP, 0, pipe);
   1378      1.14  macallan 		dbri_command_send(sc, cmd);
   1379      1.14  macallan #endif
   1380      1.14  macallan 	} else {
   1381      1.14  macallan 		/*
   1382      1.14  macallan 		 * pipe isn't active - issue an SDP command to start our
   1383      1.14  macallan 		 * chain of TDs running
   1384      1.14  macallan 		 */
   1385      1.14  macallan 		sc->sc_pipe[pipe].desc = which;
   1386      1.14  macallan 		cmd = dbri_command_lock(sc);
   1387      1.14  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
   1388      1.14  macallan 					sc->sc_pipe[pipe].sdp |
   1389      1.14  macallan 					DBRI_SDP_VALID_POINTER |
   1390      1.14  macallan 					DBRI_SDP_EVERY |
   1391      1.14  macallan 					DBRI_SDP_CLEAR);
   1392      1.14  macallan 		*(cmd++) = sc->sc_dmabase + dbri_dma_off(xmit, 0);
   1393      1.14  macallan 		dbri_command_send(sc, cmd);
   1394      1.14  macallan 		DPRINTF("%s: starting DMA\n", __func__);
   1395      1.14  macallan 	}
   1396      1.14  macallan 
   1397      1.14  macallan 	return;
   1398      1.14  macallan }
   1399      1.14  macallan 
   1400      1.14  macallan static void
   1401      1.14  macallan setup_ring_recv(struct dbri_softc *sc, int pipe, int which, int num, int blksz,
   1402      1.14  macallan 		void (*callback)(void *), void *callback_args)
   1403      1.14  macallan {
   1404      1.25   tsutsui 	volatile uint32_t *cmd;
   1405      1.34  jmcneill 	int i;
   1406      1.35       mrg #if 0
   1407      1.14  macallan 	int td_first, td_last;
   1408      1.35       mrg #endif
   1409      1.14  macallan 	bus_addr_t dmabuf, dmabase;
   1410      1.14  macallan 	struct dbri_desc *dd = &sc->sc_desc[which];
   1411      1.14  macallan 
   1412      1.14  macallan 	switch (pipe) {
   1413      1.14  macallan 		case 6:
   1414      1.14  macallan 			break;
   1415      1.14  macallan 		default:
   1416      1.14  macallan 			aprint_error("%s: illegal pipe number (%d)\n",
   1417      1.14  macallan 			    __func__, pipe);
   1418      1.14  macallan 			return;
   1419      1.14  macallan 	}
   1420      1.14  macallan 
   1421      1.35       mrg #if 0
   1422      1.14  macallan 	td_first = td_last = -1;
   1423      1.35       mrg #endif
   1424      1.14  macallan 
   1425       1.1  macallan 	if (sc->sc_pipe[pipe].sdp == 0) {
   1426      1.20  macallan 		aprint_error_dev(sc->sc_dev, "uninitialized pipe %d\n",
   1427      1.18    cegger 		    pipe);
   1428       1.1  macallan 		return;
   1429       1.1  macallan 	}
   1430       1.1  macallan 
   1431       1.1  macallan 	dmabuf = dd->dmabase;
   1432       1.1  macallan 	dmabase = sc->sc_dmabase;
   1433       1.1  macallan 
   1434      1.14  macallan 	for (i = 0; i < (num - 1); i++) {
   1435       1.1  macallan 
   1436      1.14  macallan 		sc->sc_dma->recv[i].flags = RX_BSIZE(blksz) | RX_FINAL;
   1437      1.14  macallan 		sc->sc_dma->recv[i].ba = dmabuf;
   1438      1.14  macallan 		sc->sc_dma->recv[i].nda = dmabase + dbri_dma_off(recv, i + 1);
   1439      1.14  macallan 		sc->sc_dma->recv[i].status = RX_EOF;
   1440       1.1  macallan 
   1441      1.35       mrg #if 0
   1442      1.14  macallan 		td_last = i;
   1443      1.35       mrg #endif
   1444       1.1  macallan 		dmabuf += blksz;
   1445       1.1  macallan 	}
   1446       1.5     blymn 
   1447      1.14  macallan 	sc->sc_dma->recv[i].flags = RX_BSIZE(blksz) | RX_FINAL;
   1448      1.14  macallan 
   1449      1.14  macallan 	sc->sc_dma->recv[i].ba = dmabuf;
   1450      1.14  macallan 	sc->sc_dma->recv[i].nda = dmabase + dbri_dma_off(recv, 0);
   1451      1.14  macallan 	sc->sc_dma->recv[i].status = RX_EOF;
   1452       1.5     blymn 
   1453      1.12  macallan 	dd->callback = callback;
   1454      1.12  macallan 	dd->callback_args = callback_args;
   1455       1.1  macallan 
   1456       1.1  macallan 	/* the pipe shouldn't be active */
   1457       1.1  macallan 	if (pipe_active(sc, pipe)) {
   1458      1.10  macallan 		aprint_error("pipe active (CDP)\n");
   1459       1.1  macallan 		/* pipe is already active */
   1460      1.12  macallan #if 0
   1461       1.1  macallan 		td_last = sc->sc_pipe[pipe].desc;
   1462       1.1  macallan 		while (sc->sc_desc[td_last].next != -1)
   1463       1.1  macallan 			td_last = sc->sc_desc[td_last].next;
   1464       1.1  macallan 
   1465       1.1  macallan 		sc->sc_desc[td_last].next = td_first;
   1466       1.1  macallan 		sc->sc_dma->desc[td_last].nda =
   1467       1.1  macallan 		    sc->sc_dmabase + dbri_dma_off(desc, td_first);
   1468       1.1  macallan 
   1469       1.1  macallan 		cmd = dbri_command_lock(sc);
   1470       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_CDP, 0, pipe);
   1471       1.1  macallan 		dbri_command_send(sc, cmd);
   1472      1.12  macallan #endif
   1473       1.1  macallan 	} else {
   1474       1.1  macallan 		/*
   1475       1.1  macallan 		 * pipe isn't active - issue an SDP command to start our
   1476       1.1  macallan 		 * chain of TDs running
   1477       1.1  macallan 		 */
   1478       1.1  macallan 		sc->sc_pipe[pipe].desc = which;
   1479       1.1  macallan 		cmd = dbri_command_lock(sc);
   1480       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
   1481       1.1  macallan 					sc->sc_pipe[pipe].sdp |
   1482       1.1  macallan 					DBRI_SDP_VALID_POINTER |
   1483       1.1  macallan 					DBRI_SDP_EVERY |
   1484       1.1  macallan 					DBRI_SDP_CLEAR);
   1485      1.14  macallan 		*(cmd++) = sc->sc_dmabase + dbri_dma_off(recv, 0);
   1486       1.1  macallan 		dbri_command_send(sc, cmd);
   1487      1.14  macallan 		DPRINTF("%s: starting DMA\n", __func__);
   1488       1.1  macallan 	}
   1489       1.1  macallan 
   1490       1.1  macallan 	return;
   1491       1.1  macallan }
   1492       1.1  macallan 
   1493      1.11  macallan static void
   1494       1.1  macallan pipe_ts_link(struct dbri_softc *sc, int pipe, enum io dir, int basepipe,
   1495       1.1  macallan 		int len, int cycle)
   1496       1.1  macallan {
   1497      1.25   tsutsui 	volatile uint32_t *cmd;
   1498       1.1  macallan 	int prevpipe, nextpipe;
   1499       1.1  macallan 	int val;
   1500       1.1  macallan 
   1501      1.14  macallan 	DPRINTF("%s: %d\n", __func__, pipe);
   1502       1.1  macallan 	if (pipe < 0 || pipe >= DBRI_PIPE_MAX ||
   1503       1.1  macallan 	    basepipe < 0 || basepipe >= DBRI_PIPE_MAX) {
   1504      1.20  macallan 		aprint_error_dev(sc->sc_dev, "illegal pipe numbers (%d, %d)\n",
   1505      1.18    cegger 		    pipe, basepipe);
   1506       1.1  macallan 		return;
   1507       1.1  macallan 	}
   1508       1.1  macallan 
   1509       1.1  macallan 	if (sc->sc_pipe[pipe].sdp == 0 || sc->sc_pipe[basepipe].sdp == 0) {
   1510      1.20  macallan 		aprint_error_dev(sc->sc_dev, "uninitialized pipe (%d, %d)\n",
   1511      1.18    cegger 		    pipe, basepipe);
   1512       1.1  macallan 		return;
   1513       1.1  macallan 	}
   1514       1.1  macallan 
   1515       1.1  macallan 	if (basepipe == 16 && dir == PIPEoutput && cycle == 0)
   1516       1.1  macallan 		cycle = sc->sc_chi_bpf;
   1517       1.1  macallan 
   1518       1.1  macallan 	if (basepipe == pipe)
   1519       1.1  macallan 		prevpipe = nextpipe = pipe;
   1520       1.1  macallan 	else {
   1521       1.1  macallan 		if (basepipe == 16) {
   1522       1.1  macallan 			if (dir == PIPEinput) {
   1523       1.1  macallan 				prevpipe = sc->sc_chi_pipe_in;
   1524       1.1  macallan 			} else {
   1525       1.1  macallan 				prevpipe = sc->sc_chi_pipe_out;
   1526       1.1  macallan 			}
   1527       1.1  macallan 		} else
   1528       1.1  macallan 			prevpipe = basepipe;
   1529       1.1  macallan 
   1530       1.1  macallan 		nextpipe = sc->sc_pipe[prevpipe].next;
   1531       1.1  macallan 
   1532       1.1  macallan 		while (sc->sc_pipe[nextpipe].cycle < cycle &&
   1533       1.1  macallan 		    sc->sc_pipe[nextpipe].next != basepipe) {
   1534       1.1  macallan 			prevpipe = nextpipe;
   1535       1.1  macallan 			nextpipe = sc->sc_pipe[nextpipe].next;
   1536       1.1  macallan 		}
   1537       1.1  macallan 	}
   1538       1.1  macallan 
   1539       1.1  macallan 	if (prevpipe == 16) {
   1540       1.1  macallan 		if (dir == PIPEinput) {
   1541       1.1  macallan 			sc->sc_chi_pipe_in = pipe;
   1542       1.1  macallan 		} else {
   1543       1.1  macallan 			sc->sc_chi_pipe_out = pipe;
   1544       1.1  macallan 		}
   1545       1.1  macallan 	} else
   1546       1.1  macallan 		sc->sc_pipe[prevpipe].next = pipe;
   1547       1.1  macallan 
   1548       1.1  macallan 	sc->sc_pipe[pipe].next = nextpipe;
   1549       1.1  macallan 	sc->sc_pipe[pipe].cycle = cycle;
   1550       1.1  macallan 	sc->sc_pipe[pipe].length = len;
   1551       1.1  macallan 
   1552       1.1  macallan 	cmd = dbri_command_lock(sc);
   1553       1.1  macallan 
   1554       1.1  macallan 	switch (dir) {
   1555       1.1  macallan 	case PIPEinput:
   1556       1.1  macallan 		val = DBRI_DTS_VI | DBRI_DTS_INS | DBRI_DTS_PRVIN(prevpipe);
   1557       1.1  macallan 		val |= pipe;
   1558       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
   1559       1.1  macallan 		*(cmd++) = DBRI_TS_LEN(len) | DBRI_TS_CYCLE(cycle) |
   1560       1.1  macallan 		    DBRI_TS_NEXT(nextpipe);
   1561       1.1  macallan 		*(cmd++) = 0;
   1562       1.1  macallan 		break;
   1563       1.1  macallan 	case PIPEoutput:
   1564       1.1  macallan 		val = DBRI_DTS_VO | DBRI_DTS_INS | DBRI_DTS_PRVOUT(prevpipe);
   1565       1.1  macallan 		val |= pipe;
   1566       1.1  macallan 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
   1567       1.1  macallan 		*(cmd++) = 0;
   1568       1.1  macallan 		*(cmd++) = DBRI_TS_LEN(len) | DBRI_TS_CYCLE(cycle) |
   1569       1.1  macallan 		    DBRI_TS_NEXT(nextpipe);
   1570       1.1  macallan 		break;
   1571       1.1  macallan 	default:
   1572      1.10  macallan 		DPRINTF("%s: should not have happened!\n",
   1573      1.20  macallan 		    device_xname(sc->sc_dev));
   1574       1.1  macallan 		break;
   1575       1.1  macallan 	}
   1576       1.1  macallan 
   1577       1.1  macallan 	dbri_command_send(sc, cmd);
   1578       1.1  macallan 
   1579       1.1  macallan 	return;
   1580       1.1  macallan }
   1581       1.1  macallan 
   1582      1.11  macallan static int
   1583       1.1  macallan pipe_active(struct dbri_softc *sc, int pipe)
   1584       1.1  macallan {
   1585       1.1  macallan 
   1586       1.1  macallan 	return (sc->sc_pipe[pipe].desc != -1);
   1587       1.1  macallan }
   1588       1.1  macallan 
   1589       1.1  macallan /*
   1590       1.1  macallan  * subroutines required to interface with audio(9)
   1591       1.1  macallan  */
   1592       1.1  macallan 
   1593      1.11  macallan static int
   1594      1.40     isaki dbri_query_format(void *hdl, audio_format_query_t *afp)
   1595       1.1  macallan {
   1596       1.1  macallan 
   1597      1.40     isaki 	return audio_query_format(dbri_formats, DBRI_NFORMATS, afp);
   1598       1.1  macallan }
   1599       1.1  macallan 
   1600      1.11  macallan static int
   1601      1.40     isaki dbri_set_format(void *hdl, int setmode,
   1602      1.40     isaki 		const audio_params_t *play, const audio_params_t *rec,
   1603      1.40     isaki 		audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
   1604       1.1  macallan {
   1605       1.1  macallan 	struct dbri_softc *sc = hdl;
   1606      1.11  macallan 	int rate;
   1607       1.1  macallan 
   1608      1.40     isaki 	/* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */
   1609       1.1  macallan 
   1610      1.11  macallan 	for (rate = 0; CS4215_FREQ[rate].freq; rate++)
   1611      1.40     isaki 		if (CS4215_FREQ[rate].freq == play->sample_rate)
   1612       1.1  macallan 			break;
   1613       1.1  macallan 
   1614      1.11  macallan 	if (CS4215_FREQ[rate].freq == 0)
   1615      1.40     isaki 		return EINVAL;
   1616       1.1  macallan 
   1617       1.1  macallan 	/* set frequency */
   1618       1.9  macallan 	sc->sc_mm.c.bcontrol[1] &= ~0x38;
   1619      1.11  macallan 	sc->sc_mm.c.bcontrol[1] |= CS4215_FREQ[rate].csval;
   1620       1.9  macallan 	sc->sc_mm.c.bcontrol[2] &= ~0x70;
   1621      1.11  macallan 	sc->sc_mm.c.bcontrol[2] |= CS4215_FREQ[rate].xtal;
   1622       1.1  macallan 
   1623      1.40     isaki 	/* set encoding */
   1624      1.40     isaki 	sc->sc_mm.c.bcontrol[1] &= ~3;
   1625      1.40     isaki 	sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_LINEAR16;
   1626      1.40     isaki 
   1627      1.40     isaki 	/* set channel */
   1628      1.40     isaki 	sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_STEREO;
   1629       1.1  macallan 
   1630      1.37  macallan 	sc->sc_whack_codec = 1;
   1631      1.40     isaki 	return 0;
   1632       1.1  macallan }
   1633       1.1  macallan 
   1634      1.11  macallan static int
   1635       1.1  macallan dbri_round_blocksize(void *hdl, int bs, int mode,
   1636       1.1  macallan 			const audio_params_t *param)
   1637       1.1  macallan {
   1638       1.1  macallan 
   1639  1.41.2.1    martin 	if (bs > 0x1ffc)
   1640  1.41.2.1    martin 		return 0x1ffc;
   1641      1.40     isaki 	return bs;
   1642       1.1  macallan }
   1643       1.1  macallan 
   1644      1.11  macallan static int
   1645       1.1  macallan dbri_halt_output(void *hdl)
   1646       1.1  macallan {
   1647       1.1  macallan 	struct dbri_softc *sc = hdl;
   1648       1.1  macallan 
   1649      1.14  macallan 	if (!sc->sc_playing)
   1650      1.14  macallan 		return 0;
   1651      1.14  macallan 
   1652      1.13  macallan 	sc->sc_playing = 0;
   1653       1.1  macallan 	pipe_reset(sc, 4);
   1654       1.1  macallan 	return (0);
   1655       1.1  macallan }
   1656       1.1  macallan 
   1657      1.11  macallan static int
   1658       1.1  macallan dbri_getdev(void *hdl, struct audio_device *ret)
   1659       1.1  macallan {
   1660       1.1  macallan 
   1661       1.1  macallan 	*ret = dbri_device;
   1662       1.1  macallan 	return (0);
   1663       1.1  macallan }
   1664       1.1  macallan 
   1665      1.11  macallan static int
   1666       1.1  macallan dbri_set_port(void *hdl, mixer_ctrl_t *mc)
   1667       1.1  macallan {
   1668       1.1  macallan 	struct dbri_softc *sc = hdl;
   1669       1.1  macallan 	int latt = sc->sc_latt, ratt = sc->sc_ratt;
   1670       1.1  macallan 
   1671       1.1  macallan 	switch (mc->dev) {
   1672       1.1  macallan 	    case DBRI_VOL_OUTPUT:	/* master volume */
   1673       1.1  macallan 		latt = (latt & 0xc0) | (63 -
   1674      1.39  riastrad 		    uimin(mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] >> 2, 63));
   1675       1.5     blymn 		ratt = (ratt & 0xc0) | (63 -
   1676      1.39  riastrad 		    uimin(mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] >> 2, 63));
   1677       1.1  macallan 		break;
   1678       1.1  macallan 	    case DBRI_ENABLE_MONO:	/* built-in speaker */
   1679       1.1  macallan 	    	if (mc->un.ord == 1) {
   1680       1.1  macallan 			ratt |= CS4215_SE;
   1681       1.1  macallan 		} else
   1682       1.1  macallan 			ratt &= ~CS4215_SE;
   1683       1.1  macallan 		break;
   1684       1.1  macallan 	    case DBRI_ENABLE_HEADPHONE:	/* headphones output */
   1685       1.1  macallan 	    	if (mc->un.ord == 1) {
   1686       1.1  macallan 			latt |= CS4215_HE;
   1687       1.1  macallan 		} else
   1688       1.1  macallan 			latt &= ~CS4215_HE;
   1689       1.1  macallan 		break;
   1690       1.1  macallan 	    case DBRI_ENABLE_LINE:	/* line out */
   1691       1.1  macallan 	    	if (mc->un.ord == 1) {
   1692       1.1  macallan 			latt |= CS4215_LE;
   1693       1.1  macallan 		} else
   1694       1.1  macallan 			latt &= ~CS4215_LE;
   1695       1.1  macallan 		break;
   1696      1.13  macallan 	    case DBRI_VOL_MONITOR:
   1697      1.13  macallan 		if (mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] ==
   1698      1.13  macallan 		    sc->sc_monitor)
   1699      1.13  macallan 			return 0;
   1700      1.13  macallan 		sc->sc_monitor = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
   1701      1.13  macallan 		break;
   1702      1.13  macallan 	    case DBRI_INPUT_GAIN:
   1703      1.13  macallan 		sc->sc_linp = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
   1704      1.13  macallan 		sc->sc_rinp = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
   1705      1.13  macallan 		break;
   1706      1.13  macallan 	    case DBRI_INPUT_SELECT:
   1707      1.13  macallan 	    	if (mc->un.mask == sc->sc_input)
   1708      1.13  macallan 	    		return 0;
   1709      1.13  macallan 	    	sc->sc_input =  mc->un.mask;
   1710      1.13  macallan 	    	break;
   1711       1.1  macallan 	}
   1712       1.5     blymn 
   1713       1.1  macallan 	sc->sc_latt = latt;
   1714       1.1  macallan 	sc->sc_ratt = ratt;
   1715       1.1  macallan 
   1716      1.40     isaki 	mutex_spin_enter(&sc->sc_intr_lock);
   1717       1.1  macallan 	mmcodec_setgain(sc, 0);
   1718      1.40     isaki 	mutex_spin_exit(&sc->sc_intr_lock);
   1719       1.1  macallan 
   1720       1.1  macallan 	return (0);
   1721       1.1  macallan }
   1722       1.1  macallan 
   1723      1.11  macallan static int
   1724       1.1  macallan dbri_get_port(void *hdl, mixer_ctrl_t *mc)
   1725       1.1  macallan {
   1726       1.1  macallan 	struct dbri_softc *sc = hdl;
   1727       1.1  macallan 
   1728       1.1  macallan 	switch (mc->dev) {
   1729       1.1  macallan 	    case DBRI_VOL_OUTPUT:	/* master volume */
   1730       1.5     blymn 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
   1731       1.1  macallan 		    (63 - (sc->sc_latt & 0x3f)) << 2;
   1732       1.1  macallan 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
   1733       1.1  macallan 		    (63 - (sc->sc_ratt & 0x3f)) << 2;
   1734       1.1  macallan 		return (0);
   1735       1.1  macallan 	    case DBRI_ENABLE_MONO:	/* built-in speaker */
   1736       1.1  macallan 	    	mc->un.ord = (sc->sc_ratt & CS4215_SE) ? 1 : 0;
   1737       1.1  macallan 		return 0;
   1738       1.1  macallan 	    case DBRI_ENABLE_HEADPHONE:	/* headphones output */
   1739       1.1  macallan 	    	mc->un.ord = (sc->sc_latt & CS4215_HE) ? 1 : 0;
   1740       1.1  macallan 		return 0;
   1741       1.1  macallan 	    case DBRI_ENABLE_LINE:	/* line out */
   1742       1.1  macallan 	    	mc->un.ord = (sc->sc_latt & CS4215_LE) ? 1 : 0;
   1743       1.1  macallan 		return 0;
   1744      1.13  macallan 	    case DBRI_VOL_MONITOR:
   1745      1.13  macallan 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_monitor;
   1746      1.13  macallan 		return 0;
   1747      1.13  macallan 	    case DBRI_INPUT_GAIN:
   1748      1.13  macallan 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_linp;
   1749      1.13  macallan 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_rinp;
   1750      1.13  macallan 		return 0;
   1751      1.13  macallan 	    case DBRI_INPUT_SELECT:
   1752      1.13  macallan 	    	mc->un.mask = sc->sc_input;
   1753      1.13  macallan 	    	return 0;
   1754       1.1  macallan 	}
   1755       1.1  macallan 	return (EINVAL);
   1756       1.1  macallan }
   1757       1.1  macallan 
   1758      1.11  macallan static int
   1759       1.1  macallan dbri_query_devinfo(void *hdl, mixer_devinfo_t *di)
   1760       1.1  macallan {
   1761       1.1  macallan 
   1762       1.1  macallan 	switch (di->index) {
   1763       1.1  macallan 	case DBRI_MONITOR_CLASS:
   1764       1.1  macallan 		di->mixer_class = DBRI_MONITOR_CLASS;
   1765       1.1  macallan 		strcpy(di->label.name, AudioCmonitor);
   1766       1.1  macallan 		di->type = AUDIO_MIXER_CLASS;
   1767       1.1  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1768       1.1  macallan 		return 0;
   1769      1.13  macallan 	case DBRI_OUTPUT_CLASS:
   1770      1.13  macallan 		di->mixer_class = DBRI_OUTPUT_CLASS;
   1771      1.13  macallan 		strcpy(di->label.name, AudioCoutputs);
   1772      1.13  macallan 		di->type = AUDIO_MIXER_CLASS;
   1773      1.13  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1774      1.13  macallan 		return 0;
   1775      1.13  macallan 	case DBRI_INPUT_CLASS:
   1776      1.13  macallan 		di->mixer_class = DBRI_INPUT_CLASS;
   1777      1.13  macallan 		strcpy(di->label.name, AudioCinputs);
   1778      1.13  macallan 		di->type = AUDIO_MIXER_CLASS;
   1779      1.13  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1780      1.13  macallan 		return 0;
   1781       1.1  macallan 	case DBRI_VOL_OUTPUT:	/* master volume */
   1782      1.13  macallan 		di->mixer_class = DBRI_OUTPUT_CLASS;
   1783       1.1  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1784       1.1  macallan 		strcpy(di->label.name, AudioNmaster);
   1785       1.1  macallan 		di->type = AUDIO_MIXER_VALUE;
   1786       1.1  macallan 		di->un.v.num_channels = 2;
   1787      1.29  macallan 		di->un.v.delta = 16;
   1788       1.1  macallan 		strcpy(di->un.v.units.name, AudioNvolume);
   1789       1.1  macallan 		return (0);
   1790      1.13  macallan 	case DBRI_INPUT_GAIN:	/* input gain */
   1791      1.13  macallan 		di->mixer_class = DBRI_INPUT_CLASS;
   1792      1.13  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1793      1.13  macallan 		strcpy(di->label.name, AudioNrecord);
   1794      1.13  macallan 		di->type = AUDIO_MIXER_VALUE;
   1795      1.13  macallan 		di->un.v.num_channels = 2;
   1796      1.13  macallan 		strcpy(di->un.v.units.name, AudioNvolume);
   1797      1.13  macallan 		return (0);
   1798      1.13  macallan 	case DBRI_VOL_MONITOR:	/* monitor volume */
   1799      1.13  macallan 		di->mixer_class = DBRI_MONITOR_CLASS;
   1800      1.13  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1801      1.13  macallan 		strcpy(di->label.name, AudioNmonitor);
   1802      1.13  macallan 		di->type = AUDIO_MIXER_VALUE;
   1803      1.13  macallan 		di->un.v.num_channels = 1;
   1804      1.13  macallan 		strcpy(di->un.v.units.name, AudioNvolume);
   1805      1.13  macallan 		return (0);
   1806       1.1  macallan 	case DBRI_ENABLE_MONO:	/* built-in speaker */
   1807      1.13  macallan 		di->mixer_class = DBRI_OUTPUT_CLASS;
   1808       1.1  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1809       1.1  macallan 		strcpy(di->label.name, AudioNmono);
   1810       1.1  macallan 		di->type = AUDIO_MIXER_ENUM;
   1811       1.1  macallan 		di->un.e.num_mem = 2;
   1812       1.1  macallan 		strcpy(di->un.e.member[0].label.name, AudioNoff);
   1813       1.1  macallan 		di->un.e.member[0].ord = 0;
   1814       1.1  macallan 		strcpy(di->un.e.member[1].label.name, AudioNon);
   1815       1.1  macallan 		di->un.e.member[1].ord = 1;
   1816       1.1  macallan 		return (0);
   1817       1.1  macallan 	case DBRI_ENABLE_HEADPHONE:	/* headphones output */
   1818      1.13  macallan 		di->mixer_class = DBRI_OUTPUT_CLASS;
   1819       1.1  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1820       1.1  macallan 		strcpy(di->label.name, AudioNheadphone);
   1821       1.1  macallan 		di->type = AUDIO_MIXER_ENUM;
   1822       1.1  macallan 		di->un.e.num_mem = 2;
   1823       1.1  macallan 		strcpy(di->un.e.member[0].label.name, AudioNoff);
   1824       1.1  macallan 		di->un.e.member[0].ord = 0;
   1825       1.1  macallan 		strcpy(di->un.e.member[1].label.name, AudioNon);
   1826       1.1  macallan 		di->un.e.member[1].ord = 1;
   1827       1.1  macallan 		return (0);
   1828       1.1  macallan 	case DBRI_ENABLE_LINE:	/* line out */
   1829      1.13  macallan 		di->mixer_class = DBRI_OUTPUT_CLASS;
   1830       1.1  macallan 		di->next = di->prev = AUDIO_MIXER_LAST;
   1831       1.1  macallan 		strcpy(di->label.name, AudioNline);
   1832       1.1  macallan 		di->type = AUDIO_MIXER_ENUM;
   1833       1.1  macallan 		di->un.e.num_mem = 2;
   1834       1.1  macallan 		strcpy(di->un.e.member[0].label.name, AudioNoff);
   1835       1.1  macallan 		di->un.e.member[0].ord = 0;
   1836       1.1  macallan 		strcpy(di->un.e.member[1].label.name, AudioNon);
   1837       1.1  macallan 		di->un.e.member[1].ord = 1;
   1838       1.1  macallan 		return (0);
   1839      1.13  macallan 	case DBRI_INPUT_SELECT:
   1840      1.13  macallan 		di->mixer_class = DBRI_INPUT_CLASS;
   1841      1.13  macallan 		strcpy(di->label.name, AudioNsource);
   1842      1.13  macallan 		di->type = AUDIO_MIXER_SET;
   1843      1.13  macallan 		di->prev = di->next = AUDIO_MIXER_LAST;
   1844      1.13  macallan 		di->un.s.num_mem = 2;
   1845      1.13  macallan 		strcpy(di->un.s.member[0].label.name, AudioNline);
   1846      1.13  macallan 		di->un.s.member[0].mask = 1 << 0;
   1847      1.13  macallan 		strcpy(di->un.s.member[1].label.name, AudioNmicrophone);
   1848      1.13  macallan 		di->un.s.member[1].mask = 1 << 1;
   1849      1.13  macallan 		return 0;
   1850       1.1  macallan 	}
   1851       1.5     blymn 
   1852       1.1  macallan 	return (ENXIO);
   1853       1.1  macallan }
   1854       1.1  macallan 
   1855      1.11  macallan static int
   1856       1.1  macallan dbri_get_props(void *hdl)
   1857       1.1  macallan {
   1858       1.1  macallan 
   1859      1.41     isaki 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
   1860      1.41     isaki 	    AUDIO_PROP_FULLDUPLEX;
   1861       1.1  macallan }
   1862       1.1  macallan 
   1863      1.11  macallan static int
   1864      1.37  macallan dbri_commit(void *hdl)
   1865      1.37  macallan {
   1866      1.37  macallan 	struct dbri_softc *sc = hdl;
   1867      1.37  macallan 	int ret = 0;
   1868      1.37  macallan 
   1869      1.37  macallan 	/*
   1870      1.37  macallan 	 * we only need to whack the codec if things like sample format or
   1871      1.37  macallan 	 * frequency changed, not for mixer stuff
   1872      1.37  macallan 	 */
   1873      1.37  macallan 	if (sc->sc_whack_codec == 0)
   1874      1.37  macallan 		return 0;
   1875      1.37  macallan 
   1876      1.38       mrg 	mutex_spin_enter(&sc->sc_intr_lock);
   1877      1.37  macallan 	ret = mmcodec_setcontrol(sc);
   1878      1.37  macallan 	if (ret) {
   1879      1.37  macallan 		DPRINTF("%s: control mode failed. Mutex %s PIL %x\n", __func__,
   1880      1.37  macallan 		    mutex_owned(&sc->sc_intr_lock) ? "held" : "free",
   1881      1.37  macallan 		    (getpsr() & PSR_PIL) >> 8);
   1882      1.37  macallan 	} else
   1883      1.37  macallan 		DPRINTF("%s: control mode ok\n", __func__);
   1884      1.37  macallan 	mmcodec_init_data(sc);
   1885      1.38       mrg 	mutex_spin_exit(&sc->sc_intr_lock);
   1886      1.37  macallan 	return 0;
   1887      1.37  macallan }
   1888      1.37  macallan 
   1889      1.37  macallan static int
   1890       1.1  macallan dbri_trigger_output(void *hdl, void *start, void *end, int blksize,
   1891       1.1  macallan 		    void (*intr)(void *), void *intrarg,
   1892       1.1  macallan 		    const struct audio_params *param)
   1893       1.1  macallan {
   1894       1.1  macallan 	struct dbri_softc *sc = hdl;
   1895      1.14  macallan 	unsigned long count, num;
   1896      1.14  macallan 
   1897      1.14  macallan 	if (sc->sc_playing)
   1898      1.14  macallan 		return 0;
   1899       1.1  macallan 
   1900       1.8       mrg 	count = (unsigned long)(((char *)end - (char *)start));
   1901       1.1  macallan 	num = count / blksize;
   1902       1.5     blymn 
   1903      1.10  macallan 	DPRINTF("trigger_output(%lx %lx) : %d %ld %ld\n",
   1904       1.1  macallan 	    (unsigned long)intr,
   1905      1.10  macallan 	    (unsigned long)intrarg, blksize, count, num);
   1906       1.4  macallan 
   1907       1.1  macallan 	sc->sc_params = *param;
   1908       1.1  macallan 
   1909      1.14  macallan 	/*
   1910      1.14  macallan 	 * always use DMA descriptor 0 for output
   1911      1.14  macallan 	 * no need to allocate them dynamically since we only ever have
   1912      1.14  macallan 	 * exactly one input stream and exactly one output stream
   1913      1.14  macallan 	 */
   1914      1.14  macallan 	setup_ring_xmit(sc, 4, 0, num, blksize, intr, intrarg);
   1915      1.14  macallan 	sc->sc_playing = 1;
   1916      1.14  macallan 	return 0;
   1917       1.1  macallan }
   1918       1.1  macallan 
   1919      1.13  macallan static int
   1920      1.13  macallan dbri_halt_input(void *cookie)
   1921      1.13  macallan {
   1922      1.14  macallan 	struct dbri_softc *sc = cookie;
   1923      1.14  macallan 
   1924      1.14  macallan 	if (!sc->sc_recording)
   1925      1.14  macallan 		return 0;
   1926      1.14  macallan 
   1927      1.14  macallan 	sc->sc_recording = 0;
   1928      1.14  macallan 	pipe_reset(sc, 6);
   1929      1.13  macallan 	return 0;
   1930      1.13  macallan }
   1931      1.13  macallan 
   1932      1.13  macallan static int
   1933      1.13  macallan dbri_trigger_input(void *hdl, void *start, void *end, int blksize,
   1934      1.13  macallan 		    void (*intr)(void *), void *intrarg,
   1935      1.13  macallan 		    const struct audio_params *param)
   1936      1.13  macallan {
   1937      1.13  macallan 	struct dbri_softc *sc = hdl;
   1938      1.14  macallan 	unsigned long count, num;
   1939      1.14  macallan 
   1940      1.14  macallan 	if (sc->sc_recording)
   1941      1.14  macallan 		return 0;
   1942      1.13  macallan 
   1943      1.13  macallan 	count = (unsigned long)(((char *)end - (char *)start));
   1944      1.13  macallan 	num = count / blksize;
   1945      1.13  macallan 
   1946      1.13  macallan 	DPRINTF("trigger_input(%lx %lx) : %d %ld %ld\n",
   1947      1.13  macallan 	    (unsigned long)intr,
   1948      1.13  macallan 	    (unsigned long)intrarg, blksize, count, num);
   1949      1.13  macallan 
   1950      1.13  macallan 	sc->sc_params = *param;
   1951      1.13  macallan 
   1952      1.14  macallan 	sc->sc_recording = 1;
   1953      1.14  macallan 	setup_ring_recv(sc, 6, 1, num, blksize, intr, intrarg);
   1954      1.14  macallan 	return 0;
   1955      1.13  macallan }
   1956      1.13  macallan 
   1957      1.34  jmcneill static void
   1958      1.34  jmcneill dbri_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
   1959      1.34  jmcneill {
   1960      1.34  jmcneill 	struct dbri_softc *sc = opaque;
   1961      1.34  jmcneill 
   1962      1.34  jmcneill 	*intr = &sc->sc_intr_lock;
   1963      1.34  jmcneill 	*thread = &sc->sc_lock;
   1964      1.34  jmcneill }
   1965      1.13  macallan 
   1966      1.25   tsutsui static uint32_t
   1967      1.25   tsutsui reverse_bytes(uint32_t b, int len)
   1968       1.1  macallan {
   1969       1.1  macallan 	switch (len) {
   1970       1.1  macallan 	case 32:
   1971       1.1  macallan 		b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16);
   1972       1.1  macallan 	case 16:
   1973       1.1  macallan 		b = ((b & 0xff00ff00) >>  8) | ((b & 0x00ff00ff) <<  8);
   1974       1.1  macallan 	case 8:
   1975       1.1  macallan 		b = ((b & 0xf0f0f0f0) >>  4) | ((b & 0x0f0f0f0f) <<  4);
   1976       1.1  macallan 	case 4:
   1977       1.1  macallan 		b = ((b & 0xcccccccc) >>  2) | ((b & 0x33333333) <<  2);
   1978       1.1  macallan 	case 2:
   1979       1.1  macallan 		b = ((b & 0xaaaaaaaa) >>  1) | ((b & 0x55555555) <<  1);
   1980       1.1  macallan 	case 1:
   1981       1.1  macallan 	case 0:
   1982       1.1  macallan 		break;
   1983       1.1  macallan 	default:
   1984      1.10  macallan 		DPRINTF("reverse_bytes: unsupported length\n");
   1985       1.1  macallan 	};
   1986       1.1  macallan 
   1987       1.1  macallan 	return (b);
   1988       1.1  macallan }
   1989       1.1  macallan 
   1990      1.14  macallan static void *
   1991      1.34  jmcneill dbri_malloc(void *v, int dir, size_t s)
   1992       1.1  macallan {
   1993       1.1  macallan 	struct dbri_softc *sc = v;
   1994       1.1  macallan 	struct dbri_desc *dd = &sc->sc_desc[sc->sc_desc_used];
   1995       1.1  macallan 	int rseg;
   1996       1.5     blymn 
   1997       1.5     blymn 	if (bus_dmamap_create(sc->sc_dmat, s, 1, s, 0, BUS_DMA_NOWAIT,
   1998       1.1  macallan 	    &dd->dmamap) == 0) {
   1999       1.1  macallan 		if (bus_dmamem_alloc(sc->sc_dmat, s, 0, 0, &dd->dmaseg,
   2000       1.1  macallan 		    1, &rseg, BUS_DMA_NOWAIT) == 0) {
   2001       1.1  macallan 			if (bus_dmamem_map(sc->sc_dmat, &dd->dmaseg, rseg, s,
   2002       1.5     blymn 			    &dd->buf, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) == 0) {
   2003      1.14  macallan 				if (dd->buf != NULL) {
   2004       1.5     blymn 					if (bus_dmamap_load(sc->sc_dmat,
   2005       1.5     blymn 					    dd->dmamap, dd->buf, s, NULL,
   2006       1.1  macallan 					    BUS_DMA_NOWAIT) == 0) {
   2007       1.1  macallan 						dd->len = s;
   2008       1.1  macallan 						dd->busy = 0;
   2009       1.1  macallan 						dd->callback = NULL;
   2010       1.5     blymn 						dd->dmabase =
   2011       1.1  macallan 						 dd->dmamap->dm_segs[0].ds_addr;
   2012      1.14  macallan 						DPRINTF("dbri_malloc: using buffer %d %08x\n",
   2013      1.14  macallan 						    sc->sc_desc_used, (uint32_t)dd->buf);
   2014       1.1  macallan 						sc->sc_desc_used++;
   2015       1.1  macallan 						return dd->buf;
   2016       1.1  macallan 					} else
   2017      1.10  macallan 						aprint_error("dbri_malloc: load failed\n");
   2018       1.1  macallan 				} else
   2019      1.10  macallan 					aprint_error("dbri_malloc: map returned NULL\n");
   2020       1.1  macallan 			} else
   2021      1.10  macallan 				aprint_error("dbri_malloc: map failed\n");
   2022       1.1  macallan 			bus_dmamem_free(sc->sc_dmat, &dd->dmaseg, rseg);
   2023       1.1  macallan 		} else
   2024      1.10  macallan 			aprint_error("dbri_malloc: malloc() failed\n");
   2025       1.1  macallan 		bus_dmamap_destroy(sc->sc_dmat, dd->dmamap);
   2026       1.1  macallan 	} else
   2027      1.10  macallan 		aprint_error("dbri_malloc: bus_dmamap_create() failed\n");
   2028       1.1  macallan 	return NULL;
   2029       1.1  macallan }
   2030       1.1  macallan 
   2031       1.1  macallan static void
   2032      1.34  jmcneill dbri_free(void *v, void *p, size_t size)
   2033       1.1  macallan {
   2034      1.23    martin 	struct dbri_softc *sc = v;
   2035      1.23    martin 	struct dbri_desc *dd;
   2036      1.23    martin 	int i;
   2037      1.23    martin 
   2038      1.23    martin 	for (i = 0; i < sc->sc_desc_used; i++) {
   2039      1.23    martin 		dd = &sc->sc_desc[i];
   2040      1.23    martin 		if (dd->buf == p)
   2041      1.23    martin 			break;
   2042      1.23    martin 	}
   2043      1.23    martin 	if (i >= sc->sc_desc_used)
   2044      1.23    martin 		return;
   2045      1.23    martin 	bus_dmamap_unload(sc->sc_dmat, dd->dmamap);
   2046      1.23    martin 	bus_dmamap_destroy(sc->sc_dmat, dd->dmamap);
   2047       1.1  macallan }
   2048       1.1  macallan 
   2049       1.4  macallan static int
   2050       1.4  macallan dbri_open(void *cookie, int flags)
   2051       1.4  macallan {
   2052       1.4  macallan 	struct dbri_softc *sc = cookie;
   2053       1.5     blymn 
   2054      1.14  macallan 	DPRINTF("%s: %d\n", __func__, sc->sc_refcount);
   2055      1.14  macallan 
   2056      1.38       mrg 	if (sc->sc_refcount == 0) {
   2057      1.14  macallan 		dbri_bring_up(sc);
   2058      1.38       mrg 	}
   2059      1.14  macallan 
   2060      1.14  macallan 	sc->sc_refcount++;
   2061      1.14  macallan 
   2062       1.4  macallan 	return 0;
   2063       1.4  macallan }
   2064       1.4  macallan 
   2065       1.4  macallan static void
   2066       1.4  macallan dbri_close(void *cookie)
   2067       1.4  macallan {
   2068       1.4  macallan 	struct dbri_softc *sc = cookie;
   2069       1.5     blymn 
   2070      1.14  macallan 	DPRINTF("%s: %d\n", __func__, sc->sc_refcount);
   2071      1.14  macallan 
   2072      1.14  macallan 	sc->sc_refcount--;
   2073      1.14  macallan 	KASSERT(sc->sc_refcount >= 0);
   2074      1.14  macallan 	if (sc->sc_refcount > 0)
   2075      1.14  macallan 		return;
   2076      1.14  macallan 
   2077       1.4  macallan 	dbri_set_power(sc, 0);
   2078      1.14  macallan 	sc->sc_playing = 0;
   2079      1.14  macallan 	sc->sc_recording = 0;
   2080       1.4  macallan }
   2081       1.4  macallan 
   2082      1.26  christos static bool
   2083      1.31    dyoung dbri_suspend(device_t self, const pmf_qual_t *qual)
   2084       1.4  macallan {
   2085      1.26  christos 	struct dbri_softc *sc = device_private(self);
   2086      1.26  christos 
   2087      1.36       mrg 	mutex_spin_enter(&sc->sc_intr_lock);
   2088      1.26  christos 	dbri_set_power(sc, 0);
   2089      1.36       mrg 	mutex_spin_exit(&sc->sc_intr_lock);
   2090      1.26  christos 	return true;
   2091      1.26  christos }
   2092       1.5     blymn 
   2093      1.26  christos static bool
   2094      1.31    dyoung dbri_resume(device_t self, const pmf_qual_t *qual)
   2095      1.26  christos {
   2096      1.27   tsutsui 	struct dbri_softc *sc = device_private(self);
   2097      1.27   tsutsui 
   2098      1.26  christos 	if (sc->sc_powerstate != 0)
   2099      1.27   tsutsui 		return true;
   2100      1.26  christos 	aprint_verbose("resume: %d\n", sc->sc_refcount);
   2101      1.26  christos 	if (sc->sc_playing) {
   2102      1.26  christos 		volatile uint32_t *cmd;
   2103      1.13  macallan 
   2104      1.36       mrg 		mutex_spin_enter(&sc->sc_intr_lock);
   2105      1.26  christos 		dbri_bring_up(sc);
   2106      1.26  christos 		cmd = dbri_command_lock(sc);
   2107      1.26  christos 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP,
   2108      1.26  christos 		    0, sc->sc_pipe[4].sdp |
   2109      1.26  christos 		    DBRI_SDP_VALID_POINTER |
   2110      1.26  christos 		    DBRI_SDP_EVERY | DBRI_SDP_CLEAR);
   2111      1.26  christos 		*(cmd++) = sc->sc_dmabase +
   2112      1.26  christos 		    dbri_dma_off(xmit, 0);
   2113      1.26  christos 		dbri_command_send(sc, cmd);
   2114      1.34  jmcneill 		mutex_spin_exit(&sc->sc_intr_lock);
   2115       1.4  macallan 	}
   2116      1.26  christos 	return true;
   2117       1.4  macallan }
   2118       1.5     blymn 
   2119       1.4  macallan #endif /* NAUDIO > 0 */
   2120