Home | History | Annotate | Line # | Download | only in pci
emuxki.c revision 1.74
      1  1.74   khorben /*	$NetBSD: emuxki.c,v 1.74 2022/09/07 00:44:07 khorben Exp $	*/
      2   1.1  jdolecek 
      3   1.1  jdolecek /*-
      4  1.60  jmcneill  * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
      5   1.1  jdolecek  * All rights reserved.
      6   1.1  jdolecek  *
      7   1.1  jdolecek  * This code is derived from software contributed to The NetBSD Foundation
      8  1.60  jmcneill  * by Yannick Montulet, and by Andrew Doran.
      9   1.1  jdolecek  *
     10   1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     11   1.1  jdolecek  * modification, are permitted provided that the following conditions
     12   1.1  jdolecek  * are met:
     13   1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     14   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     15   1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     18   1.1  jdolecek  *
     19   1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  jdolecek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  jdolecek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  jdolecek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  jdolecek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  jdolecek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  jdolecek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  jdolecek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  jdolecek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  jdolecek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  jdolecek  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  jdolecek  */
     31   1.1  jdolecek 
     32   1.1  jdolecek /*
     33  1.68     isaki  * EMU10K1 single voice driver
     34  1.68     isaki  * o. only 1 voice playback, 1 recording
     35  1.68     isaki  * o. only s16le 2ch 48k
     36  1.68     isaki  * This makes it simple to control buffers and interrupts
     37  1.68     isaki  * while satisfying playback and recording quality.
     38   1.1  jdolecek  */
     39   1.4     lukem 
     40   1.4     lukem #include <sys/cdefs.h>
     41  1.74   khorben __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.74 2022/09/07 00:44:07 khorben Exp $");
     42   1.1  jdolecek 
     43   1.5     lukem #include <sys/param.h>
     44   1.1  jdolecek #include <sys/device.h>
     45  1.73   khorben #include <sys/module.h>
     46   1.1  jdolecek #include <sys/errno.h>
     47   1.1  jdolecek #include <sys/systm.h>
     48   1.1  jdolecek #include <sys/audioio.h>
     49  1.60  jmcneill #include <sys/mutex.h>
     50  1.60  jmcneill #include <sys/kmem.h>
     51  1.60  jmcneill #include <sys/malloc.h>
     52  1.68     isaki #include <sys/fcntl.h>
     53  1.60  jmcneill 
     54  1.68     isaki #include <sys/bus.h>
     55  1.68     isaki #include <sys/intr.h>
     56  1.68     isaki 
     57  1.68     isaki #include <dev/audio/audio_if.h>
     58  1.60  jmcneill 
     59   1.1  jdolecek #include <dev/ic/ac97reg.h>
     60   1.1  jdolecek #include <dev/ic/ac97var.h>
     61   1.1  jdolecek 
     62  1.68     isaki #include <dev/pci/pcidevs.h>
     63  1.60  jmcneill #include <dev/pci/pcireg.h>
     64  1.60  jmcneill #include <dev/pci/pcivar.h>
     65  1.68     isaki 
     66   1.1  jdolecek #include <dev/pci/emuxkireg.h>
     67   1.1  jdolecek 
     68  1.68     isaki /* #define EMUXKI_DEBUG 1 */
     69  1.68     isaki #ifdef EMUXKI_DEBUG
     70  1.68     isaki #define emudebug EMUXKI_DEBUG
     71  1.68     isaki # define DPRINTF(fmt...)	do { if (emudebug) printf(fmt); } while (0)
     72  1.68     isaki # define DPRINTFN(n,fmt...)	do { if (emudebug>=(n)) printf(fmt); } while (0)
     73  1.68     isaki #else
     74  1.68     isaki # define DPRINTF(fmt...)	__nothing
     75  1.68     isaki # define DPRINTFN(n,fmt...)	__nothing
     76  1.68     isaki #endif
     77  1.68     isaki 
     78  1.68     isaki /*
     79  1.68     isaki  * PCI
     80  1.68     isaki  * Note: emuxki's page table entry uses only 31bit addressing.
     81  1.68     isaki  *       (Maybe, later chip has 32bit mode, but it isn't used now.)
     82  1.68     isaki  */
     83   1.1  jdolecek 
     84  1.68     isaki #define EMU_PCI_CBIO		(0x10)
     85  1.68     isaki #define EMU_SUBSYS_APS		(0x40011102)
     86   1.1  jdolecek 
     87  1.68     isaki #define EMU_PTESIZE		(4096)
     88  1.68     isaki #define EMU_MINPTE		(3)
     89  1.68     isaki /*
     90  1.68     isaki  * Hardware limit of PTE is 4096 entry but it's too big for single voice.
     91  1.68     isaki  * Reasonable candidate is:
     92  1.68     isaki  *  48kHz * 2ch * 2byte * 1sec * 3buf/EMU_PTESIZE = 141
     93  1.68     isaki  * and then round it up to 2^n.
     94  1.68     isaki  */
     95  1.68     isaki #define EMU_MAXPTE		(256)
     96  1.68     isaki #define EMU_NUMCHAN		(64)
     97   1.1  jdolecek 
     98  1.68     isaki /*
     99  1.68     isaki  * Internal recording DMA buffer
    100  1.68     isaki  */
    101  1.68     isaki /* Recommend the same size as EMU_PTESIZE to be symmetrical for play/rec */
    102  1.68     isaki #define EMU_REC_DMABLKSIZE	(4096)
    103  1.68     isaki /* must be EMU_REC_DMABLKSIZE * 2 */
    104  1.68     isaki #define EMU_REC_DMASIZE		(8192)
    105  1.68     isaki /* must be EMU_RECBS_BUFSIZE_(EMU_REC_DMASIZE) */
    106  1.68     isaki #define EMU_REC_BUFSIZE_RECBS	EMU_RECBS_BUFSIZE_8192
    107   1.1  jdolecek 
    108   1.1  jdolecek /*
    109  1.68     isaki  * DMA memory management
    110   1.1  jdolecek  */
    111   1.1  jdolecek 
    112  1.68     isaki #define EMU_DMA_ALIGN		(4096)
    113  1.68     isaki #define EMU_DMA_NSEGS		(1)
    114  1.68     isaki 
    115  1.68     isaki struct dmamem {
    116  1.68     isaki 	bus_dma_tag_t		dmat;
    117  1.68     isaki 	bus_size_t		size;
    118  1.68     isaki 	bus_size_t		align;
    119  1.68     isaki 	bus_size_t		bound;
    120  1.68     isaki 	bus_dma_segment_t	*segs;
    121  1.68     isaki 	int			nsegs;
    122  1.68     isaki 	int			rsegs;
    123  1.68     isaki 	void *			kaddr;
    124  1.68     isaki 	bus_dmamap_t		map;
    125  1.68     isaki };
    126   1.1  jdolecek 
    127  1.68     isaki #define KERNADDR(ptr)		((void *)((ptr)->kaddr))
    128   1.1  jdolecek /*
    129  1.68     isaki  * (ptr)->segs[] is CPU's PA translated by CPU's MMU.
    130  1.68     isaki  * (ptr)->map->dm_segs[] is PCI device's PA translated by PCI's MMU.
    131   1.1  jdolecek  */
    132  1.68     isaki #define DMASEGADDR(ptr, segno)	((ptr)->map->dm_segs[segno].ds_addr)
    133  1.68     isaki #define DMAADDR(ptr)		DMASEGADDR(ptr, 0)
    134  1.68     isaki #define DMASIZE(ptr)		((ptr)->size)
    135  1.68     isaki 
    136  1.68     isaki struct emuxki_softc {
    137  1.68     isaki 	device_t		sc_dev;
    138  1.68     isaki 	device_t		sc_audev;
    139  1.68     isaki 	enum {
    140  1.68     isaki 		EMUXKI_SBLIVE = 0x00,
    141  1.68     isaki 		EMUXKI_AUDIGY = 0x01,
    142  1.68     isaki 		EMUXKI_AUDIGY2 = 0x02,
    143  1.72   khorben 		EMUXKI_AUDIGY2_VALUE = 0x04,
    144  1.72   khorben 		EMUXKI_LIVE_5_1 = 0x08,
    145  1.72   khorben 		EMUXKI_APS = 0x10
    146  1.68     isaki 	} sc_type;
    147  1.68     isaki 	audio_device_t		sc_audv;	/* for GETDEV */
    148  1.68     isaki 
    149  1.68     isaki 	/* Autoconfig parameters */
    150  1.68     isaki 	bus_space_tag_t		sc_iot;
    151  1.68     isaki 	bus_space_handle_t	sc_ioh;
    152  1.68     isaki 	bus_addr_t		sc_iob;
    153  1.68     isaki 	bus_size_t		sc_ios;
    154  1.68     isaki 	pci_chipset_tag_t	sc_pc;		/* PCI tag */
    155  1.68     isaki 	bus_dma_tag_t		sc_dmat;
    156  1.68     isaki 	void			*sc_ih;		/* interrupt handler */
    157  1.68     isaki 	kmutex_t		sc_intr_lock;
    158  1.68     isaki 	kmutex_t		sc_lock;
    159  1.68     isaki 	kmutex_t		sc_index_lock;
    160  1.68     isaki 
    161  1.68     isaki 	/* register parameters */
    162  1.68     isaki 	struct dmamem		*ptb;		/* page table */
    163  1.68     isaki 
    164  1.68     isaki 	struct dmamem		*pmem;		/* play memory */
    165  1.68     isaki 	void			(*pintr)(void *);
    166  1.68     isaki 	void			*pintrarg;
    167  1.68     isaki 	audio_params_t		play;
    168  1.73   khorben 	uint32_t		pframesize;
    169  1.73   khorben 	uint32_t		pblksize;
    170  1.73   khorben 	uint32_t		plength;
    171  1.73   khorben 	uint32_t		poffset;
    172  1.68     isaki 
    173  1.68     isaki 	struct dmamem		*rmem;		/* rec internal memory */
    174  1.68     isaki 	void			(*rintr)(void *);
    175  1.68     isaki 	void			*rintrarg;
    176  1.68     isaki 	audio_params_t		rec;
    177  1.68     isaki 	void			*rptr;		/* rec MI ptr */
    178  1.68     isaki 	int			rcurrent;	/* rec software trans count */
    179  1.68     isaki 	int			rframesize;
    180  1.68     isaki 	int			rblksize;
    181  1.68     isaki 	int			rlength;
    182  1.68     isaki 	int			roffset;
    183   1.1  jdolecek 
    184  1.68     isaki 	/* others */
    185   1.1  jdolecek 
    186  1.68     isaki 	struct ac97_host_if	hostif;
    187  1.68     isaki 	struct ac97_codec_if	*codecif;
    188  1.68     isaki };
    189   1.1  jdolecek 
    190  1.68     isaki /* blackmagic */
    191  1.68     isaki #define X1(x)		((sc->sc_type & EMUXKI_AUDIGY) ? EMU_A_##x : EMU_##x)
    192  1.68     isaki #define X2(x, y)	((sc->sc_type & EMUXKI_AUDIGY) \
    193  1.68     isaki     ? EMU_A_##x(EMU_A_##y) : EMU_##x(EMU_##y))
    194  1.68     isaki #define EMU_A_DSP_FX		EMU_DSP_FX
    195  1.68     isaki #define EMU_A_DSP_IN_AC97	EMU_DSP_IN_AC97
    196   1.1  jdolecek 
    197  1.68     isaki /* prototypes */
    198  1.68     isaki static struct dmamem *dmamem_alloc(struct emuxki_softc *, size_t);
    199  1.68     isaki static void	dmamem_free(struct dmamem *);
    200  1.68     isaki static void	dmamem_sync(struct dmamem *, int);
    201  1.68     isaki static uint8_t	emuxki_readio_1(struct emuxki_softc *, int) __unused;
    202  1.68     isaki static uint16_t	emuxki_readio_2(struct emuxki_softc *, int);
    203  1.68     isaki static uint32_t	emuxki_readio_4(struct emuxki_softc *, int);
    204  1.68     isaki static void	emuxki_writeio_1(struct emuxki_softc *, int, uint8_t);
    205  1.68     isaki static void	emuxki_writeio_2(struct emuxki_softc *, int, uint16_t);
    206  1.68     isaki static void	emuxki_writeio_4(struct emuxki_softc *, int, uint32_t);
    207  1.68     isaki static uint32_t	emuxki_readptr(struct emuxki_softc *, int, int, int);
    208  1.68     isaki static void	emuxki_writeptr(struct emuxki_softc *, int, int, int, uint32_t);
    209  1.68     isaki static uint32_t	emuxki_read(struct emuxki_softc *, int, int);
    210  1.68     isaki static void	emuxki_write(struct emuxki_softc *, int, int, uint32_t);
    211  1.68     isaki static int	emuxki_match(device_t, cfdata_t, void *);
    212  1.68     isaki static void	emuxki_attach(device_t, device_t, void *);
    213  1.68     isaki static int	emuxki_detach(device_t, int);
    214  1.68     isaki static int	emuxki_init(struct emuxki_softc *);
    215  1.68     isaki static void	emuxki_dsp_addop(struct emuxki_softc *, uint16_t *, uint8_t,
    216  1.68     isaki 		    uint16_t, uint16_t, uint16_t, uint16_t);
    217  1.68     isaki static void	emuxki_initfx(struct emuxki_softc *);
    218  1.68     isaki static void	emuxki_play_start(struct emuxki_softc *, int, uint32_t,
    219  1.68     isaki 		    uint32_t);
    220  1.68     isaki static void	emuxki_play_stop(struct emuxki_softc *, int);
    221   1.1  jdolecek 
    222  1.68     isaki static int	emuxki_query_format(void *, audio_format_query_t *);
    223  1.68     isaki static int	emuxki_set_format(void *, int,
    224  1.68     isaki 		    const audio_params_t *, const audio_params_t *,
    225  1.68     isaki 		    audio_filter_reg_t *, audio_filter_reg_t *);
    226   1.3  jdolecek static int	emuxki_halt_output(void *);
    227   1.3  jdolecek static int	emuxki_halt_input(void *);
    228  1.68     isaki static int	emuxki_intr(void *);
    229   1.3  jdolecek static int	emuxki_getdev(void *, struct audio_device *);
    230   1.3  jdolecek static int	emuxki_set_port(void *, mixer_ctrl_t *);
    231   1.3  jdolecek static int	emuxki_get_port(void *, mixer_ctrl_t *);
    232   1.3  jdolecek static int	emuxki_query_devinfo(void *, mixer_devinfo_t *);
    233  1.68     isaki static void	*emuxki_allocm(void *, int, size_t);
    234  1.60  jmcneill static void	emuxki_freem(void *, void *, size_t);
    235  1.68     isaki static int	emuxki_round_blocksize(void *, int, int,
    236  1.68     isaki 		    const audio_params_t *);
    237  1.68     isaki static size_t	emuxki_round_buffersize(void *, int, size_t);
    238   1.3  jdolecek static int	emuxki_get_props(void *);
    239  1.68     isaki static int	emuxki_trigger_output(void *, void *, void *, int,
    240  1.68     isaki 		    void (*)(void *), void *, const audio_params_t *);
    241  1.68     isaki static int	emuxki_trigger_input(void *, void *, void *, int,
    242  1.68     isaki 		    void (*)(void *), void *, const audio_params_t *);
    243  1.60  jmcneill static void	emuxki_get_locks(void *, kmutex_t **, kmutex_t **);
    244   1.1  jdolecek 
    245  1.68     isaki static int	emuxki_ac97_init(struct emuxki_softc *);
    246  1.40      kent static int	emuxki_ac97_attach(void *, struct ac97_codec_if *);
    247  1.40      kent static int	emuxki_ac97_read(void *, uint8_t, uint16_t *);
    248  1.40      kent static int	emuxki_ac97_write(void *, uint8_t, uint16_t);
    249  1.40      kent static int	emuxki_ac97_reset(void *);
    250  1.68     isaki static enum ac97_host_flags	emuxki_ac97_flags(void *);
    251  1.68     isaki 
    252   1.1  jdolecek 
    253  1.58   tsutsui CFATTACH_DECL_NEW(emuxki, sizeof(struct emuxki_softc),
    254  1.12   thorpej     emuxki_match, emuxki_attach, emuxki_detach, NULL);
    255   1.1  jdolecek 
    256  1.38      yamt static const struct audio_hw_if emuxki_hw_if = {
    257  1.68     isaki 	.query_format		= emuxki_query_format,
    258  1.68     isaki 	.set_format		= emuxki_set_format,
    259  1.67     isaki 	.round_blocksize	= emuxki_round_blocksize,
    260  1.67     isaki 	.halt_output		= emuxki_halt_output,
    261  1.67     isaki 	.halt_input		= emuxki_halt_input,
    262  1.67     isaki 	.getdev			= emuxki_getdev,
    263  1.67     isaki 	.set_port		= emuxki_set_port,
    264  1.67     isaki 	.get_port		= emuxki_get_port,
    265  1.67     isaki 	.query_devinfo		= emuxki_query_devinfo,
    266  1.67     isaki 	.allocm			= emuxki_allocm,
    267  1.67     isaki 	.freem			= emuxki_freem,
    268  1.67     isaki 	.round_buffersize	= emuxki_round_buffersize,
    269  1.67     isaki 	.get_props		= emuxki_get_props,
    270  1.67     isaki 	.trigger_output		= emuxki_trigger_output,
    271  1.67     isaki 	.trigger_input		= emuxki_trigger_input,
    272  1.67     isaki 	.get_locks		= emuxki_get_locks,
    273   1.1  jdolecek };
    274   1.1  jdolecek 
    275  1.68     isaki static const struct audio_format emuxki_formats[] = {
    276  1.68     isaki 	{
    277  1.68     isaki 		.mode		= AUMODE_PLAY | AUMODE_RECORD,
    278  1.68     isaki 		.encoding	= AUDIO_ENCODING_SLINEAR_LE,
    279  1.68     isaki 		.validbits	= 16,
    280  1.68     isaki 		.precision	= 16,
    281  1.68     isaki 		.channels	= 2,
    282  1.68     isaki 		.channel_mask	= AUFMT_STEREO,
    283  1.68     isaki 		.frequency_type	= 1,
    284  1.68     isaki 		.frequency	= { 48000 },
    285  1.68     isaki 	}
    286  1.39      kent };
    287  1.68     isaki #define EMUXKI_NFORMATS	__arraycount(emuxki_formats)
    288  1.39      kent 
    289   1.1  jdolecek /*
    290  1.68     isaki  * dma memory
    291   1.1  jdolecek  */
    292   1.1  jdolecek 
    293  1.68     isaki static struct dmamem *
    294  1.68     isaki dmamem_alloc(struct emuxki_softc *sc, size_t size)
    295   1.1  jdolecek {
    296  1.68     isaki 	struct dmamem *mem;
    297  1.40      kent 
    298  1.68     isaki 	KASSERT(!mutex_owned(&sc->sc_intr_lock));
    299   1.1  jdolecek 
    300   1.1  jdolecek 	/* Allocate memory for structure */
    301  1.65       chs 	mem = kmem_alloc(sizeof(*mem), KM_SLEEP);
    302  1.68     isaki 	mem->dmat = sc->sc_dmat;
    303   1.1  jdolecek 	mem->size = size;
    304  1.68     isaki 	mem->align = EMU_DMA_ALIGN;
    305  1.68     isaki 	mem->nsegs = EMU_DMA_NSEGS;
    306   1.1  jdolecek 	mem->bound = 0;
    307   1.1  jdolecek 
    308  1.60  jmcneill 	mem->segs = kmem_alloc(mem->nsegs * sizeof(*(mem->segs)), KM_SLEEP);
    309   1.1  jdolecek 
    310  1.68     isaki 	if (bus_dmamem_alloc(mem->dmat, mem->size, mem->align, mem->bound,
    311  1.68     isaki 	    mem->segs, mem->nsegs, &mem->rsegs, BUS_DMA_WAITOK)) {
    312  1.68     isaki 		device_printf(sc->sc_dev,
    313  1.68     isaki 		    "%s bus_dmamem_alloc failed\n", __func__);
    314  1.68     isaki 		goto memfree;
    315  1.68     isaki 	}
    316  1.68     isaki 
    317  1.68     isaki 	if (bus_dmamem_map(mem->dmat, mem->segs, mem->nsegs, mem->size,
    318  1.68     isaki 	    &mem->kaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
    319  1.68     isaki 		device_printf(sc->sc_dev,
    320  1.68     isaki 		    "%s bus_dmamem_map failed\n", __func__);
    321  1.68     isaki 		goto free;
    322  1.68     isaki 	}
    323  1.68     isaki 
    324  1.68     isaki 	if (bus_dmamap_create(mem->dmat, mem->size, mem->nsegs, mem->size,
    325  1.68     isaki 	    mem->bound, BUS_DMA_WAITOK, &mem->map)) {
    326  1.68     isaki 		device_printf(sc->sc_dev,
    327  1.68     isaki 		    "%s bus_dmamap_create failed\n", __func__);
    328  1.68     isaki 		goto unmap;
    329  1.68     isaki 	}
    330  1.68     isaki 
    331  1.68     isaki 	if (bus_dmamap_load(mem->dmat, mem->map, mem->kaddr,
    332  1.68     isaki 	    mem->size, NULL, BUS_DMA_WAITOK)) {
    333  1.68     isaki 		device_printf(sc->sc_dev,
    334  1.68     isaki 		    "%s bus_dmamap_load failed\n", __func__);
    335  1.68     isaki 		goto destroy;
    336   1.1  jdolecek 	}
    337   1.1  jdolecek 
    338  1.40      kent 	return mem;
    339  1.68     isaki 
    340  1.68     isaki destroy:
    341  1.68     isaki 	bus_dmamap_destroy(mem->dmat, mem->map);
    342  1.68     isaki unmap:
    343  1.68     isaki 	bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
    344  1.68     isaki free:
    345  1.68     isaki 	bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
    346  1.68     isaki memfree:
    347  1.68     isaki 	kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
    348  1.68     isaki 	kmem_free(mem, sizeof(*mem));
    349  1.68     isaki 
    350  1.68     isaki 	return NULL;
    351   1.1  jdolecek }
    352   1.1  jdolecek 
    353   1.1  jdolecek static void
    354  1.60  jmcneill dmamem_free(struct dmamem *mem)
    355   1.1  jdolecek {
    356  1.40      kent 
    357   1.1  jdolecek 	bus_dmamap_unload(mem->dmat, mem->map);
    358   1.1  jdolecek 	bus_dmamap_destroy(mem->dmat, mem->map);
    359   1.1  jdolecek 	bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
    360   1.1  jdolecek 	bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
    361  1.68     isaki 
    362  1.68     isaki 	kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
    363  1.68     isaki 	kmem_free(mem, sizeof(*mem));
    364  1.68     isaki }
    365  1.68     isaki 
    366  1.68     isaki static void
    367  1.68     isaki dmamem_sync(struct dmamem *mem, int ops)
    368  1.68     isaki {
    369  1.68     isaki 
    370  1.68     isaki 	bus_dmamap_sync(mem->dmat, mem->map, 0, mem->size, ops);
    371   1.1  jdolecek }
    372   1.1  jdolecek 
    373   1.1  jdolecek 
    374   1.1  jdolecek /*
    375  1.68     isaki  * I/O register access
    376   1.1  jdolecek  */
    377   1.1  jdolecek 
    378  1.68     isaki static uint8_t
    379  1.68     isaki emuxki_readio_1(struct emuxki_softc *sc, int addr)
    380  1.68     isaki {
    381  1.68     isaki 
    382  1.68     isaki 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr);
    383  1.68     isaki }
    384  1.68     isaki 
    385  1.68     isaki static void
    386  1.68     isaki emuxki_writeio_1(struct emuxki_softc *sc, int addr, uint8_t data)
    387  1.68     isaki {
    388  1.68     isaki 
    389  1.68     isaki 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data);
    390  1.68     isaki }
    391  1.68     isaki 
    392  1.68     isaki static uint16_t
    393  1.68     isaki emuxki_readio_2(struct emuxki_softc *sc, int addr)
    394  1.68     isaki {
    395  1.68     isaki 
    396  1.68     isaki 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, addr);
    397  1.68     isaki }
    398  1.68     isaki 
    399  1.68     isaki static void
    400  1.68     isaki emuxki_writeio_2(struct emuxki_softc *sc, int addr, uint16_t data)
    401  1.68     isaki {
    402  1.68     isaki 
    403  1.68     isaki 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, addr, data);
    404  1.68     isaki }
    405  1.68     isaki 
    406  1.68     isaki static uint32_t
    407  1.68     isaki emuxki_readio_4(struct emuxki_softc *sc, int addr)
    408  1.68     isaki {
    409  1.68     isaki 
    410  1.68     isaki 	return bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr);
    411  1.68     isaki }
    412  1.68     isaki 
    413   1.1  jdolecek static void
    414  1.68     isaki emuxki_writeio_4(struct emuxki_softc *sc, int addr, uint32_t data)
    415   1.1  jdolecek {
    416  1.40      kent 
    417  1.68     isaki 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, data);
    418   1.1  jdolecek }
    419   1.1  jdolecek 
    420  1.68     isaki static uint32_t
    421  1.68     isaki emuxki_readptr(struct emuxki_softc *sc, int aptr, int dptr, int addr)
    422   1.1  jdolecek {
    423  1.68     isaki 	uint32_t data;
    424  1.68     isaki 
    425  1.68     isaki 	mutex_spin_enter(&sc->sc_index_lock);
    426  1.68     isaki 	emuxki_writeio_4(sc, aptr, addr);
    427  1.68     isaki 	data = emuxki_readio_4(sc, dptr);
    428  1.68     isaki 	mutex_spin_exit(&sc->sc_index_lock);
    429  1.68     isaki 	return data;
    430  1.68     isaki }
    431   1.1  jdolecek 
    432  1.68     isaki static void
    433  1.68     isaki emuxki_writeptr(struct emuxki_softc *sc, int aptr, int dptr, int addr,
    434  1.68     isaki     uint32_t data)
    435  1.68     isaki {
    436   1.1  jdolecek 
    437  1.68     isaki 	mutex_spin_enter(&sc->sc_index_lock);
    438  1.68     isaki 	emuxki_writeio_4(sc, aptr, addr);
    439  1.68     isaki 	emuxki_writeio_4(sc, dptr, data);
    440  1.68     isaki 	mutex_spin_exit(&sc->sc_index_lock);
    441  1.68     isaki }
    442   1.1  jdolecek 
    443  1.68     isaki static uint32_t
    444  1.68     isaki emuxki_read(struct emuxki_softc *sc, int ch, int addr)
    445  1.68     isaki {
    446   1.1  jdolecek 
    447  1.68     isaki 	/* Original HENTAI addressing is never supported. */
    448  1.68     isaki 	KASSERT((addr & 0xff000000) == 0);
    449   1.1  jdolecek 
    450  1.68     isaki 	return emuxki_readptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch);
    451   1.1  jdolecek }
    452   1.1  jdolecek 
    453  1.68     isaki static void
    454  1.68     isaki emuxki_write(struct emuxki_softc *sc, int ch, int addr, uint32_t data)
    455   1.1  jdolecek {
    456  1.68     isaki 
    457  1.68     isaki 	/* Original HENTAI addressing is never supported. */
    458  1.68     isaki 	KASSERT((addr & 0xff000000) == 0);
    459  1.68     isaki 
    460  1.68     isaki 	emuxki_writeptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch, data);
    461   1.1  jdolecek }
    462   1.1  jdolecek 
    463  1.68     isaki /*
    464  1.68     isaki  * MD driver
    465  1.68     isaki  */
    466  1.68     isaki 
    467   1.1  jdolecek static int
    468  1.56    cegger emuxki_match(device_t parent, cfdata_t match, void *aux)
    469   1.1  jdolecek {
    470  1.40      kent 	struct pci_attach_args *pa;
    471   1.1  jdolecek 
    472  1.40      kent 	pa = aux;
    473  1.35  christos 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
    474  1.35  christos 		return 0;
    475  1.35  christos 
    476  1.35  christos 	switch (PCI_PRODUCT(pa->pa_id)) {
    477  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE:
    478  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
    479  1.40      kent 	case PCI_PRODUCT_CREATIVELABS_AUDIGY:
    480  1.72   khorben 	case PCI_PRODUCT_CREATIVELABS_SBAUDIGY4:
    481  1.40      kent 		return 1;
    482  1.35  christos 	default:
    483  1.35  christos 		return 0;
    484  1.32    martti 	}
    485   1.1  jdolecek }
    486   1.1  jdolecek 
    487   1.1  jdolecek static void
    488  1.56    cegger emuxki_attach(device_t parent, device_t self, void *aux)
    489   1.1  jdolecek {
    490  1.40      kent 	struct emuxki_softc *sc;
    491  1.40      kent 	struct pci_attach_args *pa;
    492   1.1  jdolecek 	pci_intr_handle_t ih;
    493  1.40      kent 	const char *intrstr;
    494  1.63  christos 	char intrbuf[PCI_INTRSTR_LEN];
    495  1.68     isaki 	pcireg_t reg;
    496   1.1  jdolecek 
    497  1.57    cegger 	sc = device_private(self);
    498  1.58   tsutsui 	sc->sc_dev = self;
    499  1.40      kent 	pa = aux;
    500  1.15   thorpej 
    501  1.68     isaki 	pci_aprint_devinfo(pa, "Audio controller");
    502  1.68     isaki 	DPRINTF("dmat=%p\n", (char *)pa->pa_dmat);
    503  1.68     isaki 
    504  1.60  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    505  1.61       mrg 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    506  1.61       mrg 	mutex_init(&sc->sc_index_lock, MUTEX_DEFAULT, IPL_AUDIO);
    507  1.68     isaki 
    508  1.68     isaki 	sc->sc_pc   = pa->pa_pc;
    509  1.74   khorben 
    510  1.74   khorben 	/* EMU10K1 can only address 31 bits (2GB) */
    511  1.74   khorben 	if (bus_dmatag_subregion(pa->pa_dmat, 0, ((uint32_t)1 << 31) - 1,
    512  1.74   khorben 	    &(sc->sc_dmat), BUS_DMA_NOWAIT) != 0) {
    513  1.74   khorben 		aprint_error_dev(self,
    514  1.74   khorben 		    "WARNING: failed to restrict dma range,"
    515  1.74   khorben 		    " falling back to parent bus dma range\n");
    516  1.74   khorben 		sc->sc_dmat = pa->pa_dmat;
    517  1.74   khorben 	}
    518  1.68     isaki 
    519  1.68     isaki 	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
    520  1.68     isaki 	reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE |
    521  1.68     isaki 	    PCI_COMMAND_MEM_ENABLE;
    522  1.68     isaki 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
    523  1.60  jmcneill 
    524   1.1  jdolecek 	if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
    525  1.68     isaki 	    &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios)) {
    526  1.15   thorpej 		aprint_error(": can't map iospace\n");
    527   1.1  jdolecek 		return;
    528   1.1  jdolecek 	}
    529  1.62  drochner 
    530   1.1  jdolecek 	if (pci_intr_map(pa, &ih)) {
    531  1.58   tsutsui 		aprint_error_dev(self, "couldn't map interrupt\n");
    532  1.68     isaki 		goto unmap;
    533   1.1  jdolecek 	}
    534   1.1  jdolecek 
    535  1.63  christos 	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
    536  1.66  jdolecek 	sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO,
    537  1.66  jdolecek 	    emuxki_intr, sc, device_xname(self));
    538   1.1  jdolecek 	if (sc->sc_ih == NULL) {
    539  1.58   tsutsui 		aprint_error_dev(self, "couldn't establish interrupt");
    540   1.1  jdolecek 		if (intrstr != NULL)
    541  1.59     njoly 			aprint_error(" at %s", intrstr);
    542  1.59     njoly 		aprint_error("\n");
    543  1.68     isaki 		goto unmap;
    544   1.1  jdolecek 	}
    545  1.58   tsutsui 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
    546  1.35  christos 
    547  1.66  jdolecek 	/* XXX it's unknown whether APS is made from Audigy as well */
    548  1.72   khorben 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBAUDIGY4) {
    549  1.72   khorben 		sc->sc_type = EMUXKI_AUDIGY;
    550  1.72   khorben 		sc->sc_type |= EMUXKI_AUDIGY2;
    551  1.72   khorben 		sc->sc_type |= EMUXKI_AUDIGY2_VALUE;
    552  1.72   khorben 		strlcpy(sc->sc_audv.name, "Audigy2 (value)",
    553  1.72   khorben 		    sizeof(sc->sc_audv.name));
    554  1.72   khorben 	} else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
    555  1.40      kent 		sc->sc_type = EMUXKI_AUDIGY;
    556  1.40      kent 		if (PCI_REVISION(pa->pa_class) == 0x04) {
    557  1.40      kent 			sc->sc_type |= EMUXKI_AUDIGY2;
    558  1.64   msaitoh 			strlcpy(sc->sc_audv.name, "Audigy2",
    559  1.68     isaki 			    sizeof(sc->sc_audv.name));
    560  1.40      kent 		} else {
    561  1.64   msaitoh 			strlcpy(sc->sc_audv.name, "Audigy",
    562  1.68     isaki 			    sizeof(sc->sc_audv.name));
    563  1.40      kent 		}
    564  1.40      kent 	} else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
    565  1.40      kent 	    PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
    566  1.40      kent 		sc->sc_type = EMUXKI_APS;
    567  1.68     isaki 		strlcpy(sc->sc_audv.name, "E-mu APS", sizeof(sc->sc_audv.name));
    568  1.40      kent 	} else {
    569  1.40      kent 		sc->sc_type = EMUXKI_SBLIVE;
    570  1.68     isaki 		strlcpy(sc->sc_audv.name, "SB Live!", sizeof(sc->sc_audv.name));
    571  1.40      kent 	}
    572  1.68     isaki 	snprintf(sc->sc_audv.version, sizeof(sc->sc_audv.version), "0x%02x",
    573  1.68     isaki 	    PCI_REVISION(pa->pa_class));
    574  1.68     isaki 	strlcpy(sc->sc_audv.config, "emuxki", sizeof(sc->sc_audv.config));
    575  1.68     isaki 
    576  1.68     isaki 	if (emuxki_init(sc)) {
    577  1.68     isaki 		aprint_error("emuxki_init error\n");
    578  1.68     isaki 		goto intrdis;
    579  1.68     isaki 	}
    580  1.68     isaki 	if (emuxki_ac97_init(sc)) {
    581  1.68     isaki 		aprint_error("emuxki_ac97_init error\n");
    582  1.68     isaki 		goto intrdis;
    583  1.68     isaki 	}
    584  1.68     isaki 
    585  1.68     isaki 	sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self);
    586  1.68     isaki 	if (sc->sc_audev == NULL) {
    587  1.68     isaki 		aprint_error("audio_attach_mi error\n");
    588  1.68     isaki 		goto intrdis;
    589  1.19    toshii 	}
    590  1.68     isaki 
    591  1.68     isaki 	return;
    592  1.68     isaki 
    593  1.68     isaki intrdis:
    594  1.68     isaki 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    595  1.68     isaki unmap:
    596  1.68     isaki 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    597  1.68     isaki 	return;
    598   1.1  jdolecek }
    599   1.1  jdolecek 
    600   1.1  jdolecek static int
    601  1.56    cegger emuxki_detach(device_t self, int flags)
    602   1.1  jdolecek {
    603  1.40      kent 	struct emuxki_softc *sc;
    604   1.1  jdolecek 
    605  1.57    cegger 	sc = device_private(self);
    606  1.40      kent 	if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
    607  1.40      kent 		config_detach(sc->sc_audev, 0);
    608   1.1  jdolecek 
    609   1.1  jdolecek 	/* All voices should be stopped now but add some code here if not */
    610  1.68     isaki 	emuxki_writeio_4(sc, EMU_HCFG,
    611  1.68     isaki 	    EMU_HCFG_LOCKSOUNDCACHE |
    612  1.68     isaki 	    EMU_HCFG_LOCKTANKCACHE_MASK |
    613  1.68     isaki 	    EMU_HCFG_MUTEBUTTONENABLE);
    614  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE, 0);
    615  1.68     isaki 
    616  1.68     isaki 	/* Disable any Channels interrupts */
    617  1.68     isaki 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    618  1.68     isaki 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    619  1.68     isaki 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    620  1.68     isaki 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    621  1.68     isaki 
    622  1.68     isaki 	/* stop DSP */
    623  1.68     isaki 	emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP));
    624   1.1  jdolecek 
    625  1.68     isaki 	dmamem_free(sc->ptb);
    626   1.1  jdolecek 
    627  1.68     isaki 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    628  1.68     isaki 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    629   1.1  jdolecek 
    630  1.60  jmcneill 	mutex_destroy(&sc->sc_lock);
    631  1.60  jmcneill 	mutex_destroy(&sc->sc_intr_lock);
    632  1.60  jmcneill 	mutex_destroy(&sc->sc_index_lock);
    633  1.60  jmcneill 
    634  1.40      kent 	return 0;
    635   1.1  jdolecek }
    636   1.1  jdolecek 
    637   1.1  jdolecek static int
    638   1.1  jdolecek emuxki_init(struct emuxki_softc *sc)
    639   1.1  jdolecek {
    640  1.68     isaki 	int i;
    641  1.68     isaki 	uint32_t spcs;
    642  1.68     isaki 	uint32_t hcfg;
    643  1.68     isaki 
    644  1.68     isaki 	/* clear AUDIO bit */
    645  1.68     isaki 	emuxki_writeio_4(sc, EMU_HCFG,
    646  1.68     isaki 	    EMU_HCFG_LOCKSOUNDCACHE |
    647  1.68     isaki 	    EMU_HCFG_LOCKTANKCACHE_MASK |
    648  1.68     isaki 	    EMU_HCFG_MUTEBUTTONENABLE);
    649  1.68     isaki 
    650  1.68     isaki 	/* mask interrupt without PCIERR */
    651  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
    652  1.68     isaki 	    EMU_INTE_SAMPLERATER | /* always on this bit */
    653  1.68     isaki 	    EMU_INTE_PCIERRENABLE);
    654   1.1  jdolecek 
    655  1.68     isaki 	/* disable all channel interrupt */
    656   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    657   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    658   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    659   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    660   1.1  jdolecek 
    661   1.1  jdolecek 	/* Set recording buffers sizes to zero */
    662   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    663   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    664   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    665   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    666   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    667   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    668   1.1  jdolecek 
    669  1.40      kent 	if(sc->sc_type & EMUXKI_AUDIGY) {
    670  1.40      kent 		emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
    671  1.68     isaki 		emuxki_write(sc, 0, EMU_AC97SLOT,
    672  1.68     isaki 		    EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
    673  1.40      kent 	}
    674  1.35  christos 
    675   1.1  jdolecek 	/* Initialize all channels to stopped and no effects */
    676   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    677  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0x7f7f);
    678  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_IP, EMU_CHAN_IP_UNITY);
    679   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
    680   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
    681   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    682   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    683   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCR, 0);
    684   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PSST, 0);
    685  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_DSL, 0);
    686  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_CCCA, EMU_CHAN_CCCA_INTERPROM_1);
    687   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z1, 0);
    688   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z2, 0);
    689  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_MAPA, 0xffffffff);
    690  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_MAPB, 0xffffffff);
    691   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
    692   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
    693   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
    694   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
    695  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_PEFE, 0x007f);
    696   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
    697  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 0);
    698  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 0);
    699   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
    700   1.1  jdolecek 
    701   1.1  jdolecek 		/* these are last so OFF prevents writing */
    702  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0x8000);
    703  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0x8000);
    704  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0x7f7f);
    705   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
    706  1.68     isaki 		emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0x8000);
    707   1.1  jdolecek 	}
    708   1.1  jdolecek 
    709   1.1  jdolecek 	/* set digital outputs format */
    710  1.68     isaki 	spcs = EMU_SPCS_CLKACCY_1000PPM |
    711  1.68     isaki 	       EMU_SPCS_SAMPLERATE_48 |
    712  1.68     isaki 	       EMU_SPCS_CHANNELNUM_LEFT |
    713  1.68     isaki 	       EMU_SPCS_SOURCENUM_UNSPEC |
    714  1.68     isaki 	       EMU_SPCS_GENERATIONSTATUS |
    715  1.68     isaki 	       0x00001200 /* Cat code. */ |
    716  1.68     isaki 	       0x00000000 /* IEC-958 Mode */ |
    717  1.68     isaki 	       EMU_SPCS_EMPHASIS_NONE |
    718  1.68     isaki 	       EMU_SPCS_COPYRIGHT;
    719   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS0, spcs);
    720   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS1, spcs);
    721   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS2, spcs);
    722   1.1  jdolecek 
    723  1.72   khorben 	if (sc->sc_type & EMUXKI_AUDIGY2_VALUE) {
    724  1.72   khorben 		/* Setup SRCMulti_I2S SamplingRate */
    725  1.72   khorben 		emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE,
    726  1.72   khorben 		    emuxki_read(sc, 0, EMU_A2_SPDIF_SAMPLERATE) & 0xfffff1ff);
    727  1.72   khorben 
    728  1.72   khorben 		/* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */
    729  1.72   khorben 		emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL,
    730  1.72   khorben 		    EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
    731  1.72   khorben 
    732  1.72   khorben 		/* Setup SRCMulti Input Audio Enable */
    733  1.72   khorben 		emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA,
    734  1.72   khorben 		    0x7b0000, 0xff000000);
    735  1.72   khorben 
    736  1.72   khorben 		/* Setup SPDIF Out Audio Enable
    737  1.72   khorben 		 * The Audigy 2 Value has a separate SPDIF out,
    738  1.72   khorben 		 * so no need for a mixer switch */
    739  1.72   khorben 		emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA,
    740  1.72   khorben 		    0x7a0000, 0xff000000);
    741  1.72   khorben 		emuxki_writeio_4(sc, EMU_A_IOCFG,
    742  1.72   khorben 		    emuxki_readio_4(sc, EMU_A_IOCFG) & ~0x8); /* clear bit 3 */
    743  1.72   khorben 	} else if (sc->sc_type & EMUXKI_AUDIGY2) {
    744  1.68     isaki 		emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE,
    745  1.68     isaki 		    EMU_A2_SPDIF_UNKNOWN);
    746  1.35  christos 
    747  1.68     isaki 		emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL,
    748  1.68     isaki 		    EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
    749  1.40      kent 
    750  1.68     isaki 		emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCMULTI,
    751  1.68     isaki 		    EMU_A2_SRCMULTI_ENABLE_INPUT);
    752  1.40      kent 	}
    753  1.35  christos 
    754  1.68     isaki 	/* page table */
    755  1.68     isaki 	sc->ptb = dmamem_alloc(sc, EMU_MAXPTE * sizeof(uint32_t));
    756  1.68     isaki 	if (sc->ptb == NULL) {
    757  1.68     isaki 		device_printf(sc->sc_dev, "ptb allocation error\n");
    758  1.68     isaki 		return ENOMEM;
    759  1.68     isaki 	}
    760  1.68     isaki 	emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
    761  1.68     isaki 
    762  1.68     isaki 	emuxki_write(sc, 0, EMU_TCBS, 0);	/* This means 16K TCB */
    763  1.68     isaki 	emuxki_write(sc, 0, EMU_TCB, 0);	/* No TCB use for now */
    764  1.35  christos 
    765   1.1  jdolecek 	/* Let's play with sound processor */
    766   1.1  jdolecek 	emuxki_initfx(sc);
    767   1.1  jdolecek 
    768  1.68     isaki 	/* enable interrupt */
    769  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
    770  1.68     isaki 	    emuxki_readio_4(sc, EMU_INTE) |
    771  1.68     isaki 	    EMU_INTE_VOLINCRENABLE |
    772  1.68     isaki 	    EMU_INTE_VOLDECRENABLE |
    773  1.68     isaki 	    EMU_INTE_MUTEENABLE);
    774   1.1  jdolecek 
    775  1.72   khorben 	if (sc->sc_type & EMUXKI_AUDIGY2_VALUE) {
    776  1.72   khorben 		emuxki_writeio_4(sc, EMU_A_IOCFG,
    777  1.72   khorben 		    0x0060 | emuxki_readio_4(sc, EMU_A_IOCFG));
    778  1.72   khorben 	} else if (sc->sc_type & EMUXKI_AUDIGY2) {
    779  1.68     isaki 		emuxki_writeio_4(sc, EMU_A_IOCFG,
    780  1.72   khorben 		    EMU_A_IOCFG_GPOUT0 | emuxki_readio_4(sc, EMU_A_IOCFG));
    781   1.1  jdolecek 	}
    782   1.1  jdolecek 
    783  1.68     isaki 	/* enable AUDIO bit */
    784  1.68     isaki 	hcfg = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE;
    785   1.1  jdolecek 
    786  1.68     isaki 	if (sc->sc_type & EMUXKI_AUDIGY2) {
    787  1.68     isaki 		hcfg |= EMU_HCFG_AC3ENABLE_CDSPDIF |
    788  1.68     isaki 		        EMU_HCFG_AC3ENABLE_GPSPDIF;
    789  1.68     isaki 	} else if (sc->sc_type & EMUXKI_AUDIGY) {
    790  1.68     isaki 	} else {
    791  1.68     isaki 		hcfg |= EMU_HCFG_LOCKTANKCACHE_MASK;
    792   1.1  jdolecek 	}
    793  1.68     isaki 	/* joystick not supported now */
    794  1.68     isaki 	emuxki_writeio_4(sc, EMU_HCFG, hcfg);
    795   1.1  jdolecek 
    796  1.40      kent 	return 0;
    797   1.1  jdolecek }
    798   1.1  jdolecek 
    799  1.68     isaki /*
    800  1.68     isaki  * dsp programming
    801  1.68     isaki  */
    802  1.68     isaki 
    803   1.1  jdolecek static void
    804  1.68     isaki emuxki_dsp_addop(struct emuxki_softc *sc, uint16_t *pc, uint8_t op,
    805  1.68     isaki     uint16_t r, uint16_t a, uint16_t x, uint16_t y)
    806   1.1  jdolecek {
    807  1.68     isaki 	uint32_t loword;
    808  1.68     isaki 	uint32_t hiword;
    809  1.68     isaki 	int reg;
    810   1.1  jdolecek 
    811  1.68     isaki 	if (sc->sc_type & EMUXKI_AUDIGY) {
    812  1.68     isaki 		reg = EMU_A_MICROCODEBASE;
    813  1.68     isaki 		loword = (x << 12) & EMU_A_DSP_LOWORD_OPX_MASK;
    814  1.68     isaki 		loword |= y & EMU_A_DSP_LOWORD_OPY_MASK;
    815  1.68     isaki 		hiword = (op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK;
    816  1.68     isaki 		hiword |= (r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK;
    817  1.68     isaki 		hiword |= a & EMU_A_DSP_HIWORD_OPA_MASK;
    818  1.40      kent 	} else {
    819  1.68     isaki 		reg = EMU_MICROCODEBASE;
    820  1.68     isaki 		loword = (x << 10) & EMU_DSP_LOWORD_OPX_MASK;
    821  1.68     isaki 		loword |= y & EMU_DSP_LOWORD_OPY_MASK;
    822  1.68     isaki 		hiword = (op << 20) & EMU_DSP_HIWORD_OPCODE_MASK;
    823  1.68     isaki 		hiword |= (r << 10) & EMU_DSP_HIWORD_RESULT_MASK;
    824  1.68     isaki 		hiword |= a & EMU_DSP_HIWORD_OPA_MASK;
    825  1.40      kent 	}
    826   1.1  jdolecek 
    827  1.68     isaki 	reg += (*pc) * 2;
    828  1.68     isaki 	/* must ordering; lo, hi */
    829  1.68     isaki 	emuxki_write(sc, 0, reg, loword);
    830  1.68     isaki 	emuxki_write(sc, 0, reg + 1, hiword);
    831   1.1  jdolecek 
    832  1.68     isaki 	(*pc)++;
    833   1.1  jdolecek }
    834   1.1  jdolecek 
    835  1.68     isaki static void
    836  1.68     isaki emuxki_initfx(struct emuxki_softc *sc)
    837   1.1  jdolecek {
    838  1.68     isaki 	uint16_t pc;
    839   1.1  jdolecek 
    840  1.68     isaki 	/* Set all GPRs to 0 */
    841  1.68     isaki 	for (pc = 0; pc < 256; pc++)
    842  1.68     isaki 		emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
    843  1.68     isaki 	for (pc = 0; pc < 160; pc++) {
    844  1.68     isaki 		emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
    845  1.68     isaki 		emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
    846   1.1  jdolecek 	}
    847   1.1  jdolecek 
    848  1.68     isaki 	/* stop DSP, single step mode */
    849  1.68     isaki 	emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP));
    850  1.40      kent 
    851  1.68     isaki 	/* XXX: delay (48kHz equiv. 21us) if needed */
    852   1.1  jdolecek 
    853  1.68     isaki 	/* start DSP programming */
    854  1.68     isaki 	pc = 0;
    855   1.1  jdolecek 
    856  1.68     isaki 	/* OUT[L/R] = 0 + FX[L/R] * 1 */
    857  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    858  1.68     isaki 	    X2(DSP_OUTL, DSP_OUT_A_FRONT),
    859  1.68     isaki 	    X1(DSP_CST(0)),
    860  1.68     isaki 	    X1(DSP_FX(0)),
    861  1.68     isaki 	    X1(DSP_CST(1)));
    862  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    863  1.68     isaki 	    X2(DSP_OUTR, DSP_OUT_A_FRONT),
    864  1.68     isaki 	    X1(DSP_CST(0)),
    865  1.68     isaki 	    X1(DSP_FX(1)),
    866  1.68     isaki 	    X1(DSP_CST(1)));
    867  1.68     isaki #if 0
    868  1.68     isaki 	/* XXX: rear feature??? */
    869  1.68     isaki 	/* Rear OUT[L/R] = 0 + FX[L/R] * 1 */
    870  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    871  1.68     isaki 	    X2(DSP_OUTL, DSP_OUT_A_REAR),
    872  1.68     isaki 	    X1(DSP_CST(0)),
    873  1.68     isaki 	    X1(DSP_FX(0)),
    874  1.68     isaki 	    X1(DSP_CST(1)));
    875  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    876  1.68     isaki 	    X2(DSP_OUTR, DSP_OUT_A_REAR),
    877  1.68     isaki 	    X1(DSP_CST(0)),
    878  1.68     isaki 	    X1(DSP_FX(1)),
    879  1.68     isaki 	    X1(DSP_CST(1)));
    880  1.68     isaki #endif
    881  1.68     isaki 	/* ADC recording[L/R] = AC97 In[L/R] */
    882  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    883  1.68     isaki 	    X2(DSP_OUTL, DSP_OUT_ADC),
    884  1.68     isaki 	    X2(DSP_INL, DSP_IN_AC97),
    885  1.68     isaki 	    X1(DSP_CST(0)),
    886  1.68     isaki 	    X1(DSP_CST(0)));
    887  1.68     isaki 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    888  1.68     isaki 	    X2(DSP_OUTR, DSP_OUT_ADC),
    889  1.68     isaki 	    X2(DSP_INR, DSP_IN_AC97),
    890  1.68     isaki 	    X1(DSP_CST(0)),
    891  1.68     isaki 	    X1(DSP_CST(0)));
    892   1.1  jdolecek 
    893  1.68     isaki 	/* fill NOP the rest of the microcode */
    894  1.68     isaki 	while (pc < 512) {
    895  1.68     isaki 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    896  1.68     isaki 		    X1(DSP_CST(0)),
    897  1.68     isaki 		    X1(DSP_CST(0)),
    898  1.68     isaki 		    X1(DSP_CST(0)),
    899  1.68     isaki 		    X1(DSP_CST(0)));
    900  1.68     isaki 	}
    901   1.1  jdolecek 
    902  1.68     isaki 	/* clear single step flag, run DSP */
    903  1.68     isaki 	emuxki_write(sc, 0, X1(DBG), 0);
    904   1.1  jdolecek }
    905   1.1  jdolecek 
    906   1.1  jdolecek /*
    907  1.68     isaki  * operations
    908   1.1  jdolecek  */
    909   1.1  jdolecek 
    910   1.1  jdolecek static void
    911  1.68     isaki emuxki_play_start(struct emuxki_softc *sc, int ch, uint32_t start, uint32_t end)
    912   1.1  jdolecek {
    913  1.68     isaki 	uint32_t pitch;
    914  1.68     isaki 	uint32_t volume;
    915  1.40      kent 
    916  1.68     isaki 	/* 48kHz:16384 = 128/375 */
    917  1.68     isaki 	pitch = sc->play.sample_rate * 128 / 375;
    918  1.68     isaki 	volume = 32767;
    919   1.1  jdolecek 
    920  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_DSL,
    921  1.68     isaki 	    (0 << 24) |	/* send amound D = 0 */
    922  1.68     isaki 	    end);
    923   1.1  jdolecek 
    924  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_PSST,
    925  1.68     isaki 	    (0 << 24) |	/* send amount C = 0 */
    926  1.68     isaki 	    start);
    927   1.1  jdolecek 
    928  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_VTFT,
    929  1.68     isaki 	    (volume << 16) |
    930  1.68     isaki 	    (0xffff));	/* cutoff filter = none */
    931  1.40      kent 
    932  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_CVCF,
    933  1.68     isaki 	    (volume << 16) |
    934  1.68     isaki 	    (0xffff));	/* cutoff filter = none */
    935   1.1  jdolecek 
    936  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_PTRX,
    937  1.68     isaki 	    (pitch << 16) |
    938  1.68     isaki 	    ((ch == 0 ? 0x7f : 0) << 8) |	/* send amount A = 255,0(L) */
    939  1.68     isaki 	    ((ch == 0 ? 0 : 0x7f)));		/* send amount B = 0,255(R) */
    940  1.40      kent 
    941  1.68     isaki 	/* set the pitch to start */
    942  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_CPF,
    943  1.68     isaki 	    (pitch << 16) |
    944  1.68     isaki 	    EMU_CHAN_CPF_STEREO_MASK);	/* stereo only */
    945   1.1  jdolecek }
    946   1.1  jdolecek 
    947   1.1  jdolecek static void
    948  1.68     isaki emuxki_play_stop(struct emuxki_softc *sc, int ch)
    949  1.35  christos {
    950  1.40      kent 
    951  1.68     isaki 	/* pitch = 0 to stop playing */
    952  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_CPF, EMU_CHAN_CPF_STOP_MASK);
    953  1.68     isaki 	/* volume = 0 */
    954  1.68     isaki 	emuxki_write(sc, ch, EMU_CHAN_CVCF, 0);
    955  1.35  christos }
    956  1.35  christos 
    957  1.35  christos static void
    958  1.68     isaki emuxki_timer_start(struct emuxki_softc *sc)
    959   1.1  jdolecek {
    960  1.68     isaki 	uint32_t timer;
    961   1.1  jdolecek 
    962  1.68     isaki 	/* frame count of half PTE at 16bit, 2ch, 48kHz */
    963  1.68     isaki 	timer = EMU_PTESIZE / 4 / 2;
    964   1.1  jdolecek 
    965  1.68     isaki 	/* EMU_TIMER is 16bit register */
    966  1.68     isaki 	emuxki_writeio_2(sc, EMU_TIMER, timer);
    967  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
    968  1.68     isaki 	    emuxki_readio_4(sc, EMU_INTE) |
    969  1.68     isaki 	        EMU_INTE_INTERTIMERENB);
    970  1.68     isaki 	DPRINTF("timer start\n");
    971   1.1  jdolecek }
    972   1.1  jdolecek 
    973   1.1  jdolecek static void
    974  1.68     isaki emuxki_timer_stop(struct emuxki_softc *sc)
    975   1.1  jdolecek {
    976   1.1  jdolecek 
    977  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
    978  1.68     isaki 	    emuxki_readio_4(sc, EMU_INTE) &
    979  1.68     isaki 	        ~EMU_INTE_INTERTIMERENB);
    980  1.68     isaki 	/* EMU_TIMER is 16bit register */
    981  1.68     isaki 	emuxki_writeio_2(sc, EMU_TIMER, 0);
    982  1.68     isaki 	DPRINTF("timer stop\n");
    983   1.1  jdolecek }
    984   1.1  jdolecek 
    985   1.1  jdolecek /*
    986  1.68     isaki  * audio interface
    987   1.1  jdolecek  */
    988   1.1  jdolecek 
    989   1.1  jdolecek static int
    990  1.68     isaki emuxki_query_format(void *hdl, audio_format_query_t *afp)
    991   1.1  jdolecek {
    992  1.40      kent 
    993  1.68     isaki 	return audio_query_format(emuxki_formats, EMUXKI_NFORMATS, afp);
    994   1.1  jdolecek }
    995   1.1  jdolecek 
    996   1.1  jdolecek static int
    997  1.68     isaki emuxki_set_format(void *hdl, int setmode,
    998  1.68     isaki     const audio_params_t *play, const audio_params_t *rec,
    999  1.68     isaki     audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
   1000   1.1  jdolecek {
   1001  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1002   1.1  jdolecek 
   1003  1.68     isaki 	if ((setmode & AUMODE_PLAY))
   1004  1.68     isaki 		sc->play = *play;
   1005  1.68     isaki 	if ((setmode & AUMODE_RECORD))
   1006  1.68     isaki 		sc->rec = *rec;
   1007  1.40      kent 	return 0;
   1008   1.1  jdolecek }
   1009   1.1  jdolecek 
   1010  1.68     isaki static int
   1011  1.68     isaki emuxki_halt_output(void *hdl)
   1012   1.1  jdolecek {
   1013  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1014  1.40      kent 
   1015  1.68     isaki 	emuxki_timer_stop(sc);
   1016  1.68     isaki 	emuxki_play_stop(sc, 0);
   1017  1.68     isaki 	emuxki_play_stop(sc, 1);
   1018  1.68     isaki 	return 0;
   1019   1.1  jdolecek }
   1020   1.1  jdolecek 
   1021  1.68     isaki static int
   1022  1.68     isaki emuxki_halt_input(void *hdl)
   1023   1.1  jdolecek {
   1024  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1025   1.1  jdolecek 
   1026  1.68     isaki 	/* stop ADC */
   1027  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCCR, 0);
   1028   1.1  jdolecek 
   1029  1.68     isaki 	/* disable interrupt */
   1030  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
   1031  1.68     isaki 	    emuxki_readio_4(sc, EMU_INTE) &
   1032  1.68     isaki 	        ~EMU_INTE_ADCBUFENABLE);
   1033  1.40      kent 
   1034  1.40      kent 	return 0;
   1035   1.1  jdolecek }
   1036   1.1  jdolecek 
   1037   1.1  jdolecek static int
   1038  1.68     isaki emuxki_intr(void *hdl)
   1039   1.1  jdolecek {
   1040  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1041  1.68     isaki 	uint32_t ipr;
   1042  1.68     isaki 	uint32_t curaddr;
   1043  1.68     isaki 	int handled = 0;
   1044   1.1  jdolecek 
   1045  1.68     isaki 	mutex_spin_enter(&sc->sc_intr_lock);
   1046   1.1  jdolecek 
   1047  1.68     isaki 	ipr = emuxki_readio_4(sc, EMU_IPR);
   1048  1.68     isaki 	DPRINTFN(3, "emuxki: ipr=%08x\n", ipr);
   1049  1.68     isaki 	if (sc->pintr && (ipr & EMU_IPR_INTERVALTIMER)) {
   1050  1.68     isaki 		/* read ch 0 */
   1051  1.68     isaki 		curaddr = emuxki_read(sc, 0, EMU_CHAN_CCCA) &
   1052  1.68     isaki 		    EMU_CHAN_CCCA_CURRADDR_MASK;
   1053  1.68     isaki 		DPRINTFN(3, "curaddr=%08x\n", curaddr);
   1054  1.68     isaki 		curaddr *= sc->pframesize;
   1055  1.68     isaki 
   1056  1.68     isaki 		if (curaddr < sc->poffset)
   1057  1.68     isaki 			curaddr += sc->plength;
   1058  1.68     isaki 		if (curaddr >= sc->poffset + sc->pblksize) {
   1059  1.68     isaki 			dmamem_sync(sc->pmem, BUS_DMASYNC_POSTWRITE);
   1060  1.68     isaki 			sc->pintr(sc->pintrarg);
   1061  1.68     isaki 			sc->poffset += sc->pblksize;
   1062  1.68     isaki 			if (sc->poffset >= sc->plength) {
   1063  1.68     isaki 				sc->poffset -= sc->plength;
   1064  1.19    toshii 			}
   1065  1.68     isaki 			dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE);
   1066   1.1  jdolecek 		}
   1067  1.68     isaki 		handled = 1;
   1068   1.1  jdolecek 	}
   1069   1.1  jdolecek 
   1070  1.68     isaki 	if (sc->rintr &&
   1071  1.68     isaki 	    (ipr & (EMU_IPR_ADCBUFHALFFULL | EMU_IPR_ADCBUFFULL))) {
   1072  1.68     isaki 		char *src;
   1073  1.68     isaki 		char *dst;
   1074  1.68     isaki 
   1075  1.68     isaki 		/* Record DMA buffer has just 2 blocks */
   1076  1.68     isaki 		src = KERNADDR(sc->rmem);
   1077  1.68     isaki 		if (ipr & EMU_IPR_ADCBUFFULL) {
   1078  1.68     isaki 			/* 2nd block */
   1079  1.68     isaki 			src += EMU_REC_DMABLKSIZE;
   1080  1.35  christos 		}
   1081  1.68     isaki 		dst = (char *)sc->rptr + sc->rcurrent;
   1082   1.1  jdolecek 
   1083  1.68     isaki 		dmamem_sync(sc->rmem, BUS_DMASYNC_POSTREAD);
   1084  1.68     isaki 		memcpy(dst, src, EMU_REC_DMABLKSIZE);
   1085  1.68     isaki 		/* for next trans */
   1086  1.68     isaki 		dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD);
   1087  1.68     isaki 		sc->rcurrent += EMU_REC_DMABLKSIZE;
   1088  1.68     isaki 
   1089  1.68     isaki 		if (sc->rcurrent >= sc->roffset + sc->rblksize) {
   1090  1.68     isaki 			sc->rintr(sc->rintrarg);
   1091  1.68     isaki 			sc->roffset += sc->rblksize;
   1092  1.68     isaki 			if (sc->roffset >= sc->rlength) {
   1093  1.68     isaki 				sc->roffset = 0;
   1094  1.68     isaki 				sc->rcurrent = 0;
   1095  1.35  christos 			}
   1096  1.68     isaki 		}
   1097  1.35  christos 
   1098  1.68     isaki 		handled = 1;
   1099   1.1  jdolecek 	}
   1100   1.1  jdolecek 
   1101  1.68     isaki #if defined(EMUXKI_DEBUG)
   1102  1.68     isaki 	if (!handled) {
   1103  1.68     isaki 		char buf[1024];
   1104  1.68     isaki 		snprintb(buf, sizeof(buf),
   1105  1.68     isaki 		    "\20"
   1106  1.68     isaki 		    "\x19""RATETRCHANGE"
   1107  1.68     isaki 		    "\x18""FXDSP"
   1108  1.68     isaki 		    "\x17""FORCEINT"
   1109  1.68     isaki 		    "\x16""PCIERROR"
   1110  1.68     isaki 		    "\x15""VOLINCR"
   1111  1.68     isaki 		    "\x14""VOLDECR"
   1112  1.68     isaki 		    "\x13""MUTE"
   1113  1.68     isaki 		    "\x12""MICBUFFULL"
   1114  1.68     isaki 		    "\x11""MICBUFHALFFULL"
   1115  1.68     isaki 		    "\x10""ADCBUFFULL"
   1116  1.68     isaki 		    "\x0f""ADCBUFHALFFULL"
   1117  1.68     isaki 		    "\x0e""EFXBUFFULL"
   1118  1.68     isaki 		    "\x0d""EFXBUFHALFFULL"
   1119  1.68     isaki 		    "\x0c""GPSPDIFSTCHANGE"
   1120  1.68     isaki 		    "\x0b""CDROMSTCHANGE"
   1121  1.68     isaki 		    /*     INTERVALTIMER */
   1122  1.68     isaki 		    "\x09""MIDITRANSBUFE"
   1123  1.68     isaki 		    "\x08""MIDIRECVBUFE"
   1124  1.68     isaki 		    "\x07""CHANNELLOOP"
   1125  1.68     isaki 		    , ipr);
   1126  1.68     isaki 		DPRINTF("unexpected intr: %s\n", buf);
   1127  1.40      kent 
   1128  1.68     isaki 		/* for debugging (must not handle if !DEBUG) */
   1129  1.68     isaki 		handled = 1;
   1130   1.1  jdolecek 	}
   1131  1.19    toshii #endif
   1132  1.13  jdolecek 
   1133  1.68     isaki 	/* Reset interrupt bit */
   1134  1.68     isaki 	emuxki_writeio_4(sc, EMU_IPR, ipr);
   1135   1.1  jdolecek 
   1136  1.60  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
   1137  1.60  jmcneill 
   1138  1.68     isaki 	/* Interrupt handler must return !=0 if handled */
   1139  1.68     isaki 	return handled;
   1140   1.1  jdolecek }
   1141   1.1  jdolecek 
   1142   1.1  jdolecek static int
   1143  1.68     isaki emuxki_getdev(void *hdl, struct audio_device *dev)
   1144   1.1  jdolecek {
   1145  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1146   1.1  jdolecek 
   1147  1.68     isaki 	*dev = sc->sc_audv;
   1148  1.40      kent 	return 0;
   1149   1.1  jdolecek }
   1150   1.1  jdolecek 
   1151  1.68     isaki static int
   1152  1.68     isaki emuxki_set_port(void *hdl, mixer_ctrl_t *mctl)
   1153   1.1  jdolecek {
   1154  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1155   1.1  jdolecek 
   1156  1.68     isaki 	return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
   1157   1.1  jdolecek }
   1158   1.1  jdolecek 
   1159   1.1  jdolecek static int
   1160  1.68     isaki emuxki_get_port(void *hdl, mixer_ctrl_t *mctl)
   1161   1.1  jdolecek {
   1162  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1163   1.1  jdolecek 
   1164  1.68     isaki 	return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
   1165   1.1  jdolecek }
   1166   1.1  jdolecek 
   1167   1.1  jdolecek static int
   1168  1.68     isaki emuxki_query_devinfo(void *hdl, mixer_devinfo_t *minfo)
   1169   1.1  jdolecek {
   1170  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1171   1.1  jdolecek 
   1172  1.68     isaki 	return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
   1173   1.1  jdolecek }
   1174   1.1  jdolecek 
   1175  1.68     isaki static void *
   1176  1.68     isaki emuxki_allocm(void *hdl, int direction, size_t size)
   1177   1.1  jdolecek {
   1178  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1179  1.68     isaki 
   1180  1.68     isaki 	if (direction == AUMODE_PLAY) {
   1181  1.68     isaki 		if (sc->pmem) {
   1182  1.68     isaki 			panic("pmem already allocated\n");
   1183  1.68     isaki 			return NULL;
   1184   1.8  jdolecek 		}
   1185  1.68     isaki 		sc->pmem = dmamem_alloc(sc, size);
   1186  1.68     isaki 		return KERNADDR(sc->pmem);
   1187  1.68     isaki 	} else {
   1188  1.68     isaki 		/* rmem is fixed size internal DMA buffer */
   1189  1.68     isaki 		if (sc->rmem) {
   1190  1.68     isaki 			panic("rmem already allocated\n");
   1191  1.68     isaki 			return NULL;
   1192   1.8  jdolecek 		}
   1193  1.68     isaki 		/* rmem fixed size */
   1194  1.68     isaki 		sc->rmem = dmamem_alloc(sc, EMU_REC_DMASIZE);
   1195   1.1  jdolecek 
   1196  1.68     isaki 		/* recording MI buffer is normal kmem, software trans. */
   1197  1.68     isaki 		sc->rptr = kmem_alloc(size, KM_SLEEP);
   1198  1.68     isaki 		return sc->rptr;
   1199   1.1  jdolecek 	}
   1200   1.1  jdolecek }
   1201   1.1  jdolecek 
   1202  1.68     isaki static void
   1203  1.68     isaki emuxki_freem(void *hdl, void *ptr, size_t size)
   1204   1.1  jdolecek {
   1205  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1206   1.1  jdolecek 
   1207  1.68     isaki 	if (sc->pmem && ptr == KERNADDR(sc->pmem)) {
   1208  1.68     isaki 		dmamem_free(sc->pmem);
   1209  1.68     isaki 		sc->pmem = NULL;
   1210  1.68     isaki 	}
   1211  1.68     isaki 	if (sc->rmem && ptr == sc->rptr) {
   1212  1.68     isaki 		dmamem_free(sc->rmem);
   1213  1.68     isaki 		sc->rmem = NULL;
   1214  1.68     isaki 		kmem_free(sc->rptr, size);
   1215  1.68     isaki 		sc->rptr = NULL;
   1216  1.68     isaki 	}
   1217   1.1  jdolecek }
   1218   1.1  jdolecek 
   1219  1.68     isaki /*
   1220  1.68     isaki  * blocksize rounding to EMU_PTESIZE. It is for easy to drive.
   1221  1.68     isaki  */
   1222   1.1  jdolecek static int
   1223  1.68     isaki emuxki_round_blocksize(void *hdl, int blksize,
   1224  1.68     isaki     int mode, const audio_params_t* param)
   1225   1.1  jdolecek {
   1226   1.1  jdolecek 
   1227  1.68     isaki 	/*
   1228  1.68     isaki 	 * This is not necessary for recording, but symmetric for easy.
   1229  1.68     isaki 	 * For recording buffer/block size requirements of hardware,
   1230  1.68     isaki 	 * see EMU_RECBS_BUFSIZE_*
   1231  1.68     isaki 	 */
   1232  1.68     isaki 	if (blksize < EMU_PTESIZE)
   1233  1.68     isaki 		blksize = EMU_PTESIZE;
   1234  1.68     isaki 	return rounddown(blksize, EMU_PTESIZE);
   1235   1.1  jdolecek }
   1236   1.1  jdolecek 
   1237  1.68     isaki static size_t
   1238  1.68     isaki emuxki_round_buffersize(void *hdl, int direction, size_t bsize)
   1239   1.1  jdolecek {
   1240  1.40      kent 
   1241  1.68     isaki 	/* This is not necessary for recording, but symmetric for easy */
   1242  1.68     isaki 	if (bsize < EMU_MINPTE * EMU_PTESIZE) {
   1243  1.68     isaki 		bsize = EMU_MINPTE * EMU_PTESIZE;
   1244  1.68     isaki 	} else if (bsize > EMU_MAXPTE * EMU_PTESIZE) {
   1245  1.68     isaki 		bsize = EMU_MAXPTE * EMU_PTESIZE;
   1246  1.68     isaki 	}
   1247  1.68     isaki 	return roundup(bsize, EMU_PTESIZE);
   1248   1.1  jdolecek }
   1249   1.1  jdolecek 
   1250   1.1  jdolecek static int
   1251  1.68     isaki emuxki_get_props(void *hdl)
   1252   1.1  jdolecek {
   1253   1.1  jdolecek 
   1254  1.70     isaki 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
   1255  1.70     isaki 	    AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
   1256   1.1  jdolecek }
   1257   1.1  jdolecek 
   1258   1.1  jdolecek static int
   1259  1.68     isaki emuxki_trigger_output(void *hdl, void *start, void *end, int blksize,
   1260  1.68     isaki     void (*intr)(void *), void *arg, const audio_params_t *params)
   1261   1.1  jdolecek {
   1262  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1263  1.68     isaki 	int npage;
   1264  1.68     isaki 	uint32_t *kptb;
   1265  1.68     isaki 	bus_addr_t dpmem;
   1266  1.68     isaki 	int i;
   1267  1.68     isaki 	uint32_t hwstart;
   1268  1.68     isaki 	uint32_t hwend;
   1269  1.68     isaki 
   1270  1.68     isaki 	if (sc->pmem == NULL)
   1271  1.68     isaki 		panic("pmem == NULL\n");
   1272  1.68     isaki 	if (start != KERNADDR(sc->pmem))
   1273  1.68     isaki 		panic("start != KERNADDR(sc->pmem)\n");
   1274  1.68     isaki 
   1275  1.68     isaki 	sc->pframesize = 4;	/* channels * bit / 8 = 2*16/8=4 */
   1276  1.68     isaki 	sc->pblksize = blksize;
   1277  1.68     isaki 	sc->plength = (char *)end - (char *)start;
   1278  1.68     isaki 	sc->poffset = 0;
   1279  1.68     isaki 	npage = roundup(sc->plength, EMU_PTESIZE);
   1280   1.1  jdolecek 
   1281  1.68     isaki 	kptb = KERNADDR(sc->ptb);
   1282  1.68     isaki 	dpmem = DMAADDR(sc->pmem);
   1283  1.68     isaki 	for (i = 0; i < npage; i++) {
   1284  1.68     isaki 		kptb[i] = htole32(dpmem << 1);
   1285  1.68     isaki 		dpmem += EMU_PTESIZE;
   1286  1.68     isaki 	}
   1287  1.68     isaki 	dmamem_sync(sc->ptb, BUS_DMASYNC_PREWRITE);
   1288   1.1  jdolecek 
   1289  1.68     isaki 	hwstart = 0;
   1290  1.68     isaki 	hwend = hwstart + sc->plength / sc->pframesize;
   1291   1.1  jdolecek 
   1292  1.68     isaki 	sc->pintr = intr;
   1293  1.68     isaki 	sc->pintrarg = arg;
   1294   1.1  jdolecek 
   1295  1.68     isaki 	dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE);
   1296   1.1  jdolecek 
   1297  1.68     isaki 	emuxki_play_start(sc, 0, hwstart, hwend);
   1298  1.68     isaki 	emuxki_play_start(sc, 1, hwstart, hwend);
   1299   1.1  jdolecek 
   1300  1.68     isaki 	emuxki_timer_start(sc);
   1301   1.1  jdolecek 
   1302  1.68     isaki 	return 0;
   1303   1.1  jdolecek }
   1304   1.1  jdolecek 
   1305  1.68     isaki /*
   1306  1.68     isaki  * Recording uses temporary buffer.  Because it can use ADC_HALF/FULL
   1307  1.68     isaki  * interrupts and this method doesn't conflict with playback.
   1308  1.68     isaki  */
   1309  1.68     isaki 
   1310  1.19    toshii static int
   1311  1.68     isaki emuxki_trigger_input(void *hdl, void *start, void *end, int blksize,
   1312  1.68     isaki     void (*intr)(void *), void *arg, const audio_params_t *params)
   1313  1.19    toshii {
   1314  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1315  1.19    toshii 
   1316  1.68     isaki 	if (sc->rmem == NULL)
   1317  1.68     isaki 		panic("rmem == NULL\n");
   1318  1.68     isaki 	if (start != sc->rptr)
   1319  1.68     isaki 		panic("start != sc->rptr\n");
   1320  1.68     isaki 
   1321  1.68     isaki 	sc->rframesize = 4;	/* channels * bit / 8 = 2*16/8=4 */
   1322  1.68     isaki 	sc->rblksize = blksize;
   1323  1.68     isaki 	sc->rlength = (char *)end - (char *)start;
   1324  1.68     isaki 	sc->roffset = 0;
   1325  1.68     isaki 	sc->rcurrent = 0;
   1326  1.19    toshii 
   1327  1.68     isaki 	sc->rintr = intr;
   1328  1.68     isaki 	sc->rintrarg = arg;
   1329  1.19    toshii 
   1330  1.68     isaki 	/*
   1331  1.68     isaki 	 * Memo:
   1332  1.68     isaki 	 *  recording source is selected by AC97
   1333  1.68     isaki 	 *  AC97 input source routes to ADC by FX(DSP)
   1334  1.68     isaki 	 *
   1335  1.68     isaki 	 * Must keep following sequence order
   1336  1.68     isaki 	 */
   1337  1.40      kent 
   1338  1.68     isaki 	/* first, stop ADC */
   1339  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCCR, 0);
   1340  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCBA, 0);
   1341  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCBS, 0);
   1342   1.1  jdolecek 
   1343  1.68     isaki 	dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD);
   1344   1.1  jdolecek 
   1345  1.68     isaki 	/* ADC interrupt enable */
   1346  1.68     isaki 	emuxki_writeio_4(sc, EMU_INTE,
   1347  1.68     isaki 	    emuxki_readio_4(sc, EMU_INTE) |
   1348  1.68     isaki 	        EMU_INTE_ADCBUFENABLE);
   1349  1.68     isaki 
   1350  1.68     isaki 	/* ADC Enable */
   1351  1.68     isaki 	/* stereo, 48kHz, enable */
   1352  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCCR,
   1353  1.68     isaki 	    X1(ADCCR_LCHANENABLE) | X1(ADCCR_RCHANENABLE));
   1354  1.68     isaki 
   1355  1.68     isaki 	/* ADC buffer address */
   1356  1.68     isaki 	emuxki_write(sc, 0, X1(ADCIDX), 0);
   1357  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCBA, DMAADDR(sc->rmem));
   1358   1.1  jdolecek 
   1359  1.68     isaki 	/* ADC buffer size, to start */
   1360  1.68     isaki 	emuxki_write(sc, 0, EMU_ADCBS, EMU_REC_BUFSIZE_RECBS);
   1361   1.1  jdolecek 
   1362  1.68     isaki 	return 0;
   1363   1.1  jdolecek }
   1364   1.1  jdolecek 
   1365  1.68     isaki static void
   1366  1.68     isaki emuxki_get_locks(void *hdl, kmutex_t **intr, kmutex_t **proc)
   1367   1.1  jdolecek {
   1368  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1369   1.1  jdolecek 
   1370  1.68     isaki 	*intr = &sc->sc_intr_lock;
   1371  1.68     isaki 	*proc = &sc->sc_lock;
   1372   1.1  jdolecek }
   1373   1.1  jdolecek 
   1374  1.68     isaki /*
   1375  1.68     isaki  * AC97
   1376  1.68     isaki  */
   1377   1.1  jdolecek 
   1378   1.1  jdolecek static int
   1379  1.68     isaki emuxki_ac97_init(struct emuxki_softc *sc)
   1380   1.1  jdolecek {
   1381   1.1  jdolecek 
   1382  1.68     isaki 	sc->hostif.arg = sc;
   1383  1.68     isaki 	sc->hostif.attach = emuxki_ac97_attach;
   1384  1.68     isaki 	sc->hostif.read = emuxki_ac97_read;
   1385  1.68     isaki 	sc->hostif.write = emuxki_ac97_write;
   1386  1.68     isaki 	sc->hostif.reset = emuxki_ac97_reset;
   1387  1.68     isaki 	sc->hostif.flags = emuxki_ac97_flags;
   1388  1.68     isaki 	return ac97_attach(&sc->hostif, sc->sc_dev, &sc->sc_lock);
   1389   1.1  jdolecek }
   1390   1.1  jdolecek 
   1391   1.1  jdolecek /*
   1392   1.1  jdolecek  * AC97 callbacks
   1393   1.1  jdolecek  */
   1394   1.1  jdolecek 
   1395   1.1  jdolecek static int
   1396  1.68     isaki emuxki_ac97_attach(void *hdl, struct ac97_codec_if *codecif)
   1397   1.1  jdolecek {
   1398  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1399   1.1  jdolecek 
   1400   1.1  jdolecek 	sc->codecif = codecif;
   1401  1.40      kent 	return 0;
   1402   1.1  jdolecek }
   1403   1.1  jdolecek 
   1404   1.1  jdolecek static int
   1405  1.68     isaki emuxki_ac97_read(void *hdl, uint8_t reg, uint16_t *val)
   1406   1.1  jdolecek {
   1407  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1408   1.1  jdolecek 
   1409  1.68     isaki 	mutex_spin_enter(&sc->sc_index_lock);
   1410  1.68     isaki 	emuxki_writeio_1(sc, EMU_AC97ADDR, reg);
   1411  1.68     isaki 	*val = emuxki_readio_2(sc, EMU_AC97DATA);
   1412  1.68     isaki 	mutex_spin_exit(&sc->sc_index_lock);
   1413   1.1  jdolecek 
   1414  1.40      kent 	return 0;
   1415   1.1  jdolecek }
   1416   1.1  jdolecek 
   1417   1.1  jdolecek static int
   1418  1.68     isaki emuxki_ac97_write(void *hdl, uint8_t reg, uint16_t val)
   1419   1.1  jdolecek {
   1420  1.68     isaki 	struct emuxki_softc *sc = hdl;
   1421   1.1  jdolecek 
   1422  1.68     isaki 	mutex_spin_enter(&sc->sc_index_lock);
   1423  1.68     isaki 	emuxki_writeio_1(sc, EMU_AC97ADDR, reg);
   1424  1.68     isaki 	emuxki_writeio_2(sc, EMU_AC97DATA, val);
   1425  1.68     isaki 	mutex_spin_exit(&sc->sc_index_lock);
   1426   1.1  jdolecek 
   1427  1.40      kent 	return 0;
   1428   1.1  jdolecek }
   1429   1.1  jdolecek 
   1430  1.36      kent static int
   1431  1.68     isaki emuxki_ac97_reset(void *hdl)
   1432   1.1  jdolecek {
   1433  1.40      kent 
   1434  1.36      kent 	return 0;
   1435   1.6  jdolecek }
   1436   1.6  jdolecek 
   1437  1.68     isaki static enum ac97_host_flags
   1438  1.68     isaki emuxki_ac97_flags(void *hdl)
   1439   1.6  jdolecek {
   1440  1.40      kent 
   1441  1.40      kent 	return AC97_HOST_SWAPPED_CHANNELS;
   1442   1.1  jdolecek }
   1443  1.73   khorben 
   1444  1.73   khorben MODULE(MODULE_CLASS_DRIVER, emuxki, "pci,audio");
   1445  1.73   khorben 
   1446  1.73   khorben #ifdef _MODULE
   1447  1.73   khorben #include "ioconf.c"
   1448  1.73   khorben #endif
   1449  1.73   khorben 
   1450  1.73   khorben static int
   1451  1.73   khorben emuxki_modcmd(modcmd_t cmd, void *opaque)
   1452  1.73   khorben {
   1453  1.73   khorben 	int error = 0;
   1454  1.73   khorben 
   1455  1.73   khorben 	switch (cmd) {
   1456  1.73   khorben 	case MODULE_CMD_INIT:
   1457  1.73   khorben #ifdef _MODULE
   1458  1.73   khorben 		error = config_init_component(cfdriver_ioconf_emuxki,
   1459  1.73   khorben 		    cfattach_ioconf_emuxki, cfdata_ioconf_emuxki);
   1460  1.73   khorben #endif
   1461  1.73   khorben 		return error;
   1462  1.73   khorben 	case MODULE_CMD_FINI:
   1463  1.73   khorben #ifdef _MODULE
   1464  1.73   khorben 		error = config_fini_component(cfdriver_ioconf_emuxki,
   1465  1.73   khorben 		    cfattach_ioconf_emuxki, cfdata_ioconf_emuxki);
   1466  1.73   khorben #endif
   1467  1.73   khorben 		return error;
   1468  1.73   khorben 	default:
   1469  1.73   khorben 		return ENOTTY;
   1470  1.73   khorben 	}
   1471  1.73   khorben }
   1472