Home | History | Annotate | Line # | Download | only in pci
emuxki.c revision 1.39
      1  1.39      kent /*	$NetBSD: emuxki.c,v 1.39 2005/01/10 22:01:37 kent Exp $	*/
      2   1.1  jdolecek 
      3   1.1  jdolecek /*-
      4   1.1  jdolecek  * Copyright (c) 2001 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.1  jdolecek  * by Yannick Montulet.
      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  * 3. All advertising materials mentioning features or use of this software
     19   1.1  jdolecek  *    must display the following acknowledgement:
     20   1.1  jdolecek  *	This product includes software developed by the NetBSD
     21   1.1  jdolecek  *	Foundation, Inc. and its contributors.
     22   1.1  jdolecek  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1  jdolecek  *    contributors may be used to endorse or promote products derived
     24   1.1  jdolecek  *    from this software without specific prior written permission.
     25   1.1  jdolecek  *
     26   1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1  jdolecek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1  jdolecek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1  jdolecek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1  jdolecek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1  jdolecek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1  jdolecek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1  jdolecek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1  jdolecek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1  jdolecek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1  jdolecek  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1  jdolecek  */
     38   1.1  jdolecek 
     39   1.1  jdolecek /*
     40   1.1  jdolecek  * Driver for Creative Labs SBLive! series and probably PCI512.
     41   1.1  jdolecek  *
     42   1.1  jdolecek  * Known bugs:
     43   1.1  jdolecek  * - inversed stereo at ac97 codec level
     44   1.1  jdolecek  *   (XXX jdolecek - don't see the problem? maybe because auvia(4) has
     45   1.1  jdolecek  *    it swapped too?)
     46  1.37   dsainty  * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers
     47   1.1  jdolecek  *   (and presumably all speakers that support front and rear jack-in)
     48   1.1  jdolecek  *
     49   1.1  jdolecek  * TODO:
     50   1.1  jdolecek  * - Digital Outputs
     51   1.1  jdolecek  * - (midi/mpu),joystick support
     52   1.1  jdolecek  * - Multiple voices play (problem with /dev/audio architecture)
     53   1.1  jdolecek  * - Multiple sources recording (Pb with audio(4))
     54  1.37   dsainty  * - Independent modification of each channel's parameters (via mixer ?)
     55   1.1  jdolecek  * - DSP FX patches (to make fx like chipmunk)
     56   1.1  jdolecek  */
     57   1.4     lukem 
     58   1.4     lukem #include <sys/cdefs.h>
     59  1.39      kent __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.39 2005/01/10 22:01:37 kent Exp $");
     60   1.1  jdolecek 
     61   1.5     lukem #include <sys/param.h>
     62   1.1  jdolecek #include <sys/device.h>
     63   1.1  jdolecek #include <sys/errno.h>
     64   1.1  jdolecek #include <sys/malloc.h>
     65   1.1  jdolecek #include <sys/systm.h>
     66   1.1  jdolecek #include <sys/audioio.h>
     67   1.1  jdolecek #include <sys/select.h>
     68   1.1  jdolecek #include <dev/pci/pcireg.h>
     69   1.1  jdolecek #include <dev/pci/pcivar.h>
     70   1.1  jdolecek #include <dev/pci/pcidevs.h>
     71   1.1  jdolecek #include <dev/audio_if.h>
     72   1.1  jdolecek #include <dev/audiovar.h>
     73   1.1  jdolecek #include <dev/auconv.h>
     74   1.1  jdolecek #include <dev/mulaw.h>
     75   1.1  jdolecek #include <dev/ic/ac97reg.h>
     76   1.1  jdolecek #include <dev/ic/ac97var.h>
     77   1.1  jdolecek 
     78   1.1  jdolecek #include <dev/pci/emuxkireg.h>
     79   1.1  jdolecek #include <dev/pci/emuxkivar.h>
     80   1.1  jdolecek 
     81  1.26       wiz /* autoconf goo */
     82   1.3  jdolecek static int  emuxki_match(struct device *, struct cfdata *, void *);
     83   1.3  jdolecek static void emuxki_attach(struct device *, struct device *, void *);
     84   1.3  jdolecek static int  emuxki_detach(struct device *, int);
     85   1.1  jdolecek 
     86  1.26       wiz /* DMA mem mgmt */
     87   1.3  jdolecek static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
     88  1.16   thorpej 				 int, struct malloc_type *, int);
     89  1.16   thorpej static void           dmamem_free(struct dmamem *, struct malloc_type *);
     90   1.1  jdolecek 
     91   1.1  jdolecek /* Emu10k1 init & shutdown */
     92   1.3  jdolecek static int  emuxki_init(struct emuxki_softc *);
     93   1.3  jdolecek static void emuxki_shutdown(struct emuxki_softc *);
     94   1.1  jdolecek 
     95   1.1  jdolecek /* Emu10k1 mem mgmt */
     96  1.16   thorpej static void   *emuxki_pmem_alloc(struct emuxki_softc *, size_t,
     97  1.16   thorpej 		struct malloc_type *,int);
     98  1.16   thorpej static void   *emuxki_rmem_alloc(struct emuxki_softc *, size_t,
     99  1.16   thorpej 		struct malloc_type *,int);
    100   1.1  jdolecek 
    101   1.1  jdolecek /*
    102   1.1  jdolecek  * Emu10k1 channels funcs : There is no direct access to channels, everything
    103   1.1  jdolecek  * is done through voices I will at least provide channel based fx params
    104   1.1  jdolecek  * modification, later...
    105   1.1  jdolecek  */
    106   1.1  jdolecek 
    107   1.1  jdolecek /* Emu10k1 voice mgmt */
    108   1.3  jdolecek static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
    109   1.6  jdolecek 					     u_int8_t);
    110   1.3  jdolecek static void   emuxki_voice_delete(struct emuxki_voice *);
    111   1.3  jdolecek static int    emuxki_voice_set_audioparms(struct emuxki_voice *, u_int8_t,
    112   1.6  jdolecek 					  u_int8_t, u_int32_t);
    113   1.1  jdolecek /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
    114   1.3  jdolecek static int emuxki_voice_set_bufparms(struct emuxki_voice *,
    115   1.6  jdolecek 				     void *, u_int32_t, u_int16_t);
    116   1.3  jdolecek static void emuxki_voice_commit_parms(struct emuxki_voice *);
    117  1.35  christos static int emuxki_voice_adc_rate(struct emuxki_voice *);
    118   1.3  jdolecek static u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
    119   1.3  jdolecek static void emuxki_voice_start(struct emuxki_voice *,
    120   1.6  jdolecek 			       void (*) (void *), void *);
    121   1.3  jdolecek static void emuxki_voice_halt(struct emuxki_voice *);
    122   1.1  jdolecek 
    123   1.1  jdolecek /*
    124   1.1  jdolecek  * Emu10k1 stream mgmt : not done yet
    125   1.1  jdolecek  */
    126   1.1  jdolecek #if 0
    127   1.3  jdolecek static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
    128   1.3  jdolecek static void   emuxki_stream_delete(struct emuxki_stream *);
    129   1.3  jdolecek static int    emuxki_stream_set_audio_params(struct emuxki_stream *, u_int8_t,
    130   1.6  jdolecek 					     u_int8_t, u_int8_t, u_int16_t);
    131   1.3  jdolecek static void   emuxki_stream_start(struct emuxki_stream *);
    132   1.3  jdolecek static void   emuxki_stream_halt(struct emuxki_stream *);
    133   1.1  jdolecek #endif
    134   1.1  jdolecek 
    135   1.1  jdolecek /* audio interface callbacks */
    136   1.1  jdolecek 
    137   1.3  jdolecek static int	emuxki_open(void *, int);
    138   1.3  jdolecek static void	emuxki_close(void *);
    139   1.1  jdolecek 
    140   1.3  jdolecek static int	emuxki_query_encoding(void *, struct audio_encoding *);
    141  1.39      kent static int	emuxki_set_params(void *, int, int, audio_params_t *,
    142  1.39      kent 				  audio_params_t *, stream_filter_list_t *,
    143  1.39      kent 				  stream_filter_list_t *);
    144   1.1  jdolecek 
    145  1.39      kent static int	emuxki_round_blocksize(void *, int, int, const audio_params_t *);
    146   1.3  jdolecek static size_t	emuxki_round_buffersize(void *, int, size_t);
    147   1.1  jdolecek 
    148   1.3  jdolecek static int	emuxki_trigger_output(void *, void *, void *, int,
    149   1.1  jdolecek 				      void (*)(void *), void *,
    150  1.39      kent 				      const audio_params_t *);
    151   1.3  jdolecek static int	emuxki_trigger_input(void *, void *, void *, int,
    152   1.6  jdolecek 				     void (*) (void *), void *,
    153  1.39      kent 				     const audio_params_t *);
    154   1.3  jdolecek static int	emuxki_halt_output(void *);
    155   1.3  jdolecek static int	emuxki_halt_input(void *);
    156   1.3  jdolecek 
    157   1.3  jdolecek static int	emuxki_getdev(void *, struct audio_device *);
    158   1.3  jdolecek static int	emuxki_set_port(void *, mixer_ctrl_t *);
    159   1.3  jdolecek static int	emuxki_get_port(void *, mixer_ctrl_t *);
    160   1.3  jdolecek static int	emuxki_query_devinfo(void *, mixer_devinfo_t *);
    161   1.1  jdolecek 
    162  1.16   thorpej static void    *emuxki_allocm(void *, int, size_t, struct malloc_type *, int);
    163  1.16   thorpej static void	emuxki_freem(void *, void *, struct malloc_type *);
    164   1.1  jdolecek 
    165   1.3  jdolecek static paddr_t	emuxki_mappage(void *, void *, off_t, int);
    166   1.3  jdolecek static int	emuxki_get_props(void *);
    167   1.1  jdolecek 
    168   1.1  jdolecek /* Interrupt handler */
    169   1.3  jdolecek static int  emuxki_intr(void *);
    170   1.1  jdolecek 
    171   1.1  jdolecek /* Emu10k1 AC97 interface callbacks */
    172   1.3  jdolecek static int  emuxki_ac97_attach(void *, struct ac97_codec_if *);
    173   1.3  jdolecek static int  emuxki_ac97_read(void *, u_int8_t, u_int16_t *);
    174   1.3  jdolecek static int  emuxki_ac97_write(void *, u_int8_t, u_int16_t);
    175  1.36      kent static int  emuxki_ac97_reset(void *);
    176   1.6  jdolecek static enum ac97_host_flags emuxki_ac97_flags(void *);
    177   1.1  jdolecek 
    178   1.1  jdolecek /*
    179   1.1  jdolecek  * Autoconfig goo.
    180   1.1  jdolecek  */
    181  1.11   thorpej CFATTACH_DECL(emuxki, sizeof(struct emuxki_softc),
    182  1.12   thorpej     emuxki_match, emuxki_attach, emuxki_detach, NULL);
    183   1.1  jdolecek 
    184  1.38      yamt static const struct audio_hw_if emuxki_hw_if = {
    185   1.1  jdolecek 	emuxki_open,
    186   1.1  jdolecek 	emuxki_close,
    187   1.1  jdolecek 	NULL,			/* drain */
    188   1.1  jdolecek 	emuxki_query_encoding,
    189   1.1  jdolecek 	emuxki_set_params,
    190  1.19    toshii 	emuxki_round_blocksize,
    191   1.1  jdolecek 	NULL,			/* commit settings */
    192   1.1  jdolecek 	NULL,			/* init_output */
    193   1.1  jdolecek 	NULL,			/* init_input */
    194   1.1  jdolecek 	NULL,			/* start_output */
    195   1.1  jdolecek 	NULL,			/* start_input */
    196   1.1  jdolecek 	emuxki_halt_output,
    197   1.1  jdolecek 	emuxki_halt_input,
    198   1.1  jdolecek 	NULL,			/* speaker_ctl */
    199   1.1  jdolecek 	emuxki_getdev,
    200   1.1  jdolecek 	NULL,			/* setfd */
    201   1.1  jdolecek 	emuxki_set_port,
    202   1.1  jdolecek 	emuxki_get_port,
    203   1.1  jdolecek 	emuxki_query_devinfo,
    204   1.1  jdolecek 	emuxki_allocm,
    205   1.1  jdolecek 	emuxki_freem,
    206   1.1  jdolecek 	emuxki_round_buffersize,
    207   1.1  jdolecek 	emuxki_mappage,
    208   1.1  jdolecek 	emuxki_get_props,
    209   1.1  jdolecek 	emuxki_trigger_output,
    210   1.1  jdolecek 	emuxki_trigger_input,
    211   1.1  jdolecek 	NULL,			/* dev_ioctl */
    212   1.1  jdolecek };
    213   1.1  jdolecek 
    214  1.20      fvdl #if 0
    215  1.19    toshii static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
    216  1.19    toshii     { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
    217  1.20      fvdl #endif
    218  1.19    toshii static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
    219  1.19    toshii     { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
    220  1.19    toshii static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
    221  1.19    toshii     { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
    222  1.19    toshii static const int emuxki_recbuf_sz[] = {
    223  1.19    toshii 	0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
    224  1.19    toshii 	2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
    225  1.19    toshii 	12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
    226  1.19    toshii 	57344, 65536
    227  1.19    toshii };
    228  1.19    toshii 
    229  1.39      kent #define EMUXKI_NFORMATS	4
    230  1.39      kent static const struct audio_format emuxki_formats[EMUXKI_NFORMATS] = {
    231  1.39      kent 	{NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
    232  1.39      kent 	 2, AUFMT_STEREO, 0, {4000, 48000}},
    233  1.39      kent 	{NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
    234  1.39      kent 	 1, AUFMT_MONAURAL, 0, {4000, 48000}},
    235  1.39      kent 	{NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
    236  1.39      kent 	 2, AUFMT_STEREO, 0, {4000, 48000}},
    237  1.39      kent 	{NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
    238  1.39      kent 	 1, AUFMT_MONAURAL, 0, {4000, 48000}},
    239  1.39      kent };
    240  1.39      kent 
    241   1.1  jdolecek /*
    242  1.26       wiz  * DMA memory mgmt
    243   1.1  jdolecek  */
    244   1.1  jdolecek 
    245   1.1  jdolecek static void
    246  1.16   thorpej dmamem_delete(struct dmamem *mem, struct malloc_type *type)
    247   1.1  jdolecek {
    248   1.1  jdolecek 	free(mem->segs, type);
    249   1.1  jdolecek 	free(mem, type);
    250   1.1  jdolecek }
    251   1.1  jdolecek 
    252   1.1  jdolecek static struct dmamem *
    253   1.1  jdolecek dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align,
    254  1.16   thorpej 	     int nsegs, struct malloc_type *type, int flags)
    255   1.1  jdolecek {
    256   1.1  jdolecek 	struct dmamem	*mem;
    257   1.1  jdolecek 	int		bus_dma_flags;
    258   1.1  jdolecek 
    259   1.1  jdolecek 	/* Allocate memory for structure */
    260   1.1  jdolecek 	if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
    261   1.1  jdolecek 		return (NULL);
    262   1.1  jdolecek 	mem->dmat = dmat;
    263   1.1  jdolecek 	mem->size = size;
    264   1.1  jdolecek 	mem->align = align;
    265   1.1  jdolecek 	mem->nsegs = nsegs;
    266   1.1  jdolecek 	mem->bound = 0;
    267   1.1  jdolecek 
    268   1.1  jdolecek 	mem->segs = malloc(mem->nsegs * sizeof(*(mem->segs)), type, flags);
    269   1.1  jdolecek 	if (mem->segs == NULL) {
    270   1.1  jdolecek 		free(mem, type);
    271   1.1  jdolecek 		return (NULL);
    272   1.1  jdolecek 	}
    273   1.1  jdolecek 
    274   1.1  jdolecek 	bus_dma_flags = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
    275   1.1  jdolecek 	if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
    276   1.1  jdolecek 			     mem->segs, mem->nsegs, &(mem->rsegs),
    277   1.1  jdolecek 			     bus_dma_flags)) {
    278   1.1  jdolecek 		dmamem_delete(mem, type);
    279   1.1  jdolecek 		return (NULL);
    280   1.1  jdolecek 	}
    281   1.1  jdolecek 
    282   1.1  jdolecek 	if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
    283   1.1  jdolecek 			   &(mem->kaddr), bus_dma_flags | BUS_DMA_COHERENT)) {
    284   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    285   1.1  jdolecek 		dmamem_delete(mem, type);
    286   1.1  jdolecek 		return (NULL);
    287   1.1  jdolecek 	}
    288   1.1  jdolecek 
    289   1.1  jdolecek 	if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
    290   1.1  jdolecek 			      mem->bound, bus_dma_flags, &(mem->map))) {
    291   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    292   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    293   1.1  jdolecek 		dmamem_delete(mem, type);
    294   1.1  jdolecek 		return (NULL);
    295   1.1  jdolecek 	}
    296   1.1  jdolecek 
    297   1.1  jdolecek 	if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
    298   1.1  jdolecek 			    mem->size, NULL, bus_dma_flags)) {
    299   1.1  jdolecek 		bus_dmamap_destroy(dmat, mem->map);
    300   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    301   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    302   1.1  jdolecek 		dmamem_delete(mem, type);
    303   1.1  jdolecek 		return (NULL);
    304   1.1  jdolecek 	}
    305   1.1  jdolecek 
    306   1.1  jdolecek 	return (mem);
    307   1.1  jdolecek }
    308   1.1  jdolecek 
    309   1.1  jdolecek static void
    310  1.16   thorpej dmamem_free(struct dmamem *mem, struct malloc_type *type)
    311   1.1  jdolecek {
    312   1.1  jdolecek 	bus_dmamap_unload(mem->dmat, mem->map);
    313   1.1  jdolecek 	bus_dmamap_destroy(mem->dmat, mem->map);
    314   1.1  jdolecek 	bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
    315   1.1  jdolecek 	bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
    316   1.1  jdolecek 	dmamem_delete(mem, type);
    317   1.1  jdolecek }
    318   1.1  jdolecek 
    319   1.1  jdolecek 
    320   1.1  jdolecek /*
    321   1.1  jdolecek  * Autoconf device callbacks : attach and detach
    322   1.1  jdolecek  */
    323   1.1  jdolecek 
    324   1.1  jdolecek static void
    325   1.1  jdolecek emuxki_pci_shutdown(struct emuxki_softc *sc)
    326   1.1  jdolecek {
    327   1.1  jdolecek 	if (sc->sc_ih != NULL)
    328   1.1  jdolecek 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    329   1.1  jdolecek 	if (sc->sc_ios)
    330   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    331   1.1  jdolecek }
    332   1.1  jdolecek 
    333   1.1  jdolecek static int
    334   1.1  jdolecek emuxki_scinit(struct emuxki_softc *sc)
    335   1.1  jdolecek {
    336   1.1  jdolecek 	int             err;
    337   1.1  jdolecek 
    338   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    339   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    340   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    341   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    342   1.1  jdolecek 		EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
    343   1.1  jdolecek 
    344   1.1  jdolecek 	if ((err = emuxki_init(sc)))
    345   1.1  jdolecek 		return (err);
    346   1.1  jdolecek 
    347  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY2) {
    348  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    349  1.35  christos 			EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
    350  1.35  christos 			EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
    351  1.35  christos 	} else if (sc->sc_type & EMUXKI_AUDIGY) {
    352  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    353  1.35  christos 			EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
    354  1.35  christos 	} else {
    355  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    356  1.35  christos 			EMU_HCFG_AUDIOENABLE |
    357  1.35  christos 			EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
    358  1.35  christos 	}
    359   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    360   1.1  jdolecek 		bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
    361   1.1  jdolecek 		EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
    362   1.1  jdolecek 		EMU_INTE_MUTEENABLE);
    363  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY2) {
    364  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
    365  1.35  christos 			EMU_A_IOCFG_GPOUT0 |
    366  1.35  christos 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
    367  1.35  christos 	}
    368   1.1  jdolecek 
    369   1.1  jdolecek 	/* No multiple voice support for now */
    370   1.1  jdolecek 	sc->pvoice = sc->rvoice = NULL;
    371   1.1  jdolecek 
    372   1.1  jdolecek 	return (0);
    373   1.1  jdolecek }
    374   1.1  jdolecek 
    375   1.1  jdolecek static int
    376   1.1  jdolecek emuxki_ac97_init(struct emuxki_softc *sc)
    377   1.1  jdolecek {
    378   1.1  jdolecek 	sc->hostif.arg = sc;
    379   1.1  jdolecek 	sc->hostif.attach = emuxki_ac97_attach;
    380   1.1  jdolecek 	sc->hostif.read = emuxki_ac97_read;
    381   1.1  jdolecek 	sc->hostif.write = emuxki_ac97_write;
    382   1.1  jdolecek 	sc->hostif.reset = emuxki_ac97_reset;
    383   1.6  jdolecek 	sc->hostif.flags = emuxki_ac97_flags;
    384  1.39      kent 	return ac97_attach(&sc->hostif, &sc->sc_dev);
    385   1.1  jdolecek }
    386   1.1  jdolecek 
    387   1.1  jdolecek static int
    388   1.1  jdolecek emuxki_match(struct device *parent, struct cfdata *match, void *aux)
    389   1.1  jdolecek {
    390   1.1  jdolecek 	struct pci_attach_args *pa = aux;
    391   1.1  jdolecek 
    392  1.35  christos 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
    393  1.35  christos 		return 0;
    394  1.35  christos 
    395  1.35  christos 	switch (PCI_PRODUCT(pa->pa_id)) {
    396  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE:
    397  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
    398  1.35  christos  	case PCI_PRODUCT_CREATIVELABS_AUDIGY:
    399  1.35  christos  		return 1;
    400  1.35  christos 	default:
    401  1.35  christos 		return 0;
    402  1.32    martti 	}
    403   1.1  jdolecek }
    404   1.1  jdolecek 
    405   1.1  jdolecek static void
    406   1.1  jdolecek emuxki_attach(struct device *parent, struct device *self, void *aux)
    407   1.1  jdolecek {
    408   1.1  jdolecek 	struct emuxki_softc *sc = (struct emuxki_softc *) self;
    409   1.1  jdolecek 	struct pci_attach_args *pa = aux;
    410   1.1  jdolecek 	char            devinfo[256];
    411   1.1  jdolecek 	pci_intr_handle_t ih;
    412   1.1  jdolecek 	const char     *intrstr;
    413   1.1  jdolecek 
    414  1.15   thorpej 	aprint_naive(": Audio controller\n");
    415  1.15   thorpej 
    416   1.1  jdolecek 	if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
    417   1.1  jdolecek 	    &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob),
    418   1.1  jdolecek 			   &(sc->sc_ios))) {
    419  1.15   thorpej 		aprint_error(": can't map iospace\n");
    420   1.1  jdolecek 		return;
    421   1.1  jdolecek 	}
    422  1.33    itojun 	pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
    423  1.15   thorpej 	aprint_normal(": %s\n", devinfo);
    424   1.1  jdolecek 
    425   1.1  jdolecek 	sc->sc_pc   = pa->pa_pc;
    426   1.1  jdolecek 	sc->sc_dmat = pa->pa_dmat;
    427   1.1  jdolecek 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
    428   1.1  jdolecek 		pci_conf_read(pa->pa_pc, pa->pa_tag,
    429   1.1  jdolecek 		(PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE));
    430   1.1  jdolecek 
    431   1.1  jdolecek 	if (pci_intr_map(pa, &ih)) {
    432  1.15   thorpej 		aprint_error("%s: couldn't map interrupt\n",
    433   1.2  jdolecek 			sc->sc_dev.dv_xname);
    434   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    435   1.1  jdolecek 		return;
    436   1.1  jdolecek 	}
    437   1.1  jdolecek 
    438   1.1  jdolecek 	intrstr = pci_intr_string(pa->pa_pc, ih);
    439   1.1  jdolecek 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, emuxki_intr,
    440   1.1  jdolecek 		sc);
    441   1.1  jdolecek 	if (sc->sc_ih == NULL) {
    442  1.15   thorpej 		aprint_error("%s: couldn't establish interrupt",
    443  1.15   thorpej 		    sc->sc_dev.dv_xname);
    444   1.1  jdolecek 		if (intrstr != NULL)
    445  1.15   thorpej 			aprint_normal(" at %s", intrstr);
    446  1.15   thorpej 		aprint_normal("\n");
    447   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    448   1.1  jdolecek 		return;
    449   1.1  jdolecek 	}
    450  1.35  christos 
    451  1.37   dsainty  /* XXX it's unknown whether APS is made from Audigy as well */
    452  1.35  christos         if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
    453  1.35  christos                 sc->sc_type = EMUXKI_AUDIGY;
    454  1.35  christos                 if (PCI_REVISION(pa->pa_class) == 0x04) {
    455  1.35  christos                         sc->sc_type |= EMUXKI_AUDIGY2;
    456  1.35  christos                         strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name);
    457  1.35  christos                 } else {
    458  1.35  christos                         strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name);
    459  1.35  christos                 }
    460  1.35  christos         } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
    461  1.35  christos             PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
    462  1.35  christos                 sc->sc_type = EMUXKI_APS;
    463  1.35  christos                 strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
    464  1.35  christos         } else {
    465  1.35  christos                 sc->sc_type = EMUXKI_SBLIVE;
    466  1.35  christos                 strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
    467  1.35  christos         }
    468  1.35  christos         snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
    469  1.35  christos                  PCI_REVISION(pa->pa_class));
    470  1.35  christos         strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
    471   1.1  jdolecek 
    472   1.1  jdolecek 	if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
    473  1.19    toshii 	    (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
    474   1.1  jdolecek 		emuxki_pci_shutdown(sc);
    475  1.19    toshii 		return;
    476  1.19    toshii 	}
    477  1.35  christos 	aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
    478  1.19    toshii #if 0
    479  1.19    toshii 	sc->rsourcectl.dev =
    480  1.19    toshii 	    sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
    481  1.19    toshii 						   AudioNsource, NULL);
    482  1.19    toshii 	sc->rsourcectl.cp = AUDIO_MIXER_ENUM;
    483  1.19    toshii #endif
    484   1.1  jdolecek }
    485   1.1  jdolecek 
    486   1.1  jdolecek static int
    487   1.1  jdolecek emuxki_detach(struct device *self, int flags)
    488   1.1  jdolecek {
    489   1.1  jdolecek 	struct emuxki_softc *sc = (struct emuxki_softc *) self;
    490   1.1  jdolecek 
    491   1.1  jdolecek         if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
    492  1.29    simonb 	        config_detach(sc->sc_audev, 0);
    493   1.1  jdolecek 
    494   1.1  jdolecek 	/* All voices should be stopped now but add some code here if not */
    495   1.1  jdolecek 
    496   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    497   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    498   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    499   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
    500   1.1  jdolecek 
    501   1.1  jdolecek 	emuxki_shutdown(sc);
    502   1.1  jdolecek 
    503   1.1  jdolecek 	emuxki_pci_shutdown(sc);
    504   1.1  jdolecek 
    505   1.1  jdolecek 	return (0);
    506   1.1  jdolecek }
    507   1.1  jdolecek 
    508   1.1  jdolecek 
    509   1.1  jdolecek /* Misc stuff relative to emu10k1 */
    510   1.1  jdolecek 
    511   1.1  jdolecek static u_int32_t
    512   1.1  jdolecek emuxki_rate_to_pitch(u_int32_t rate)
    513   1.1  jdolecek {
    514   1.1  jdolecek 	static const u_int32_t logMagTable[128] = {
    515   1.1  jdolecek 		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
    516   1.1  jdolecek 		0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
    517   1.1  jdolecek 		0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
    518   1.1  jdolecek 		0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
    519   1.1  jdolecek 		0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
    520   1.1  jdolecek 		0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
    521   1.1  jdolecek 		0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
    522   1.1  jdolecek 		0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
    523   1.1  jdolecek 		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
    524   1.1  jdolecek 		0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
    525   1.1  jdolecek 		0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
    526   1.1  jdolecek 		0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
    527   1.1  jdolecek 		0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
    528   1.1  jdolecek 		0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
    529   1.1  jdolecek 		0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
    530   1.1  jdolecek 		0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
    531   1.1  jdolecek 		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
    532   1.1  jdolecek 		0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
    533   1.1  jdolecek 		0xfd1a7, 0xfe8df
    534   1.1  jdolecek 	};
    535   1.1  jdolecek 	static const u_int8_t logSlopeTable[128] = {
    536   1.1  jdolecek 		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
    537   1.1  jdolecek 		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
    538   1.1  jdolecek 		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
    539   1.1  jdolecek 		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
    540   1.1  jdolecek 		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
    541   1.1  jdolecek 		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
    542   1.1  jdolecek 		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
    543   1.1  jdolecek 		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
    544   1.1  jdolecek 		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
    545   1.1  jdolecek 		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
    546   1.1  jdolecek 		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
    547   1.1  jdolecek 		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
    548   1.1  jdolecek 		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
    549   1.1  jdolecek 		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
    550   1.1  jdolecek 		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
    551   1.1  jdolecek 		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
    552   1.1  jdolecek 	};
    553   1.1  jdolecek 	int8_t          i;
    554   1.1  jdolecek 
    555   1.1  jdolecek 	if (rate == 0)
    556   1.1  jdolecek 		return 0;	/* Bail out if no leading "1" */
    557   1.1  jdolecek 	rate *= 11185;		/* Scale 48000 to 0x20002380 */
    558   1.1  jdolecek 	for (i = 31; i > 0; i--) {
    559   1.1  jdolecek 		if (rate & 0x80000000) {	/* Detect leading "1" */
    560   1.1  jdolecek 			return (((u_int32_t) (i - 15) << 20) +
    561   1.1  jdolecek 				logMagTable[0x7f & (rate >> 24)] +
    562   1.1  jdolecek 				(0x7f & (rate >> 17)) *
    563   1.1  jdolecek 				logSlopeTable[0x7f & (rate >> 24)]);
    564   1.1  jdolecek 		}
    565   1.1  jdolecek 		rate <<= 1;
    566   1.1  jdolecek 	}
    567   1.1  jdolecek 
    568   1.1  jdolecek 	return 0;		/* Should never reach this point */
    569   1.1  jdolecek }
    570   1.1  jdolecek 
    571   1.1  jdolecek /* Emu10k1 Low level */
    572   1.1  jdolecek 
    573   1.1  jdolecek static u_int32_t
    574   1.1  jdolecek emuxki_read(struct emuxki_softc *sc, u_int16_t chano, u_int32_t reg)
    575   1.1  jdolecek {
    576   1.1  jdolecek 	u_int32_t       ptr, mask = 0xffffffff;
    577   1.1  jdolecek 	u_int8_t        size, offset = 0;
    578   1.1  jdolecek 	int             s;
    579   1.1  jdolecek 
    580  1.35  christos 	ptr = ((((u_int32_t) reg) << 16) &
    581  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    582  1.35  christos 			EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
    583   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    584   1.1  jdolecek 	if (reg & 0xff000000) {
    585   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    586   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    587   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    588   1.1  jdolecek 	}
    589   1.1  jdolecek 
    590   1.1  jdolecek 	s = splaudio();
    591   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    592   1.1  jdolecek 	ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
    593   1.1  jdolecek 		>> offset;
    594   1.1  jdolecek 	splx(s);
    595   1.1  jdolecek 
    596   1.1  jdolecek 	return (ptr);
    597   1.1  jdolecek }
    598   1.1  jdolecek 
    599   1.1  jdolecek static void
    600   1.1  jdolecek emuxki_write(struct emuxki_softc *sc, u_int16_t chano,
    601   1.1  jdolecek 	      u_int32_t reg, u_int32_t data)
    602   1.1  jdolecek {
    603   1.1  jdolecek 	u_int32_t       ptr, mask;
    604   1.1  jdolecek 	u_int8_t        size, offset;
    605   1.1  jdolecek 	int             s;
    606   1.1  jdolecek 
    607  1.35  christos 	ptr = ((((u_int32_t) reg) << 16) &
    608  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    609  1.35  christos 			EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
    610   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    611   1.1  jdolecek 	if (reg & 0xff000000) {
    612   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    613   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    614   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    615   1.1  jdolecek 		data = ((data << offset) & mask) |
    616   1.1  jdolecek 			(emuxki_read(sc, chano, reg & 0xffff) & ~mask);
    617   1.1  jdolecek 	}
    618   1.1  jdolecek 
    619   1.1  jdolecek 	s = splaudio();
    620   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    621   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
    622   1.1  jdolecek 	splx(s);
    623   1.1  jdolecek }
    624   1.1  jdolecek 
    625   1.1  jdolecek /* Microcode should this go in /sys/dev/microcode ? */
    626   1.1  jdolecek 
    627   1.1  jdolecek static void
    628   1.1  jdolecek emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
    629   1.1  jdolecek {
    630  1.35  christos 	emuxki_write(sc, 0,
    631  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    632  1.35  christos 			EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
    633  1.35  christos 		 data);
    634   1.1  jdolecek }
    635   1.1  jdolecek 
    636   1.1  jdolecek static void
    637   1.1  jdolecek emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
    638   1.1  jdolecek 		  u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
    639   1.1  jdolecek {
    640  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY) {
    641  1.35  christos 		emuxki_write_micro(sc, *pc << 1,
    642  1.35  christos 			((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
    643  1.35  christos 			(y & EMU_A_DSP_LOWORD_OPY_MASK));
    644  1.35  christos 		emuxki_write_micro(sc, (*pc << 1) + 1,
    645  1.35  christos 			((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
    646  1.35  christos 			((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
    647  1.35  christos 			(a & EMU_A_DSP_HIWORD_OPA_MASK));
    648  1.35  christos 	} else {
    649  1.35  christos 		emuxki_write_micro(sc, *pc << 1,
    650  1.35  christos 			((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
    651  1.35  christos 			(y & EMU_DSP_LOWORD_OPY_MASK));
    652  1.35  christos 		emuxki_write_micro(sc, (*pc << 1) + 1,
    653  1.35  christos 			((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
    654  1.35  christos 			((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
    655  1.35  christos 			(a & EMU_DSP_HIWORD_OPA_MASK));
    656  1.35  christos 	}
    657  1.35  christos   	(*pc)++;
    658   1.1  jdolecek }
    659   1.1  jdolecek 
    660   1.1  jdolecek /* init and shutdown */
    661   1.1  jdolecek 
    662   1.1  jdolecek static void
    663   1.1  jdolecek emuxki_initfx(struct emuxki_softc *sc)
    664   1.1  jdolecek {
    665   1.1  jdolecek 	u_int16_t       pc;
    666   1.1  jdolecek 
    667   1.1  jdolecek 	/* Set all GPRs to 0 */
    668   1.1  jdolecek 	for (pc = 0; pc < 256; pc++)
    669   1.1  jdolecek 		emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
    670   1.1  jdolecek 	for (pc = 0; pc < 160; pc++) {
    671   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
    672   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
    673   1.1  jdolecek 	}
    674   1.1  jdolecek 	pc = 0;
    675   1.1  jdolecek 
    676  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY) {
    677  1.35  christos 		/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
    678  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    679  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
    680  1.35  christos 				  EMU_A_DSP_CST(0),
    681  1.35  christos 				  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
    682  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    683  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
    684  1.35  christos 				  EMU_A_DSP_CST(0),
    685  1.35  christos 				  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
    686  1.35  christos 
    687  1.35  christos 		/* Rear channel OUT (l/r) = FX[2/3] * 4 */
    688   1.1  jdolecek #if 0
    689  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    690  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
    691  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
    692  1.35  christos 				  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
    693  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    694  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
    695  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
    696  1.35  christos 				  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
    697  1.35  christos #endif
    698  1.35  christos 		/* ADC recording (l/r) = AC97 In (l/r) */
    699  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    700  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
    701  1.35  christos 				  EMU_A_DSP_INL(EMU_DSP_IN_AC97),
    702  1.35  christos 				  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    703  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    704  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
    705  1.35  christos 				  EMU_A_DSP_INR(EMU_DSP_IN_AC97),
    706  1.35  christos 				  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    707  1.35  christos 
    708  1.35  christos 		/* zero out the rest of the microcode */
    709  1.35  christos 		while (pc < 512)
    710  1.35  christos 			emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    711  1.35  christos 					  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
    712  1.35  christos 					  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    713  1.35  christos 
    714  1.35  christos 		emuxki_write(sc, 0, EMU_A_DBG, 0);	/* Is it really necessary ? */
    715  1.35  christos 	} else {
    716  1.35  christos 		/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
    717  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    718  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
    719  1.35  christos 				  EMU_DSP_CST(0),
    720  1.35  christos 				  EMU_DSP_FX(0), EMU_DSP_CST(4));
    721  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    722  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
    723  1.35  christos 				  EMU_DSP_CST(0),
    724  1.35  christos 				  EMU_DSP_FX(1), EMU_DSP_CST(4));
    725  1.35  christos 
    726  1.35  christos 		/* Rear channel OUT (l/r) = FX[2/3] * 4 */
    727  1.35  christos #if 0
    728  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    729  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
    730  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
    731  1.35  christos 				  EMU_DSP_FX(0), EMU_DSP_CST(4));
    732  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    733  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
    734  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
    735  1.35  christos 				  EMU_DSP_FX(1), EMU_DSP_CST(4));
    736  1.35  christos #endif
    737  1.35  christos 		/* ADC recording (l/r) = AC97 In (l/r) */
    738   1.1  jdolecek 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    739  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
    740  1.35  christos 				  EMU_DSP_INL(EMU_DSP_IN_AC97),
    741   1.1  jdolecek 				  EMU_DSP_CST(0), EMU_DSP_CST(0));
    742  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    743  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
    744  1.35  christos 				  EMU_DSP_INR(EMU_DSP_IN_AC97),
    745  1.35  christos 				  EMU_DSP_CST(0), EMU_DSP_CST(0));
    746  1.35  christos 
    747  1.35  christos 		/* zero out the rest of the microcode */
    748  1.35  christos 		while (pc < 512)
    749  1.35  christos 			emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    750  1.35  christos 					  EMU_DSP_CST(0), EMU_DSP_CST(0),
    751  1.35  christos 					  EMU_DSP_CST(0), EMU_DSP_CST(0));
    752   1.1  jdolecek 
    753  1.35  christos 		emuxki_write(sc, 0, EMU_DBG, 0);	/* Is it really necessary ? */
    754  1.35  christos 	}
    755   1.1  jdolecek }
    756   1.1  jdolecek 
    757   1.1  jdolecek static int
    758   1.1  jdolecek emuxki_init(struct emuxki_softc *sc)
    759   1.1  jdolecek {
    760   1.1  jdolecek 	u_int16_t       i;
    761   1.1  jdolecek 	u_int32_t       spcs, *ptb;
    762   1.1  jdolecek 	bus_addr_t      silentpage;
    763   1.1  jdolecek 
    764   1.1  jdolecek 	/* disable any channel interrupt */
    765   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    766   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    767   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    768   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    769   1.1  jdolecek 
    770   1.1  jdolecek 	/* Set recording buffers sizes to zero */
    771   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    772   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    773   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    774   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    775   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    776   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    777   1.1  jdolecek 
    778  1.35  christos         if(sc->sc_type & EMUXKI_AUDIGY) {
    779  1.35  christos                 emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
    780  1.35  christos                 emuxki_write(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
    781  1.35  christos         }
    782  1.35  christos 
    783   1.1  jdolecek 	/* Initialize all channels to stopped and no effects */
    784   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    785   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    786   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IP, 0);
    787   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
    788   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
    789   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    790   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    791   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCR, 0);
    792   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PSST, 0);
    793   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DSL, 0x10);	/* Why 16 ? */
    794   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
    795   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z1, 0);
    796   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z2, 0);
    797   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
    798   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
    799   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
    800   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
    801   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
    802   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
    803   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
    804   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
    805   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
    806   1.1  jdolecek 
    807   1.1  jdolecek 		/* these are last so OFF prevents writing */
    808   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
    809   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
    810   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
    811   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
    812   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
    813   1.1  jdolecek 	}
    814   1.1  jdolecek 
    815   1.1  jdolecek 	/* set digital outputs format */
    816   1.1  jdolecek 	spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
    817   1.1  jdolecek 	      EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
    818   1.1  jdolecek 		EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
    819   1.1  jdolecek 		0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
    820   1.1  jdolecek 		EMU_SPCS_COPYRIGHT);
    821   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS0, spcs);
    822   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS1, spcs);
    823   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS2, spcs);
    824   1.1  jdolecek 
    825  1.35  christos         if(sc->sc_type & EMUXKI_AUDIGY2) {
    826  1.35  christos                 emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, EMU_A2_SPDIF_UNKNOWN);
    827  1.35  christos 
    828  1.35  christos                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCSEL);
    829  1.35  christos                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA,
    830  1.35  christos                         EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
    831  1.35  christos 
    832  1.35  christos                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCMULTI);
    833  1.35  christos                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, EMU_A2_SRCMULTI_ENABLE_INPUT);
    834  1.35  christos         }
    835  1.35  christos 
    836  1.35  christos 
    837   1.1  jdolecek 	/* Let's play with sound processor */
    838   1.1  jdolecek 	emuxki_initfx(sc);
    839   1.1  jdolecek 
    840   1.1  jdolecek 	/* Here is our Page Table */
    841   1.1  jdolecek 	if ((sc->ptb = dmamem_alloc(sc->sc_dmat,
    842   1.1  jdolecek 	    EMU_MAXPTE * sizeof(u_int32_t),
    843   1.1  jdolecek 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG,
    844   1.1  jdolecek 	    M_DEVBUF, M_WAITOK)) == NULL)
    845   1.1  jdolecek 		return (ENOMEM);
    846   1.1  jdolecek 
    847   1.1  jdolecek 	/* This is necessary unless you like Metallic noise... */
    848   1.1  jdolecek 	if ((sc->silentpage = dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
    849   1.1  jdolecek 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG, M_DEVBUF, M_WAITOK))==NULL){
    850   1.1  jdolecek 		dmamem_free(sc->ptb, M_DEVBUF);
    851   1.1  jdolecek 		return (ENOMEM);
    852   1.1  jdolecek 	}
    853   1.1  jdolecek 
    854   1.1  jdolecek 	/* Zero out the silent page */
    855   1.1  jdolecek 	/* This might not be always true, it might be 128 for 8bit channels */
    856   1.1  jdolecek 	memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
    857   1.1  jdolecek 
    858   1.1  jdolecek 	/*
    859   1.1  jdolecek 	 * Set all the PTB Entries to the silent page We shift the physical
    860   1.1  jdolecek 	 * address by one and OR it with the page number. I don't know what
    861   1.1  jdolecek 	 * the ORed index is for, might be a very useful unused feature...
    862   1.1  jdolecek 	 */
    863   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
    864   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
    865   1.1  jdolecek 	for (i = 0; i < EMU_MAXPTE; i++)
    866  1.34   tsutsui 		ptb[i] = htole32(silentpage | i);
    867   1.1  jdolecek 
    868   1.1  jdolecek 	/* Write PTB address and set TCB to none */
    869   1.1  jdolecek 	emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
    870   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);	/* This means 16K TCB */
    871   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* No TCB use for now */
    872   1.1  jdolecek 
    873   1.1  jdolecek 	/*
    874   1.1  jdolecek 	 * Set channels MAPs to the silent page.
    875   1.1  jdolecek 	 * I don't know what MAPs are for.
    876   1.1  jdolecek 	 */
    877   1.1  jdolecek 	silentpage |= EMU_CHAN_MAP_PTI_MASK;
    878   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    879   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
    880   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
    881   1.1  jdolecek 		sc->channel[i] = NULL;
    882   1.1  jdolecek 	}
    883   1.1  jdolecek 
    884   1.1  jdolecek 	/* Init voices list */
    885   1.1  jdolecek 	LIST_INIT(&(sc->voices));
    886   1.1  jdolecek 
    887   1.1  jdolecek 	/* Timer is stopped */
    888   1.1  jdolecek 	sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
    889   1.1  jdolecek 	return (0);
    890   1.1  jdolecek }
    891   1.1  jdolecek 
    892   1.1  jdolecek static void
    893   1.1  jdolecek emuxki_shutdown(struct emuxki_softc *sc)
    894   1.1  jdolecek {
    895   1.1  jdolecek 	u_int32_t       i;
    896   1.1  jdolecek 
    897   1.1  jdolecek 	/* Disable any Channels interrupts */
    898   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    899   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    900   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    901   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    902   1.1  jdolecek 
    903   1.1  jdolecek 	/*
    904   1.1  jdolecek 	 * Should do some voice(stream) stopping stuff here, that's what will
    905   1.1  jdolecek 	 * stop and deallocate all channels.
    906   1.1  jdolecek 	 */
    907   1.1  jdolecek 
    908   1.1  jdolecek 	/* Stop all channels */
    909   1.1  jdolecek 	/* XXX This shouldn't be necessary, I'll remove once everything works */
    910   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++)
    911   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    912   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    913   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
    914   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
    915   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    916   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    917   1.1  jdolecek 	}
    918   1.1  jdolecek 
    919   1.1  jdolecek 	/*
    920   1.1  jdolecek 	 * Deallocate Emu10k1 caches and recording buffers. Again it will be
    921   1.1  jdolecek 	 * removed because it will be done in voice shutdown.
    922   1.1  jdolecek 	 */
    923   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    924   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    925   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    926   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    927  1.35  christos         if(sc->sc_type & EMUXKI_AUDIGY) {
    928  1.35  christos                 emuxki_write(sc, 0, EMU_A_FXWC1, 0);
    929  1.35  christos                 emuxki_write(sc, 0, EMU_A_FXWC2, 0);
    930  1.35  christos         } else {
    931  1.35  christos                 emuxki_write(sc, 0, EMU_FXWC, 0);
    932  1.35  christos         }
    933   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    934   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    935   1.1  jdolecek 
    936   1.1  jdolecek 	/*
    937   1.1  jdolecek 	 * XXX I don't know yet how I will handle tank cache buffer,
    938   1.1  jdolecek 	 * I don't even clearly  know what it is for.
    939   1.1  jdolecek 	 */
    940   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* 16K again */
    941   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);
    942   1.1  jdolecek 
    943   1.1  jdolecek 	emuxki_write(sc, 0, EMU_DBG, 0x8000);	/* necessary ? */
    944   1.1  jdolecek 
    945   1.1  jdolecek 	dmamem_free(sc->silentpage, M_DEVBUF);
    946   1.1  jdolecek 	dmamem_free(sc->ptb, M_DEVBUF);
    947   1.1  jdolecek }
    948   1.1  jdolecek 
    949  1.25       wiz /* Emu10k1 Memory management */
    950   1.1  jdolecek 
    951   1.1  jdolecek static struct emuxki_mem *
    952   1.1  jdolecek emuxki_mem_new(struct emuxki_softc *sc, int ptbidx,
    953  1.16   thorpej 		size_t size, struct malloc_type *type, int flags)
    954   1.1  jdolecek {
    955   1.1  jdolecek 	struct emuxki_mem *mem;
    956   1.1  jdolecek 
    957   1.1  jdolecek 	if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
    958   1.1  jdolecek 		return (NULL);
    959   1.1  jdolecek 
    960   1.1  jdolecek 	mem->ptbidx = ptbidx;
    961   1.1  jdolecek 	if ((mem->dmamem = dmamem_alloc(sc->sc_dmat, size, EMU_DMA_ALIGN,
    962   1.1  jdolecek 	    EMU_DMAMEM_NSEG, type, flags)) == NULL) {
    963   1.1  jdolecek 		free(mem, type);
    964   1.1  jdolecek 		return (NULL);
    965   1.1  jdolecek 	}
    966   1.1  jdolecek 	return (mem);
    967   1.1  jdolecek }
    968   1.1  jdolecek 
    969   1.1  jdolecek static void
    970  1.16   thorpej emuxki_mem_delete(struct emuxki_mem *mem, struct malloc_type *type)
    971   1.1  jdolecek {
    972   1.1  jdolecek 	dmamem_free(mem->dmamem, type);
    973   1.1  jdolecek 	free(mem, type);
    974   1.1  jdolecek }
    975   1.1  jdolecek 
    976   1.1  jdolecek static void *
    977  1.16   thorpej emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size,
    978  1.16   thorpej     struct malloc_type *type, int flags)
    979   1.1  jdolecek {
    980   1.1  jdolecek 	int             i, j, s;
    981   1.1  jdolecek 	size_t          numblocks;
    982   1.1  jdolecek 	struct emuxki_mem *mem;
    983   1.1  jdolecek 	u_int32_t      *ptb, silentpage;
    984   1.1  jdolecek 
    985   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
    986   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
    987   1.1  jdolecek 	numblocks = size / EMU_PTESIZE;
    988   1.1  jdolecek 	if (size % EMU_PTESIZE)
    989   1.1  jdolecek 		numblocks++;
    990   1.1  jdolecek 
    991   1.1  jdolecek 	for (i = 0; i < EMU_MAXPTE; i++)
    992  1.34   tsutsui 		if ((le32toh(ptb[i]) & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
    993   1.1  jdolecek 			/* We look for a free PTE */
    994   1.1  jdolecek 			s = splaudio();
    995   1.1  jdolecek 			for (j = 0; j < numblocks; j++)
    996  1.34   tsutsui 				if ((le32toh(ptb[i + j])
    997  1.34   tsutsui 				    & EMU_CHAN_MAP_PTE_MASK) != silentpage)
    998   1.1  jdolecek 					break;
    999   1.1  jdolecek 			if (j == numblocks) {
   1000   1.1  jdolecek 				if ((mem = emuxki_mem_new(sc, i,
   1001   1.1  jdolecek 						size, type, flags)) == NULL) {
   1002   1.1  jdolecek 					splx(s);
   1003   1.1  jdolecek 					return (NULL);
   1004   1.1  jdolecek 				}
   1005   1.1  jdolecek 				for (j = 0; j < numblocks; j++)
   1006   1.1  jdolecek 					ptb[i + j] =
   1007  1.34   tsutsui 					    htole32((((DMAADDR(mem->dmamem) +
   1008  1.34   tsutsui 					    j * EMU_PTESIZE)) << 1) | (i + j));
   1009   1.1  jdolecek 				LIST_INSERT_HEAD(&(sc->mem), mem, next);
   1010   1.1  jdolecek 				splx(s);
   1011   1.1  jdolecek 				return (KERNADDR(mem->dmamem));
   1012   1.1  jdolecek 			} else
   1013   1.1  jdolecek 				i += j;
   1014   1.1  jdolecek 			splx(s);
   1015   1.1  jdolecek 		}
   1016   1.1  jdolecek 	return (NULL);
   1017   1.1  jdolecek }
   1018   1.1  jdolecek 
   1019   1.1  jdolecek static void *
   1020  1.16   thorpej emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size,
   1021  1.16   thorpej     struct malloc_type *type, int flags)
   1022   1.1  jdolecek {
   1023   1.1  jdolecek 	struct emuxki_mem *mem;
   1024   1.1  jdolecek 	int             s;
   1025   1.1  jdolecek 
   1026   1.1  jdolecek 	mem = emuxki_mem_new(sc, EMU_RMEM, size, type, flags);
   1027   1.1  jdolecek 	if (mem == NULL)
   1028   1.1  jdolecek 		return (NULL);
   1029   1.1  jdolecek 
   1030   1.1  jdolecek 	s = splaudio();
   1031   1.1  jdolecek 	LIST_INSERT_HEAD(&(sc->mem), mem, next);
   1032   1.1  jdolecek 	splx(s);
   1033   1.1  jdolecek 
   1034   1.1  jdolecek 	return (KERNADDR(mem->dmamem));
   1035   1.1  jdolecek }
   1036   1.1  jdolecek 
   1037   1.1  jdolecek /*
   1038  1.25       wiz  * emuxki_channel_* : Channel management functions
   1039   1.1  jdolecek  * emuxki_chanparms_* : Channel parameters modification functions
   1040   1.1  jdolecek  */
   1041   1.1  jdolecek 
   1042   1.1  jdolecek /*
   1043   1.1  jdolecek  * is splaudio necessary here, can the same voice be manipulated by two
   1044   1.1  jdolecek  * different threads at a time ?
   1045   1.1  jdolecek  */
   1046   1.1  jdolecek static void
   1047   1.1  jdolecek emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
   1048   1.1  jdolecek {
   1049   1.1  jdolecek 	chan->fxsend.a.level = chan->fxsend.b.level =
   1050  1.35  christos 	chan->fxsend.c.level = chan->fxsend.d.level =
   1051  1.35  christos 	/* for audigy */
   1052  1.35  christos 	chan->fxsend.e.level = chan->fxsend.f.level =
   1053  1.35  christos 	chan->fxsend.g.level = chan->fxsend.h.level =
   1054  1.35  christos 		chan->voice->sc->sc_type & EMUXKI_AUDIGY ?
   1055  1.35  christos 			0xc0 : 0xff;	/* not max */
   1056  1.35  christos 
   1057   1.1  jdolecek 	chan->fxsend.a.dest = 0x0;
   1058   1.1  jdolecek 	chan->fxsend.b.dest = 0x1;
   1059   1.1  jdolecek 	chan->fxsend.c.dest = 0x2;
   1060   1.1  jdolecek 	chan->fxsend.d.dest = 0x3;
   1061  1.35  christos 	/* for audigy */
   1062  1.35  christos 	chan->fxsend.e.dest = 0x4;
   1063  1.35  christos 	chan->fxsend.f.dest = 0x5;
   1064  1.35  christos 	chan->fxsend.g.dest = 0x6;
   1065  1.35  christos 	chan->fxsend.h.dest = 0x7;
   1066   1.1  jdolecek 
   1067  1.17       wiz 	chan->pitch.initial = 0x0000;	/* shouldn't it be 0xE000 ? */
   1068   1.1  jdolecek 	chan->pitch.current = 0x0000;	/* should it be 0x0400 */
   1069   1.1  jdolecek 	chan->pitch.target = 0x0000;	/* the unity pitch shift ? */
   1070   1.1  jdolecek 	chan->pitch.envelope_amount = 0x00;	/* none */
   1071   1.1  jdolecek 
   1072   1.1  jdolecek 	chan->initial_attenuation = 0x00;	/* no attenuation */
   1073   1.1  jdolecek 	chan->volume.current = 0x0000;	/* no volume */
   1074   1.1  jdolecek 	chan->volume.target = 0xffff;
   1075   1.1  jdolecek 	chan->volume.envelope.current_state = 0x8000;	/* 0 msec delay */
   1076   1.1  jdolecek 	chan->volume.envelope.hold_time = 0x7f;	/* 0 msec */
   1077   1.1  jdolecek 	chan->volume.envelope.attack_time = 0x7F;	/* 5.5msec */
   1078   1.1  jdolecek 	chan->volume.envelope.sustain_level = 0x7F;	/* full  */
   1079   1.1  jdolecek 	chan->volume.envelope.decay_time = 0x7F;	/* 22msec  */
   1080   1.1  jdolecek 
   1081   1.1  jdolecek 	chan->filter.initial_cutoff_frequency = 0xff;	/* no filter */
   1082   1.1  jdolecek 	chan->filter.current_cutoff_frequency = 0xffff;	/* no filtering */
   1083   1.1  jdolecek 	chan->filter.target_cutoff_frequency = 0xffff;	/* no filtering */
   1084   1.1  jdolecek 	chan->filter.lowpass_resonance_height = 0x0;
   1085   1.1  jdolecek 	chan->filter.interpolation_ROM = 0x1;	/* full band */
   1086   1.1  jdolecek 	chan->filter.envelope_amount = 0x7f;	/* none */
   1087   1.1  jdolecek 	chan->filter.LFO_modulation_depth = 0x00;	/* none */
   1088   1.1  jdolecek 
   1089   1.1  jdolecek 	chan->loop.start = 0x000000;
   1090   1.1  jdolecek 	chan->loop.end = 0x000010;	/* Why ? */
   1091   1.1  jdolecek 
   1092   1.1  jdolecek 	chan->modulation.envelope.current_state = 0x8000;
   1093   1.1  jdolecek 	chan->modulation.envelope.hold_time = 0x00;	/* 127 better ? */
   1094   1.1  jdolecek 	chan->modulation.envelope.attack_time = 0x00;	/* infinite */
   1095   1.1  jdolecek 	chan->modulation.envelope.sustain_level = 0x00;	/* off */
   1096   1.1  jdolecek 	chan->modulation.envelope.decay_time = 0x7f;	/* 22 msec */
   1097   1.1  jdolecek 	chan->modulation.LFO_state = 0x8000;
   1098   1.1  jdolecek 
   1099   1.1  jdolecek 	chan->vibrato_LFO.state = 0x8000;
   1100   1.1  jdolecek 	chan->vibrato_LFO.modulation_depth = 0x00;	/* none */
   1101   1.1  jdolecek 	chan->vibrato_LFO.vibrato_depth = 0x00;
   1102   1.1  jdolecek 	chan->vibrato_LFO.frequency = 0x00;	/* Why set to 24 when
   1103   1.1  jdolecek 						 * initialized ? */
   1104   1.1  jdolecek 
   1105   1.1  jdolecek 	chan->tremolo_depth = 0x00;
   1106   1.1  jdolecek }
   1107   1.1  jdolecek 
   1108   1.1  jdolecek /* only call it at splaudio */
   1109   1.1  jdolecek static struct emuxki_channel *
   1110   1.1  jdolecek emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
   1111   1.1  jdolecek {
   1112   1.1  jdolecek 	struct emuxki_channel *chan;
   1113   1.1  jdolecek 
   1114   1.1  jdolecek 	chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
   1115   1.1  jdolecek 	if (chan == NULL)
   1116   1.1  jdolecek 		return (NULL);
   1117   1.1  jdolecek 
   1118   1.1  jdolecek 	chan->voice = voice;
   1119   1.1  jdolecek 	chan->num = num;
   1120   1.1  jdolecek 	emuxki_chanparms_set_defaults(chan);
   1121   1.1  jdolecek 	chan->voice->sc->channel[num] = chan;
   1122   1.1  jdolecek 	return (chan);
   1123   1.1  jdolecek }
   1124   1.1  jdolecek 
   1125   1.1  jdolecek /* only call it at splaudio */
   1126   1.1  jdolecek static void
   1127   1.1  jdolecek emuxki_channel_delete(struct emuxki_channel *chan)
   1128   1.1  jdolecek {
   1129   1.1  jdolecek 	chan->voice->sc->channel[chan->num] = NULL;
   1130   1.1  jdolecek 	free(chan, M_DEVBUF);
   1131   1.1  jdolecek }
   1132   1.1  jdolecek 
   1133   1.1  jdolecek static void
   1134   1.1  jdolecek emuxki_channel_set_fxsend(struct emuxki_channel *chan,
   1135   1.1  jdolecek 			   struct emuxki_chanparms_fxsend *fxsend)
   1136   1.1  jdolecek {
   1137   1.1  jdolecek 	/* Could do a memcpy ...*/
   1138   1.1  jdolecek 	chan->fxsend.a.level = fxsend->a.level;
   1139   1.1  jdolecek 	chan->fxsend.b.level = fxsend->b.level;
   1140   1.1  jdolecek 	chan->fxsend.c.level = fxsend->c.level;
   1141   1.1  jdolecek 	chan->fxsend.d.level = fxsend->d.level;
   1142   1.1  jdolecek 	chan->fxsend.a.dest = fxsend->a.dest;
   1143   1.1  jdolecek 	chan->fxsend.b.dest = fxsend->b.dest;
   1144   1.1  jdolecek 	chan->fxsend.c.dest = fxsend->c.dest;
   1145   1.1  jdolecek 	chan->fxsend.d.dest = fxsend->d.dest;
   1146  1.35  christos 
   1147  1.35  christos 	/* for audigy */
   1148  1.35  christos 	chan->fxsend.e.level = fxsend->e.level;
   1149  1.35  christos 	chan->fxsend.f.level = fxsend->f.level;
   1150  1.35  christos 	chan->fxsend.g.level = fxsend->g.level;
   1151  1.35  christos 	chan->fxsend.h.level = fxsend->h.level;
   1152  1.35  christos 	chan->fxsend.e.dest = fxsend->e.dest;
   1153  1.35  christos 	chan->fxsend.f.dest = fxsend->f.dest;
   1154  1.35  christos 	chan->fxsend.g.dest = fxsend->g.dest;
   1155  1.35  christos 	chan->fxsend.h.dest = fxsend->h.dest;
   1156   1.1  jdolecek }
   1157   1.1  jdolecek 
   1158   1.1  jdolecek static void
   1159   1.1  jdolecek emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate)
   1160   1.1  jdolecek {
   1161   1.1  jdolecek 	chan->pitch.target = (srate << 8) / 375;
   1162   1.1  jdolecek 	chan->pitch.target = (chan->pitch.target >> 1) +
   1163   1.1  jdolecek 		(chan->pitch.target & 1);
   1164   1.1  jdolecek 	chan->pitch.target &= 0xffff;
   1165   1.1  jdolecek 	chan->pitch.current = chan->pitch.target;
   1166  1.17       wiz 	chan->pitch.initial =
   1167   1.1  jdolecek 		(emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
   1168   1.1  jdolecek }
   1169   1.1  jdolecek 
   1170   1.1  jdolecek /* voice params must be set before calling this */
   1171   1.1  jdolecek static void
   1172   1.1  jdolecek emuxki_channel_set_bufparms(struct emuxki_channel *chan,
   1173   1.1  jdolecek 			     u_int32_t start, u_int32_t end)
   1174   1.1  jdolecek {
   1175   1.1  jdolecek 	chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
   1176   1.1  jdolecek 	chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
   1177   1.1  jdolecek }
   1178   1.1  jdolecek 
   1179   1.1  jdolecek static void
   1180  1.35  christos emuxki_channel_commit_fx(struct emuxki_channel *chan)
   1181  1.35  christos {
   1182  1.35  christos 	struct emuxki_softc *sc = chan->voice->sc;
   1183  1.35  christos         u_int8_t	chano = chan->num;
   1184  1.35  christos 
   1185  1.35  christos         if(sc->sc_type & EMUXKI_AUDIGY) {
   1186  1.35  christos                 emuxki_write(sc, chano, EMU_A_CHAN_FXRT1,
   1187  1.35  christos                               (chan->fxsend.d.dest << 24) |
   1188  1.35  christos                               (chan->fxsend.c.dest << 16) |
   1189  1.35  christos                               (chan->fxsend.b.dest << 8) |
   1190  1.35  christos                               (chan->fxsend.a.dest));
   1191  1.35  christos                 emuxki_write(sc, chano, EMU_A_CHAN_FXRT2,
   1192  1.35  christos                               (chan->fxsend.h.dest << 24) |
   1193  1.35  christos                               (chan->fxsend.g.dest << 16) |
   1194  1.35  christos                               (chan->fxsend.f.dest << 8) |
   1195  1.35  christos                               (chan->fxsend.e.dest));
   1196  1.35  christos                 emuxki_write(sc, chano, EMU_A_CHAN_SENDAMOUNTS,
   1197  1.35  christos                               (chan->fxsend.e.level << 24) |
   1198  1.35  christos                               (chan->fxsend.f.level << 16) |
   1199  1.35  christos                               (chan->fxsend.g.level << 8) |
   1200  1.35  christos                               (chan->fxsend.h.level));
   1201  1.35  christos         } else {
   1202  1.35  christos                 emuxki_write(sc, chano, EMU_CHAN_FXRT,
   1203  1.35  christos                               (chan->fxsend.d.dest << 28) |
   1204  1.35  christos                               (chan->fxsend.c.dest << 24) |
   1205  1.35  christos                               (chan->fxsend.b.dest << 20) |
   1206  1.35  christos                               (chan->fxsend.a.dest << 16));
   1207  1.35  christos         }
   1208  1.35  christos 
   1209  1.35  christos         emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
   1210  1.35  christos                       (chan->fxsend.a.level << 8) | chan->fxsend.b.level);
   1211  1.35  christos         emuxki_write(sc, chano, EMU_CHAN_DSL,
   1212  1.35  christos                       (chan->fxsend.d.level << 24) | chan->loop.end);
   1213  1.35  christos         emuxki_write(sc, chano, EMU_CHAN_PSST,
   1214  1.35  christos                       (chan->fxsend.c.level << 24) | chan->loop.start);
   1215  1.35  christos }
   1216  1.35  christos 
   1217  1.35  christos static void
   1218   1.1  jdolecek emuxki_channel_commit_parms(struct emuxki_channel *chan)
   1219   1.1  jdolecek {
   1220   1.1  jdolecek 	struct emuxki_voice *voice = chan->voice;
   1221   1.1  jdolecek 	struct emuxki_softc *sc = voice->sc;
   1222   1.1  jdolecek 	u_int32_t start, mapval;
   1223   1.1  jdolecek 	u_int8_t chano = chan->num;
   1224   1.1  jdolecek 	int s;
   1225   1.1  jdolecek 
   1226   1.1  jdolecek 	start = chan->loop.start +
   1227   1.1  jdolecek 		(voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1228   1.1  jdolecek 	mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
   1229   1.1  jdolecek 
   1230   1.1  jdolecek 	s = splaudio();
   1231   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
   1232  1.35  christos 
   1233  1.35  christos 	emuxki_channel_commit_fx(chan);
   1234  1.35  christos 
   1235   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCCA,
   1236   1.1  jdolecek 		(chan->filter.lowpass_resonance_height << 28) |
   1237   1.1  jdolecek 		(chan->filter.interpolation_ROM << 25) |
   1238   1.1  jdolecek 		(voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
   1239   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
   1240   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
   1241   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
   1242   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
   1243   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
   1244   1.1  jdolecek 		chan->filter.current_cutoff_frequency);
   1245   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
   1246   1.1  jdolecek 		chan->filter.target_cutoff_frequency);
   1247   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
   1248   1.1  jdolecek 		(chan->modulation.envelope.hold_time << 8) |
   1249   1.1  jdolecek 		chan->modulation.envelope.attack_time);
   1250   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
   1251   1.1  jdolecek 		(chan->modulation.envelope.sustain_level << 8) |
   1252   1.1  jdolecek 		chan->modulation.envelope.decay_time);
   1253   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
   1254   1.1  jdolecek 		chan->modulation.LFO_state);
   1255   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
   1256   1.1  jdolecek 		chan->vibrato_LFO.state);
   1257   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FMMOD,
   1258   1.1  jdolecek 		(chan->vibrato_LFO.modulation_depth << 8) |
   1259   1.1  jdolecek 		chan->filter.LFO_modulation_depth);
   1260   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
   1261   1.1  jdolecek 		(chan->tremolo_depth << 8));
   1262   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
   1263   1.1  jdolecek 		(chan->vibrato_LFO.vibrato_depth << 8) |
   1264   1.1  jdolecek 		chan->vibrato_LFO.frequency);
   1265   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
   1266   1.1  jdolecek 		chan->modulation.envelope.current_state);
   1267   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
   1268   1.1  jdolecek 		(chan->volume.envelope.hold_time << 8) |
   1269   1.1  jdolecek 		chan->volume.envelope.attack_time);
   1270   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
   1271   1.1  jdolecek 		chan->volume.envelope.current_state);
   1272   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PEFE,
   1273   1.1  jdolecek 		(chan->pitch.envelope_amount << 8) |
   1274   1.1  jdolecek 		chan->filter.envelope_amount);
   1275   1.1  jdolecek 	splx(s);
   1276   1.1  jdolecek }
   1277   1.1  jdolecek 
   1278   1.1  jdolecek static void
   1279   1.1  jdolecek emuxki_channel_start(struct emuxki_channel *chan)
   1280   1.1  jdolecek {
   1281   1.1  jdolecek 	struct emuxki_voice *voice = chan->voice;
   1282   1.1  jdolecek 	struct emuxki_softc *sc = voice->sc;
   1283   1.1  jdolecek 	u_int8_t        cache_sample, cache_invalid_size, chano = chan->num;
   1284   1.1  jdolecek 	u_int32_t       sample;
   1285   1.1  jdolecek 	int             s;
   1286   1.1  jdolecek 
   1287   1.1  jdolecek 	cache_sample = voice->stereo ? 4 : 2;
   1288   1.1  jdolecek 	sample = voice->b16 ? 0x00000000 : 0x80808080;
   1289   1.1  jdolecek 	cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1290   1.1  jdolecek 
   1291   1.1  jdolecek 	s = splaudio();
   1292   1.1  jdolecek 	while (cache_sample--) {
   1293   1.1  jdolecek 		emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
   1294   1.1  jdolecek 			sample);
   1295   1.1  jdolecek 	}
   1296   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
   1297   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
   1298   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
   1299   1.1  jdolecek 		cache_invalid_size);
   1300   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN,
   1301   1.1  jdolecek 		(chan->filter.target_cutoff_frequency << 8) |
   1302   1.1  jdolecek 		chan->initial_attenuation);
   1303   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
   1304   1.1  jdolecek 		chan->volume.target);
   1305   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
   1306   1.1  jdolecek 		chan->volume.current);
   1307   1.1  jdolecek 	emuxki_write(sc, 0,
   1308   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
   1309   1.1  jdolecek 		0);	/* Clear stop on loop */
   1310   1.1  jdolecek 	emuxki_write(sc, 0,
   1311   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
   1312   1.1  jdolecek 		0);	/* Clear loop interrupt */
   1313   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
   1314   1.1  jdolecek 		(chan->volume.envelope.sustain_level << 8) |
   1315   1.1  jdolecek 		chan->volume.envelope.decay_time);
   1316   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
   1317   1.1  jdolecek 		chan->pitch.target);
   1318   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
   1319   1.1  jdolecek 		chan->pitch.current);
   1320  1.17       wiz 	emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.initial);
   1321   1.1  jdolecek 
   1322   1.1  jdolecek 	splx(s);
   1323   1.1  jdolecek }
   1324   1.1  jdolecek 
   1325   1.1  jdolecek static void
   1326   1.1  jdolecek emuxki_channel_stop(struct emuxki_channel *chan)
   1327   1.1  jdolecek {
   1328   1.1  jdolecek 	int s;
   1329   1.1  jdolecek 	u_int8_t chano = chan->num;
   1330   1.1  jdolecek 	struct emuxki_softc *sc = chan->voice->sc;
   1331   1.1  jdolecek 
   1332   1.1  jdolecek 	s = splaudio();
   1333   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
   1334   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
   1335   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
   1336   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
   1337   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
   1338   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IP, 0);
   1339   1.1  jdolecek 	splx(s);
   1340   1.1  jdolecek }
   1341   1.1  jdolecek 
   1342   1.1  jdolecek /*
   1343  1.25       wiz  * Voices management
   1344  1.37   dsainty  * emuxki_voice_dataloc : use(play or rec) independent dataloc union helpers
   1345   1.1  jdolecek  * emuxki_voice_channel_* : play part of dataloc union helpers
   1346   1.1  jdolecek  * emuxki_voice_recsrc_* : rec part of dataloc union helpers
   1347   1.1  jdolecek  */
   1348   1.1  jdolecek 
   1349   1.1  jdolecek /* Allocate channels for voice in case of play voice */
   1350   1.1  jdolecek static int
   1351   1.1  jdolecek emuxki_voice_channel_create(struct emuxki_voice *voice)
   1352   1.1  jdolecek {
   1353   1.1  jdolecek 	struct emuxki_channel **channel = voice->sc->channel;
   1354   1.1  jdolecek 	u_int8_t i, stereo = voice->stereo;
   1355   1.1  jdolecek 	int s;
   1356   1.1  jdolecek 
   1357   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i += stereo + 1) {
   1358   1.1  jdolecek 		if ((stereo && (channel[i + 1] != NULL)) ||
   1359   1.1  jdolecek 		    (channel[i] != NULL))	/* Looking for free channels */
   1360   1.1  jdolecek 			continue;
   1361   1.1  jdolecek 		s = splaudio();
   1362   1.1  jdolecek 		if (stereo) {
   1363   1.1  jdolecek 			voice->dataloc.chan[1] =
   1364   1.1  jdolecek 				emuxki_channel_new(voice, i + 1);
   1365   1.1  jdolecek 			if (voice->dataloc.chan[1] == NULL) {
   1366   1.1  jdolecek 				splx(s);
   1367   1.1  jdolecek 				return (ENOMEM);
   1368   1.1  jdolecek 			}
   1369   1.1  jdolecek 		}
   1370   1.1  jdolecek 		voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
   1371   1.1  jdolecek 		if (voice->dataloc.chan[0] == NULL) {
   1372   1.1  jdolecek 			if (stereo) {
   1373   1.1  jdolecek 				emuxki_channel_delete(voice->dataloc.chan[1]);
   1374   1.1  jdolecek 				voice->dataloc.chan[1] = NULL;
   1375   1.1  jdolecek 			}
   1376   1.1  jdolecek 			splx(s);
   1377   1.1  jdolecek 			return (ENOMEM);
   1378   1.1  jdolecek 		}
   1379   1.1  jdolecek 		splx(s);
   1380   1.1  jdolecek 		return (0);
   1381   1.1  jdolecek 	}
   1382   1.1  jdolecek 	return (EAGAIN);
   1383   1.1  jdolecek }
   1384   1.1  jdolecek 
   1385   1.1  jdolecek /* When calling this function we assume no one can access the voice */
   1386   1.1  jdolecek static void
   1387   1.1  jdolecek emuxki_voice_channel_destroy(struct emuxki_voice *voice)
   1388   1.1  jdolecek {
   1389   1.1  jdolecek 	emuxki_channel_delete(voice->dataloc.chan[0]);
   1390   1.1  jdolecek 	voice->dataloc.chan[0] = NULL;
   1391   1.1  jdolecek 	if (voice->stereo)
   1392   1.1  jdolecek 		emuxki_channel_delete(voice->dataloc.chan[1]);
   1393   1.1  jdolecek 	voice->dataloc.chan[1] = NULL;
   1394   1.1  jdolecek }
   1395   1.1  jdolecek 
   1396   1.1  jdolecek /*
   1397   1.1  jdolecek  * Will come back when used in voice_dataloc_create
   1398   1.1  jdolecek  */
   1399   1.1  jdolecek static int
   1400   1.1  jdolecek emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
   1401   1.1  jdolecek {
   1402  1.19    toshii 	if (source < 0 || source >= EMU_NUMRECSRCS) {
   1403  1.19    toshii #ifdef EMUXKI_DEBUG
   1404  1.37   dsainty 		printf("Tried to reserve invalid source: %d\n", source);
   1405  1.19    toshii #endif
   1406  1.19    toshii 		return (EINVAL);
   1407  1.19    toshii 	}
   1408  1.19    toshii 	if (voice->sc->recsrc[source] == voice)
   1409  1.19    toshii 		return (0);			/* XXX */
   1410  1.19    toshii 	if (voice->sc->recsrc[source] != NULL)
   1411   1.1  jdolecek 		return (EBUSY);
   1412  1.19    toshii 	voice->sc->recsrc[source] = voice;
   1413   1.1  jdolecek 	return (0);
   1414   1.1  jdolecek }
   1415  1.19    toshii 
   1416   1.1  jdolecek /* When calling this function we assume the voice is stopped */
   1417   1.1  jdolecek static void
   1418   1.1  jdolecek emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
   1419   1.1  jdolecek {
   1420   1.1  jdolecek 	sc->recsrc[source] = NULL;
   1421   1.1  jdolecek }
   1422   1.1  jdolecek 
   1423   1.1  jdolecek static int
   1424   1.1  jdolecek emuxki_voice_dataloc_create(struct emuxki_voice *voice)
   1425   1.1  jdolecek {
   1426   1.1  jdolecek 	int             error;
   1427   1.1  jdolecek 
   1428   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1429   1.1  jdolecek 		if ((error = emuxki_voice_channel_create(voice)))
   1430   1.1  jdolecek 			return (error);
   1431   1.1  jdolecek 	} else {
   1432  1.19    toshii 		if ((error =
   1433  1.19    toshii 		    emuxki_recsrc_reserve(voice, voice->dataloc.source)))
   1434  1.19    toshii 			return (error);
   1435   1.1  jdolecek 	}
   1436   1.1  jdolecek 	return (0);
   1437   1.1  jdolecek }
   1438   1.1  jdolecek 
   1439   1.1  jdolecek static void
   1440   1.1  jdolecek emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
   1441   1.1  jdolecek {
   1442   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1443   1.1  jdolecek 		if (voice->dataloc.chan[0] != NULL)
   1444   1.1  jdolecek 			emuxki_voice_channel_destroy(voice);
   1445   1.1  jdolecek 	} else {
   1446   1.1  jdolecek 		if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
   1447   1.1  jdolecek 			emuxki_voice_recsrc_release(voice->sc,
   1448   1.1  jdolecek 						     voice->dataloc.source);
   1449   1.1  jdolecek 			voice->dataloc.source = EMU_RECSRC_NOTSET;
   1450   1.1  jdolecek 		}
   1451   1.1  jdolecek 	}
   1452   1.1  jdolecek }
   1453   1.1  jdolecek 
   1454   1.1  jdolecek static struct emuxki_voice *
   1455   1.1  jdolecek emuxki_voice_new(struct emuxki_softc *sc, u_int8_t use)
   1456   1.1  jdolecek {
   1457   1.1  jdolecek 	struct emuxki_voice *voice;
   1458   1.1  jdolecek 	int             s;
   1459   1.1  jdolecek 
   1460   1.7  jdolecek 	s = splaudio();
   1461   1.7  jdolecek 	voice = sc->lvoice;
   1462   1.7  jdolecek 	sc->lvoice = NULL;
   1463   1.7  jdolecek 	splx(s);
   1464   1.7  jdolecek 
   1465  1.24    toshii 	if (!voice) {
   1466   1.7  jdolecek 		if (!(voice = malloc(sizeof(*voice), M_DEVBUF, M_WAITOK)))
   1467   1.7  jdolecek 			return (NULL);
   1468  1.24    toshii 	} else if (voice->use != use)
   1469  1.24    toshii 		emuxki_voice_dataloc_destroy(voice);
   1470  1.24    toshii 	else
   1471  1.24    toshii 		goto skip_initialize;
   1472  1.19    toshii 
   1473  1.19    toshii 	voice->sc = sc;
   1474  1.19    toshii 	voice->state = !EMU_VOICE_STATE_STARTED;
   1475  1.19    toshii 	voice->stereo = EMU_VOICE_STEREO_NOTSET;
   1476  1.19    toshii 	voice->b16 = 0;
   1477  1.19    toshii 	voice->sample_rate = 0;
   1478  1.19    toshii 	if (use & EMU_VOICE_USE_PLAY)
   1479  1.19    toshii 		voice->dataloc.chan[0] = voice->dataloc.chan[1] = NULL;
   1480  1.19    toshii 	else
   1481  1.19    toshii 		voice->dataloc.source = EMU_RECSRC_NOTSET;
   1482  1.19    toshii 	voice->buffer = NULL;
   1483  1.19    toshii 	voice->blksize = 0;
   1484  1.19    toshii 	voice->trigblk = 0;
   1485  1.19    toshii 	voice->blkmod = 0;
   1486  1.19    toshii 	voice->inth = NULL;
   1487  1.19    toshii 	voice->inthparam = NULL;
   1488   1.1  jdolecek 	voice->use = use;
   1489   1.1  jdolecek 
   1490  1.24    toshii skip_initialize:
   1491   1.1  jdolecek 	s = splaudio();
   1492   1.1  jdolecek 	LIST_INSERT_HEAD((&sc->voices), voice, next);
   1493   1.1  jdolecek 	splx(s);
   1494   1.1  jdolecek 
   1495   1.1  jdolecek 	return (voice);
   1496   1.1  jdolecek }
   1497   1.1  jdolecek 
   1498   1.1  jdolecek static void
   1499   1.1  jdolecek emuxki_voice_delete(struct emuxki_voice *voice)
   1500   1.1  jdolecek {
   1501   1.7  jdolecek 	struct emuxki_softc *sc = voice->sc;
   1502   1.7  jdolecek 	struct emuxki_voice *lvoice;
   1503   1.7  jdolecek 	int s;
   1504   1.1  jdolecek 
   1505   1.1  jdolecek 	if (voice->state & EMU_VOICE_STATE_STARTED)
   1506   1.1  jdolecek 		emuxki_voice_halt(voice);
   1507   1.1  jdolecek 
   1508   1.1  jdolecek 	s = splaudio();
   1509   1.1  jdolecek 	LIST_REMOVE(voice, next);
   1510   1.7  jdolecek 	lvoice = sc->lvoice;
   1511   1.7  jdolecek 	sc->lvoice = voice;
   1512   1.1  jdolecek 	splx(s);
   1513   1.1  jdolecek 
   1514   1.7  jdolecek 	if (lvoice) {
   1515   1.7  jdolecek 		emuxki_voice_dataloc_destroy(lvoice);
   1516   1.7  jdolecek 		free(lvoice, M_DEVBUF);
   1517   1.7  jdolecek 	}
   1518   1.1  jdolecek }
   1519   1.1  jdolecek 
   1520   1.1  jdolecek static int
   1521   1.1  jdolecek emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo)
   1522   1.1  jdolecek {
   1523   1.1  jdolecek 	int	error;
   1524  1.28  christos 	emuxki_recsrc_t source = 0; /* XXX: gcc */
   1525   1.1  jdolecek 	struct emuxki_chanparms_fxsend fxsend;
   1526   1.1  jdolecek 
   1527  1.19    toshii 	if (! (voice->use & EMU_VOICE_USE_PLAY))
   1528  1.19    toshii 		source = voice->dataloc.source;
   1529   1.1  jdolecek 	emuxki_voice_dataloc_destroy(voice);
   1530  1.19    toshii 	if (! (voice->use & EMU_VOICE_USE_PLAY))
   1531  1.19    toshii 		voice->dataloc.source = source;
   1532   1.1  jdolecek 	voice->stereo = stereo;
   1533   1.1  jdolecek 	if ((error = emuxki_voice_dataloc_create(voice)))
   1534   1.1  jdolecek 	  return (error);
   1535   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1536   1.1  jdolecek 		fxsend.a.dest = 0x0;
   1537   1.1  jdolecek 		fxsend.b.dest = 0x1;
   1538   1.1  jdolecek 		fxsend.c.dest = 0x2;
   1539   1.1  jdolecek 		fxsend.d.dest = 0x3;
   1540  1.35  christos 		/* for audigy */
   1541  1.35  christos 		fxsend.e.dest = 0x4;
   1542  1.35  christos 		fxsend.f.dest = 0x5;
   1543  1.35  christos 		fxsend.g.dest = 0x6;
   1544  1.35  christos 		fxsend.h.dest = 0x7;
   1545   1.1  jdolecek 		if (voice->stereo) {
   1546   1.7  jdolecek 			fxsend.a.level = fxsend.c.level = 0xc0;
   1547   1.1  jdolecek 			fxsend.b.level = fxsend.d.level = 0x00;
   1548  1.35  christos 			fxsend.e.level = fxsend.g.level = 0xc0;
   1549  1.35  christos 			fxsend.f.level = fxsend.h.level = 0x00;
   1550   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[0],
   1551   1.1  jdolecek 						   &fxsend);
   1552   1.1  jdolecek 			fxsend.a.level = fxsend.c.level = 0x00;
   1553   1.7  jdolecek 			fxsend.b.level = fxsend.d.level = 0xc0;
   1554  1.35  christos 			fxsend.e.level = fxsend.g.level = 0x00;
   1555  1.35  christos 			fxsend.f.level = fxsend.h.level = 0xc0;
   1556   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[1],
   1557   1.1  jdolecek 						   &fxsend);
   1558   1.1  jdolecek 		} /* No else : default is good for mono */
   1559   1.1  jdolecek 	}
   1560   1.1  jdolecek 	return (0);
   1561   1.1  jdolecek }
   1562   1.1  jdolecek 
   1563   1.1  jdolecek static int
   1564   1.1  jdolecek emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate)
   1565   1.1  jdolecek {
   1566   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1567   1.1  jdolecek 		if ((srate < 4000) || (srate > 48000))
   1568   1.1  jdolecek 			return (EINVAL);
   1569   1.1  jdolecek 		voice->sample_rate = srate;
   1570   1.1  jdolecek 		emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
   1571   1.1  jdolecek 		if (voice->stereo)
   1572   1.1  jdolecek 			emuxki_channel_set_srate(voice->dataloc.chan[1],
   1573   1.1  jdolecek 						  srate);
   1574   1.1  jdolecek 	} else {
   1575  1.35  christos 		if ((srate < 8000) || (srate > 48000))
   1576  1.19    toshii 			return (EINVAL);
   1577  1.19    toshii 		voice->sample_rate = srate;
   1578  1.35  christos 		if (emuxki_voice_adc_rate(voice) < 0) {
   1579  1.35  christos 			voice->sample_rate = 0;
   1580  1.35  christos 			return (EINVAL);
   1581  1.35  christos 		}
   1582   1.1  jdolecek 	}
   1583   1.1  jdolecek 	return (0);
   1584   1.1  jdolecek }
   1585   1.1  jdolecek 
   1586   1.1  jdolecek static int
   1587   1.1  jdolecek emuxki_voice_set_audioparms(struct emuxki_voice *voice, u_int8_t stereo,
   1588   1.1  jdolecek 			     u_int8_t b16, u_int32_t srate)
   1589   1.1  jdolecek {
   1590  1.28  christos 	int             error = 0;
   1591   1.1  jdolecek 
   1592   1.1  jdolecek 	if (voice->stereo == stereo && voice->b16 == b16 &&
   1593   1.1  jdolecek 	    voice->sample_rate == srate)
   1594   1.1  jdolecek 		return (0);
   1595   1.1  jdolecek 
   1596   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1597  1.18   tsutsui 	printf("Setting %s voice params : %s, %u bits, %u Hz\n",
   1598   1.1  jdolecek 	       (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
   1599   1.1  jdolecek 	       stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
   1600   1.1  jdolecek #endif
   1601   1.1  jdolecek 
   1602   1.1  jdolecek 	if (voice->stereo != stereo) {
   1603   1.1  jdolecek 		if ((error = emuxki_voice_set_stereo(voice, stereo)))
   1604   1.1  jdolecek 			return (error);
   1605   1.1  jdolecek 	 }
   1606   1.1  jdolecek 	voice->b16 = b16;
   1607   1.1  jdolecek 	if (voice->sample_rate != srate)
   1608  1.23    toshii 		error = emuxki_voice_set_srate(voice, srate);
   1609  1.23    toshii 	return error;
   1610   1.1  jdolecek }
   1611   1.1  jdolecek 
   1612   1.1  jdolecek /* voice audio parms (see just before) must be set prior to this */
   1613   1.1  jdolecek static int
   1614   1.1  jdolecek emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
   1615   1.1  jdolecek 			   u_int32_t bufsize, u_int16_t blksize)
   1616   1.1  jdolecek {
   1617   1.1  jdolecek 	struct emuxki_mem *mem;
   1618   1.1  jdolecek 	struct emuxki_channel **chan;
   1619   1.1  jdolecek 	u_int32_t start, end;
   1620   1.1  jdolecek 	u_int8_t sample_size;
   1621  1.19    toshii 	int idx;
   1622   1.1  jdolecek 	int error = EFAULT;
   1623   1.1  jdolecek 
   1624   1.1  jdolecek 	LIST_FOREACH(mem, &voice->sc->mem, next) {
   1625   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   1626   1.1  jdolecek 			continue;
   1627   1.1  jdolecek 
   1628   1.1  jdolecek 		voice->buffer = mem;
   1629   1.1  jdolecek 		sample_size = (voice->b16 + 1) * (voice->stereo + 1);
   1630   1.1  jdolecek 		voice->trigblk = 0;	/* This shouldn't be needed */
   1631   1.1  jdolecek 		voice->blkmod = bufsize / blksize;
   1632   1.1  jdolecek 		if (bufsize % blksize) 	  /* This should not happen */
   1633   1.1  jdolecek 			voice->blkmod++;
   1634   1.1  jdolecek 		error = 0;
   1635   1.1  jdolecek 
   1636   1.1  jdolecek 		if (voice->use & EMU_VOICE_USE_PLAY) {
   1637  1.19    toshii 			voice->blksize = blksize / sample_size;
   1638   1.1  jdolecek 			chan = voice->dataloc.chan;
   1639   1.1  jdolecek 			start = mem->ptbidx << 12;
   1640   1.1  jdolecek 			end = start + bufsize / sample_size;
   1641   1.1  jdolecek 			emuxki_channel_set_bufparms(chan[0],
   1642   1.1  jdolecek 						     start, end);
   1643   1.1  jdolecek 			if (voice->stereo)
   1644   1.1  jdolecek 				emuxki_channel_set_bufparms(chan[1],
   1645   1.1  jdolecek 				     start, end);
   1646   1.1  jdolecek 			voice->timerate = (u_int32_t) 48000 *
   1647   1.1  jdolecek 			                voice->blksize / voice->sample_rate;
   1648   1.1  jdolecek 			if (voice->timerate < 5)
   1649   1.1  jdolecek 				error = EINVAL;
   1650   1.1  jdolecek 		} else {
   1651  1.19    toshii 			voice->blksize = blksize;
   1652  1.19    toshii 			for(idx = sizeof(emuxki_recbuf_sz) /
   1653  1.19    toshii 			    sizeof(emuxki_recbuf_sz[0]); --idx >= 0;)
   1654  1.19    toshii 				if (emuxki_recbuf_sz[idx] == bufsize)
   1655  1.19    toshii 					break;
   1656  1.19    toshii 			if (idx < 0) {
   1657  1.19    toshii #ifdef EMUXKI_DEBUG
   1658  1.19    toshii 				printf("Invalid bufsize: %d\n", bufsize);
   1659  1.19    toshii #endif
   1660  1.19    toshii 				return (EINVAL);
   1661  1.19    toshii 			}
   1662  1.19    toshii 			emuxki_write(voice->sc, 0,
   1663  1.19    toshii 			    emuxki_recsrc_szreg[voice->dataloc.source], idx);
   1664  1.19    toshii 			emuxki_write(voice->sc, 0,
   1665  1.19    toshii 			    emuxki_recsrc_bufaddrreg[voice->dataloc.source],
   1666  1.19    toshii 			    DMAADDR(mem->dmamem));
   1667  1.19    toshii 
   1668  1.19    toshii 			/* Use timer to emulate DMA completion interrupt */
   1669  1.19    toshii 			voice->timerate = (u_int32_t) 48000 * blksize /
   1670  1.19    toshii 			    (voice->sample_rate * sample_size);
   1671  1.19    toshii 			if (voice->timerate < 5) {
   1672   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1673  1.19    toshii 				printf("Invalid timerate: %d, blksize %d\n",
   1674  1.19    toshii 				    voice->timerate, blksize);
   1675   1.1  jdolecek #endif
   1676  1.19    toshii 				error = EINVAL;
   1677  1.19    toshii 			}
   1678   1.1  jdolecek 		}
   1679   1.1  jdolecek 
   1680   1.1  jdolecek 		break;
   1681   1.1  jdolecek 	}
   1682   1.1  jdolecek 
   1683   1.1  jdolecek 	return (error);
   1684   1.1  jdolecek }
   1685   1.1  jdolecek 
   1686   1.1  jdolecek static void
   1687   1.1  jdolecek emuxki_voice_commit_parms(struct emuxki_voice *voice)
   1688   1.1  jdolecek {
   1689   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1690   1.1  jdolecek 		emuxki_channel_commit_parms(voice->dataloc.chan[0]);
   1691   1.1  jdolecek 		if (voice->stereo)
   1692   1.1  jdolecek 			emuxki_channel_commit_parms(voice->dataloc.chan[1]);
   1693   1.1  jdolecek 	}
   1694   1.1  jdolecek }
   1695   1.1  jdolecek 
   1696   1.1  jdolecek static u_int32_t
   1697   1.1  jdolecek emuxki_voice_curaddr(struct emuxki_voice *voice)
   1698   1.1  jdolecek {
   1699  1.35  christos 	int idxreg = 0;
   1700  1.19    toshii 
   1701  1.19    toshii 	/* XXX different semantics in these cases */
   1702  1.35  christos 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1703  1.19    toshii 		/* returns number of samples (an l/r pair counts 1) */
   1704   1.1  jdolecek 		return (emuxki_read(voice->sc,
   1705   1.1  jdolecek 				     voice->dataloc.chan[0]->num,
   1706   1.1  jdolecek 				     EMU_CHAN_CCCA_CURRADDR) -
   1707   1.1  jdolecek 			voice->dataloc.chan[0]->loop.start);
   1708  1.35  christos 	} else {
   1709  1.19    toshii 		/* returns number of bytes */
   1710  1.35  christos 		switch (voice->dataloc.source) {
   1711  1.35  christos 			case EMU_RECSRC_MIC:
   1712  1.35  christos 				idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
   1713  1.35  christos 					EMU_A_MICIDX : EMU_MICIDX;
   1714  1.35  christos 				break;
   1715  1.35  christos 			case EMU_RECSRC_ADC:
   1716  1.35  christos 				idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
   1717  1.35  christos 					EMU_A_ADCIDX : EMU_ADCIDX;
   1718  1.35  christos 				break;
   1719  1.35  christos 			case EMU_RECSRC_FX:
   1720  1.35  christos 				idxreg = EMU_FXIDX;
   1721  1.35  christos 				break;
   1722  1.35  christos 			default:
   1723  1.35  christos #ifdef EMUXKI_DEBUG
   1724  1.35  christos 				printf("emu: bad recording source!\n");
   1725  1.35  christos #endif
   1726  1.35  christos 				break;
   1727  1.35  christos 		}
   1728  1.35  christos 		return (emuxki_read(voice->sc, 0, EMU_RECIDX(idxreg))
   1729  1.35  christos 				& EMU_RECIDX_MASK);
   1730  1.35  christos 	}
   1731   1.1  jdolecek 	return (0);
   1732   1.1  jdolecek }
   1733   1.1  jdolecek 
   1734   1.1  jdolecek static void
   1735   1.1  jdolecek emuxki_resched_timer(struct emuxki_softc *sc)
   1736   1.1  jdolecek {
   1737   1.1  jdolecek 	struct emuxki_voice *voice;
   1738   1.1  jdolecek 	u_int16_t       timerate = 1024;
   1739   1.1  jdolecek 	u_int8_t	active = 0;
   1740   1.1  jdolecek 	int s;
   1741   1.1  jdolecek 
   1742   1.1  jdolecek 	s = splaudio();
   1743   1.1  jdolecek 	LIST_FOREACH(voice, &sc->voices, next) {
   1744  1.19    toshii 		if ((voice->state & EMU_VOICE_STATE_STARTED) == 0)
   1745   1.1  jdolecek 			continue;
   1746   1.1  jdolecek 		active = 1;
   1747   1.1  jdolecek 		if (voice->timerate < timerate)
   1748   1.1  jdolecek 			timerate = voice->timerate;
   1749   1.1  jdolecek 	}
   1750   1.1  jdolecek 
   1751   1.1  jdolecek 	if (timerate & ~EMU_TIMER_RATE_MASK)
   1752   1.1  jdolecek 		timerate = 0;
   1753  1.14      tron 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
   1754   1.1  jdolecek 	if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1755   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1756   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
   1757   1.1  jdolecek 			~EMU_INTE_INTERTIMERENB);
   1758   1.1  jdolecek 		sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
   1759   1.1  jdolecek 	} else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1760   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1761   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
   1762   1.1  jdolecek 			EMU_INTE_INTERTIMERENB);
   1763   1.1  jdolecek 		sc->timerstate |= EMU_TIMER_STATE_ENABLED;
   1764   1.1  jdolecek 	}
   1765   1.1  jdolecek 	splx(s);
   1766   1.1  jdolecek }
   1767   1.1  jdolecek 
   1768  1.35  christos static int
   1769  1.35  christos emuxki_voice_adc_rate(struct emuxki_voice *voice)
   1770  1.35  christos {
   1771  1.35  christos 	switch(voice->sample_rate) {
   1772  1.35  christos 		case 48000:
   1773  1.35  christos 			return EMU_ADCCR_SAMPLERATE_48;
   1774  1.35  christos 			break;
   1775  1.35  christos 		case 44100:
   1776  1.35  christos 			return EMU_ADCCR_SAMPLERATE_44;
   1777  1.35  christos 			break;
   1778  1.35  christos 		case 32000:
   1779  1.35  christos 			return EMU_ADCCR_SAMPLERATE_32;
   1780  1.35  christos 			break;
   1781  1.35  christos 		case 24000:
   1782  1.35  christos 			return EMU_ADCCR_SAMPLERATE_24;
   1783  1.35  christos 			break;
   1784  1.35  christos 		case 22050:
   1785  1.35  christos 			return EMU_ADCCR_SAMPLERATE_22;
   1786  1.35  christos 			break;
   1787  1.35  christos 		case 16000:
   1788  1.35  christos 			return EMU_ADCCR_SAMPLERATE_16;
   1789  1.35  christos 			break;
   1790  1.35  christos 		case 12000:
   1791  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1792  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_12;
   1793  1.35  christos 			else {
   1794  1.35  christos #ifdef EMUXKI_DEBUG
   1795  1.35  christos 				printf("recording sample_rate not supported : %u\n", voice->sample_rate);
   1796  1.35  christos #endif
   1797  1.35  christos 				return (-1);
   1798  1.35  christos 			}
   1799  1.35  christos 			break;
   1800  1.35  christos 		case 11000:
   1801  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1802  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_11;
   1803  1.35  christos 			else
   1804  1.35  christos 				return EMU_ADCCR_SAMPLERATE_11;
   1805  1.35  christos 			break;
   1806  1.35  christos 		case 8000:
   1807  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1808  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_8;
   1809  1.35  christos 			else
   1810  1.35  christos 				return EMU_ADCCR_SAMPLERATE_8;
   1811  1.35  christos 			break;
   1812  1.35  christos 		default:
   1813  1.35  christos #ifdef EMUXKI_DEBUG
   1814  1.35  christos 				printf("recording sample_rate not supported : %u\n", voice->sample_rate);
   1815  1.35  christos #endif
   1816  1.35  christos 				return (-1);
   1817  1.35  christos 	}
   1818  1.35  christos 	return (-1);  /* shouldn't get here */
   1819  1.35  christos }
   1820  1.35  christos 
   1821  1.35  christos 
   1822   1.1  jdolecek static void
   1823   1.1  jdolecek emuxki_voice_start(struct emuxki_voice *voice,
   1824   1.1  jdolecek 		    void (*inth) (void *), void *inthparam)
   1825   1.1  jdolecek {
   1826  1.19    toshii 	u_int32_t val;
   1827  1.19    toshii 
   1828   1.1  jdolecek 	voice->inth = inth;
   1829   1.1  jdolecek 	voice->inthparam = inthparam;
   1830   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1831   1.1  jdolecek 		voice->trigblk = 1;
   1832   1.1  jdolecek 		emuxki_channel_start(voice->dataloc.chan[0]);
   1833   1.1  jdolecek 		if (voice->stereo)
   1834   1.1  jdolecek 			emuxki_channel_start(voice->dataloc.chan[1]);
   1835  1.19    toshii 	} else {
   1836  1.19    toshii 		voice->trigblk = 1;
   1837  1.35  christos 		switch (voice->dataloc.source) {
   1838  1.19    toshii 		case EMU_RECSRC_ADC:
   1839  1.19    toshii 			/* XXX need to program DSP to output L+R
   1840  1.19    toshii 			 * XXX in monaural case? */
   1841  1.35  christos 			if (voice->sc->sc_type & EMUXKI_AUDIGY) {
   1842  1.35  christos 				val = EMU_A_ADCCR_LCHANENABLE;
   1843  1.35  christos 				if (voice->stereo)
   1844  1.35  christos 					val |= EMU_A_ADCCR_RCHANENABLE;
   1845  1.35  christos 			} else {
   1846  1.35  christos 				val = EMU_ADCCR_LCHANENABLE;
   1847  1.35  christos 				if (voice->stereo)
   1848  1.35  christos 					val |= EMU_ADCCR_RCHANENABLE;
   1849  1.35  christos 			}
   1850  1.35  christos 			val |= emuxki_voice_adc_rate(voice);
   1851  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
   1852  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, val);
   1853  1.19    toshii 			break;
   1854  1.19    toshii 		case EMU_RECSRC_MIC:
   1855  1.19    toshii 		case EMU_RECSRC_FX:
   1856  1.19    toshii 			printf("unimplemented\n");
   1857  1.19    toshii 			break;
   1858  1.35  christos 		case EMU_RECSRC_NOTSET:
   1859  1.35  christos 		default:
   1860  1.35  christos 		        break;
   1861  1.19    toshii 		}
   1862  1.19    toshii #if 0
   1863  1.19    toshii 		/* DMA completion interrupt is useless; use timer */
   1864  1.19    toshii 		int s;
   1865  1.19    toshii 		s = splaudio();
   1866  1.35  christos 		val = emu_rd(sc, INTE, 4);
   1867  1.19    toshii 		val |= emuxki_recsrc_intrmasks[voice->dataloc.source];
   1868  1.35  christos 		emu_wr(sc, INTE, val, 4);
   1869  1.19    toshii 		splx(s);
   1870  1.19    toshii #endif
   1871   1.1  jdolecek 	}
   1872   1.1  jdolecek 	voice->state |= EMU_VOICE_STATE_STARTED;
   1873  1.19    toshii 	emuxki_resched_timer(voice->sc);
   1874   1.1  jdolecek }
   1875   1.1  jdolecek 
   1876   1.1  jdolecek static void
   1877   1.1  jdolecek emuxki_voice_halt(struct emuxki_voice *voice)
   1878   1.1  jdolecek {
   1879   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1880   1.1  jdolecek 		emuxki_channel_stop(voice->dataloc.chan[0]);
   1881   1.1  jdolecek 		if (voice->stereo)
   1882   1.1  jdolecek 			emuxki_channel_stop(voice->dataloc.chan[1]);
   1883  1.19    toshii 	} else {
   1884  1.19    toshii 		switch (voice->dataloc.source) {
   1885  1.19    toshii 		case EMU_RECSRC_ADC:
   1886  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
   1887  1.19    toshii 			break;
   1888  1.19    toshii 		case EMU_RECSRC_FX:
   1889  1.19    toshii 		case EMU_RECSRC_MIC:
   1890  1.19    toshii 			printf("unimplemented\n");
   1891  1.19    toshii 			break;
   1892  1.19    toshii 		case EMU_RECSRC_NOTSET:
   1893  1.19    toshii 			printf("Bad dataloc.source\n");
   1894  1.19    toshii 		}
   1895  1.19    toshii 		/* This should reset buffer pointer */
   1896  1.19    toshii 		emuxki_write(voice->sc, 0,
   1897  1.19    toshii 		    emuxki_recsrc_szreg[voice->dataloc.source],
   1898  1.19    toshii 		    EMU_RECBS_BUFSIZE_NONE);
   1899  1.19    toshii #if 0
   1900  1.19    toshii 		int s;
   1901  1.19    toshii 		s = splaudio();
   1902  1.35  christos 		val = emu_rd(sc, INTE, 4);
   1903  1.19    toshii 		val &= ~emuxki_recsrc_intrmasks[voice->dataloc.source];
   1904  1.35  christos 		emu_wr(sc, INTE, val, 4);
   1905  1.19    toshii 		splx(s);
   1906  1.19    toshii #endif
   1907   1.1  jdolecek 	}
   1908   1.1  jdolecek 	voice->state &= ~EMU_VOICE_STATE_STARTED;
   1909  1.19    toshii 	emuxki_resched_timer(voice->sc);
   1910   1.1  jdolecek }
   1911   1.1  jdolecek 
   1912   1.1  jdolecek /*
   1913   1.1  jdolecek  * The interrupt handler
   1914   1.1  jdolecek  */
   1915   1.1  jdolecek static int
   1916   1.1  jdolecek emuxki_intr(void *arg)
   1917   1.1  jdolecek {
   1918   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   1919   1.1  jdolecek 	u_int32_t       ipr, curblk;
   1920   1.1  jdolecek 	struct emuxki_voice *voice;
   1921  1.13  jdolecek 	int claim = 0;
   1922   1.1  jdolecek 
   1923   1.1  jdolecek 	while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
   1924   1.1  jdolecek 		if (ipr & EMU_IPR_INTERVALTIMER) {
   1925   1.1  jdolecek 			LIST_FOREACH(voice, &sc->voices, next) {
   1926  1.19    toshii 				if ((voice->state &
   1927   1.1  jdolecek 				      EMU_VOICE_STATE_STARTED) == 0)
   1928   1.1  jdolecek 					continue;
   1929   1.1  jdolecek 
   1930   1.1  jdolecek 				curblk = emuxki_voice_curaddr(voice) /
   1931   1.1  jdolecek 				       voice->blksize;
   1932  1.19    toshii #if 0
   1933   1.1  jdolecek 				if (curblk == voice->trigblk) {
   1934   1.1  jdolecek 					voice->inth(voice->inthparam);
   1935   1.1  jdolecek 					voice->trigblk++;
   1936   1.1  jdolecek 					voice->trigblk %= voice->blkmod;
   1937   1.1  jdolecek 				}
   1938  1.19    toshii #else
   1939  1.19    toshii 				while ((curblk >= voice->trigblk &&
   1940  1.19    toshii 				    curblk < (voice->trigblk + voice->blkmod / 2)) ||
   1941  1.19    toshii 				    ((int)voice->trigblk - (int)curblk) >
   1942  1.19    toshii 				    (voice->blkmod / 2 + 1)) {
   1943  1.19    toshii 					voice->inth(voice->inthparam);
   1944  1.19    toshii 					voice->trigblk++;
   1945  1.19    toshii 					voice->trigblk %= voice->blkmod;
   1946  1.19    toshii 				}
   1947  1.19    toshii #endif
   1948   1.1  jdolecek 			}
   1949   1.1  jdolecek 		}
   1950   1.1  jdolecek 
   1951   1.1  jdolecek 		/* Got interrupt */
   1952   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
   1953  1.13  jdolecek 
   1954  1.13  jdolecek 		claim = 1;
   1955   1.1  jdolecek 	}
   1956   1.1  jdolecek 
   1957  1.13  jdolecek 	return (claim);
   1958   1.1  jdolecek }
   1959   1.1  jdolecek 
   1960   1.1  jdolecek 
   1961   1.1  jdolecek /*
   1962   1.1  jdolecek  * Audio Architecture callbacks
   1963   1.1  jdolecek  */
   1964   1.1  jdolecek 
   1965   1.1  jdolecek static int
   1966   1.1  jdolecek emuxki_open(void *addr, int flags)
   1967   1.1  jdolecek {
   1968   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1969   1.1  jdolecek 
   1970   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1971   1.1  jdolecek 	printf("%s: emuxki_open called\n", sc->sc_dev.dv_xname);
   1972   1.1  jdolecek #endif
   1973   1.1  jdolecek 
   1974   1.1  jdolecek 	/*
   1975   1.1  jdolecek 	 * Multiple voice support would be added as soon as I find a way to
   1976   1.1  jdolecek 	 * trick the audio arch into supporting multiple voices.
   1977   1.1  jdolecek 	 * Or I might integrate a modified audio arch supporting
   1978   1.1  jdolecek 	 * multiple voices.
   1979   1.1  jdolecek 	 */
   1980   1.1  jdolecek 
   1981   1.1  jdolecek 	/*
   1982   1.1  jdolecek 	 * I did this because i have problems identifying the selected
   1983   1.1  jdolecek 	 * recording source(s) which is necessary when setting recording
   1984  1.31       wiz 	 * params This will be addressed very soon
   1985   1.1  jdolecek 	 */
   1986  1.19    toshii 	if (flags & AUOPEN_READ) {
   1987  1.19    toshii 		sc->rvoice = emuxki_voice_new(sc, 0 /* EMU_VOICE_USE_RECORD */);
   1988  1.19    toshii 		if (sc->rvoice == NULL)
   1989  1.19    toshii 			return (EBUSY);
   1990  1.19    toshii 
   1991  1.19    toshii 		/* XXX Hardcode RECSRC_ADC for now */
   1992  1.19    toshii 		sc->rvoice->dataloc.source = EMU_RECSRC_ADC;
   1993  1.19    toshii 	}
   1994   1.1  jdolecek 
   1995   1.1  jdolecek 	if (flags & AUOPEN_WRITE) {
   1996   1.1  jdolecek 		sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
   1997   1.1  jdolecek 		if (sc->pvoice == NULL) {
   1998   1.8  jdolecek 			if (sc->rvoice) {
   1999   1.1  jdolecek 				emuxki_voice_delete(sc->rvoice);
   2000   1.8  jdolecek 				sc->rvoice = NULL;
   2001   1.8  jdolecek 			}
   2002   1.1  jdolecek 			return (EBUSY);
   2003   1.1  jdolecek 		}
   2004   1.1  jdolecek 	}
   2005   1.1  jdolecek 
   2006   1.1  jdolecek 	return (0);
   2007   1.1  jdolecek }
   2008   1.1  jdolecek 
   2009   1.1  jdolecek static void
   2010   1.1  jdolecek emuxki_close(void *addr)
   2011   1.1  jdolecek {
   2012   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2013   1.1  jdolecek 
   2014   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2015   1.1  jdolecek 	printf("%s: emu10K1_close called\n", sc->sc_dev.dv_xname);
   2016   1.1  jdolecek #endif
   2017   1.1  jdolecek 
   2018   1.1  jdolecek 	/* No multiple voice support for now */
   2019   1.8  jdolecek 	if (sc->rvoice != NULL) {
   2020   1.1  jdolecek 		emuxki_voice_delete(sc->rvoice);
   2021   1.8  jdolecek 		sc->rvoice = NULL;
   2022   1.8  jdolecek 	}
   2023   1.8  jdolecek 	if (sc->pvoice != NULL) {
   2024   1.1  jdolecek 		emuxki_voice_delete(sc->pvoice);
   2025   1.8  jdolecek 		sc->pvoice = NULL;
   2026   1.8  jdolecek 	}
   2027   1.1  jdolecek }
   2028   1.1  jdolecek 
   2029   1.1  jdolecek static int
   2030   1.1  jdolecek emuxki_query_encoding(void *addr, struct audio_encoding *fp)
   2031   1.1  jdolecek {
   2032   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2033   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2034   1.1  jdolecek 
   2035   1.1  jdolecek 	printf("%s: emuxki_query_encoding called\n", sc->sc_dev.dv_xname);
   2036   1.1  jdolecek #endif
   2037   1.1  jdolecek 
   2038   1.1  jdolecek 	switch (fp->index) {
   2039   1.1  jdolecek 	case 0:
   2040   1.1  jdolecek 		strcpy(fp->name, AudioEulinear);
   2041   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR;
   2042   1.1  jdolecek 		fp->precision = 8;
   2043   1.1  jdolecek 		fp->flags = 0;
   2044   1.1  jdolecek 		break;
   2045   1.1  jdolecek 	case 1:
   2046   1.1  jdolecek 		strcpy(fp->name, AudioEmulaw);
   2047   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULAW;
   2048   1.1  jdolecek 		fp->precision = 8;
   2049   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2050   1.1  jdolecek 		break;
   2051   1.1  jdolecek 	case 2:
   2052   1.1  jdolecek 		strcpy(fp->name, AudioEalaw);
   2053   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ALAW;
   2054   1.1  jdolecek 		fp->precision = 8;
   2055   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2056   1.1  jdolecek 		break;
   2057   1.1  jdolecek 	case 3:
   2058   1.1  jdolecek 		strcpy(fp->name, AudioEslinear);
   2059   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR;
   2060   1.1  jdolecek 		fp->precision = 8;
   2061   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2062   1.1  jdolecek 		break;
   2063   1.1  jdolecek 	case 4:
   2064   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_le);
   2065   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
   2066   1.1  jdolecek 		fp->precision = 16;
   2067   1.1  jdolecek 		fp->flags = 0;
   2068   1.1  jdolecek 		break;
   2069   1.1  jdolecek 	case 5:
   2070   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_le);
   2071   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
   2072   1.1  jdolecek 		fp->precision = 16;
   2073   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2074   1.1  jdolecek 		break;
   2075   1.1  jdolecek 	case 6:
   2076   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_be);
   2077   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
   2078   1.1  jdolecek 		fp->precision = 16;
   2079   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2080   1.1  jdolecek 		break;
   2081   1.1  jdolecek 	case 7:
   2082   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_be);
   2083   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
   2084   1.1  jdolecek 		fp->precision = 16;
   2085   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2086   1.1  jdolecek 		break;
   2087   1.1  jdolecek 	default:
   2088   1.1  jdolecek 		return (EINVAL);
   2089   1.1  jdolecek 	}
   2090   1.1  jdolecek 	return (0);
   2091   1.1  jdolecek }
   2092   1.1  jdolecek 
   2093   1.1  jdolecek static int
   2094  1.39      kent emuxki_set_vparms(struct emuxki_voice *voice, const audio_params_t *p,
   2095  1.39      kent 		  stream_filter_list_t *fil)
   2096   1.1  jdolecek {
   2097  1.39      kent 	int mode, i;
   2098   1.1  jdolecek 
   2099   1.1  jdolecek 	mode = (voice->use & EMU_VOICE_USE_PLAY) ?
   2100   1.1  jdolecek 		AUMODE_PLAY : AUMODE_RECORD;
   2101  1.39      kent 	i = auconv_set_converter(emuxki_formats, EMUXKI_NFORMATS,
   2102  1.39      kent 				 mode, p, FALSE, fil);
   2103  1.39      kent 	if (i < 0)
   2104  1.39      kent 		return EINVAL;
   2105  1.39      kent 	if (fil->req_size > 0)
   2106  1.39      kent 		p = &fil->filters[0].param;
   2107  1.39      kent 	return emuxki_voice_set_audioparms
   2108  1.39      kent 		(voice, p->channels == 2, p->precision == 16, p->sample_rate);
   2109   1.1  jdolecek }
   2110   1.1  jdolecek 
   2111   1.1  jdolecek static int
   2112   1.1  jdolecek emuxki_set_params(void *addr, int setmode, int usemode,
   2113  1.39      kent 		  audio_params_t *play, audio_params_t *rec,
   2114  1.39      kent 		  stream_filter_list_t *pfil, stream_filter_list_t *rfil)
   2115   1.1  jdolecek {
   2116   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2117  1.35  christos 	int	     mode, error;
   2118   1.1  jdolecek 	struct audio_params *p;
   2119   1.8  jdolecek 	struct emuxki_voice *v;
   2120  1.39      kent 	stream_filter_list_t *fil;
   2121   1.1  jdolecek 
   2122   1.1  jdolecek 	for (mode = AUMODE_RECORD; mode != -1;
   2123   1.1  jdolecek 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
   2124   1.1  jdolecek 		if ((usemode & setmode & mode) == 0)
   2125   1.1  jdolecek 			continue;
   2126   1.1  jdolecek 
   2127   1.8  jdolecek 		if (mode == AUMODE_PLAY) {
   2128   1.8  jdolecek 			p = play;
   2129  1.39      kent 			fil = pfil;
   2130   1.8  jdolecek 			v = sc->pvoice;
   2131   1.8  jdolecek 		} else {
   2132   1.8  jdolecek 			p = rec;
   2133  1.39      kent 			fil = rfil;
   2134   1.8  jdolecek 			v = sc->rvoice;
   2135   1.8  jdolecek 		}
   2136   1.8  jdolecek 
   2137   1.8  jdolecek 		if (v == NULL) {
   2138   1.8  jdolecek 			continue;
   2139   1.8  jdolecek 		}
   2140   1.1  jdolecek 
   2141   1.1  jdolecek 		/* No multiple voice support for now */
   2142  1.39      kent 		if ((error = emuxki_set_vparms(v, p, fil)))
   2143   1.1  jdolecek 			return (error);
   2144   1.1  jdolecek 	}
   2145   1.1  jdolecek 
   2146   1.1  jdolecek 	return (0);
   2147   1.1  jdolecek }
   2148   1.1  jdolecek 
   2149   1.1  jdolecek static int
   2150   1.1  jdolecek emuxki_halt_output(void *addr)
   2151   1.1  jdolecek {
   2152   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2153   1.1  jdolecek 
   2154   1.1  jdolecek 	/* No multiple voice support for now */
   2155   1.1  jdolecek 	if (sc->pvoice == NULL)
   2156   1.1  jdolecek 		return (ENXIO);
   2157   1.1  jdolecek 
   2158   1.1  jdolecek 	emuxki_voice_halt(sc->pvoice);
   2159   1.1  jdolecek 	return (0);
   2160   1.1  jdolecek }
   2161   1.1  jdolecek 
   2162   1.1  jdolecek static int
   2163   1.1  jdolecek emuxki_halt_input(void *addr)
   2164   1.1  jdolecek {
   2165   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2166   1.1  jdolecek 
   2167   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2168   1.1  jdolecek 	printf("%s: emuxki_halt_input called\n", sc->sc_dev.dv_xname);
   2169   1.1  jdolecek #endif
   2170   1.1  jdolecek 
   2171   1.1  jdolecek 	/* No multiple voice support for now */
   2172   1.1  jdolecek 	if (sc->rvoice == NULL)
   2173   1.1  jdolecek 		return (ENXIO);
   2174   1.1  jdolecek 	emuxki_voice_halt(sc->rvoice);
   2175   1.1  jdolecek 	return (0);
   2176   1.1  jdolecek }
   2177   1.1  jdolecek 
   2178   1.1  jdolecek static int
   2179   1.1  jdolecek emuxki_getdev(void *addr, struct audio_device *dev)
   2180   1.1  jdolecek {
   2181  1.35  christos 	struct emuxki_softc *sc = addr;
   2182  1.35  christos 	*dev = sc->sc_audv;
   2183   1.1  jdolecek 
   2184   1.1  jdolecek 	return (0);
   2185   1.1  jdolecek }
   2186   1.1  jdolecek 
   2187   1.1  jdolecek static int
   2188   1.1  jdolecek emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
   2189   1.1  jdolecek {
   2190   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2191   1.1  jdolecek 
   2192   1.1  jdolecek 	return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
   2193   1.1  jdolecek }
   2194   1.1  jdolecek 
   2195   1.1  jdolecek static int
   2196   1.1  jdolecek emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
   2197   1.1  jdolecek {
   2198   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2199   1.1  jdolecek 
   2200   1.1  jdolecek 	return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
   2201   1.1  jdolecek }
   2202   1.1  jdolecek 
   2203   1.1  jdolecek static int
   2204   1.1  jdolecek emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
   2205   1.1  jdolecek {
   2206   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2207   1.1  jdolecek 
   2208   1.1  jdolecek 	return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
   2209   1.1  jdolecek }
   2210   1.1  jdolecek 
   2211   1.1  jdolecek static void *
   2212  1.16   thorpej emuxki_allocm(void *addr, int direction, size_t size,
   2213  1.16   thorpej     struct malloc_type *type, int flags)
   2214   1.1  jdolecek {
   2215   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2216   1.1  jdolecek 
   2217   1.1  jdolecek 	if (direction == AUMODE_PLAY)
   2218   1.1  jdolecek 		return emuxki_pmem_alloc(sc, size, type, flags);
   2219   1.1  jdolecek 	else
   2220   1.1  jdolecek 		return emuxki_rmem_alloc(sc, size, type, flags);
   2221   1.1  jdolecek }
   2222   1.1  jdolecek 
   2223   1.1  jdolecek static void
   2224  1.16   thorpej emuxki_freem(void *addr, void *ptr, struct malloc_type *type)
   2225   1.1  jdolecek {
   2226   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2227  1.35  christos 	int	     i, s;
   2228   1.1  jdolecek 	struct emuxki_mem *mem;
   2229  1.35  christos 	size_t	  numblocks;
   2230   1.1  jdolecek 	u_int32_t      *ptb, silentpage;
   2231   1.1  jdolecek 
   2232   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
   2233   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
   2234   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   2235   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   2236   1.1  jdolecek 			continue;
   2237   1.1  jdolecek 
   2238   1.1  jdolecek 		s = splaudio();
   2239   1.1  jdolecek 		if (mem->ptbidx != EMU_RMEM) {
   2240   1.1  jdolecek 			numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
   2241   1.1  jdolecek 			if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
   2242   1.1  jdolecek 				numblocks++;
   2243   1.1  jdolecek 			for (i = 0; i < numblocks; i++)
   2244   1.1  jdolecek 				ptb[mem->ptbidx + i] =
   2245  1.34   tsutsui 				    htole32(silentpage | (mem->ptbidx + i));
   2246   1.1  jdolecek 		}
   2247   1.1  jdolecek 		LIST_REMOVE(mem, next);
   2248   1.1  jdolecek 		splx(s);
   2249   1.1  jdolecek 
   2250   1.1  jdolecek 		emuxki_mem_delete(mem, type);
   2251   1.1  jdolecek 		break;
   2252   1.1  jdolecek 	}
   2253   1.1  jdolecek }
   2254   1.1  jdolecek 
   2255  1.19    toshii /* blocksize should be a divisor of allowable buffersize */
   2256  1.19    toshii /* XXX probably this could be done better */
   2257  1.19    toshii static int
   2258  1.39      kent emuxki_round_blocksize(void *addr, int blksize,
   2259  1.39      kent 		       int mode, const audio_params_t* param)
   2260  1.19    toshii {
   2261  1.19    toshii #if 0
   2262  1.19    toshii 	struct emuxki_softc *sc = addr;
   2263  1.19    toshii 	struct audio_softc *au;
   2264  1.19    toshii #endif
   2265  1.19    toshii 	int bufsize;
   2266  1.19    toshii #if 0
   2267  1.19    toshii 	if (sc == NULL)
   2268  1.19    toshii 		return blksize;
   2269  1.19    toshii 
   2270  1.19    toshii 	au = (void *)sc->sc_audev;
   2271  1.19    toshii 	if (au == NULL)
   2272  1.19    toshii 		return blksize;
   2273  1.19    toshii 
   2274  1.19    toshii 	bufsize = emuxki_round_buffersize(sc, AUMODE_RECORD,
   2275  1.19    toshii 	    au->sc_rr.bufsize);
   2276  1.19    toshii #else
   2277  1.19    toshii 	bufsize = 65536;
   2278  1.19    toshii #endif
   2279  1.19    toshii 
   2280  1.19    toshii 	while (bufsize > blksize)
   2281  1.19    toshii 		bufsize /= 2;
   2282  1.19    toshii 
   2283  1.19    toshii 	return bufsize;
   2284  1.19    toshii }
   2285  1.19    toshii 
   2286   1.1  jdolecek static size_t
   2287   1.1  jdolecek emuxki_round_buffersize(void *addr, int direction, size_t bsize)
   2288   1.1  jdolecek {
   2289   1.1  jdolecek 
   2290   1.1  jdolecek 	if (direction == AUMODE_PLAY) {
   2291   1.1  jdolecek 		if (bsize < EMU_PTESIZE)
   2292   1.1  jdolecek 			bsize = EMU_PTESIZE;
   2293   1.1  jdolecek 		else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
   2294   1.1  jdolecek 			bsize = EMU_PTESIZE * EMU_MAXPTE;
   2295   1.1  jdolecek 		/* Would be better if set to max available */
   2296   1.1  jdolecek 		else if (bsize % EMU_PTESIZE)
   2297   1.1  jdolecek 			bsize = bsize -
   2298   1.1  jdolecek 				(bsize % EMU_PTESIZE) +
   2299   1.1  jdolecek 				EMU_PTESIZE;
   2300   1.1  jdolecek 	} else {
   2301   1.1  jdolecek 		int idx;
   2302   1.1  jdolecek 
   2303   1.1  jdolecek 		/* find nearest lower recbuf size */
   2304  1.19    toshii 		for(idx = sizeof(emuxki_recbuf_sz) /
   2305  1.19    toshii 		    sizeof(emuxki_recbuf_sz[0]); --idx >= 0; ) {
   2306  1.19    toshii 			if (bsize >= emuxki_recbuf_sz[idx]) {
   2307  1.19    toshii 				bsize = emuxki_recbuf_sz[idx];
   2308   1.1  jdolecek 				break;
   2309   1.1  jdolecek 			}
   2310   1.1  jdolecek 		}
   2311   1.1  jdolecek 
   2312   1.1  jdolecek 		if (bsize == 0)
   2313   1.1  jdolecek 			bsize = 384;
   2314   1.1  jdolecek 	}
   2315   1.1  jdolecek 
   2316   1.1  jdolecek 	return (bsize);
   2317   1.1  jdolecek }
   2318   1.1  jdolecek 
   2319   1.1  jdolecek static paddr_t
   2320   1.1  jdolecek emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
   2321   1.1  jdolecek {
   2322   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2323   1.1  jdolecek 	struct emuxki_mem *mem;
   2324   1.1  jdolecek 
   2325   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   2326   1.1  jdolecek 		if (KERNADDR(mem->dmamem) == ptr) {
   2327   1.1  jdolecek 			struct dmamem *dm = mem->dmamem;
   2328   1.1  jdolecek 
   2329   1.1  jdolecek 			return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
   2330   1.1  jdolecek 			       off, prot, BUS_DMA_WAITOK);
   2331   1.1  jdolecek 		}
   2332   1.1  jdolecek 	}
   2333   1.1  jdolecek 
   2334   1.1  jdolecek 	return (-1);
   2335   1.1  jdolecek }
   2336   1.1  jdolecek 
   2337   1.1  jdolecek static int
   2338   1.1  jdolecek emuxki_get_props(void *addr)
   2339   1.1  jdolecek {
   2340   1.1  jdolecek 	return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
   2341   1.1  jdolecek 		AUDIO_PROP_FULLDUPLEX);
   2342   1.1  jdolecek }
   2343   1.1  jdolecek 
   2344   1.1  jdolecek static int
   2345   1.1  jdolecek emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
   2346   1.1  jdolecek 		       void (*inth) (void *), void *inthparam,
   2347  1.39      kent 		       const audio_params_t *params)
   2348   1.1  jdolecek {
   2349   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2350   1.1  jdolecek 	/* No multiple voice support for now */
   2351   1.1  jdolecek 	struct emuxki_voice *voice = sc->pvoice;
   2352  1.35  christos 	int	     error;
   2353   1.1  jdolecek 
   2354   1.1  jdolecek 	if (voice == NULL)
   2355   1.1  jdolecek 		return (ENXIO);
   2356  1.39      kent 	if ((error = emuxki_voice_set_audioparms(voice, params->channels == 2,
   2357  1.39      kent 						 params->precision == 16,
   2358  1.39      kent 						 params->sample_rate)))
   2359   1.1  jdolecek 		return (error);
   2360   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   2361   1.1  jdolecek 				(caddr_t)end - (caddr_t)start, blksize)))
   2362   1.1  jdolecek 		return (error);
   2363   1.1  jdolecek 	emuxki_voice_commit_parms(voice);
   2364   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   2365   1.1  jdolecek 
   2366   1.1  jdolecek 	return (0);
   2367   1.1  jdolecek }
   2368   1.1  jdolecek 
   2369   1.1  jdolecek static int
   2370   1.1  jdolecek emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
   2371   1.1  jdolecek 		      void (*inth) (void *), void *inthparam,
   2372  1.39      kent 		      const audio_params_t *params)
   2373   1.1  jdolecek {
   2374   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   2375   1.1  jdolecek 	/* No multiple voice support for now */
   2376   1.1  jdolecek 	struct emuxki_voice *voice = sc->rvoice;
   2377  1.35  christos 	int	error;
   2378   1.1  jdolecek 
   2379   1.1  jdolecek 	if (voice == NULL)
   2380   1.1  jdolecek 		return (ENXIO);
   2381  1.39      kent 	if ((error = emuxki_voice_set_audioparms(voice, params->channels == 2,
   2382  1.39      kent 						 params->precision == 16,
   2383  1.39      kent 						 params->sample_rate)))
   2384   1.1  jdolecek 		return (error);
   2385   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   2386   1.1  jdolecek 						(caddr_t)end - (caddr_t)start,
   2387   1.1  jdolecek 						blksize)))
   2388   1.1  jdolecek 		return (error);
   2389   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   2390   1.1  jdolecek 
   2391   1.1  jdolecek 	return (0);
   2392   1.1  jdolecek }
   2393   1.1  jdolecek 
   2394   1.1  jdolecek 
   2395   1.1  jdolecek /*
   2396   1.1  jdolecek  * AC97 callbacks
   2397   1.1  jdolecek  */
   2398   1.1  jdolecek 
   2399   1.1  jdolecek static int
   2400   1.1  jdolecek emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
   2401   1.1  jdolecek {
   2402   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2403   1.1  jdolecek 
   2404   1.1  jdolecek 	sc->codecif = codecif;
   2405   1.1  jdolecek 	return (0);
   2406   1.1  jdolecek }
   2407   1.1  jdolecek 
   2408   1.1  jdolecek static int
   2409   1.1  jdolecek emuxki_ac97_read(void *arg, u_int8_t reg, u_int16_t *val)
   2410   1.1  jdolecek {
   2411   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2412   1.1  jdolecek 	int s;
   2413   1.1  jdolecek 
   2414   1.1  jdolecek 	s = splaudio();
   2415   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2416   1.1  jdolecek 	*val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
   2417   1.1  jdolecek 	splx(s);
   2418   1.1  jdolecek 
   2419   1.1  jdolecek 	return (0);
   2420   1.1  jdolecek }
   2421   1.1  jdolecek 
   2422   1.1  jdolecek static int
   2423   1.1  jdolecek emuxki_ac97_write(void *arg, u_int8_t reg, u_int16_t val)
   2424   1.1  jdolecek {
   2425   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2426   1.1  jdolecek 	int s;
   2427   1.1  jdolecek 
   2428   1.1  jdolecek 	s = splaudio();
   2429   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2430   1.1  jdolecek 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
   2431   1.1  jdolecek 	splx(s);
   2432   1.1  jdolecek 
   2433   1.1  jdolecek 	return (0);
   2434   1.1  jdolecek }
   2435   1.1  jdolecek 
   2436  1.36      kent static int
   2437   1.1  jdolecek emuxki_ac97_reset(void *arg)
   2438   1.1  jdolecek {
   2439  1.36      kent 	return 0;
   2440   1.6  jdolecek }
   2441   1.6  jdolecek 
   2442   1.6  jdolecek enum ac97_host_flags
   2443   1.6  jdolecek emuxki_ac97_flags(void *arg)
   2444   1.6  jdolecek {
   2445   1.6  jdolecek   return (AC97_HOST_SWAPPED_CHANNELS);
   2446   1.1  jdolecek }
   2447