Home | History | Annotate | Line # | Download | only in pci
gcscaudio.c revision 1.15.10.2
      1  1.15.10.2    martin /*	$NetBSD: gcscaudio.c,v 1.15.10.2 2020/04/08 14:08:09 martin Exp $	*/
      2        1.1  jmcneill 
      3        1.1  jmcneill /*-
      4        1.1  jmcneill  * Copyright (c) 2008 SHIMIZU Ryo <ryo (at) nerv.org>
      5        1.1  jmcneill  * All rights reserved.
      6        1.1  jmcneill  *
      7        1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
      8        1.1  jmcneill  * modification, are permitted provided that the following conditions
      9        1.1  jmcneill  * are met:
     10        1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     11        1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     12        1.1  jmcneill  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1  jmcneill  *    notice, this list of conditions and the following disclaimer in the
     14        1.1  jmcneill  *    documentation and/or other materials provided with the distribution.
     15        1.1  jmcneill  *
     16        1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17        1.1  jmcneill  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18        1.1  jmcneill  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19        1.1  jmcneill  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20        1.1  jmcneill  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21        1.1  jmcneill  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22        1.1  jmcneill  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23        1.1  jmcneill  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24        1.1  jmcneill  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25        1.1  jmcneill  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26        1.1  jmcneill  * POSSIBILITY OF SUCH DAMAGE.
     27        1.1  jmcneill  */
     28        1.1  jmcneill 
     29        1.1  jmcneill #include <sys/cdefs.h>
     30  1.15.10.2    martin __KERNEL_RCSID(0, "$NetBSD: gcscaudio.c,v 1.15.10.2 2020/04/08 14:08:09 martin Exp $");
     31        1.1  jmcneill 
     32        1.1  jmcneill #include <sys/param.h>
     33        1.1  jmcneill #include <sys/systm.h>
     34        1.8  jmcneill #include <sys/kmem.h>
     35        1.1  jmcneill #include <sys/device.h>
     36        1.1  jmcneill #include <sys/queue.h>
     37        1.1  jmcneill 
     38        1.1  jmcneill #include <dev/pci/pcidevs.h>
     39        1.1  jmcneill #include <dev/pci/pcivar.h>
     40        1.1  jmcneill 
     41        1.1  jmcneill #include <sys/audioio.h>
     42  1.15.10.1  christos #include <dev/audio/audio_if.h>
     43  1.15.10.1  christos 
     44        1.1  jmcneill #include <dev/ic/ac97reg.h>
     45        1.1  jmcneill #include <dev/ic/ac97var.h>
     46        1.1  jmcneill 
     47        1.1  jmcneill #include <dev/pci/gcscaudioreg.h>
     48        1.1  jmcneill 
     49        1.1  jmcneill 
     50        1.1  jmcneill #define	GCSCAUDIO_NPRDTABLE	256	/* including a JMP-PRD for loop */
     51        1.1  jmcneill #define	GCSCAUDIO_PRD_SIZE_MAX	65532	/* limited by CS5536 Controller */
     52        1.1  jmcneill #define	GCSCAUDIO_BUFSIZE_MAX	(GCSCAUDIO_PRD_SIZE_MAX * (GCSCAUDIO_NPRDTABLE - 1))
     53        1.1  jmcneill 
     54        1.1  jmcneill struct gcscaudio_prd {
     55        1.1  jmcneill 	/* PRD table for play/rec */
     56        1.1  jmcneill 	struct gcscaudio_prdtables {
     57        1.1  jmcneill #define	PRD_TABLE_FRONT		0
     58        1.1  jmcneill #define	PRD_TABLE_SURR		1
     59        1.1  jmcneill #define	PRD_TABLE_CENTER	2
     60        1.1  jmcneill #define	PRD_TABLE_LFE		3
     61        1.1  jmcneill #define	PRD_TABLE_REC		4
     62        1.1  jmcneill #define	PRD_TABLE_MAX		5
     63        1.1  jmcneill 		struct acc_prd prdtbl[PRD_TABLE_MAX][GCSCAUDIO_NPRDTABLE];
     64        1.1  jmcneill 	} *p_prdtables;
     65        1.1  jmcneill 	bus_dmamap_t p_prdmap;
     66        1.1  jmcneill 	bus_dma_segment_t p_prdsegs[1];
     67        1.1  jmcneill 	int p_prdnseg;
     68        1.1  jmcneill };
     69        1.1  jmcneill 
     70        1.1  jmcneill struct gcscaudio_dma {
     71        1.1  jmcneill 	LIST_ENTRY(gcscaudio_dma) list;
     72        1.1  jmcneill 	bus_dmamap_t map;
     73        1.1  jmcneill 	void *addr;
     74        1.1  jmcneill 	size_t size;
     75        1.1  jmcneill 	bus_dma_segment_t segs[1];
     76        1.1  jmcneill 	int nseg;
     77        1.1  jmcneill };
     78        1.1  jmcneill 
     79        1.1  jmcneill struct gcscaudio_softc_ch {
     80        1.1  jmcneill 	void (*ch_intr)(void *);
     81        1.1  jmcneill 	void *ch_intr_arg;
     82        1.1  jmcneill 	struct audio_params ch_params;
     83        1.1  jmcneill };
     84        1.1  jmcneill 
     85        1.1  jmcneill struct gcscaudio_softc {
     86       1.12    nonaka 	device_t sc_dev;
     87        1.8  jmcneill 	kmutex_t sc_lock;
     88        1.8  jmcneill 	kmutex_t sc_intr_lock;
     89        1.1  jmcneill 	pci_chipset_tag_t sc_pc;
     90        1.1  jmcneill 	pcitag_t sc_pt;
     91        1.1  jmcneill 	void *sc_ih;
     92        1.1  jmcneill 	bus_space_tag_t sc_iot;
     93        1.1  jmcneill 	bus_space_handle_t sc_ioh;
     94        1.1  jmcneill 	bus_size_t sc_ios;
     95        1.1  jmcneill 	bus_dma_tag_t sc_dmat;
     96        1.1  jmcneill 
     97        1.1  jmcneill 	/* allocated DMA buffer list */
     98        1.1  jmcneill 	LIST_HEAD(, gcscaudio_dma) sc_dmalist;
     99        1.1  jmcneill 
    100        1.1  jmcneill #define GCSCAUDIO_MAXFORMATS	4
    101        1.1  jmcneill 	struct audio_format sc_formats[GCSCAUDIO_MAXFORMATS];
    102        1.1  jmcneill 	int sc_nformats;
    103        1.1  jmcneill 
    104        1.1  jmcneill 	/* AC97 codec */
    105        1.1  jmcneill 	struct ac97_host_if host_if;
    106        1.1  jmcneill 	struct ac97_codec_if *codec_if;
    107        1.1  jmcneill 
    108        1.1  jmcneill 	/* input, output channels */
    109        1.1  jmcneill 	struct gcscaudio_softc_ch sc_play;
    110        1.1  jmcneill 	struct gcscaudio_softc_ch sc_rec;
    111        1.1  jmcneill 	struct gcscaudio_prd sc_prd;
    112        1.1  jmcneill 
    113        1.1  jmcneill 	/* multi channel splitter work; {4,6}ch stream to {2,4} DMA buffers */
    114        1.1  jmcneill 	void *sc_mch_split_buf;
    115        1.1  jmcneill 	void *sc_mch_split_start;
    116        1.1  jmcneill 	int sc_mch_split_off;
    117        1.1  jmcneill 	int sc_mch_split_size;
    118        1.1  jmcneill 	int sc_mch_split_blksize;
    119        1.1  jmcneill 	void (*sc_mch_splitter)(void *, void *, int, int);
    120        1.1  jmcneill 	bool sc_spdif;
    121        1.1  jmcneill };
    122        1.1  jmcneill 
    123        1.1  jmcneill /* for cfattach */
    124        1.2    cegger static int gcscaudio_match(device_t, cfdata_t, void *);
    125        1.1  jmcneill static void gcscaudio_attach(device_t, device_t, void *);
    126        1.1  jmcneill 
    127        1.1  jmcneill /* for audio_hw_if */
    128        1.1  jmcneill static int gcscaudio_open(void *, int);
    129        1.1  jmcneill static void gcscaudio_close(void *);
    130  1.15.10.1  christos static int gcscaudio_query_format(void *, audio_format_query_t *);
    131  1.15.10.1  christos static int gcscaudio_set_format(void *, int,
    132  1.15.10.1  christos                                 const audio_params_t *, const audio_params_t *,
    133  1.15.10.1  christos                                 audio_filter_reg_t *, audio_filter_reg_t *);
    134        1.1  jmcneill static int gcscaudio_round_blocksize(void *, int, int, const audio_params_t *);
    135        1.1  jmcneill static int gcscaudio_halt_output(void *);
    136        1.1  jmcneill static int gcscaudio_halt_input(void *);
    137        1.1  jmcneill static int gcscaudio_getdev(void *, struct audio_device *);
    138        1.1  jmcneill static int gcscaudio_set_port(void *, mixer_ctrl_t *);
    139        1.1  jmcneill static int gcscaudio_get_port(void *, mixer_ctrl_t *);
    140        1.1  jmcneill static int gcscaudio_query_devinfo(void *, mixer_devinfo_t *);
    141        1.8  jmcneill static void *gcscaudio_malloc(void *, int, size_t);
    142        1.8  jmcneill static void gcscaudio_free(void *, void *, size_t);
    143        1.1  jmcneill static size_t gcscaudio_round_buffersize(void *, int, size_t);
    144        1.1  jmcneill static int gcscaudio_get_props(void *);
    145        1.1  jmcneill static int gcscaudio_trigger_output(void *, void *, void *, int,
    146        1.1  jmcneill                                     void (*)(void *), void *,
    147        1.1  jmcneill                                     const audio_params_t *);
    148        1.1  jmcneill static int gcscaudio_trigger_input(void *, void *, void *, int,
    149        1.1  jmcneill                                    void (*)(void *), void *,
    150        1.1  jmcneill                                    const audio_params_t *);
    151        1.8  jmcneill static void gcscaudio_get_locks(void *, kmutex_t **, kmutex_t **);
    152        1.5    dyoung static bool gcscaudio_resume(device_t, const pmf_qual_t *);
    153        1.1  jmcneill static int gcscaudio_intr(void *);
    154        1.1  jmcneill 
    155        1.1  jmcneill /* for codec_if */
    156        1.1  jmcneill static int gcscaudio_attach_codec(void *, struct ac97_codec_if *);
    157        1.1  jmcneill static int gcscaudio_write_codec(void *, uint8_t, uint16_t);
    158        1.1  jmcneill static int gcscaudio_read_codec(void *, uint8_t, uint16_t *);
    159        1.1  jmcneill static int gcscaudio_reset_codec(void *);
    160        1.1  jmcneill static void gcscaudio_spdif_event_codec(void *, bool);
    161        1.1  jmcneill 
    162        1.1  jmcneill /* misc */
    163        1.1  jmcneill static int gcscaudio_append_formats(struct gcscaudio_softc *,
    164        1.1  jmcneill                                     const struct audio_format *);
    165        1.1  jmcneill static int gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *);
    166        1.1  jmcneill static int gcscaudio_allocate_dma(struct gcscaudio_softc *, size_t, void **,
    167        1.1  jmcneill                                   bus_dma_segment_t *, int, int *,
    168        1.8  jmcneill                                   bus_dmamap_t *);
    169        1.1  jmcneill 
    170        1.1  jmcneill 
    171       1.12    nonaka CFATTACH_DECL_NEW(gcscaudio, sizeof (struct gcscaudio_softc),
    172        1.1  jmcneill     gcscaudio_match, gcscaudio_attach, NULL, NULL);
    173        1.1  jmcneill 
    174        1.1  jmcneill 
    175        1.1  jmcneill static struct audio_device gcscaudio_device = {
    176        1.1  jmcneill 	"AMD Geode CS5536",
    177        1.1  jmcneill 	"",
    178        1.1  jmcneill 	"gcscaudio"
    179        1.1  jmcneill };
    180        1.1  jmcneill 
    181        1.1  jmcneill static const struct audio_hw_if gcscaudio_hw_if = {
    182        1.1  jmcneill 	.open			= gcscaudio_open,
    183        1.1  jmcneill 	.close			= gcscaudio_close,
    184  1.15.10.1  christos 	.query_format		= gcscaudio_query_format,
    185  1.15.10.1  christos 	.set_format		= gcscaudio_set_format,
    186        1.1  jmcneill 	.round_blocksize	= gcscaudio_round_blocksize,
    187        1.1  jmcneill 	.commit_settings	= NULL,
    188        1.1  jmcneill 	.init_output		= NULL,
    189        1.1  jmcneill 	.init_input		= NULL,
    190        1.1  jmcneill 	.start_output		= NULL,
    191        1.1  jmcneill 	.start_input		= NULL,
    192        1.1  jmcneill 	.halt_output		= gcscaudio_halt_output,
    193        1.1  jmcneill 	.halt_input		= gcscaudio_halt_input,
    194        1.1  jmcneill 	.speaker_ctl		= NULL,
    195        1.1  jmcneill 	.getdev			= gcscaudio_getdev,
    196        1.1  jmcneill 	.set_port		= gcscaudio_set_port,
    197        1.1  jmcneill 	.get_port		= gcscaudio_get_port,
    198        1.1  jmcneill 	.query_devinfo		= gcscaudio_query_devinfo,
    199        1.1  jmcneill 	.allocm			= gcscaudio_malloc,
    200        1.1  jmcneill 	.freem			= gcscaudio_free,
    201        1.1  jmcneill 	.round_buffersize	= gcscaudio_round_buffersize,
    202        1.1  jmcneill 	.get_props		= gcscaudio_get_props,
    203        1.1  jmcneill 	.trigger_output		= gcscaudio_trigger_output,
    204        1.1  jmcneill 	.trigger_input		= gcscaudio_trigger_input,
    205        1.1  jmcneill 	.dev_ioctl		= NULL,
    206        1.8  jmcneill 	.get_locks		= gcscaudio_get_locks,
    207        1.1  jmcneill };
    208        1.1  jmcneill 
    209  1.15.10.1  christos #define GCSCAUDIO_FORMAT(aumode, ch, chmask) \
    210  1.15.10.1  christos 	{ \
    211  1.15.10.1  christos 		.mode		= (aumode), \
    212  1.15.10.1  christos 		.encoding	= AUDIO_ENCODING_SLINEAR_LE, \
    213  1.15.10.1  christos 		.validbits	= 16, \
    214  1.15.10.1  christos 		.precision	= 16, \
    215  1.15.10.1  christos 		.channels	= (ch), \
    216  1.15.10.1  christos 		.channel_mask	= (chmask), \
    217  1.15.10.1  christos 		.frequency_type	= 0, \
    218  1.15.10.1  christos 		.frequency	= { 8000, 48000 }, \
    219  1.15.10.1  christos 	}
    220  1.15.10.1  christos static const struct audio_format gcscaudio_formats_2ch =
    221  1.15.10.1  christos 	GCSCAUDIO_FORMAT(AUMODE_PLAY | AUMODE_RECORD, 2, AUFMT_STEREO);
    222        1.1  jmcneill 
    223  1.15.10.1  christos static const struct audio_format gcscaudio_formats_4ch =
    224  1.15.10.1  christos 	GCSCAUDIO_FORMAT(AUMODE_PLAY                , 4, AUFMT_SURROUND4);
    225        1.1  jmcneill 
    226  1.15.10.1  christos static const struct audio_format gcscaudio_formats_6ch =
    227  1.15.10.1  christos 	GCSCAUDIO_FORMAT(AUMODE_PLAY                , 6, AUFMT_DOLBY_5_1);
    228        1.1  jmcneill 
    229        1.1  jmcneill static int
    230        1.2    cegger gcscaudio_match(device_t parent, cfdata_t match, void *aux)
    231        1.1  jmcneill {
    232        1.1  jmcneill 	struct pci_attach_args *pa;
    233        1.1  jmcneill 
    234        1.1  jmcneill 	pa = (struct pci_attach_args *)aux;
    235        1.1  jmcneill 	if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) &&
    236        1.1  jmcneill 	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_CS5536_AUDIO))
    237        1.1  jmcneill 		return 1;
    238        1.1  jmcneill 
    239        1.1  jmcneill 	return 0;
    240        1.1  jmcneill }
    241        1.1  jmcneill 
    242        1.1  jmcneill static int
    243        1.1  jmcneill gcscaudio_append_formats(struct gcscaudio_softc *sc,
    244        1.1  jmcneill                          const struct audio_format *format)
    245        1.1  jmcneill {
    246        1.1  jmcneill 	if (sc->sc_nformats >= GCSCAUDIO_MAXFORMATS) {
    247       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "too many formats\n");
    248        1.1  jmcneill 		return EINVAL;
    249        1.1  jmcneill 	}
    250        1.1  jmcneill 	sc->sc_formats[sc->sc_nformats++] = *format;
    251        1.1  jmcneill 	return 0;
    252        1.1  jmcneill }
    253        1.1  jmcneill 
    254        1.1  jmcneill static void
    255        1.1  jmcneill gcscaudio_attach(device_t parent, device_t self, void *aux)
    256        1.1  jmcneill {
    257        1.1  jmcneill 	struct gcscaudio_softc *sc;
    258        1.1  jmcneill 	struct pci_attach_args *pa;
    259        1.1  jmcneill 	const char *intrstr;
    260        1.1  jmcneill 	pci_intr_handle_t ih;
    261        1.1  jmcneill 	int rc, i;
    262       1.14  christos 	char intrbuf[PCI_INTRSTR_LEN];
    263        1.1  jmcneill 
    264        1.1  jmcneill 	sc = device_private(self);
    265        1.1  jmcneill 
    266       1.12    nonaka 	sc->sc_dev = self;
    267       1.12    nonaka 
    268        1.1  jmcneill 	aprint_naive(": Audio controller\n");
    269        1.1  jmcneill 
    270        1.1  jmcneill 	pa = aux;
    271        1.1  jmcneill 	sc->sc_pc = pa->pa_pc;
    272        1.1  jmcneill 	sc->sc_pt = pa->pa_tag;
    273        1.1  jmcneill 	sc->sc_dmat = pa->pa_dmat;
    274        1.1  jmcneill 	LIST_INIT(&sc->sc_dmalist);
    275        1.1  jmcneill 	sc->sc_mch_split_buf = NULL;
    276        1.8  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    277        1.9       mrg 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    278        1.1  jmcneill 
    279        1.1  jmcneill 	aprint_normal(": AMD Geode CS5536 Audio\n");
    280        1.1  jmcneill 
    281        1.1  jmcneill 	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
    282        1.1  jmcneill 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios)) {
    283       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "can't map i/o space\n");
    284        1.1  jmcneill 		return;
    285        1.1  jmcneill 	}
    286        1.1  jmcneill 
    287        1.1  jmcneill 	if (pci_intr_map(pa, &ih)) {
    288       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n");
    289        1.1  jmcneill 		goto attach_failure_unmap;
    290        1.1  jmcneill 	}
    291       1.14  christos 	intrstr = pci_intr_string(sc->sc_pc, ih, intrbuf, sizeof(intrbuf));
    292        1.1  jmcneill 
    293  1.15.10.1  christos 	sc->sc_ih = pci_intr_establish_xname(sc->sc_pc, ih, IPL_AUDIO,
    294  1.15.10.1  christos 	    gcscaudio_intr, sc, device_xname(self));
    295        1.1  jmcneill 	if (sc->sc_ih == NULL) {
    296       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "couldn't establish interrupt");
    297        1.1  jmcneill 		if (intrstr != NULL)
    298        1.3     njoly 			aprint_error(" at %s", intrstr);
    299        1.3     njoly 		aprint_error("\n");
    300        1.1  jmcneill 		goto attach_failure_unmap;
    301        1.1  jmcneill 	}
    302        1.1  jmcneill 
    303       1.12    nonaka 	aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
    304        1.1  jmcneill 
    305        1.1  jmcneill 
    306        1.1  jmcneill 	if (gcscaudio_allocate_dma(sc, sizeof(*sc->sc_prd.p_prdtables),
    307        1.1  jmcneill 	    (void **)&(sc->sc_prd.p_prdtables), sc->sc_prd.p_prdsegs, 1,
    308        1.8  jmcneill 	    &(sc->sc_prd.p_prdnseg), &(sc->sc_prd.p_prdmap)) != 0)
    309        1.1  jmcneill 		goto attach_failure_intr;
    310        1.1  jmcneill 
    311        1.1  jmcneill 	sc->host_if.arg = sc;
    312        1.1  jmcneill 	sc->host_if.attach = gcscaudio_attach_codec;
    313        1.1  jmcneill 	sc->host_if.read = gcscaudio_read_codec;
    314        1.1  jmcneill 	sc->host_if.write = gcscaudio_write_codec;
    315        1.1  jmcneill 	sc->host_if.reset = gcscaudio_reset_codec;
    316        1.1  jmcneill 	sc->host_if.spdif_event = gcscaudio_spdif_event_codec;
    317        1.1  jmcneill 
    318        1.8  jmcneill 	if ((rc = ac97_attach(&sc->host_if, self, &sc->sc_lock)) != 0) {
    319       1.12    nonaka 		aprint_error_dev(sc->sc_dev,
    320        1.1  jmcneill 		    "can't attach codec (error=%d)\n", rc);
    321        1.1  jmcneill 		goto attach_failure_intr;
    322        1.1  jmcneill 	}
    323        1.1  jmcneill 
    324        1.1  jmcneill 	if (!pmf_device_register(self, NULL, gcscaudio_resume))
    325        1.1  jmcneill 		aprint_error_dev(self, "couldn't establish power handler\n");
    326        1.1  jmcneill 
    327        1.1  jmcneill 
    328        1.1  jmcneill 	sc->sc_nformats = 0;
    329        1.1  jmcneill 	gcscaudio_append_formats(sc, &gcscaudio_formats_2ch);
    330       1.10  jmcneill 
    331       1.10  jmcneill 	mutex_enter(&sc->sc_lock);
    332        1.1  jmcneill 	if (AC97_IS_4CH(sc->codec_if))
    333        1.1  jmcneill 		gcscaudio_append_formats(sc, &gcscaudio_formats_4ch);
    334        1.1  jmcneill 	if (AC97_IS_6CH(sc->codec_if))
    335        1.1  jmcneill 		gcscaudio_append_formats(sc, &gcscaudio_formats_6ch);
    336        1.1  jmcneill 	if (AC97_IS_FIXED_RATE(sc->codec_if)) {
    337        1.1  jmcneill 		for (i = 0; i < sc->sc_nformats; i++) {
    338        1.1  jmcneill 			sc->sc_formats[i].frequency_type = 1;
    339        1.1  jmcneill 			sc->sc_formats[i].frequency[0] = 48000;
    340        1.1  jmcneill 		}
    341        1.1  jmcneill 	}
    342       1.10  jmcneill 	mutex_exit(&sc->sc_lock);
    343        1.1  jmcneill 
    344       1.12    nonaka 	audio_attach_mi(&gcscaudio_hw_if, sc, sc->sc_dev);
    345        1.1  jmcneill 	return;
    346        1.1  jmcneill 
    347        1.1  jmcneill attach_failure_intr:
    348        1.1  jmcneill 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    349        1.1  jmcneill attach_failure_unmap:
    350        1.1  jmcneill 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    351        1.1  jmcneill 	return;
    352        1.1  jmcneill }
    353        1.1  jmcneill 
    354        1.1  jmcneill static int
    355        1.1  jmcneill gcscaudio_attach_codec(void *arg, struct ac97_codec_if *codec_if)
    356        1.1  jmcneill {
    357        1.1  jmcneill 	struct gcscaudio_softc *sc;
    358        1.1  jmcneill 
    359        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    360        1.1  jmcneill 	sc->codec_if = codec_if;
    361        1.1  jmcneill 	return 0;
    362        1.1  jmcneill }
    363        1.1  jmcneill 
    364        1.1  jmcneill static int
    365        1.1  jmcneill gcscaudio_reset_codec(void *arg)
    366        1.1  jmcneill {
    367        1.1  jmcneill 	struct gcscaudio_softc *sc;
    368        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    369        1.1  jmcneill 
    370        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
    371        1.1  jmcneill 	    ACC_CODEC_CNTL_LNK_WRM_RST |
    372        1.1  jmcneill 	    ACC_CODEC_CNTL_CMD_NEW);
    373        1.1  jmcneill 
    374        1.1  jmcneill 	if (gcscaudio_wait_ready_codec(sc, "reset timeout\n"))
    375        1.1  jmcneill 		return 1;
    376        1.1  jmcneill 
    377        1.1  jmcneill 	return 0;
    378        1.1  jmcneill }
    379        1.1  jmcneill 
    380        1.1  jmcneill static void
    381        1.1  jmcneill gcscaudio_spdif_event_codec(void *arg, bool flag)
    382        1.1  jmcneill {
    383        1.1  jmcneill 	struct gcscaudio_softc *sc;
    384        1.1  jmcneill 
    385        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    386        1.1  jmcneill 	sc->sc_spdif = flag;
    387        1.1  jmcneill }
    388        1.1  jmcneill 
    389        1.1  jmcneill static int
    390        1.1  jmcneill gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *timeout_msg)
    391        1.1  jmcneill {
    392        1.1  jmcneill 	int i;
    393        1.1  jmcneill 
    394        1.1  jmcneill #define GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT	500
    395        1.1  jmcneill 	for (i = GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT; (i >= 0) &&
    396        1.1  jmcneill 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL) &
    397        1.1  jmcneill 	    ACC_CODEC_CNTL_CMD_NEW); i--)
    398        1.1  jmcneill 		delay(1);
    399        1.1  jmcneill 
    400        1.1  jmcneill 	if (i < 0) {
    401       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "%s", timeout_msg);
    402        1.1  jmcneill 		return 1;
    403        1.1  jmcneill 	}
    404        1.1  jmcneill 
    405        1.1  jmcneill 	return 0;
    406        1.1  jmcneill }
    407        1.1  jmcneill 
    408        1.1  jmcneill static int
    409        1.1  jmcneill gcscaudio_write_codec(void *arg, uint8_t reg, uint16_t val)
    410        1.1  jmcneill {
    411        1.1  jmcneill 	struct gcscaudio_softc *sc;
    412        1.1  jmcneill 
    413        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    414        1.1  jmcneill 
    415        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
    416        1.1  jmcneill 	    ACC_CODEC_CNTL_WRITE_CMD |
    417        1.1  jmcneill 	    ACC_CODEC_CNTL_CMD_NEW |
    418        1.1  jmcneill 	    ACC_CODEC_REG2ADDR(reg) |
    419        1.1  jmcneill 	    (val & ACC_CODEC_CNTL_CMD_DATA_MASK));
    420        1.1  jmcneill 
    421        1.1  jmcneill 	if (gcscaudio_wait_ready_codec(sc, "codec write timeout\n"))
    422        1.1  jmcneill 		return 1;
    423        1.1  jmcneill 
    424        1.1  jmcneill #ifdef GCSCAUDIO_CODEC_DEBUG
    425       1.12    nonaka 	aprint_error_dev(sc->sc_dev, "codec write: reg=0x%02x, val=0x%04x\n",
    426        1.1  jmcneill 	    reg, val);
    427        1.1  jmcneill #endif
    428        1.1  jmcneill 
    429        1.1  jmcneill 	return 0;
    430        1.1  jmcneill }
    431        1.1  jmcneill 
    432        1.1  jmcneill static int
    433        1.1  jmcneill gcscaudio_read_codec(void *arg, uint8_t reg, uint16_t *val)
    434        1.1  jmcneill {
    435        1.1  jmcneill 	struct gcscaudio_softc *sc;
    436        1.1  jmcneill 	uint32_t v;
    437        1.1  jmcneill 	int i;
    438        1.1  jmcneill 
    439        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    440        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
    441        1.1  jmcneill 	    ACC_CODEC_CNTL_READ_CMD | ACC_CODEC_CNTL_CMD_NEW |
    442        1.1  jmcneill 	    ACC_CODEC_REG2ADDR(reg));
    443        1.1  jmcneill 
    444        1.1  jmcneill 	if (gcscaudio_wait_ready_codec(sc, "codec write timeout for reading"))
    445        1.1  jmcneill 		return 1;
    446        1.1  jmcneill 
    447        1.1  jmcneill #define GCSCAUDIO_READ_CODEC_TIMEOUT	50
    448        1.1  jmcneill 	for (i = GCSCAUDIO_READ_CODEC_TIMEOUT; i >= 0; i--) {
    449        1.1  jmcneill 		v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_STATUS);
    450        1.1  jmcneill 		if ((v & ACC_CODEC_STATUS_STS_NEW) &&
    451        1.1  jmcneill 		    (ACC_CODEC_ADDR2REG(v) == reg))
    452        1.1  jmcneill 			break;
    453        1.1  jmcneill 
    454        1.1  jmcneill 		delay(10);
    455        1.1  jmcneill 	}
    456        1.1  jmcneill 
    457        1.1  jmcneill 	if (i < 0) {
    458       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "codec read timeout\n");
    459        1.1  jmcneill 		return 1;
    460        1.1  jmcneill 	}
    461        1.1  jmcneill 
    462        1.1  jmcneill #ifdef GCSCAUDIO_CODEC_DEBUG
    463       1.12    nonaka 	aprint_error_dev(sc->sc_dev, "codec read: reg=0x%02x, val=0x%04x\n",
    464        1.1  jmcneill 	    reg, v & ACC_CODEC_STATUS_STS_DATA_MASK);
    465        1.1  jmcneill #endif
    466        1.1  jmcneill 
    467        1.1  jmcneill 	*val = v;
    468        1.1  jmcneill 	return 0;
    469        1.1  jmcneill }
    470        1.1  jmcneill 
    471        1.1  jmcneill static int
    472        1.1  jmcneill gcscaudio_open(void *arg, int flags)
    473        1.1  jmcneill {
    474        1.1  jmcneill 	struct gcscaudio_softc *sc;
    475        1.1  jmcneill 
    476        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    477        1.1  jmcneill 	sc->codec_if->vtbl->lock(sc->codec_if);
    478        1.1  jmcneill 	return 0;
    479        1.1  jmcneill }
    480        1.1  jmcneill 
    481        1.1  jmcneill static void
    482        1.1  jmcneill gcscaudio_close(void *arg)
    483        1.1  jmcneill {
    484        1.1  jmcneill 	struct gcscaudio_softc *sc;
    485        1.1  jmcneill 
    486        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    487        1.1  jmcneill 	sc->codec_if->vtbl->unlock(sc->codec_if);
    488        1.1  jmcneill }
    489        1.1  jmcneill 
    490        1.1  jmcneill static int
    491  1.15.10.1  christos gcscaudio_query_format(void *arg, audio_format_query_t *afp)
    492        1.1  jmcneill {
    493        1.1  jmcneill 	struct gcscaudio_softc *sc;
    494        1.1  jmcneill 
    495        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    496  1.15.10.1  christos 	return audio_query_format(sc->sc_formats, sc->sc_nformats, afp);
    497        1.1  jmcneill }
    498        1.1  jmcneill 
    499        1.1  jmcneill static int
    500  1.15.10.1  christos gcscaudio_set_format(void *arg, int setmode,
    501  1.15.10.1  christos                      const audio_params_t *play, const audio_params_t *rec,
    502  1.15.10.1  christos                      audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    503        1.1  jmcneill {
    504  1.15.10.1  christos 	struct gcscaudio_softc *sc;
    505  1.15.10.1  christos 	int rate;
    506  1.15.10.1  christos 	int error;
    507        1.1  jmcneill 
    508  1.15.10.1  christos 	sc = (struct gcscaudio_softc *)arg;
    509        1.1  jmcneill 
    510  1.15.10.1  christos 	if (setmode & AUMODE_PLAY) {
    511        1.1  jmcneill 		if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
    512       1.13       ryo 			/* setup rate of DAC */
    513  1.15.10.1  christos 			rate = play->sample_rate;
    514        1.1  jmcneill 			if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
    515  1.15.10.1  christos 			    AC97_REG_PCM_FRONT_DAC_RATE, &rate)) != 0)
    516        1.1  jmcneill 				return error;
    517        1.1  jmcneill 
    518        1.1  jmcneill 			/* additional rate of DAC for Surround */
    519  1.15.10.1  christos 			rate = play->sample_rate;
    520  1.15.10.1  christos 			if ((play->channels >= 4) &&
    521        1.1  jmcneill 			    (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
    522  1.15.10.1  christos 			    AC97_REG_PCM_SURR_DAC_RATE, &rate)) != 0)
    523        1.1  jmcneill 				return error;
    524        1.1  jmcneill 
    525        1.1  jmcneill 			/* additional rate of DAC for LowFrequencyEffect */
    526  1.15.10.1  christos 			rate = play->sample_rate;
    527  1.15.10.1  christos 			if ((play->channels == 6) &&
    528        1.1  jmcneill 			    (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
    529  1.15.10.1  christos 			    AC97_REG_PCM_LFE_DAC_RATE, &rate)) != 0)
    530        1.1  jmcneill 				return error;
    531        1.1  jmcneill 		}
    532  1.15.10.1  christos 		sc->sc_play.ch_params = *rec;
    533        1.1  jmcneill 	}
    534  1.15.10.1  christos 	if (setmode & AUMODE_RECORD) {
    535        1.1  jmcneill 		if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
    536       1.13       ryo 			/* setup rate of ADC */
    537  1.15.10.1  christos 			rate = rec->sample_rate;
    538        1.1  jmcneill 			if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
    539  1.15.10.1  christos 			    AC97_REG_PCM_LR_ADC_RATE, &rate)) != 0)
    540        1.1  jmcneill 				return error;
    541        1.1  jmcneill 		}
    542  1.15.10.1  christos 		sc->sc_rec.ch_params = *rec;
    543        1.1  jmcneill 	}
    544        1.1  jmcneill 
    545        1.1  jmcneill 	return 0;
    546        1.1  jmcneill }
    547        1.1  jmcneill 
    548        1.1  jmcneill static int
    549        1.1  jmcneill gcscaudio_round_blocksize(void *arg, int blk, int mode,
    550        1.1  jmcneill                           const audio_params_t *param)
    551        1.1  jmcneill {
    552  1.15.10.2    martin 
    553        1.1  jmcneill 	if (blk > GCSCAUDIO_PRD_SIZE_MAX)
    554        1.1  jmcneill 		blk = GCSCAUDIO_PRD_SIZE_MAX;
    555  1.15.10.2    martin 	blk = rounddown(blk, param->channels * param->precision / NBBY);
    556        1.1  jmcneill 
    557        1.1  jmcneill 	return blk;
    558        1.1  jmcneill }
    559        1.1  jmcneill 
    560        1.1  jmcneill static int
    561        1.1  jmcneill gcscaudio_halt_output(void *arg)
    562        1.1  jmcneill {
    563        1.1  jmcneill 	struct gcscaudio_softc *sc;
    564        1.1  jmcneill 
    565        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    566        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
    567        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_DISABLE);
    568        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
    569        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_DISABLE);
    570        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
    571        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_DISABLE);
    572        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
    573        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_DISABLE);
    574        1.1  jmcneill 	sc->sc_play.ch_intr = NULL;
    575        1.1  jmcneill 
    576        1.1  jmcneill 	/* channel splitter */
    577        1.1  jmcneill 	sc->sc_mch_splitter = NULL;
    578        1.1  jmcneill 	if (sc->sc_mch_split_buf)
    579        1.8  jmcneill 		gcscaudio_free(sc, sc->sc_mch_split_buf, sc->sc_mch_split_size);
    580        1.1  jmcneill 	sc->sc_mch_split_buf = NULL;
    581        1.1  jmcneill 
    582        1.1  jmcneill 	return 0;
    583        1.1  jmcneill }
    584        1.1  jmcneill 
    585        1.1  jmcneill static int
    586        1.1  jmcneill gcscaudio_halt_input(void *arg)
    587        1.1  jmcneill {
    588        1.1  jmcneill 	struct gcscaudio_softc *sc;
    589        1.1  jmcneill 
    590        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    591        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
    592        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_DISABLE);
    593        1.1  jmcneill 	sc->sc_rec.ch_intr = NULL;
    594        1.1  jmcneill 	return 0;
    595        1.1  jmcneill }
    596        1.1  jmcneill 
    597        1.1  jmcneill static int
    598        1.1  jmcneill gcscaudio_getdev(void *addr, struct audio_device *retp)
    599        1.1  jmcneill {
    600        1.1  jmcneill 	*retp = gcscaudio_device;
    601        1.1  jmcneill 	return 0;
    602        1.1  jmcneill }
    603        1.1  jmcneill 
    604        1.1  jmcneill static int
    605        1.1  jmcneill gcscaudio_set_port(void *addr, mixer_ctrl_t *cp)
    606        1.1  jmcneill {
    607        1.1  jmcneill 	struct gcscaudio_softc *sc;
    608        1.1  jmcneill 
    609        1.1  jmcneill 	sc = addr;
    610        1.1  jmcneill 	return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
    611        1.1  jmcneill }
    612        1.1  jmcneill 
    613        1.1  jmcneill static int
    614        1.1  jmcneill gcscaudio_get_port(void *addr, mixer_ctrl_t *cp)
    615        1.1  jmcneill {
    616        1.1  jmcneill 	struct gcscaudio_softc *sc;
    617        1.1  jmcneill 
    618        1.1  jmcneill 	sc = addr;
    619        1.1  jmcneill 	return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
    620        1.1  jmcneill }
    621        1.1  jmcneill 
    622        1.1  jmcneill static int
    623        1.1  jmcneill gcscaudio_query_devinfo(void *addr, mixer_devinfo_t *dip)
    624        1.1  jmcneill {
    625        1.1  jmcneill 	struct gcscaudio_softc *sc;
    626        1.1  jmcneill 
    627        1.1  jmcneill 	sc = addr;
    628        1.1  jmcneill 	return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip);
    629        1.1  jmcneill }
    630        1.1  jmcneill 
    631        1.1  jmcneill static void *
    632        1.8  jmcneill gcscaudio_malloc(void *arg, int direction, size_t size)
    633        1.1  jmcneill {
    634        1.1  jmcneill 	struct gcscaudio_softc *sc;
    635        1.1  jmcneill 	struct gcscaudio_dma *p;
    636        1.1  jmcneill 	int error;
    637        1.1  jmcneill 
    638        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    639        1.1  jmcneill 
    640        1.8  jmcneill 	p = kmem_alloc(sizeof(*p), KM_SLEEP);
    641        1.1  jmcneill 	p->size = size;
    642        1.1  jmcneill 
    643        1.1  jmcneill 	error = gcscaudio_allocate_dma(sc, size, &p->addr,
    644        1.8  jmcneill 	    p->segs, sizeof(p->segs)/sizeof(p->segs[0]), &p->nseg, &p->map);
    645        1.1  jmcneill 	if (error) {
    646        1.8  jmcneill 		kmem_free(p, sizeof(*p));
    647        1.1  jmcneill 		return NULL;
    648        1.1  jmcneill 	}
    649        1.1  jmcneill 
    650        1.1  jmcneill 	LIST_INSERT_HEAD(&sc->sc_dmalist, p, list);
    651        1.1  jmcneill 	return p->addr;
    652        1.1  jmcneill }
    653        1.1  jmcneill 
    654        1.1  jmcneill static void
    655        1.8  jmcneill gcscaudio_free(void *arg, void *ptr, size_t size)
    656        1.1  jmcneill {
    657        1.1  jmcneill 	struct gcscaudio_softc *sc;
    658        1.1  jmcneill 	struct gcscaudio_dma *p;
    659        1.1  jmcneill 
    660        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
    661        1.1  jmcneill 
    662        1.1  jmcneill 	LIST_FOREACH(p, &sc->sc_dmalist, list) {
    663        1.1  jmcneill 		if (p->addr == ptr) {
    664        1.1  jmcneill 			bus_dmamap_unload(sc->sc_dmat, p->map);
    665        1.1  jmcneill 			bus_dmamap_destroy(sc->sc_dmat, p->map);
    666        1.1  jmcneill 			bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
    667        1.1  jmcneill 			bus_dmamem_free(sc->sc_dmat, p->segs, p->nseg);
    668        1.1  jmcneill 
    669        1.1  jmcneill 			LIST_REMOVE(p, list);
    670        1.8  jmcneill 			kmem_free(p, sizeof(*p));
    671        1.1  jmcneill 			break;
    672        1.1  jmcneill 		}
    673        1.1  jmcneill 	}
    674        1.1  jmcneill }
    675        1.1  jmcneill 
    676        1.1  jmcneill static size_t
    677        1.1  jmcneill gcscaudio_round_buffersize(void *addr, int direction, size_t size)
    678        1.1  jmcneill {
    679        1.1  jmcneill 	if (size > GCSCAUDIO_BUFSIZE_MAX)
    680        1.1  jmcneill 		size = GCSCAUDIO_BUFSIZE_MAX;
    681        1.1  jmcneill 
    682        1.1  jmcneill 	return size;
    683        1.1  jmcneill }
    684        1.1  jmcneill 
    685        1.1  jmcneill static int
    686        1.1  jmcneill gcscaudio_get_props(void *addr)
    687        1.1  jmcneill {
    688        1.1  jmcneill 
    689  1.15.10.1  christos 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
    690  1.15.10.1  christos 	    AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
    691        1.1  jmcneill }
    692        1.1  jmcneill 
    693        1.1  jmcneill static int
    694        1.1  jmcneill build_prdtables(struct gcscaudio_softc *sc, int prdidx,
    695        1.1  jmcneill                 void *addr, size_t size, int blksize, int blklen, int blkoff)
    696        1.1  jmcneill {
    697        1.1  jmcneill 	struct gcscaudio_dma *p;
    698        1.1  jmcneill 	struct acc_prd *prdp;
    699        1.1  jmcneill 	bus_addr_t paddr;
    700        1.1  jmcneill 	int i;
    701        1.1  jmcneill 
    702        1.1  jmcneill 	/* get physical address of start */
    703        1.1  jmcneill 	paddr = (bus_addr_t)0;
    704        1.1  jmcneill 	LIST_FOREACH(p, &sc->sc_dmalist, list) {
    705        1.1  jmcneill 		if (p->addr == addr) {
    706        1.1  jmcneill 			paddr = p->map->dm_segs[0].ds_addr;
    707        1.1  jmcneill 			break;
    708        1.1  jmcneill 		}
    709        1.1  jmcneill 	}
    710        1.1  jmcneill 	if (!paddr) {
    711       1.12    nonaka 		aprint_error_dev(sc->sc_dev, "bad addr %p\n", addr);
    712        1.1  jmcneill 		return EINVAL;
    713        1.1  jmcneill 	}
    714        1.1  jmcneill 
    715        1.1  jmcneill #define PRDADDR(prdidx,idx) \
    716        1.1  jmcneill 	(sc->sc_prd.p_prdmap->dm_segs[0].ds_addr) + sizeof(struct acc_prd) * \
    717        1.1  jmcneill 	(((prdidx) * GCSCAUDIO_NPRDTABLE) + (idx))
    718        1.1  jmcneill 
    719        1.1  jmcneill 	/*
    720        1.1  jmcneill 	 * build PRD table
    721        1.1  jmcneill 	 *   prdtbl[] = <PRD0>, <PRD1>, <PRD2>, ..., <PRDn>, <jmp to PRD0>
    722        1.1  jmcneill 	 */
    723        1.1  jmcneill 	prdp = sc->sc_prd.p_prdtables->prdtbl[prdidx];
    724        1.1  jmcneill 	for (i = 0; size > 0; size -= blksize, i++) {
    725        1.1  jmcneill 		prdp[i].address = paddr + blksize * i + blkoff;
    726        1.1  jmcneill 		prdp[i].ctrlsize =
    727        1.1  jmcneill 		    (size < blklen ? size : blklen) | ACC_BMx_PRD_CTRL_EOP;
    728        1.1  jmcneill 	}
    729        1.1  jmcneill 	prdp[i].address = PRDADDR(prdidx, 0);
    730        1.1  jmcneill 	prdp[i].ctrlsize = ACC_BMx_PRD_CTRL_JMP;
    731        1.1  jmcneill 
    732        1.1  jmcneill 	bus_dmamap_sync(sc->sc_dmat, sc->sc_prd.p_prdmap, 0,
    733        1.1  jmcneill 	    sizeof(struct acc_prd) * i, BUS_DMASYNC_PREWRITE);
    734        1.1  jmcneill 
    735        1.1  jmcneill 	return 0;
    736        1.1  jmcneill }
    737        1.1  jmcneill 
    738        1.1  jmcneill static void
    739        1.1  jmcneill split_buffer_4ch(void *dst, void *src, int size, int blksize)
    740        1.1  jmcneill {
    741        1.1  jmcneill 	int left, i;
    742        1.1  jmcneill 	uint16_t *s, *d;
    743        1.1  jmcneill 
    744        1.1  jmcneill 	/*
    745        1.1  jmcneill 	 * src[blk0]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
    746        1.1  jmcneill 	 * src[blk1]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
    747        1.1  jmcneill 	 * src[blk2]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
    748        1.1  jmcneill 	 *     :
    749        1.1  jmcneill 	 *
    750        1.1  jmcneill 	 *   rearrange to
    751        1.1  jmcneill 	 *
    752        1.1  jmcneill 	 * src[blk0]: L,R,L,R,L,R,L,R,..
    753        1.1  jmcneill 	 * src[blk1]: L,R,L,R,L,R,L,R,..
    754        1.1  jmcneill 	 * src[blk2]: L,R,L,R,L,R,L,R,..
    755        1.1  jmcneill 	 *     :
    756        1.1  jmcneill 	 * dst[blk0]: SL,SR,SL,SR,SL,SR,SL,SR,..
    757        1.1  jmcneill 	 * dst[blk1]: SL,SR,SL,SR,SL,SR,SL,SR,..
    758        1.1  jmcneill 	 * dst[blk2]: SL,SR,SL,SR,SL,SR,SL,SR,..
    759        1.1  jmcneill 	 *     :
    760        1.1  jmcneill 	 */
    761        1.1  jmcneill 	for (left = size; left > 0; left -= blksize) {
    762        1.1  jmcneill 		s = (uint16_t *)src;
    763        1.1  jmcneill 		d = (uint16_t *)dst;
    764        1.1  jmcneill 		for (i = 0; i < blksize / sizeof(uint16_t) / 4; i++) {
    765        1.1  jmcneill 			/* L,R,SL,SR -> SL,SR */
    766        1.1  jmcneill 			s++;
    767        1.1  jmcneill 			s++;
    768        1.1  jmcneill 			*d++ = *s++;
    769        1.1  jmcneill 			*d++ = *s++;
    770        1.1  jmcneill 		}
    771        1.1  jmcneill 
    772        1.1  jmcneill 		s = (uint16_t *)src;
    773        1.1  jmcneill 		d = (uint16_t *)src;
    774        1.1  jmcneill 		for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
    775        1.1  jmcneill 			/* L,R,SL,SR -> L,R */
    776        1.1  jmcneill 			*d++ = *s++;
    777        1.1  jmcneill 			*d++ = *s++;
    778        1.1  jmcneill 			s++;
    779        1.1  jmcneill 			s++;
    780        1.1  jmcneill 		}
    781        1.1  jmcneill 
    782        1.1  jmcneill 		src = (char *)src + blksize;
    783        1.1  jmcneill 		dst = (char *)dst + blksize;
    784        1.1  jmcneill 	}
    785        1.1  jmcneill }
    786        1.1  jmcneill 
    787        1.1  jmcneill static void
    788        1.1  jmcneill split_buffer_6ch(void *dst, void *src, int size, int blksize)
    789        1.1  jmcneill {
    790        1.1  jmcneill 	int left, i;
    791        1.1  jmcneill 	uint16_t *s, *d, *dc, *dl;
    792        1.1  jmcneill 
    793        1.1  jmcneill 	/*
    794        1.1  jmcneill 	 * by default, treat as WAV style 5.1ch order
    795        1.1  jmcneill 	 *   5.1ch(WAV): L R C LFE SL SR
    796        1.1  jmcneill 	 *   5.1ch(AAC): C L R SL SR LFE
    797        1.1  jmcneill 	 *        :
    798        1.1  jmcneill 	 */
    799        1.1  jmcneill 
    800        1.1  jmcneill 	/*
    801        1.1  jmcneill 	 * src[blk0]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
    802        1.1  jmcneill 	 * src[blk1]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
    803        1.1  jmcneill 	 * src[blk2]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
    804        1.1  jmcneill 	 *     :
    805        1.1  jmcneill 	 * src[N-1] : L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
    806        1.1  jmcneill 	 *
    807        1.1  jmcneill 	 *   rearrange to
    808        1.1  jmcneill 	 *
    809        1.1  jmcneill 	 * src[blk0]: L,R,L,R,..
    810        1.1  jmcneill 	 * src[blk1]: L,R,L,R,..
    811        1.1  jmcneill 	 * src[blk2]: L,R,L,R,..
    812        1.1  jmcneill 	 *     :
    813        1.1  jmcneill 	 *
    814        1.1  jmcneill 	 * dst[blk0]: SL,SR,SL,SR,..
    815        1.1  jmcneill 	 * dst[blk1]: SL,SR,SL,SR,..
    816        1.1  jmcneill 	 * dst[blk2]: SL,SR,SL,SR,..
    817        1.1  jmcneill 	 *     :
    818        1.1  jmcneill 	 *
    819        1.1  jmcneill 	 * dst[N/2+0]: C,C,C,..
    820        1.1  jmcneill 	 * dst[N/2+1]: C,C,C,..
    821        1.1  jmcneill 	 *     :
    822        1.1  jmcneill 	 *
    823        1.1  jmcneill 	 * dst[N/2+N/4+0]: LFE,LFE,LFE,..
    824        1.1  jmcneill 	 * dst[N/2+N/4+1]: LFE,LFE,LFE,..
    825        1.1  jmcneill 	 *     :
    826        1.1  jmcneill 	 */
    827        1.1  jmcneill 
    828        1.1  jmcneill 	for (left = size; left > 0; left -= blksize) {
    829        1.1  jmcneill 		s = (uint16_t *)src;
    830        1.1  jmcneill 		d = (uint16_t *)dst;
    831        1.1  jmcneill 		dc = (uint16_t *)((char *)dst + blksize / 2);
    832        1.1  jmcneill 		dl = (uint16_t *)((char *)dst + blksize / 2 + blksize / 4);
    833        1.1  jmcneill 		for (i = 0; i < blksize / sizeof(uint16_t) / 6; i++) {
    834        1.1  jmcneill #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
    835        1.1  jmcneill 			/*
    836        1.1  jmcneill 			 * AAC: [C,L,R,SL,SR,LFE]
    837        1.1  jmcneill 			 *  => [SL,SR]
    838        1.1  jmcneill 			 *  => [C]
    839        1.1  jmcneill 			 *  => [LFE]
    840        1.1  jmcneill 			 */
    841        1.1  jmcneill 			*dc++ = s[0];	/* C */
    842        1.1  jmcneill 			*dl++ = s[5];	/* LFE */
    843        1.1  jmcneill 			*d++ = s[3];	/* SL */
    844        1.1  jmcneill 			*d++ = s[4];	/* SR */
    845        1.1  jmcneill #else
    846        1.1  jmcneill 			/*
    847        1.1  jmcneill 			 * WAV: [L,R,C,LFE,SL,SR]
    848        1.1  jmcneill 			 *  => [SL,SR]
    849        1.1  jmcneill 			 *  => [C]
    850        1.1  jmcneill 			 *  => [LFE]
    851        1.1  jmcneill 			 */
    852        1.1  jmcneill 			*dc++ = s[2];	/* C */
    853        1.1  jmcneill 			*dl++ = s[3];	/* LFE */
    854        1.1  jmcneill 			*d++ = s[4];	/* SL */
    855        1.1  jmcneill 			*d++ = s[5];	/* SR */
    856        1.1  jmcneill #endif
    857        1.1  jmcneill 			s += 6;
    858        1.1  jmcneill 		}
    859        1.1  jmcneill 
    860        1.1  jmcneill 		s = (uint16_t *)src;
    861        1.1  jmcneill 		d = (uint16_t *)src;
    862        1.1  jmcneill 		for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
    863        1.1  jmcneill #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
    864        1.1  jmcneill 			/* AAC: [C,L,R,SL,SR,LFE] => [L,R] */
    865        1.1  jmcneill 			*d++ = s[1];
    866        1.1  jmcneill 			*d++ = s[2];
    867        1.1  jmcneill #else
    868        1.1  jmcneill 			/* WAV: [L,R,C,LFE,SL,SR] => [L,R] */
    869        1.1  jmcneill 			*d++ = s[0];
    870        1.1  jmcneill 			*d++ = s[1];
    871        1.1  jmcneill #endif
    872        1.1  jmcneill 			s += 6;
    873        1.1  jmcneill 		}
    874        1.1  jmcneill 
    875        1.1  jmcneill 		src = (char *)src + blksize;
    876        1.1  jmcneill 		dst = (char *)dst + blksize;
    877        1.1  jmcneill 	}
    878        1.1  jmcneill }
    879        1.1  jmcneill 
    880        1.1  jmcneill static void
    881        1.1  jmcneill channel_splitter(struct gcscaudio_softc *sc)
    882        1.1  jmcneill {
    883        1.1  jmcneill 	int splitsize, left;
    884        1.1  jmcneill 	void *src, *dst;
    885        1.1  jmcneill 
    886        1.1  jmcneill 	if (sc->sc_mch_splitter == NULL)
    887        1.1  jmcneill 		return;
    888        1.1  jmcneill 
    889        1.1  jmcneill 	left = sc->sc_mch_split_size - sc->sc_mch_split_off;
    890        1.1  jmcneill 	splitsize = sc->sc_mch_split_blksize;
    891        1.1  jmcneill 	if (left < splitsize)
    892        1.1  jmcneill 		splitsize = left;
    893        1.1  jmcneill 
    894        1.1  jmcneill 	src = (char *)sc->sc_mch_split_start + sc->sc_mch_split_off;
    895        1.1  jmcneill 	dst = (char *)sc->sc_mch_split_buf + sc->sc_mch_split_off;
    896        1.1  jmcneill 
    897        1.1  jmcneill 	sc->sc_mch_splitter(dst, src, splitsize, sc->sc_mch_split_blksize);
    898        1.1  jmcneill 
    899        1.1  jmcneill 	sc->sc_mch_split_off += sc->sc_mch_split_blksize;
    900        1.1  jmcneill 	if (sc->sc_mch_split_off >= sc->sc_mch_split_size)
    901        1.1  jmcneill 		sc->sc_mch_split_off = 0;
    902        1.1  jmcneill }
    903        1.1  jmcneill 
    904        1.1  jmcneill static int
    905        1.1  jmcneill gcscaudio_trigger_output(void *addr, void *start, void *end, int blksize,
    906        1.1  jmcneill                          void (*intr)(void *), void *arg,
    907        1.1  jmcneill                          const audio_params_t *param)
    908        1.1  jmcneill {
    909        1.1  jmcneill 	struct gcscaudio_softc *sc;
    910        1.1  jmcneill 	size_t size;
    911        1.1  jmcneill 
    912        1.1  jmcneill 	sc = (struct gcscaudio_softc *)addr;
    913        1.1  jmcneill 	sc->sc_play.ch_intr = intr;
    914        1.1  jmcneill 	sc->sc_play.ch_intr_arg = arg;
    915        1.1  jmcneill 	size = (char *)end - (char *)start;
    916        1.1  jmcneill 
    917        1.1  jmcneill 	switch (sc->sc_play.ch_params.channels) {
    918        1.1  jmcneill 	case 2:
    919        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
    920        1.1  jmcneill 		    blksize, 0))
    921        1.1  jmcneill 			return EINVAL;
    922        1.1  jmcneill 
    923        1.1  jmcneill 		if (!AC97_IS_4CH(sc->codec_if)) {
    924        1.1  jmcneill 			/*
    925        1.1  jmcneill 			 * output 2ch PCM to FRONT.LR(BM0)
    926        1.1  jmcneill 			 *
    927        1.1  jmcneill 			 * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
    928        1.1  jmcneill 			 *
    929        1.1  jmcneill 			 */
    930        1.1  jmcneill 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
    931        1.1  jmcneill 			    PRDADDR(PRD_TABLE_FRONT, 0));
    932        1.1  jmcneill 
    933        1.1  jmcneill 			/* start DMA transfer */
    934        1.1  jmcneill 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
    935        1.1  jmcneill 			    ACC_BMx_CMD_WRITE |
    936        1.1  jmcneill 			    ACC_BMx_CMD_BYTE_ORD_EL |
    937        1.1  jmcneill 			    ACC_BMx_CMD_BM_CTL_ENABLE);
    938        1.1  jmcneill 		} else {
    939        1.1  jmcneill 			/*
    940        1.1  jmcneill 			 * output same PCM to FRONT.LR(BM0) and SURROUND.LR(BM6).
    941        1.1  jmcneill 			 * CENTER(BM4) and LFE(BM7) doesn't sound.
    942        1.1  jmcneill 			 *
    943        1.1  jmcneill 			 * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
    944        1.1  jmcneill 			 *                             BM6: (same of BM0)
    945        1.1  jmcneill 			 *                             BM4: none
    946        1.1  jmcneill 			 *                             BM7: none
    947        1.1  jmcneill 			 */
    948        1.1  jmcneill 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
    949        1.1  jmcneill 			    PRDADDR(PRD_TABLE_FRONT, 0));
    950        1.1  jmcneill 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
    951        1.1  jmcneill 			    PRDADDR(PRD_TABLE_FRONT, 0));
    952        1.1  jmcneill 
    953        1.1  jmcneill 			/* start DMA transfer */
    954        1.1  jmcneill 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
    955        1.1  jmcneill 			    ACC_BMx_CMD_WRITE |
    956        1.1  jmcneill 			    ACC_BMx_CMD_BYTE_ORD_EL |
    957        1.1  jmcneill 			    ACC_BMx_CMD_BM_CTL_ENABLE);
    958        1.1  jmcneill 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
    959        1.1  jmcneill 			    ACC_BMx_CMD_WRITE |
    960        1.1  jmcneill 			    ACC_BMx_CMD_BYTE_ORD_EL |
    961        1.1  jmcneill 			    ACC_BMx_CMD_BM_CTL_ENABLE);
    962        1.1  jmcneill 		}
    963        1.1  jmcneill 		break;
    964        1.1  jmcneill 	case 4:
    965        1.1  jmcneill 		/*
    966        1.1  jmcneill 		 * output 4ch PCM split to FRONT.LR(BM0) and SURROUND.LR(BM6).
    967        1.1  jmcneill 		 * CENTER(BM4) and LFE(BM7) doesn't sound.
    968        1.1  jmcneill 		 *
    969        1.1  jmcneill 		 * rearrange ordered channel to continuous per channel
    970        1.1  jmcneill 		 *
    971        1.1  jmcneill 		 *   4ch: L,R,SL,SR,L,R,SL,SR,... => BM0: L,R,L,R,...
    972        1.1  jmcneill 		 *                                   BM6: SL,SR,SL,SR,...
    973        1.1  jmcneill 		 *                                   BM4: none
    974        1.1  jmcneill 		 *                                   BM7: none
    975        1.1  jmcneill 		 */
    976        1.1  jmcneill 		if (sc->sc_mch_split_buf)
    977        1.8  jmcneill 			gcscaudio_free(sc, sc->sc_mch_split_buf,
    978        1.8  jmcneill 			    sc->sc_mch_split_size);
    979        1.1  jmcneill 
    980        1.1  jmcneill 		if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
    981        1.8  jmcneill 		    size)) == NULL)
    982        1.1  jmcneill 			return ENOMEM;
    983        1.1  jmcneill 
    984        1.1  jmcneill 		/*
    985        1.1  jmcneill 		 * 1st and 2nd blocks are split immediately.
    986        1.1  jmcneill 		 * Other blocks will be split synchronous with intr.
    987        1.1  jmcneill 		 */
    988        1.1  jmcneill 		split_buffer_4ch(sc->sc_mch_split_buf, start, blksize * 2,
    989        1.1  jmcneill 		    blksize);
    990        1.1  jmcneill 
    991        1.1  jmcneill 		sc->sc_mch_split_start = start;
    992        1.1  jmcneill 		sc->sc_mch_split_size = size;
    993        1.1  jmcneill 		sc->sc_mch_split_blksize = blksize;
    994        1.1  jmcneill 		sc->sc_mch_split_off = (blksize * 2) % size;
    995        1.1  jmcneill 		sc->sc_mch_splitter = split_buffer_4ch;	/* split function */
    996        1.1  jmcneill 
    997        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
    998        1.1  jmcneill 		    blksize / 2, 0))
    999        1.1  jmcneill 			return EINVAL;
   1000        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
   1001        1.1  jmcneill 		    size, blksize, blksize / 2, 0))
   1002        1.1  jmcneill 			return EINVAL;
   1003        1.1  jmcneill 
   1004        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
   1005        1.1  jmcneill 		    PRDADDR(PRD_TABLE_FRONT, 0));
   1006        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
   1007        1.1  jmcneill 		    PRDADDR(PRD_TABLE_SURR, 0));
   1008        1.1  jmcneill 
   1009        1.1  jmcneill 		/* start DMA transfer */
   1010        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
   1011        1.1  jmcneill 		    ACC_BMx_CMD_WRITE |
   1012        1.1  jmcneill 		    ACC_BMx_CMD_BYTE_ORD_EL |
   1013        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1014        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
   1015        1.1  jmcneill 		    ACC_BMx_CMD_WRITE |
   1016        1.1  jmcneill 		    ACC_BMx_CMD_BYTE_ORD_EL |
   1017        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1018        1.1  jmcneill 		break;
   1019        1.1  jmcneill 	case 6:
   1020        1.1  jmcneill 		/*
   1021        1.1  jmcneill 		 * output 6ch PCM split to
   1022        1.1  jmcneill 		 * FRONT.LR(BM0), SURROUND.LR(BM6), CENTER(BM4) and LFE(BM7)
   1023        1.1  jmcneill 		 *
   1024        1.1  jmcneill 		 * rearrange ordered channel to continuous per channel
   1025        1.1  jmcneill 		 *
   1026        1.1  jmcneill 		 *   5.1ch: L,R,C,LFE,SL,SR,... => BM0: L,R,...
   1027        1.1  jmcneill 		 *                                 BM4: C,...
   1028        1.1  jmcneill 		 *                                 BM6: SL,SR,...
   1029        1.1  jmcneill 		 *                                 BM7: LFE,...
   1030        1.1  jmcneill 		 *
   1031        1.1  jmcneill 		 */
   1032        1.1  jmcneill 		if (sc->sc_mch_split_buf)
   1033        1.8  jmcneill 			gcscaudio_free(sc, sc->sc_mch_split_buf,
   1034        1.8  jmcneill 			    sc->sc_mch_split_size);
   1035        1.1  jmcneill 
   1036        1.1  jmcneill 		if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
   1037        1.8  jmcneill 		    size)) == NULL)
   1038        1.1  jmcneill 			return ENOMEM;
   1039        1.1  jmcneill 
   1040        1.1  jmcneill 		/*
   1041        1.1  jmcneill 		 * 1st and 2nd blocks are split immediately.
   1042        1.1  jmcneill 		 * Other block will be split synchronous with intr.
   1043        1.1  jmcneill 		 */
   1044        1.1  jmcneill 		split_buffer_6ch(sc->sc_mch_split_buf, start, blksize * 2,
   1045        1.1  jmcneill 		    blksize);
   1046        1.1  jmcneill 
   1047        1.1  jmcneill 		sc->sc_mch_split_start = start;
   1048        1.1  jmcneill 		sc->sc_mch_split_size = size;
   1049        1.1  jmcneill 		sc->sc_mch_split_blksize = blksize;
   1050        1.1  jmcneill 		sc->sc_mch_split_off = (blksize * 2) % size;
   1051        1.1  jmcneill 		sc->sc_mch_splitter = split_buffer_6ch;	/* split function */
   1052        1.1  jmcneill 
   1053        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
   1054        1.1  jmcneill 		    blksize / 3, 0))
   1055        1.1  jmcneill 			return EINVAL;
   1056        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_CENTER, sc->sc_mch_split_buf,
   1057        1.1  jmcneill 		    size, blksize, blksize / 3, blksize / 2))
   1058        1.1  jmcneill 			return EINVAL;
   1059        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
   1060        1.1  jmcneill 		    size, blksize, blksize / 3, 0))
   1061        1.1  jmcneill 			return EINVAL;
   1062        1.1  jmcneill 		if (build_prdtables(sc, PRD_TABLE_LFE, sc->sc_mch_split_buf,
   1063        1.1  jmcneill 		    size, blksize, blksize / 3, blksize / 2 + blksize / 4))
   1064        1.1  jmcneill 			return EINVAL;
   1065        1.1  jmcneill 
   1066        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
   1067        1.1  jmcneill 		    PRDADDR(PRD_TABLE_FRONT, 0));
   1068        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_PRD,
   1069        1.1  jmcneill 		    PRDADDR(PRD_TABLE_CENTER, 0));
   1070        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
   1071        1.1  jmcneill 		    PRDADDR(PRD_TABLE_SURR, 0));
   1072        1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_PRD,
   1073        1.1  jmcneill 		    PRDADDR(PRD_TABLE_LFE, 0));
   1074        1.1  jmcneill 
   1075        1.1  jmcneill 		/* start DMA transfer */
   1076        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
   1077        1.1  jmcneill 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
   1078        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1079        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
   1080        1.1  jmcneill 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
   1081        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1082        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
   1083        1.1  jmcneill 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
   1084        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1085        1.1  jmcneill 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
   1086        1.1  jmcneill 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
   1087        1.1  jmcneill 		    ACC_BMx_CMD_BM_CTL_ENABLE);
   1088        1.1  jmcneill 		break;
   1089        1.1  jmcneill 	}
   1090        1.1  jmcneill 
   1091        1.1  jmcneill 	return 0;
   1092        1.1  jmcneill }
   1093        1.1  jmcneill 
   1094        1.1  jmcneill static int
   1095        1.1  jmcneill gcscaudio_trigger_input(void *addr, void *start, void *end, int blksize,
   1096        1.1  jmcneill                         void (*intr)(void *), void *arg,
   1097        1.1  jmcneill                         const audio_params_t *param)
   1098        1.1  jmcneill {
   1099        1.1  jmcneill 	struct gcscaudio_softc *sc;
   1100        1.1  jmcneill 	size_t size;
   1101        1.1  jmcneill 
   1102        1.1  jmcneill 	sc = (struct gcscaudio_softc *)addr;
   1103        1.1  jmcneill 	sc->sc_rec.ch_intr = intr;
   1104        1.1  jmcneill 	sc->sc_rec.ch_intr_arg = arg;
   1105        1.1  jmcneill 	size = (char *)end - (char *)start;
   1106        1.1  jmcneill 
   1107        1.1  jmcneill 	if (build_prdtables(sc, PRD_TABLE_REC, start, size, blksize, blksize, 0))
   1108        1.1  jmcneill 		return EINVAL;
   1109        1.1  jmcneill 
   1110        1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_PRD,
   1111        1.1  jmcneill 	    PRDADDR(PRD_TABLE_REC, 0));
   1112        1.1  jmcneill 
   1113        1.1  jmcneill 	/* start transfer */
   1114        1.1  jmcneill 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
   1115        1.1  jmcneill 	    ACC_BMx_CMD_READ |
   1116        1.1  jmcneill 	    ACC_BMx_CMD_BYTE_ORD_EL |
   1117        1.1  jmcneill 	    ACC_BMx_CMD_BM_CTL_ENABLE);
   1118        1.1  jmcneill 
   1119        1.1  jmcneill 	return 0;
   1120        1.1  jmcneill }
   1121        1.1  jmcneill 
   1122        1.8  jmcneill static void
   1123        1.8  jmcneill gcscaudio_get_locks(void *arg, kmutex_t **intr, kmutex_t **thread)
   1124        1.8  jmcneill {
   1125        1.8  jmcneill 	struct gcscaudio_softc *sc;
   1126        1.8  jmcneill 
   1127        1.8  jmcneill 	sc = (struct gcscaudio_softc *)arg;
   1128        1.8  jmcneill 
   1129        1.8  jmcneill 	*intr = &sc->sc_intr_lock;
   1130        1.8  jmcneill 	*thread = &sc->sc_lock;
   1131        1.8  jmcneill }
   1132        1.8  jmcneill 
   1133        1.1  jmcneill static int
   1134        1.1  jmcneill gcscaudio_intr(void *arg)
   1135        1.1  jmcneill {
   1136        1.1  jmcneill 	struct gcscaudio_softc *sc;
   1137        1.1  jmcneill 	uint16_t intr;
   1138        1.1  jmcneill 	uint8_t bmstat;
   1139        1.1  jmcneill 	int nintr;
   1140        1.1  jmcneill 
   1141        1.1  jmcneill 	nintr = 0;
   1142        1.1  jmcneill 	sc = (struct gcscaudio_softc *)arg;
   1143        1.8  jmcneill 
   1144        1.8  jmcneill 	mutex_spin_enter(&sc->sc_intr_lock);
   1145        1.8  jmcneill 
   1146        1.1  jmcneill 	intr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ACC_IRQ_STATUS);
   1147        1.1  jmcneill 	if (intr == 0)
   1148        1.8  jmcneill 		goto done;
   1149        1.1  jmcneill 
   1150        1.1  jmcneill 	/* Front output */
   1151        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM0_IRQ_STS) {
   1152        1.1  jmcneill 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_STATUS);
   1153        1.1  jmcneill 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
   1154       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM0: Bus Master Error\n");
   1155        1.1  jmcneill 		if (!(bmstat & ACC_BMx_STATUS_EOP))
   1156       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM0: NO End of Page?\n");
   1157        1.1  jmcneill 
   1158        1.1  jmcneill 		if (sc->sc_play.ch_intr) {
   1159        1.1  jmcneill 			sc->sc_play.ch_intr(sc->sc_play.ch_intr_arg);
   1160        1.1  jmcneill 			channel_splitter(sc);
   1161        1.1  jmcneill 		}
   1162        1.1  jmcneill 		nintr++;
   1163        1.1  jmcneill 	}
   1164        1.1  jmcneill 
   1165        1.1  jmcneill 	/* Center output */
   1166        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM4_IRQ_STS) {
   1167        1.1  jmcneill 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_STATUS);
   1168        1.1  jmcneill 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
   1169       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM4: Bus Master Error\n");
   1170        1.1  jmcneill 		if (!(bmstat & ACC_BMx_STATUS_EOP))
   1171       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM4: NO End of Page?\n");
   1172        1.1  jmcneill 
   1173        1.1  jmcneill 		nintr++;
   1174        1.1  jmcneill 	}
   1175        1.1  jmcneill 
   1176        1.1  jmcneill 	/* Surround output */
   1177        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM6_IRQ_STS) {
   1178        1.1  jmcneill 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_STATUS);
   1179        1.1  jmcneill 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
   1180       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM6: Bus Master Error\n");
   1181        1.1  jmcneill 		if (!(bmstat & ACC_BMx_STATUS_EOP))
   1182       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM6: NO End of Page?\n");
   1183        1.1  jmcneill 
   1184        1.1  jmcneill 		nintr++;
   1185        1.1  jmcneill 	}
   1186        1.1  jmcneill 
   1187        1.1  jmcneill 	/* LowFrequencyEffect output */
   1188        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM7_IRQ_STS) {
   1189        1.1  jmcneill 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_STATUS);
   1190        1.1  jmcneill 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
   1191       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM7: Bus Master Error\n");
   1192        1.1  jmcneill 		if (!(bmstat & ACC_BMx_STATUS_EOP))
   1193       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM7: NO End of Page?\n");
   1194        1.1  jmcneill 
   1195        1.1  jmcneill 		nintr++;
   1196        1.1  jmcneill 	}
   1197        1.1  jmcneill 
   1198        1.1  jmcneill 	/* record */
   1199        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM1_IRQ_STS) {
   1200        1.1  jmcneill 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_STATUS);
   1201        1.1  jmcneill 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
   1202       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM1: Bus Master Error\n");
   1203        1.1  jmcneill 		if (!(bmstat & ACC_BMx_STATUS_EOP))
   1204       1.12    nonaka 			aprint_normal_dev(sc->sc_dev, "BM1: NO End of Page?\n");
   1205        1.1  jmcneill 
   1206        1.1  jmcneill 		if (sc->sc_rec.ch_intr) {
   1207        1.1  jmcneill 			sc->sc_rec.ch_intr(sc->sc_rec.ch_intr_arg);
   1208        1.1  jmcneill 		}
   1209        1.1  jmcneill 		nintr++;
   1210        1.1  jmcneill 	}
   1211        1.1  jmcneill 
   1212        1.1  jmcneill #ifdef GCSCAUDIO_DEBUG
   1213        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_IRQ_STS)
   1214       1.12    nonaka 		aprint_normal_dev(sc->sc_dev, "Codec GPIO IRQ Status\n");
   1215        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_WU_IRQ_STS)
   1216       1.12    nonaka 		aprint_normal_dev(sc->sc_dev, "Codec GPIO Wakeup IRQ Status\n");
   1217        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM2_IRQ_STS)
   1218       1.12    nonaka 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 2 IRQ Status\n");
   1219        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM3_IRQ_STS)
   1220       1.12    nonaka 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 3 IRQ Status\n");
   1221        1.1  jmcneill 	if (intr & ACC_IRQ_STATUS_BM5_IRQ_STS)
   1222       1.12    nonaka 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 5 IRQ Status\n");
   1223        1.1  jmcneill #endif
   1224        1.1  jmcneill 
   1225        1.8  jmcneill done:
   1226        1.8  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
   1227        1.8  jmcneill 
   1228        1.1  jmcneill 	return nintr ? 1 : 0;
   1229        1.1  jmcneill }
   1230        1.1  jmcneill 
   1231        1.1  jmcneill static bool
   1232        1.5    dyoung gcscaudio_resume(device_t dv, const pmf_qual_t *qual)
   1233        1.1  jmcneill {
   1234        1.1  jmcneill 	struct gcscaudio_softc *sc = device_private(dv);
   1235        1.1  jmcneill 
   1236        1.1  jmcneill 	gcscaudio_reset_codec(sc);
   1237        1.1  jmcneill 	DELAY(1000);
   1238        1.1  jmcneill 	(sc->codec_if->vtbl->restore_ports)(sc->codec_if);
   1239        1.1  jmcneill 
   1240        1.1  jmcneill 	return true;
   1241        1.1  jmcneill }
   1242        1.1  jmcneill 
   1243        1.1  jmcneill static int
   1244        1.1  jmcneill gcscaudio_allocate_dma(struct gcscaudio_softc *sc, size_t size, void **addrp,
   1245        1.1  jmcneill                        bus_dma_segment_t *seglist, int nseg, int *rsegp,
   1246        1.8  jmcneill                        bus_dmamap_t *mapp)
   1247        1.1  jmcneill {
   1248        1.1  jmcneill 	int error;
   1249        1.1  jmcneill 
   1250        1.1  jmcneill 	if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, seglist,
   1251        1.8  jmcneill 	    nseg, rsegp, BUS_DMA_WAITOK)) != 0) {
   1252       1.12    nonaka 		aprint_error_dev(sc->sc_dev,
   1253        1.1  jmcneill 		    "unable to allocate DMA buffer, error=%d\n", error);
   1254        1.1  jmcneill 		goto fail_alloc;
   1255        1.1  jmcneill 	}
   1256        1.1  jmcneill 
   1257        1.1  jmcneill 	if ((error = bus_dmamem_map(sc->sc_dmat, seglist, nseg, size, addrp,
   1258        1.8  jmcneill 	    BUS_DMA_WAITOK | BUS_DMA_COHERENT)) != 0) {
   1259       1.12    nonaka 		aprint_error_dev(sc->sc_dev,
   1260        1.1  jmcneill 		    "unable to map DMA buffer, error=%d\n",
   1261        1.1  jmcneill 		    error);
   1262        1.1  jmcneill 		goto fail_map;
   1263        1.1  jmcneill 	}
   1264        1.1  jmcneill 
   1265        1.1  jmcneill 	if ((error = bus_dmamap_create(sc->sc_dmat, size, nseg, size, 0,
   1266        1.8  jmcneill 	    BUS_DMA_WAITOK, mapp)) != 0) {
   1267       1.12    nonaka 		aprint_error_dev(sc->sc_dev,
   1268        1.1  jmcneill 		    "unable to create DMA map, error=%d\n", error);
   1269        1.1  jmcneill 		goto fail_create;
   1270        1.1  jmcneill 	}
   1271        1.1  jmcneill 
   1272        1.1  jmcneill 	if ((error = bus_dmamap_load(sc->sc_dmat, *mapp, *addrp, size, NULL,
   1273        1.8  jmcneill 	    BUS_DMA_WAITOK)) != 0) {
   1274       1.12    nonaka 		aprint_error_dev(sc->sc_dev,
   1275        1.1  jmcneill 		    "unable to load DMA map, error=%d\n", error);
   1276        1.1  jmcneill 		goto fail_load;
   1277        1.1  jmcneill 	}
   1278        1.1  jmcneill 
   1279        1.1  jmcneill 	return 0;
   1280        1.1  jmcneill 
   1281        1.1  jmcneill fail_load:
   1282        1.1  jmcneill 	bus_dmamap_destroy(sc->sc_dmat, *mapp);
   1283        1.1  jmcneill fail_create:
   1284        1.1  jmcneill 	bus_dmamem_unmap(sc->sc_dmat, *addrp, size);
   1285        1.1  jmcneill fail_map:
   1286        1.1  jmcneill 	bus_dmamem_free(sc->sc_dmat, seglist, nseg);
   1287        1.1  jmcneill fail_alloc:
   1288        1.1  jmcneill 	return error;
   1289        1.1  jmcneill }
   1290