xref: /freebsd/sys/dev/sound/pci/emu10kx.c (revision 041b706b)
1d056fa04SAlexander Leidinger /*-
2d056fa04SAlexander Leidinger  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3d056fa04SAlexander Leidinger  * Copyright (c) 2003-2006 Yuriy Tsibizov <yuriy.tsibizov@gfk.ru>
4d056fa04SAlexander Leidinger  * All rights reserved.
5d056fa04SAlexander Leidinger  *
6d056fa04SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
7d056fa04SAlexander Leidinger  * modification, are permitted provided that the following conditions
8d056fa04SAlexander Leidinger  * are met:
9d056fa04SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
10d056fa04SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer.
11d056fa04SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
12d056fa04SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
13d056fa04SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
14d056fa04SAlexander Leidinger  *
15d056fa04SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d056fa04SAlexander Leidinger  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d056fa04SAlexander Leidinger  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d056fa04SAlexander Leidinger  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d056fa04SAlexander Leidinger  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d056fa04SAlexander Leidinger  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d056fa04SAlexander Leidinger  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d056fa04SAlexander Leidinger  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
23d056fa04SAlexander Leidinger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d056fa04SAlexander Leidinger  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d056fa04SAlexander Leidinger  * SUCH DAMAGE.
26d056fa04SAlexander Leidinger  *
27d056fa04SAlexander Leidinger  * $FreeBSD$
28d056fa04SAlexander Leidinger  */
29d056fa04SAlexander Leidinger 
30d056fa04SAlexander Leidinger #include <sys/param.h>
31d056fa04SAlexander Leidinger #include <sys/types.h>
32d056fa04SAlexander Leidinger #include <sys/bus.h>
33d056fa04SAlexander Leidinger #include <machine/bus.h>
34d056fa04SAlexander Leidinger #include <sys/rman.h>
35d056fa04SAlexander Leidinger #include <sys/systm.h>
36d056fa04SAlexander Leidinger #include <sys/sbuf.h>
37d056fa04SAlexander Leidinger #include <sys/queue.h>
38d056fa04SAlexander Leidinger #include <sys/lock.h>
39d056fa04SAlexander Leidinger #include <sys/mutex.h>
40d056fa04SAlexander Leidinger #include <sys/sysctl.h>
41d056fa04SAlexander Leidinger 
42d056fa04SAlexander Leidinger #include <dev/pci/pcireg.h>
43d056fa04SAlexander Leidinger #include <dev/pci/pcivar.h>
44d056fa04SAlexander Leidinger 
45d056fa04SAlexander Leidinger #include <machine/clock.h>	/* for DELAY */
46d056fa04SAlexander Leidinger 
47d056fa04SAlexander Leidinger #include <dev/sound/chip.h>
48d056fa04SAlexander Leidinger #include <dev/sound/pcm/sound.h>
49d056fa04SAlexander Leidinger #include <dev/sound/pcm/ac97.h>
50d056fa04SAlexander Leidinger 
51d056fa04SAlexander Leidinger #include "opt_emu10kx.h"
52d056fa04SAlexander Leidinger #include <dev/sound/pci/emu10kx.h>
53d056fa04SAlexander Leidinger 
54d056fa04SAlexander Leidinger /* hw flags */
55d056fa04SAlexander Leidinger #define	HAS_51		0x0001
56d056fa04SAlexander Leidinger #define	HAS_71		0x0002
57d056fa04SAlexander Leidinger #define	HAS_AC97	0x0004
58d056fa04SAlexander Leidinger 
59d056fa04SAlexander Leidinger #define	IS_EMU10K1	0x0008
60d056fa04SAlexander Leidinger #define	IS_EMU10K2	0x0010
61d056fa04SAlexander Leidinger #define	IS_CA0102	0x0020
62d056fa04SAlexander Leidinger #define	IS_CA0108	0x0040
63d056fa04SAlexander Leidinger #define	IS_UNKNOWN	0x0080
64d056fa04SAlexander Leidinger 
65d056fa04SAlexander Leidinger #define	BROKEN_DIGITAL	0x0100
66d056fa04SAlexander Leidinger #define	DIGITAL_ONLY	0x0200
67d056fa04SAlexander Leidinger 
68d056fa04SAlexander Leidinger #define	IS_CARDBUS	0x0400
69d056fa04SAlexander Leidinger 
70d056fa04SAlexander Leidinger #define	MODE_ANALOG	1
71d056fa04SAlexander Leidinger #define	MODE_DIGITAL	2
72d056fa04SAlexander Leidinger #define	SPDIF_MODE_PCM	1
73d056fa04SAlexander Leidinger #define	SPDIF_MODE_AC3	2
74d056fa04SAlexander Leidinger 
75d056fa04SAlexander Leidinger #define	MACS	0x0
76d056fa04SAlexander Leidinger #define	MACS1	0x1
77d056fa04SAlexander Leidinger #define	MACW	0x2
78d056fa04SAlexander Leidinger #define	MACW1	0x3
79d056fa04SAlexander Leidinger #define	MACINTS	0x4
80d056fa04SAlexander Leidinger #define	MACINTW	0x5
81d056fa04SAlexander Leidinger #define	ACC3	0x6
82d056fa04SAlexander Leidinger #define	MACMV	0x7
83d056fa04SAlexander Leidinger #define	ANDXOR	0x8
84d056fa04SAlexander Leidinger #define	TSTNEG	0x9
85d056fa04SAlexander Leidinger #define	LIMIT	0xA
86d056fa04SAlexander Leidinger #define	LIMIT1	0xB
87d056fa04SAlexander Leidinger #define	LOG	0xC
88d056fa04SAlexander Leidinger #define	EXP	0xD
89d056fa04SAlexander Leidinger #define	INTERP	0xE
90d056fa04SAlexander Leidinger #define	SKIP	0xF
91d056fa04SAlexander Leidinger 
92d056fa04SAlexander Leidinger #define	GPR(i)	(sc->gpr_base+(i))
93d056fa04SAlexander Leidinger #define	INP(i)	(sc->input_base+(i))
94d056fa04SAlexander Leidinger #define	OUTP(i)	(sc->output_base+(i))
95d056fa04SAlexander Leidinger #define	FX(i)	(i)
96d056fa04SAlexander Leidinger #define	FX2(i)	(sc->efxc_base+(i))
97d056fa04SAlexander Leidinger #define	DSP_CONST(i) (sc->dsp_zero+(i))
98d056fa04SAlexander Leidinger 
99d056fa04SAlexander Leidinger #define	COND_NORMALIZED	DSP_CONST(0x1)
100d056fa04SAlexander Leidinger #define	COND_BORROW	DSP_CONST(0x2)
101d056fa04SAlexander Leidinger #define	COND_MINUS	DSP_CONST(0x3)
102d056fa04SAlexander Leidinger #define	COND_LESS_ZERO	DSP_CONST(0x4)
103d056fa04SAlexander Leidinger #define	COND_EQ_ZERO	DSP_CONST(0x5)
104d056fa04SAlexander Leidinger #define	COND_SATURATION	DSP_CONST(0x6)
105d056fa04SAlexander Leidinger #define	COND_NEQ_ZERO	DSP_CONST(0x8)
106d056fa04SAlexander Leidinger 
107d056fa04SAlexander Leidinger /* Live! Inputs */
108d056fa04SAlexander Leidinger #define	IN_AC97_L 	0x00
109d056fa04SAlexander Leidinger #define	IN_AC97_R 	0x01
110d056fa04SAlexander Leidinger #define	IN_AC97		IN_AC97_L
111d056fa04SAlexander Leidinger #define	IN_SPDIF_CD_L	0x02
112d056fa04SAlexander Leidinger #define	IN_SPDIF_CD_R	0x03
113d056fa04SAlexander Leidinger #define	IN_SPDIF_CD	IN_SPDIF_CD_L
114d056fa04SAlexander Leidinger #define	IN_ZOOM_L 	0x04
115d056fa04SAlexander Leidinger #define	IN_ZOOM_R 	0x05
116d056fa04SAlexander Leidinger #define	IN_ZOOM		IN_ZOOM_L
117d056fa04SAlexander Leidinger #define	IN_TOSLINK_L	0x06
118d056fa04SAlexander Leidinger #define	IN_TOSLINK_R	0x07
119d056fa04SAlexander Leidinger #define	IN_TOSLINK	IN_TOSLINK_L
120d056fa04SAlexander Leidinger #define	IN_LINE1_L	0x08
121d056fa04SAlexander Leidinger #define	IN_LINE1_R	0x09
122d056fa04SAlexander Leidinger #define	IN_LINE1	IN_LINE1_L
123d056fa04SAlexander Leidinger #define	IN_COAX_SPDIF_L	0x0a
124d056fa04SAlexander Leidinger #define	IN_COAX_SPDIF_R	0x0b
125d056fa04SAlexander Leidinger #define	IN_COAX_SPDIF	IN_COAX_SPDIF_L
126d056fa04SAlexander Leidinger #define	IN_LINE2_L	0x0c
127d056fa04SAlexander Leidinger #define	IN_LINE2_R	0x0d
128d056fa04SAlexander Leidinger #define	IN_LINE2	IN_LINE2_L
129d056fa04SAlexander Leidinger #define	IN_0E		0x0e
130d056fa04SAlexander Leidinger #define	IN_0F		0x0f
131d056fa04SAlexander Leidinger 
132d056fa04SAlexander Leidinger /* Outputs */
133d056fa04SAlexander Leidinger #define	OUT_AC97_L	0x00
134d056fa04SAlexander Leidinger #define	OUT_AC97_R	0x01
135d056fa04SAlexander Leidinger #define	OUT_AC97	OUT_AC97_L
136d056fa04SAlexander Leidinger #define	OUT_A_FRONT	OUT_AC97
137d056fa04SAlexander Leidinger #define	OUT_TOSLINK_L 	0x02
138d056fa04SAlexander Leidinger #define	OUT_TOSLINK_R 	0x03
139d056fa04SAlexander Leidinger #define	OUT_TOSLINK	OUT_TOSLINK_L
140d056fa04SAlexander Leidinger #define	OUT_D_CENTER	0x04
141d056fa04SAlexander Leidinger #define	OUT_D_SUB	0x05
142d056fa04SAlexander Leidinger #define	OUT_HEADPHONE_L	0x06
143d056fa04SAlexander Leidinger #define	OUT_HEADPHONE_R	0x07
144d056fa04SAlexander Leidinger #define	OUT_HEADPHONE	OUT_HEADPHONE_L
145d056fa04SAlexander Leidinger #define	OUT_REAR_L	0x08
146d056fa04SAlexander Leidinger #define	OUT_REAR_R	0x09
147d056fa04SAlexander Leidinger #define	OUT_REAR	OUT_REAR_L
148d056fa04SAlexander Leidinger #define	OUT_ADC_REC_L 	0x0a
149d056fa04SAlexander Leidinger #define	OUT_ADC_REC_R	0x0b
150d056fa04SAlexander Leidinger #define	OUT_ADC_REC	OUT_ADC_REC_L
151d056fa04SAlexander Leidinger #define	OUT_MIC_CAP	0x0c
152f856af04SAlexander Leidinger 
153f856af04SAlexander Leidinger /* Live! 5.1 Digital, non-standart 5.1 (center & sub) outputs */
154d056fa04SAlexander Leidinger #define	OUT_A_CENTER	0x11
155d056fa04SAlexander Leidinger #define	OUT_A_SUB	0x12
156d056fa04SAlexander Leidinger 
157d056fa04SAlexander Leidinger /* Audigy Inputs */
158d056fa04SAlexander Leidinger #define	A_IN_AC97_L	0x00
159d056fa04SAlexander Leidinger #define	A_IN_AC97_R	0x01
160d056fa04SAlexander Leidinger #define	A_IN_AC97	A_IN_AC97_L
161d056fa04SAlexander Leidinger #define	A_IN_SPDIF_CD_L	0x02
162d056fa04SAlexander Leidinger #define	A_IN_SPDIF_CD_R	0x03
163d056fa04SAlexander Leidinger #define	A_IN_SPDIF_CD	A_IN_SPDIF_CD_L
164d056fa04SAlexander Leidinger #define	A_IN_O_SPDIF_L	0x04
165d056fa04SAlexander Leidinger #define	A_IN_O_SPDIF_R	0x05
166d056fa04SAlexander Leidinger #define	A_IN_O_SPDIF	A_IN_O_SPDIF_L
167d056fa04SAlexander Leidinger #define	A_IN_LINE2_L	0x08
168d056fa04SAlexander Leidinger #define	A_IN_LINE2_R	0x09
169d056fa04SAlexander Leidinger #define	A_IN_LINE2	A_IN_LINE2_L
170d056fa04SAlexander Leidinger #define	A_IN_R_SPDIF_L	0x0a
171d056fa04SAlexander Leidinger #define	A_IN_R_SPDIF_R	0x0b
172d056fa04SAlexander Leidinger #define	A_IN_R_SPDIF	A_IN_R_SPDIF_L
173d056fa04SAlexander Leidinger #define	A_IN_AUX2_L	0x0c
174d056fa04SAlexander Leidinger #define	A_IN_AUX2_R	0x0d
175d056fa04SAlexander Leidinger #define	A_IN_AUX2	A_IN_AUX2_L
176d056fa04SAlexander Leidinger 
177d056fa04SAlexander Leidinger /* Audigiy Outputs */
178d056fa04SAlexander Leidinger #define	A_OUT_D_FRONT_L	0x00
179d056fa04SAlexander Leidinger #define	A_OUT_D_FRONT_R	0x01
180d056fa04SAlexander Leidinger #define	A_OUT_D_FRONT	A_OUT_D_FRONT_L
181d056fa04SAlexander Leidinger #define	A_OUT_D_CENTER	0x02
182d056fa04SAlexander Leidinger #define	A_OUT_D_SUB	0x03
183d056fa04SAlexander Leidinger #define	A_OUT_D_SIDE_L	0x04
184d056fa04SAlexander Leidinger #define	A_OUT_D_SIDE_R	0x05
185d056fa04SAlexander Leidinger #define	A_OUT_D_SIDE	A_OUT_D_SIDE_L
186d056fa04SAlexander Leidinger #define	A_OUT_D_REAR_L	0x06
187d056fa04SAlexander Leidinger #define	A_OUT_D_REAR_R	0x07
188d056fa04SAlexander Leidinger #define	A_OUT_D_REAR	A_OUT_D_REAR_L
189d056fa04SAlexander Leidinger 
190d056fa04SAlexander Leidinger /* on Audigy Platinum only */
191d056fa04SAlexander Leidinger #define	A_OUT_HPHONE_L	0x04
192d056fa04SAlexander Leidinger #define	A_OUT_HPHONE_R	0x05
193d056fa04SAlexander Leidinger #define	A_OUT_HPHONE	A_OUT_HPHONE_L
194d056fa04SAlexander Leidinger 
195d056fa04SAlexander Leidinger #define	A_OUT_A_FRONT_L	0x08
196d056fa04SAlexander Leidinger #define	A_OUT_A_FRONT_R	0x09
197d056fa04SAlexander Leidinger #define	A_OUT_A_FRONT	A_OUT_A_FRONT_L
198d056fa04SAlexander Leidinger #define	A_OUT_A_CENTER	0x0a
199d056fa04SAlexander Leidinger #define	A_OUT_A_SUB	0x0b
200d056fa04SAlexander Leidinger #define	A_OUT_A_SIDE_L	0x0c
201d056fa04SAlexander Leidinger #define	A_OUT_A_SIDE_R	0x0d
202d056fa04SAlexander Leidinger #define	A_OUT_A_SIDE	A_OUT_A_SIDE_L
203d056fa04SAlexander Leidinger #define	A_OUT_A_REAR_L	0x0e
204d056fa04SAlexander Leidinger #define	A_OUT_A_REAR_R	0x0f
205d056fa04SAlexander Leidinger #define	A_OUT_A_REAR	A_OUT_A_REAR_L
206d056fa04SAlexander Leidinger #define	A_OUT_AC97_L	0x10
207d056fa04SAlexander Leidinger #define	A_OUT_AC97_R	0x11
208d056fa04SAlexander Leidinger #define	A_OUT_AC97	A_OUT_AC97_L
209d056fa04SAlexander Leidinger #define	A_OUT_ADC_REC_L	0x16
210d056fa04SAlexander Leidinger #define	A_OUT_ADC_REC_R	0x17
211d056fa04SAlexander Leidinger #define	A_OUT_ADC_REC	A_OUT_ADC_REC_L
212d056fa04SAlexander Leidinger 
213d056fa04SAlexander Leidinger #include "emu10k1-alsa%diked.h"
214d056fa04SAlexander Leidinger #include "p16v-alsa%diked.h"
215d056fa04SAlexander Leidinger #include "p17v-alsa%diked.h"
216d056fa04SAlexander Leidinger 
217d056fa04SAlexander Leidinger #define	C_FRONT_L	0
218d056fa04SAlexander Leidinger #define	C_FRONT_R	1
219d056fa04SAlexander Leidinger #define	C_REC_L		2
220d056fa04SAlexander Leidinger #define	C_REC_R		3
221d056fa04SAlexander Leidinger #define	C_REAR_L	4
222d056fa04SAlexander Leidinger #define	C_REAR_R	5
223d056fa04SAlexander Leidinger #define	C_CENTER	6
224d056fa04SAlexander Leidinger #define	C_SUB		7
225d056fa04SAlexander Leidinger #define	C_SIDE_L	8
226d056fa04SAlexander Leidinger #define	C_SIDE_R	9
227d056fa04SAlexander Leidinger #define	NUM_CACHES	10
228d056fa04SAlexander Leidinger 
229f856af04SAlexander Leidinger #define	NUM_DUMMIES	64
230f856af04SAlexander Leidinger 
231d056fa04SAlexander Leidinger #define	EMU_MAX_GPR	512
232d056fa04SAlexander Leidinger #define	EMU_MAX_IRQ_CONSUMERS 32
233d056fa04SAlexander Leidinger 
234d056fa04SAlexander Leidinger struct emu_voice {
235d056fa04SAlexander Leidinger 	int	vnum;
236feaa7fe1SAlexander Leidinger 	unsigned int	b16:1, stereo:1, busy:1, running:1, ismaster:1;
237d056fa04SAlexander Leidinger 	int	speed;
238d056fa04SAlexander Leidinger 	int	start;
239d056fa04SAlexander Leidinger 	int	end;
240d056fa04SAlexander Leidinger 	int	vol;
241d056fa04SAlexander Leidinger 	uint32_t buf;
242d056fa04SAlexander Leidinger 	void	*vbuf;
243d056fa04SAlexander Leidinger 	struct emu_voice *slave;
244d056fa04SAlexander Leidinger 	uint32_t sa;
245d056fa04SAlexander Leidinger 	uint32_t ea;
246d056fa04SAlexander Leidinger };
247d056fa04SAlexander Leidinger 
248d056fa04SAlexander Leidinger struct emu_memblk {
249d056fa04SAlexander Leidinger 	SLIST_ENTRY(emu_memblk)	link;
250d056fa04SAlexander Leidinger 	void		*buf;
251d056fa04SAlexander Leidinger 	char		owner[16];
252d056fa04SAlexander Leidinger 	bus_addr_t	buf_addr;
253d056fa04SAlexander Leidinger 	uint32_t	pte_start, pte_size;
254d056fa04SAlexander Leidinger };
255d056fa04SAlexander Leidinger 
256d056fa04SAlexander Leidinger struct emu_mem {
257e4c87b14SAlexander Leidinger 	uint8_t		bmap[EMU_MAXPAGES / 8];
258d056fa04SAlexander Leidinger 	uint32_t	*ptb_pages;
259d056fa04SAlexander Leidinger 	void		*silent_page;
260d056fa04SAlexander Leidinger 	bus_addr_t	silent_page_addr;
261d056fa04SAlexander Leidinger 	bus_addr_t	ptb_pages_addr;
262d056fa04SAlexander Leidinger 	bus_dma_tag_t	dmat;
263d056fa04SAlexander Leidinger 	SLIST_HEAD(, emu_memblk) blocks;
264d056fa04SAlexander Leidinger };
265d056fa04SAlexander Leidinger 
266d056fa04SAlexander Leidinger /* rm */
267d056fa04SAlexander Leidinger struct emu_rm {
268d056fa04SAlexander Leidinger 	struct emu_sc_info *card;
269d056fa04SAlexander Leidinger 	struct mtx	gpr_lock;
270d056fa04SAlexander Leidinger 	signed int	allocmap[EMU_MAX_GPR];
271d056fa04SAlexander Leidinger 	int		num_gprs;
272d056fa04SAlexander Leidinger 	int		last_free_gpr;
273d056fa04SAlexander Leidinger 	int 		num_used;
274d056fa04SAlexander Leidinger };
275d056fa04SAlexander Leidinger 
276d056fa04SAlexander Leidinger struct emu_intr_handler {
277d056fa04SAlexander Leidinger 	void*		softc;
278d056fa04SAlexander Leidinger 	uint32_t	intr_mask;
279d056fa04SAlexander Leidinger 	uint32_t	inte_mask;
280d056fa04SAlexander Leidinger 	uint32_t(*irq_func) (void *softc, uint32_t irq);
281d056fa04SAlexander Leidinger };
282d056fa04SAlexander Leidinger 
283d056fa04SAlexander Leidinger struct emu_sc_info {
284d056fa04SAlexander Leidinger 	struct mtx	lock;
285d056fa04SAlexander Leidinger 	struct mtx	rw;		/* Hardware exclusive access lock */
286d056fa04SAlexander Leidinger 
287d056fa04SAlexander Leidinger 	/* Hardware and subdevices */
288d056fa04SAlexander Leidinger 	device_t	dev;
289f856af04SAlexander Leidinger 	device_t	pcm[RT_COUNT];
290d056fa04SAlexander Leidinger 	device_t	midi[2];
291d056fa04SAlexander Leidinger 	uint32_t	type;
292d056fa04SAlexander Leidinger 	uint32_t	rev;
293d056fa04SAlexander Leidinger 
294d056fa04SAlexander Leidinger 	bus_space_tag_t	st;
295d056fa04SAlexander Leidinger 	bus_space_handle_t sh;
296d056fa04SAlexander Leidinger 
297d056fa04SAlexander Leidinger 	struct cdev	*cdev;		/* /dev/emu10k character device */
298d056fa04SAlexander Leidinger 	struct mtx	emu10kx_lock;
299d056fa04SAlexander Leidinger 	int		emu10kx_isopen;
300d056fa04SAlexander Leidinger 	struct sbuf	emu10kx_sbuf;
301d056fa04SAlexander Leidinger 	int		emu10kx_bufptr;
302d056fa04SAlexander Leidinger 
303d056fa04SAlexander Leidinger 
304d056fa04SAlexander Leidinger 	/* Resources */
305d056fa04SAlexander Leidinger 	struct resource	*reg;
306d056fa04SAlexander Leidinger 	struct resource	*irq;
307d056fa04SAlexander Leidinger 	void 		*ih;
308d056fa04SAlexander Leidinger 
309d056fa04SAlexander Leidinger 	/* IRQ handlers */
310d056fa04SAlexander Leidinger 	struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS];
311d056fa04SAlexander Leidinger 
312d056fa04SAlexander Leidinger 	/* Card HW configuration */
313d056fa04SAlexander Leidinger 	unsigned int	mchannel_fx;
314d056fa04SAlexander Leidinger 	unsigned int	dsp_zero;
315d056fa04SAlexander Leidinger 	unsigned int	code_base;
316d056fa04SAlexander Leidinger 	unsigned int	code_size;
317d056fa04SAlexander Leidinger 	unsigned int	gpr_base;
318d056fa04SAlexander Leidinger 	unsigned int	num_gprs;
319d056fa04SAlexander Leidinger 	unsigned int	input_base;
320d056fa04SAlexander Leidinger 	unsigned int	output_base;
321d056fa04SAlexander Leidinger 	unsigned int	efxc_base;
322d056fa04SAlexander Leidinger 	unsigned int	opcode_shift;
323d056fa04SAlexander Leidinger 	unsigned int	high_operand_shift;
324d056fa04SAlexander Leidinger 	unsigned int	address_mask;
325d056fa04SAlexander Leidinger 	uint32_t 	is_emu10k1:1, is_emu10k2, is_ca0102, is_ca0108:1,
326d056fa04SAlexander Leidinger 			has_ac97:1, has_51:1, has_71:1,
327d056fa04SAlexander Leidinger 			enable_ir:1, enable_debug:1,
328d056fa04SAlexander Leidinger 			broken_digital:1, is_cardbus:1;
329d056fa04SAlexander Leidinger 
330d056fa04SAlexander Leidinger 	unsigned int 	num_inputs;
331d056fa04SAlexander Leidinger 	unsigned int 	num_outputs;
332d056fa04SAlexander Leidinger 	unsigned int 	num_fxbuses;
333d056fa04SAlexander Leidinger 	unsigned int 	routing_code_start;
334d056fa04SAlexander Leidinger 	unsigned int	routing_code_end;
335d056fa04SAlexander Leidinger 
336d056fa04SAlexander Leidinger 	/* HW resources */
337d056fa04SAlexander Leidinger 	struct emu_voice voice[NUM_G];			/* Hardware voices */
338d056fa04SAlexander Leidinger 	uint32_t	irq_mask[EMU_MAX_IRQ_CONSUMERS]; /* IRQ manager data */
339d056fa04SAlexander Leidinger 	int 		timer[EMU_MAX_IRQ_CONSUMERS];	/* timer */
340d056fa04SAlexander Leidinger 	int		timerinterval;
341d056fa04SAlexander Leidinger 	struct		emu_rm *rm;
342d056fa04SAlexander Leidinger 	struct		emu_mem mem;			/* memory */
343d056fa04SAlexander Leidinger 
344d056fa04SAlexander Leidinger 	/* Mixer */
345d056fa04SAlexander Leidinger 	int		mixer_gpr[NUM_MIXERS];
346d056fa04SAlexander Leidinger 	int		mixer_volcache[NUM_MIXERS];
347d056fa04SAlexander Leidinger 	int		cache_gpr[NUM_CACHES];
348f856af04SAlexander Leidinger 	int		dummy_gpr[NUM_DUMMIES];
349d056fa04SAlexander Leidinger 	struct sysctl_ctx_list	*ctx;
350d056fa04SAlexander Leidinger 	struct sysctl_oid	*root;
351d056fa04SAlexander Leidinger };
352d056fa04SAlexander Leidinger 
353d056fa04SAlexander Leidinger static void	emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error);
354d056fa04SAlexander Leidinger static void*	emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr);
355d056fa04SAlexander Leidinger static void	emu_free(struct emu_mem *mem, void *dmabuf);
356d056fa04SAlexander Leidinger static void*	emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner);
357d056fa04SAlexander Leidinger static int	emu_memfree(struct emu_mem *mem, void *membuf);
358d056fa04SAlexander Leidinger static int	emu_memstart(struct emu_mem *mem, void *membuf);
359d056fa04SAlexander Leidinger 
360d056fa04SAlexander Leidinger /* /dev */
361d056fa04SAlexander Leidinger static int	emu10kx_dev_init(struct emu_sc_info *sc);
362d056fa04SAlexander Leidinger static int	emu10kx_dev_uninit(struct emu_sc_info *sc);
363d056fa04SAlexander Leidinger static int	emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s);
364d056fa04SAlexander Leidinger 
365d056fa04SAlexander Leidinger static void	emumix_set_mode(struct emu_sc_info *sc, int mode);
366d056fa04SAlexander Leidinger static void	emumix_set_spdif_mode(struct emu_sc_info *sc, int mode);
367d056fa04SAlexander Leidinger static void	emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol);
368d056fa04SAlexander Leidinger static void	emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val);
369d056fa04SAlexander Leidinger static int	sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS);
370d056fa04SAlexander Leidinger 
371d056fa04SAlexander Leidinger static int	emu_rm_init(struct emu_sc_info *sc);
372d056fa04SAlexander Leidinger static int	emu_rm_uninit(struct emu_sc_info *sc);
373d056fa04SAlexander Leidinger static int	emu_rm_gpr_alloc(struct emu_rm *rm, int count);
374d056fa04SAlexander Leidinger 
375f856af04SAlexander Leidinger static unsigned int emu_getcard(device_t dev);
376d056fa04SAlexander Leidinger static uint32_t	emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size);
377d056fa04SAlexander Leidinger static void	emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size);
378d056fa04SAlexander Leidinger static void	emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data);
379d056fa04SAlexander Leidinger 
380d056fa04SAlexander Leidinger static void	emu_vstop(struct emu_sc_info *sc, char channel, int enable);
381d056fa04SAlexander Leidinger 
382d056fa04SAlexander Leidinger static void	emu_intr(void *p);
383d056fa04SAlexander Leidinger static void	emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data);
384d056fa04SAlexander Leidinger static void	emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc);
385d056fa04SAlexander Leidinger static void	emu_initefx(struct emu_sc_info *sc);
386d056fa04SAlexander Leidinger 
387d056fa04SAlexander Leidinger static int	emu_cardbus_init(struct emu_sc_info *sc);
38855837609SAriff Abdullah static int	emu_init(struct emu_sc_info *sc);
389d056fa04SAlexander Leidinger static int	emu_uninit(struct emu_sc_info *sc);
390d056fa04SAlexander Leidinger 
391d056fa04SAlexander Leidinger static int	emu_read_ivar(device_t bus __unused, device_t dev, int ivar_index, uintptr_t * result);
392d056fa04SAlexander Leidinger static int	emu_write_ivar(device_t bus __unused, device_t dev __unused,
393d056fa04SAlexander Leidinger     int ivar_index, uintptr_t value __unused);
394d056fa04SAlexander Leidinger 
395d056fa04SAlexander Leidinger static int	emu_pci_probe(device_t dev);
396d056fa04SAlexander Leidinger static int	emu_pci_attach(device_t dev);
397d056fa04SAlexander Leidinger static int	emu_pci_detach(device_t dev);
398d056fa04SAlexander Leidinger static int	emu_modevent(module_t mod __unused, int cmd, void *data __unused);
399d056fa04SAlexander Leidinger 
400d056fa04SAlexander Leidinger /* Supported cards */
401d056fa04SAlexander Leidinger struct emu_hwinfo {
402d056fa04SAlexander Leidinger 	uint16_t	vendor;
403d056fa04SAlexander Leidinger 	uint16_t	device;
404d056fa04SAlexander Leidinger 	uint16_t	subvendor;
405d056fa04SAlexander Leidinger 	uint16_t	subdevice;
406d056fa04SAlexander Leidinger 	char		SBcode[8];
407d056fa04SAlexander Leidinger 	char		desc[32];
408d056fa04SAlexander Leidinger 	int		flags;
409d056fa04SAlexander Leidinger };
410d056fa04SAlexander Leidinger 
411d056fa04SAlexander Leidinger static struct emu_hwinfo emu_cards[] = {
412f856af04SAlexander Leidinger 	{0xffff, 0xffff, 0xffff, 0xffff, "BADCRD", "Not a compatible card", 0},
413d056fa04SAlexander Leidinger 	/* 0x0020..0x002f 4.0 EMU10K1 cards */
414d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x0020, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
415d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x0021, "CT4620", "SBLive!", HAS_AC97 | IS_EMU10K1},
416d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x002f, "CT????", "SBLive! mainboard implementation", HAS_AC97 | IS_EMU10K1},
417d056fa04SAlexander Leidinger 
418d056fa04SAlexander Leidinger 	/* (range unknown) 5.1 EMU10K1 cards */
419d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x100a, "CT????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
420d056fa04SAlexander Leidinger 
421d056fa04SAlexander Leidinger 	/* 0x80??..0x805? 4.0 EMU10K1 cards */
422d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8022, "CT4780", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
423d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8023, "CT4790", "SB PCI512", HAS_AC97 | IS_EMU10K1},
424d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8024, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
425d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8025, "CT????", "SBLive! Mainboard Implementation", HAS_AC97 | IS_EMU10K1},
426d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8026, "CT4830", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
427d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8027, "CT4832", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
428d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8028, "CT4760", "SBLive! OEM version", HAS_AC97 | IS_EMU10K1},
429d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8031, "CT4831", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
430d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8040, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
431d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8051, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
432d056fa04SAlexander Leidinger 
433d056fa04SAlexander Leidinger 	/* 0x8061..0x???? 5.1 EMU10K1  cards */
434d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8061, "SB????", "SBLive! Player 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
435d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8064, "SB????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
436d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8065, "SB0220", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
437d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8066, "CT4780", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
438d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x8067, "SB????", "SBLive!", HAS_AC97 | HAS_51 | IS_EMU10K1},
439d056fa04SAlexander Leidinger 
440d056fa04SAlexander Leidinger 	/* Generic SB Live! */
441d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x0000, "SB????", "SBLive! (Unknown model)", HAS_AC97 | IS_EMU10K1},
442d056fa04SAlexander Leidinger 
443d056fa04SAlexander Leidinger 	/* 0x0041..0x0043 EMU10K2 (some kind of Audigy) cards */
444d056fa04SAlexander Leidinger 
445d056fa04SAlexander Leidinger 	/* 0x0051..0x0051 5.1 CA0100-IAF cards */
446d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x0051, "SB0090", "Audigy", HAS_AC97 | HAS_51 | IS_EMU10K2},
447d056fa04SAlexander Leidinger 	/* ES is CA0100-IDF chip that don't work in digital mode */
448d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x0052, "SB0160", "Audigy ES", HAS_AC97 | HAS_71 | IS_EMU10K2 | BROKEN_DIGITAL},
449d056fa04SAlexander Leidinger 	/* 0x0053..0x005C 5.1 CA0101-NAF cards */
450d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x0053, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
451d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x0058, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
452d056fa04SAlexander Leidinger 
453d056fa04SAlexander Leidinger 	/* 0x1002..0x1009 5.1 CA0102-IAT cards */
454d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x1002, "SB????", "Audigy 2 Platinum", HAS_51 | IS_CA0102},
455d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x1005, "SB????", "Audigy 2 Platinum EX", HAS_51 | IS_CA0102},
456d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x1007, "SB0240", "Audigy 2", HAS_AC97 | HAS_51 | IS_CA0102},
457d056fa04SAlexander Leidinger 
458d056fa04SAlexander Leidinger 	/* 0x2001..0x2003 7.1 CA0102-ICT cards */
459d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2001, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
460d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2002, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
461f856af04SAlexander Leidinger 	/* XXX No reports about 0x2003 & 0x2004 cards */
462f856af04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2003, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
463f856af04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2004, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
464f856af04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2005, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
465d056fa04SAlexander Leidinger 
466d056fa04SAlexander Leidinger 	/* (range unknown) 7.1 CA0102-xxx Audigy 4 cards */
467d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x2007, "SB0380", "Audigy 4 Pro", HAS_AC97 | HAS_71 | IS_CA0102},
468d056fa04SAlexander Leidinger 
469d056fa04SAlexander Leidinger 	/* Generic Audigy or Audigy 2 */
470d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x0000, "SB????", "Audigy (Unknown model)", HAS_AC97 | HAS_51 | IS_EMU10K2},
471d056fa04SAlexander Leidinger 
472d056fa04SAlexander Leidinger 	/* We don't support CA0103-DAT (Audigy LS) cards */
473d056fa04SAlexander Leidinger 	/* There is NO CA0104-xxx cards */
474d056fa04SAlexander Leidinger 	/* There is NO CA0105-xxx cards */
475d056fa04SAlexander Leidinger 	/* We don't support CA0106-DAT (SB Live! 24 bit) cards */
476d056fa04SAlexander Leidinger 	/* There is NO CA0107-xxx cards */
477d056fa04SAlexander Leidinger 
478d056fa04SAlexander Leidinger 	/* 0x1000..0x1001 7.1 CA0108-IAT cards */
479d056fa04SAlexander Leidinger 	{0x1102, 0x0008, 0x1102, 0x1000, "SB????", "Audigy 2 LS", HAS_AC97 | HAS_51 | IS_CA0108 | DIGITAL_ONLY},
480d056fa04SAlexander Leidinger 	{0x1102, 0x0008, 0x1102, 0x1001, "SB0400", "Audigy 2 Value", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
481d056fa04SAlexander Leidinger 	{0x1102, 0x0008, 0x1102, 0x1021, "SB0610", "Audigy 4", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
482d056fa04SAlexander Leidinger 
483d056fa04SAlexander Leidinger 	{0x1102, 0x0008, 0x1102, 0x2001, "SB0530", "Audigy 2 ZS CardBus", HAS_AC97 | HAS_71 | IS_CA0108 | IS_CARDBUS},
484d056fa04SAlexander Leidinger 
485d056fa04SAlexander Leidinger 	{0x1102, 0x0008, 0x0000, 0x0000, "SB????", "Audigy 2 Value (Unknown model)", HAS_AC97 | HAS_51 | IS_CA0108},
486d056fa04SAlexander Leidinger };
487d056fa04SAlexander Leidinger /* Unsupported cards */
488d056fa04SAlexander Leidinger 
489d056fa04SAlexander Leidinger static struct emu_hwinfo emu_bad_cards[] = {
490d056fa04SAlexander Leidinger 	/* APS cards should be possible to support */
491d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x4001, "EMUAPS", "E-mu APS", 0},
492d056fa04SAlexander Leidinger 	{0x1102, 0x0002, 0x1102, 0x4002, "EMUAPS", "E-mu APS", 0},
493d056fa04SAlexander Leidinger 	{0x1102, 0x0004, 0x1102, 0x4001, "EMU???", "E-mu 1212m [4001]", 0},
494d056fa04SAlexander Leidinger 	/* Similar-named ("Live!" or "Audigy") cards on different chipsets */
495d056fa04SAlexander Leidinger 	{0x1102, 0x8064, 0x0000, 0x0000, "SB0100", "SBLive! 5.1 OEM", 0},
496d056fa04SAlexander Leidinger 	{0x1102, 0x0006, 0x0000, 0x0000, "SB0200", "DELL OEM SBLive! Value", 0},
497d056fa04SAlexander Leidinger 	{0x1102, 0x0007, 0x0000, 0x0000, "SB0310", "Audigy LS", 0},
498d056fa04SAlexander Leidinger };
499d056fa04SAlexander Leidinger 
500d056fa04SAlexander Leidinger /*
501d056fa04SAlexander Leidinger  * Get best known information about device.
502d056fa04SAlexander Leidinger  */
503f856af04SAlexander Leidinger static unsigned int
504d056fa04SAlexander Leidinger emu_getcard(device_t dev)
505d056fa04SAlexander Leidinger {
506d056fa04SAlexander Leidinger 	uint16_t device;
507d056fa04SAlexander Leidinger 	uint16_t subdevice;
508d056fa04SAlexander Leidinger 	int n_cards;
509f856af04SAlexander Leidinger 	unsigned int thiscard;
510d056fa04SAlexander Leidinger 	int i;
511d056fa04SAlexander Leidinger 
512d056fa04SAlexander Leidinger 	device = pci_read_config(dev, PCIR_DEVICE, /* bytes */ 2);
513d056fa04SAlexander Leidinger 	subdevice = pci_read_config(dev, PCIR_SUBDEV_0, /* bytes */ 2);
514d056fa04SAlexander Leidinger 
515d056fa04SAlexander Leidinger 	n_cards = sizeof(emu_cards) / sizeof(struct emu_hwinfo);
516f856af04SAlexander Leidinger 	thiscard = 0;
517f856af04SAlexander Leidinger 	for (i = 1; i < n_cards; i++) {
518d056fa04SAlexander Leidinger 		if (device == emu_cards[i].device) {
519d056fa04SAlexander Leidinger 			if (subdevice == emu_cards[i].subdevice) {
520d056fa04SAlexander Leidinger 				thiscard = i;
521d056fa04SAlexander Leidinger 				break;
522d056fa04SAlexander Leidinger 			}
523d056fa04SAlexander Leidinger 			if (0x0000 == emu_cards[i].subdevice) {
524d056fa04SAlexander Leidinger 				thiscard = i;
525d056fa04SAlexander Leidinger 				/* don't break, we can get more specific card
526d056fa04SAlexander Leidinger 				 * later in the list */
527d056fa04SAlexander Leidinger 			}
528d056fa04SAlexander Leidinger 		}
529d056fa04SAlexander Leidinger 	}
530d056fa04SAlexander Leidinger 
531d056fa04SAlexander Leidinger 	n_cards = sizeof(emu_bad_cards) / sizeof(struct emu_hwinfo);
532d056fa04SAlexander Leidinger 	for (i = 0; i < n_cards; i++) {
533d056fa04SAlexander Leidinger 		if (device == emu_bad_cards[i].device) {
534d056fa04SAlexander Leidinger 			if (subdevice == emu_bad_cards[i].subdevice) {
535f856af04SAlexander Leidinger 				thiscard = 0;
536d056fa04SAlexander Leidinger 				break;
537d056fa04SAlexander Leidinger 			}
538d056fa04SAlexander Leidinger 			if (0x0000 == emu_bad_cards[i].subdevice) {
539f856af04SAlexander Leidinger 				thiscard = 0;
540d056fa04SAlexander Leidinger 				break;	/* we avoid all this cards */
541d056fa04SAlexander Leidinger 			}
542d056fa04SAlexander Leidinger 		}
543d056fa04SAlexander Leidinger 	}
544d056fa04SAlexander Leidinger 	return (thiscard);
545d056fa04SAlexander Leidinger }
546d056fa04SAlexander Leidinger 
547d056fa04SAlexander Leidinger 
548d056fa04SAlexander Leidinger /*
549d056fa04SAlexander Leidinger  * Base hardware interface are 32 (Audigy) or 64 (Audigy2) registers.
550d056fa04SAlexander Leidinger  * Some of them are used directly, some of them provide pointer / data pairs.
551d056fa04SAlexander Leidinger  */
552d056fa04SAlexander Leidinger static uint32_t
553d056fa04SAlexander Leidinger emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
554d056fa04SAlexander Leidinger {
555d056fa04SAlexander Leidinger 
556d056fa04SAlexander Leidinger 	KASSERT(sc != NULL, ("emu_rd: NULL sc"));
557d056fa04SAlexander Leidinger 	switch (size) {
558d056fa04SAlexander Leidinger 	case 1:
559d056fa04SAlexander Leidinger 		return (bus_space_read_1(sc->st, sc->sh, regno));
560d056fa04SAlexander Leidinger 	case 2:
561d056fa04SAlexander Leidinger 		return (bus_space_read_2(sc->st, sc->sh, regno));
562d056fa04SAlexander Leidinger 	case 4:
563d056fa04SAlexander Leidinger 		return (bus_space_read_4(sc->st, sc->sh, regno));
564d056fa04SAlexander Leidinger 	}
565d056fa04SAlexander Leidinger 	return (0xffffffff);
566d056fa04SAlexander Leidinger }
567d056fa04SAlexander Leidinger 
568d056fa04SAlexander Leidinger static void
569d056fa04SAlexander Leidinger emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
570d056fa04SAlexander Leidinger {
571d056fa04SAlexander Leidinger 
572d056fa04SAlexander Leidinger 	KASSERT(sc != NULL, ("emu_rd: NULL sc"));
573d056fa04SAlexander Leidinger 	switch (size) {
574d056fa04SAlexander Leidinger 	case 1:
575d056fa04SAlexander Leidinger 		bus_space_write_1(sc->st, sc->sh, regno, data);
576d056fa04SAlexander Leidinger 		break;
577d056fa04SAlexander Leidinger 	case 2:
578d056fa04SAlexander Leidinger 		bus_space_write_2(sc->st, sc->sh, regno, data);
579d056fa04SAlexander Leidinger 		break;
580d056fa04SAlexander Leidinger 	case 4:
581d056fa04SAlexander Leidinger 		bus_space_write_4(sc->st, sc->sh, regno, data);
582d056fa04SAlexander Leidinger 		break;
583d056fa04SAlexander Leidinger 	}
584d056fa04SAlexander Leidinger }
585d056fa04SAlexander Leidinger /*
586d056fa04SAlexander Leidinger  * PTR / DATA interface. Access to EMU10Kx is made
587d056fa04SAlexander Leidinger  * via (channel, register) pair. Some registers are channel-specific,
588d056fa04SAlexander Leidinger  * some not.
589d056fa04SAlexander Leidinger  */
590d056fa04SAlexander Leidinger uint32_t
591d056fa04SAlexander Leidinger emu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg)
592d056fa04SAlexander Leidinger {
593d056fa04SAlexander Leidinger 	uint32_t ptr, val, mask, size, offset;
594d056fa04SAlexander Leidinger 
595d056fa04SAlexander Leidinger 	ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK);
596d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
597d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, PTR, ptr, 4);
598d056fa04SAlexander Leidinger 	val = emu_rd_nolock(sc, DATA, 4);
599d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
600d056fa04SAlexander Leidinger 	/*
601d056fa04SAlexander Leidinger 	 * XXX Some register numbers has data size and offset encoded in
602d056fa04SAlexander Leidinger 	 * it to get only part of 32bit register. This use is not described
603d056fa04SAlexander Leidinger 	 * in register name, be careful!
604d056fa04SAlexander Leidinger 	 */
605d056fa04SAlexander Leidinger 	if (reg & 0xff000000) {
606d056fa04SAlexander Leidinger 		size = (reg >> 24) & 0x3f;
607d056fa04SAlexander Leidinger 		offset = (reg >> 16) & 0x1f;
608d056fa04SAlexander Leidinger 		mask = ((1 << size) - 1) << offset;
609d056fa04SAlexander Leidinger 		val &= mask;
610d056fa04SAlexander Leidinger 		val >>= offset;
611d056fa04SAlexander Leidinger 	}
612d056fa04SAlexander Leidinger 	return (val);
613d056fa04SAlexander Leidinger }
614d056fa04SAlexander Leidinger 
615d056fa04SAlexander Leidinger void
616d056fa04SAlexander Leidinger emu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data)
617d056fa04SAlexander Leidinger {
618d056fa04SAlexander Leidinger 	uint32_t ptr, mask, size, offset;
619d056fa04SAlexander Leidinger 	ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK);
620d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
621d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, PTR, ptr, 4);
622d056fa04SAlexander Leidinger 	/*
623d056fa04SAlexander Leidinger 	 * XXX Another kind of magic encoding in register number. This can
624d056fa04SAlexander Leidinger 	 * give you side effect - it will read previous data from register
625d056fa04SAlexander Leidinger 	 * and change only required bits.
626d056fa04SAlexander Leidinger 	 */
627d056fa04SAlexander Leidinger 	if (reg & 0xff000000) {
628d056fa04SAlexander Leidinger 		size = (reg >> 24) & 0x3f;
629d056fa04SAlexander Leidinger 		offset = (reg >> 16) & 0x1f;
630d056fa04SAlexander Leidinger 		mask = ((1 << size) - 1) << offset;
631d056fa04SAlexander Leidinger 		data <<= offset;
632d056fa04SAlexander Leidinger 		data &= mask;
633d056fa04SAlexander Leidinger 		data |= emu_rd_nolock(sc, DATA, 4) & ~mask;
634d056fa04SAlexander Leidinger 	}
635d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, DATA, data, 4);
636d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
637d056fa04SAlexander Leidinger }
638d056fa04SAlexander Leidinger /*
639d056fa04SAlexander Leidinger  * PTR2 / DATA2 interface. Access to P16v is made
640d056fa04SAlexander Leidinger  * via (channel, register) pair. Some registers are channel-specific,
641d056fa04SAlexander Leidinger  * some not. This interface is supported by CA0102 and CA0108 chips only.
642d056fa04SAlexander Leidinger  */
643d056fa04SAlexander Leidinger uint32_t
644d056fa04SAlexander Leidinger emu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg)
645d056fa04SAlexander Leidinger {
646d056fa04SAlexander Leidinger 	uint32_t val;
647d056fa04SAlexander Leidinger 
648d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
649d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4);
650d056fa04SAlexander Leidinger 	val = emu_rd_nolock(sc, DATA2, 4);
651d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
652d056fa04SAlexander Leidinger 	return (val);
653d056fa04SAlexander Leidinger }
654d056fa04SAlexander Leidinger 
655d056fa04SAlexander Leidinger void
656d056fa04SAlexander Leidinger emu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data)
657d056fa04SAlexander Leidinger {
658d056fa04SAlexander Leidinger 
659d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
660d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4);
661d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, DATA2, data, 4);
662d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
663d056fa04SAlexander Leidinger }
664d056fa04SAlexander Leidinger /*
665d056fa04SAlexander Leidinger  * XXX CardBus interface. Not tested on any real hardware.
666d056fa04SAlexander Leidinger  */
667d056fa04SAlexander Leidinger static void
668d056fa04SAlexander Leidinger emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data)
669d056fa04SAlexander Leidinger {
670d056fa04SAlexander Leidinger 	uint32_t val;
671d056fa04SAlexander Leidinger 
672d056fa04SAlexander Leidinger 	/* 0x38 is IPE3 (CD S/PDIF interrupt pending register) on CA0102 Seems
673d056fa04SAlexander Leidinger 	 * to be some reg/value accessible kind of config register on CardBus
674d056fa04SAlexander Leidinger 	 * CA0108, with value(?) in top 16 bit, address(?) in low 16 */
675d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
676d056fa04SAlexander Leidinger 	val = emu_rd_nolock(sc, 0x38, 4);
677d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, 0x38, data, 4);
678d056fa04SAlexander Leidinger 	val = emu_rd_nolock(sc, 0x38, 4);
679d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
680d056fa04SAlexander Leidinger }
681d056fa04SAlexander Leidinger 
682d056fa04SAlexander Leidinger /*
683d056fa04SAlexander Leidinger  * Direct hardware register access
684d056fa04SAlexander Leidinger  */
685d056fa04SAlexander Leidinger void
686d056fa04SAlexander Leidinger emu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
687d056fa04SAlexander Leidinger {
688d056fa04SAlexander Leidinger 
689d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
690d056fa04SAlexander Leidinger 	emu_wr_nolock(sc, regno, data, size);
691d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
692d056fa04SAlexander Leidinger }
693d056fa04SAlexander Leidinger 
694d056fa04SAlexander Leidinger uint32_t
695d056fa04SAlexander Leidinger emu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
696d056fa04SAlexander Leidinger {
697d056fa04SAlexander Leidinger 	uint32_t rd;
698d056fa04SAlexander Leidinger 
699d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
700d056fa04SAlexander Leidinger 	rd = emu_rd_nolock(sc, regno, size);
701d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
702d056fa04SAlexander Leidinger 	return (rd);
703d056fa04SAlexander Leidinger }
704d056fa04SAlexander Leidinger 
705d056fa04SAlexander Leidinger /*
706d056fa04SAlexander Leidinger  * Enabling IR MIDI messages is another kind of black magic. It just
707d056fa04SAlexander Leidinger  * has to be made this way. It really do it.
708d056fa04SAlexander Leidinger  */
709d056fa04SAlexander Leidinger void
710d056fa04SAlexander Leidinger emu_enable_ir(struct emu_sc_info *sc)
711d056fa04SAlexander Leidinger {
712d056fa04SAlexander Leidinger 	uint32_t iocfg;
713d056fa04SAlexander Leidinger 
714d056fa04SAlexander Leidinger 	mtx_lock(&sc->rw);
715d056fa04SAlexander Leidinger 	if (sc->is_emu10k2 || sc->is_ca0102) {
716d056fa04SAlexander Leidinger 		iocfg = emu_rd_nolock(sc, A_IOCFG, 2);
717d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT2, 2);
718d056fa04SAlexander Leidinger 		DELAY(500);
719d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, 2);
720d056fa04SAlexander Leidinger 		DELAY(500);
721d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1, 2);
722d056fa04SAlexander Leidinger 		DELAY(100);
723d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, A_IOCFG, iocfg, 2);
724d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Audigy IR MIDI events enabled.\n");
725d056fa04SAlexander Leidinger 		sc->enable_ir = 1;
726d056fa04SAlexander Leidinger 	}
727d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
728d056fa04SAlexander Leidinger 		iocfg = emu_rd_nolock(sc, HCFG, 4);
729d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT2, 4);
730d056fa04SAlexander Leidinger 		DELAY(500);
731d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT1 | HCFG_GPOUT2, 4);
732d056fa04SAlexander Leidinger 		DELAY(100);
733d056fa04SAlexander Leidinger 		emu_wr_nolock(sc, HCFG, iocfg, 4);
734d056fa04SAlexander Leidinger 		device_printf(sc->dev, "SB Live! IR MIDI events enabled.\n");
735d056fa04SAlexander Leidinger 		sc->enable_ir = 1;
736d056fa04SAlexander Leidinger 	}
737d056fa04SAlexander Leidinger 	mtx_unlock(&sc->rw);
738d056fa04SAlexander Leidinger }
739d056fa04SAlexander Leidinger 
740d056fa04SAlexander Leidinger 
741d056fa04SAlexander Leidinger /*
742d056fa04SAlexander Leidinger  * emu_timer_ - HW timer managment
743d056fa04SAlexander Leidinger  */
744d056fa04SAlexander Leidinger int
745d056fa04SAlexander Leidinger emu_timer_create(struct emu_sc_info *sc)
746d056fa04SAlexander Leidinger {
747d056fa04SAlexander Leidinger 	int i, timer;
748d056fa04SAlexander Leidinger 
749d056fa04SAlexander Leidinger 	timer = -1;
750d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
751d056fa04SAlexander Leidinger 		if (sc->timer[i] == 0) {
752d056fa04SAlexander Leidinger 			sc->timer[i] = -1;	/* disable it */
753d056fa04SAlexander Leidinger 			timer = i;
754d056fa04SAlexander Leidinger 			return (timer);
755d056fa04SAlexander Leidinger 		}
756d056fa04SAlexander Leidinger 
757d056fa04SAlexander Leidinger 	return (-1);
758d056fa04SAlexander Leidinger }
759d056fa04SAlexander Leidinger 
760d056fa04SAlexander Leidinger int
761d056fa04SAlexander Leidinger emu_timer_set(struct emu_sc_info *sc, int timer, int delay)
762d056fa04SAlexander Leidinger {
763d056fa04SAlexander Leidinger 	int i;
764d056fa04SAlexander Leidinger 
765f856af04SAlexander Leidinger 	if(timer < 0)
766f856af04SAlexander Leidinger 		return (-1);
767f856af04SAlexander Leidinger 
768d056fa04SAlexander Leidinger 	RANGE(delay, 16, 1024);
769f856af04SAlexander Leidinger 	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
770d056fa04SAlexander Leidinger 
771d056fa04SAlexander Leidinger 	sc->timer[timer] = delay;
772d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
773d056fa04SAlexander Leidinger 		if (sc->timerinterval > sc->timer[i])
774d056fa04SAlexander Leidinger 			sc->timerinterval = sc->timer[i];
775d056fa04SAlexander Leidinger 
776d056fa04SAlexander Leidinger 	emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
777d056fa04SAlexander Leidinger 	return (timer);
778d056fa04SAlexander Leidinger }
779d056fa04SAlexander Leidinger 
780d056fa04SAlexander Leidinger int
781d056fa04SAlexander Leidinger emu_timer_enable(struct emu_sc_info *sc, int timer, int go)
782d056fa04SAlexander Leidinger {
783d056fa04SAlexander Leidinger 	uint32_t x;
784d056fa04SAlexander Leidinger 	int ena_int;
785d056fa04SAlexander Leidinger 	int i;
786d056fa04SAlexander Leidinger 
787f856af04SAlexander Leidinger 	if(timer < 0)
788f856af04SAlexander Leidinger 		return (-1);
789f856af04SAlexander Leidinger 
790f856af04SAlexander Leidinger 	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
791f856af04SAlexander Leidinger 
792d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
793d056fa04SAlexander Leidinger 
794d056fa04SAlexander Leidinger 	if ((go == 1) && (sc->timer[timer] < 0))
795d056fa04SAlexander Leidinger 		sc->timer[timer] = -sc->timer[timer];
796d056fa04SAlexander Leidinger 	if ((go == 0) && (sc->timer[timer] > 0))
797d056fa04SAlexander Leidinger 		sc->timer[timer] = -sc->timer[timer];
798d056fa04SAlexander Leidinger 
799d056fa04SAlexander Leidinger 	ena_int = 0;
800d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
801d056fa04SAlexander Leidinger 		if (sc->timerinterval > sc->timer[i])
802d056fa04SAlexander Leidinger 			sc->timerinterval = sc->timer[i];
803d056fa04SAlexander Leidinger 		if (sc->timer[i] > 0)
804d056fa04SAlexander Leidinger 			ena_int = 1;
805d056fa04SAlexander Leidinger 	}
806d056fa04SAlexander Leidinger 
807d056fa04SAlexander Leidinger 	emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
808d056fa04SAlexander Leidinger 
809d056fa04SAlexander Leidinger 	if (ena_int == 1) {
810d056fa04SAlexander Leidinger 		x = emu_rd(sc, INTE, 4);
811d056fa04SAlexander Leidinger 		x |= INTE_INTERVALTIMERENB;
812d056fa04SAlexander Leidinger 		emu_wr(sc, INTE, x, 4);
813d056fa04SAlexander Leidinger 	} else {
814d056fa04SAlexander Leidinger 		x = emu_rd(sc, INTE, 4);
815d056fa04SAlexander Leidinger 		x &= ~INTE_INTERVALTIMERENB;
816d056fa04SAlexander Leidinger 		emu_wr(sc, INTE, x, 4);
817d056fa04SAlexander Leidinger 	}
818d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
819d056fa04SAlexander Leidinger 	return (0);
820d056fa04SAlexander Leidinger }
821d056fa04SAlexander Leidinger 
822d056fa04SAlexander Leidinger int
823d056fa04SAlexander Leidinger emu_timer_clear(struct emu_sc_info *sc, int timer)
824d056fa04SAlexander Leidinger {
825f856af04SAlexander Leidinger 	if(timer < 0)
826f856af04SAlexander Leidinger 		return (-1);
827f856af04SAlexander Leidinger 
828f856af04SAlexander Leidinger 	RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
829f856af04SAlexander Leidinger 
830d056fa04SAlexander Leidinger 	emu_timer_enable(sc, timer, 0);
831d056fa04SAlexander Leidinger 
832d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
833d056fa04SAlexander Leidinger 	if (sc->timer[timer] != 0)
834d056fa04SAlexander Leidinger 		sc->timer[timer] = 0;
835d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
836d056fa04SAlexander Leidinger 
837d056fa04SAlexander Leidinger 	return (timer);
838d056fa04SAlexander Leidinger }
839d056fa04SAlexander Leidinger 
840d056fa04SAlexander Leidinger /*
841d056fa04SAlexander Leidinger  * emu_intr_ - HW interrupt handler managment
842d056fa04SAlexander Leidinger  */
843d056fa04SAlexander Leidinger int
844d056fa04SAlexander Leidinger emu_intr_register(struct emu_sc_info *sc, uint32_t inte_mask, uint32_t intr_mask, uint32_t(*func) (void *softc, uint32_t irq), void *isc)
845d056fa04SAlexander Leidinger {
846d056fa04SAlexander Leidinger 	int i;
847d056fa04SAlexander Leidinger 	uint32_t x;
848d056fa04SAlexander Leidinger 
849d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
850d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
851d056fa04SAlexander Leidinger 		if (sc->ihandler[i].inte_mask == 0) {
852d056fa04SAlexander Leidinger 			sc->ihandler[i].inte_mask = inte_mask;
853d056fa04SAlexander Leidinger 			sc->ihandler[i].intr_mask = intr_mask;
854d056fa04SAlexander Leidinger 			sc->ihandler[i].softc = isc;
855d056fa04SAlexander Leidinger 			sc->ihandler[i].irq_func = func;
856d056fa04SAlexander Leidinger 			x = emu_rd(sc, INTE, 4);
857d056fa04SAlexander Leidinger 			x |= inte_mask;
858d056fa04SAlexander Leidinger 			emu_wr(sc, INTE, x, 4);
859d056fa04SAlexander Leidinger 			mtx_unlock(&sc->lock);
860f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
861f856af04SAlexander Leidinger 			device_printf(sc->dev, "ihandle %d registered\n", i);
862f856af04SAlexander Leidinger #endif
863d056fa04SAlexander Leidinger 			return (i);
864d056fa04SAlexander Leidinger 		}
865d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
866f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
867f856af04SAlexander Leidinger 	device_printf(sc->dev, "ihandle not registered\n");
868f856af04SAlexander Leidinger #endif
869d056fa04SAlexander Leidinger 	return (-1);
870d056fa04SAlexander Leidinger }
871d056fa04SAlexander Leidinger 
872d056fa04SAlexander Leidinger int
873d056fa04SAlexander Leidinger emu_intr_unregister(struct emu_sc_info *sc, int hnumber)
874d056fa04SAlexander Leidinger {
875d056fa04SAlexander Leidinger 	uint32_t x;
876d056fa04SAlexander Leidinger 	int i;
877d056fa04SAlexander Leidinger 
878d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
879d056fa04SAlexander Leidinger 
880d056fa04SAlexander Leidinger 	if (sc->ihandler[hnumber].inte_mask == 0) {
881d056fa04SAlexander Leidinger 		mtx_unlock(&sc->lock);
882d056fa04SAlexander Leidinger 		return (-1);
883d056fa04SAlexander Leidinger 	}
884d056fa04SAlexander Leidinger 
885d056fa04SAlexander Leidinger 	x = emu_rd(sc, INTE, 4);
886d056fa04SAlexander Leidinger 	x &= ~sc->ihandler[hnumber].inte_mask;
887d056fa04SAlexander Leidinger 
888d056fa04SAlexander Leidinger 	sc->ihandler[hnumber].inte_mask = 0;
889d056fa04SAlexander Leidinger 	sc->ihandler[hnumber].intr_mask = 0;
890d056fa04SAlexander Leidinger 	sc->ihandler[hnumber].softc = NULL;
891d056fa04SAlexander Leidinger 	sc->ihandler[hnumber].irq_func = NULL;
892d056fa04SAlexander Leidinger 
893d056fa04SAlexander Leidinger 	/* other interupt handlers may use this INTE value */
894d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
895d056fa04SAlexander Leidinger 		if (sc->ihandler[i].inte_mask != 0)
896d056fa04SAlexander Leidinger 			x |= sc->ihandler[i].inte_mask;
897d056fa04SAlexander Leidinger 
898d056fa04SAlexander Leidinger 	emu_wr(sc, INTE, x, 4);
899d056fa04SAlexander Leidinger 
900d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
901d056fa04SAlexander Leidinger 	return (hnumber);
902d056fa04SAlexander Leidinger }
903d056fa04SAlexander Leidinger 
904d056fa04SAlexander Leidinger static void
905d056fa04SAlexander Leidinger emu_intr(void *p)
906d056fa04SAlexander Leidinger {
907d056fa04SAlexander Leidinger 	struct emu_sc_info *sc = (struct emu_sc_info *)p;
908d056fa04SAlexander Leidinger 	uint32_t stat, ack;
909d056fa04SAlexander Leidinger 	int i;
910d056fa04SAlexander Leidinger 
911d056fa04SAlexander Leidinger 	for (;;) {
912d056fa04SAlexander Leidinger 		stat = emu_rd(sc, IPR, 4);
913d056fa04SAlexander Leidinger 		ack = 0;
914d056fa04SAlexander Leidinger 		if (stat == 0)
915d056fa04SAlexander Leidinger 			break;
916d056fa04SAlexander Leidinger 		emu_wr(sc, IPR, stat, 4);
917d056fa04SAlexander Leidinger 		for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
918d056fa04SAlexander Leidinger 			if ((((sc->ihandler[i].intr_mask) & stat) != 0) &&
919d056fa04SAlexander Leidinger 			    (((void *)sc->ihandler[i].irq_func) != NULL)) {
920d056fa04SAlexander Leidinger 				ack |= sc->ihandler[i].irq_func(sc->ihandler[i].softc,
921d056fa04SAlexander Leidinger 				    (sc->ihandler[i].intr_mask) & stat);
922d056fa04SAlexander Leidinger 			}
923d056fa04SAlexander Leidinger 		}
924f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
925f856af04SAlexander Leidinger 	if(stat & (~ack))
926f856af04SAlexander Leidinger 		device_printf(sc->dev, "Unhandled interrupt: %08x\n", stat & (~ack));
927f856af04SAlexander Leidinger #endif
928d056fa04SAlexander Leidinger 	}
929d056fa04SAlexander Leidinger 
930d056fa04SAlexander Leidinger 	if ((sc->is_ca0102) || (sc->is_ca0108))
931d056fa04SAlexander Leidinger 		for (;;) {
932d056fa04SAlexander Leidinger 			stat = emu_rd(sc, IPR2, 4);
933d056fa04SAlexander Leidinger 			ack = 0;
934d056fa04SAlexander Leidinger 			if (stat == 0)
935d056fa04SAlexander Leidinger 				break;
936d056fa04SAlexander Leidinger 			emu_wr(sc, IPR2, stat, 4);
937d056fa04SAlexander Leidinger 			device_printf(sc->dev, "IPR2: %08x\n", stat);
938d056fa04SAlexander Leidinger 			break;	/* to avoid infinite loop. shoud be removed
939d056fa04SAlexander Leidinger 				 * after completion of P16V interface. */
940d056fa04SAlexander Leidinger 		}
941d056fa04SAlexander Leidinger 
942d056fa04SAlexander Leidinger 	if (sc->is_ca0102)
943d056fa04SAlexander Leidinger 		for (;;) {
944d056fa04SAlexander Leidinger 			stat = emu_rd(sc, IPR3, 4);
945d056fa04SAlexander Leidinger 			ack = 0;
946d056fa04SAlexander Leidinger 			if (stat == 0)
947d056fa04SAlexander Leidinger 				break;
948d056fa04SAlexander Leidinger 			emu_wr(sc, IPR3, stat, 4);
949d056fa04SAlexander Leidinger 			device_printf(sc->dev, "IPR3: %08x\n", stat);
950d056fa04SAlexander Leidinger 			break;	/* to avoid infinite loop. should be removed
951d056fa04SAlexander Leidinger 				 * after completion of S/PDIF interface */
952d056fa04SAlexander Leidinger 		}
953d056fa04SAlexander Leidinger }
954d056fa04SAlexander Leidinger 
955d056fa04SAlexander Leidinger 
956d056fa04SAlexander Leidinger /*
957d056fa04SAlexander Leidinger  * Get data from private emu10kx structure for PCM buffer allocation.
958d056fa04SAlexander Leidinger  * Used by PCM code only.
959d056fa04SAlexander Leidinger  */
960d056fa04SAlexander Leidinger bus_dma_tag_t
961d056fa04SAlexander Leidinger emu_gettag(struct emu_sc_info *sc)
962d056fa04SAlexander Leidinger {
963d056fa04SAlexander Leidinger 	return (sc->mem.dmat);
964d056fa04SAlexander Leidinger }
965d056fa04SAlexander Leidinger 
966d056fa04SAlexander Leidinger static void
967d056fa04SAlexander Leidinger emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error)
968d056fa04SAlexander Leidinger {
969d056fa04SAlexander Leidinger 	bus_addr_t *phys = (bus_addr_t *) arg;
970d056fa04SAlexander Leidinger 
971d056fa04SAlexander Leidinger 	*phys = error ? 0 : (bus_addr_t) segs->ds_addr;
972d056fa04SAlexander Leidinger 
973d056fa04SAlexander Leidinger 	if (bootverbose) {
974d056fa04SAlexander Leidinger 		printf("emu10kx: setmap (%lx, %lx), nseg=%d, error=%d\n",
975d056fa04SAlexander Leidinger 		    (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
976d056fa04SAlexander Leidinger 		    nseg, error);
977d056fa04SAlexander Leidinger 	}
978d056fa04SAlexander Leidinger }
979d056fa04SAlexander Leidinger 
980d056fa04SAlexander Leidinger static void *
981d056fa04SAlexander Leidinger emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr)
982d056fa04SAlexander Leidinger {
983d056fa04SAlexander Leidinger 	void *dmabuf;
984d056fa04SAlexander Leidinger 	bus_dmamap_t map;
985d056fa04SAlexander Leidinger 
986d056fa04SAlexander Leidinger 	*addr = 0;
987d056fa04SAlexander Leidinger 	if (bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map))
988d056fa04SAlexander Leidinger 		return (NULL);
989d056fa04SAlexander Leidinger 	if (bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0) || !*addr)
990d056fa04SAlexander Leidinger 		return (NULL);
991d056fa04SAlexander Leidinger 	return (dmabuf);
992d056fa04SAlexander Leidinger }
993d056fa04SAlexander Leidinger 
994d056fa04SAlexander Leidinger static void
995d056fa04SAlexander Leidinger emu_free(struct emu_mem *mem, void *dmabuf)
996d056fa04SAlexander Leidinger {
997d056fa04SAlexander Leidinger 	bus_dmamem_free(mem->dmat, dmabuf, NULL);
998d056fa04SAlexander Leidinger }
999d056fa04SAlexander Leidinger 
1000d056fa04SAlexander Leidinger static void *
1001d056fa04SAlexander Leidinger emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *owner)
1002d056fa04SAlexander Leidinger {
1003d056fa04SAlexander Leidinger 	uint32_t blksz, start, idx, ofs, tmp, found;
1004d056fa04SAlexander Leidinger 	struct emu_memblk *blk;
1005d056fa04SAlexander Leidinger 	void *membuf;
1006d056fa04SAlexander Leidinger 
1007d056fa04SAlexander Leidinger 	blksz = sz / EMUPAGESIZE;
1008d056fa04SAlexander Leidinger 	if (sz > (blksz * EMUPAGESIZE))
1009d056fa04SAlexander Leidinger 		blksz++;
1010e4c87b14SAlexander Leidinger 	if (blksz > EMU_MAX_BUFSZ / EMUPAGESIZE)
1011e4c87b14SAlexander Leidinger 		return (NULL);
1012d056fa04SAlexander Leidinger 	/* find a free block in the bitmap */
1013d056fa04SAlexander Leidinger 	found = 0;
1014d056fa04SAlexander Leidinger 	start = 1;
1015e4c87b14SAlexander Leidinger 	while (!found && start + blksz < EMU_MAXPAGES) {
1016d056fa04SAlexander Leidinger 		found = 1;
1017d056fa04SAlexander Leidinger 		for (idx = start; idx < start + blksz; idx++)
1018d056fa04SAlexander Leidinger 			if (mem->bmap[idx >> 3] & (1 << (idx & 7)))
1019d056fa04SAlexander Leidinger 				found = 0;
1020d056fa04SAlexander Leidinger 		if (!found)
1021d056fa04SAlexander Leidinger 			start++;
1022d056fa04SAlexander Leidinger 	}
1023d056fa04SAlexander Leidinger 	if (!found)
1024d056fa04SAlexander Leidinger 		return (NULL);
1025d056fa04SAlexander Leidinger 	blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
1026d056fa04SAlexander Leidinger 	if (blk == NULL)
1027d056fa04SAlexander Leidinger 		return (NULL);
1028d056fa04SAlexander Leidinger 	bzero(blk, sizeof(*blk));
1029d056fa04SAlexander Leidinger 	membuf = emu_malloc(mem, sz, &blk->buf_addr);
1030d056fa04SAlexander Leidinger 	*addr = blk->buf_addr;
1031d056fa04SAlexander Leidinger 	if (membuf == NULL) {
1032d056fa04SAlexander Leidinger 		free(blk, M_DEVBUF);
1033d056fa04SAlexander Leidinger 		return (NULL);
1034d056fa04SAlexander Leidinger 	}
1035d056fa04SAlexander Leidinger 	blk->buf = membuf;
1036d056fa04SAlexander Leidinger 	blk->pte_start = start;
1037d056fa04SAlexander Leidinger 	blk->pte_size = blksz;
1038d056fa04SAlexander Leidinger 	strncpy(blk->owner, owner, 15);
1039d056fa04SAlexander Leidinger 	blk->owner[15] = '\0';
1040d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
1041d056fa04SAlexander Leidinger 	printf("emu10kx emu_memalloc: allocating %d for %s\n", blk->pte_size, blk->owner);
1042d056fa04SAlexander Leidinger #endif
1043d056fa04SAlexander Leidinger 	ofs = 0;
1044d056fa04SAlexander Leidinger 	for (idx = start; idx < start + blksz; idx++) {
1045d056fa04SAlexander Leidinger 		mem->bmap[idx >> 3] |= 1 << (idx & 7);
1046d056fa04SAlexander Leidinger 		tmp = (uint32_t) (u_long) ((uint8_t *) blk->buf_addr + ofs);
1047d056fa04SAlexander Leidinger 		mem->ptb_pages[idx] = (tmp << 1) | idx;
1048d056fa04SAlexander Leidinger 		ofs += EMUPAGESIZE;
1049d056fa04SAlexander Leidinger 	}
1050d056fa04SAlexander Leidinger 	SLIST_INSERT_HEAD(&mem->blocks, blk, link);
1051d056fa04SAlexander Leidinger 	return (membuf);
1052d056fa04SAlexander Leidinger }
1053d056fa04SAlexander Leidinger 
1054d056fa04SAlexander Leidinger static int
1055d056fa04SAlexander Leidinger emu_memfree(struct emu_mem *mem, void *membuf)
1056d056fa04SAlexander Leidinger {
1057d056fa04SAlexander Leidinger 	uint32_t idx, tmp;
1058d056fa04SAlexander Leidinger 	struct emu_memblk *blk, *i;
1059d056fa04SAlexander Leidinger 
1060d056fa04SAlexander Leidinger 	blk = NULL;
1061d056fa04SAlexander Leidinger 	SLIST_FOREACH(i, &mem->blocks, link) {
1062d056fa04SAlexander Leidinger 		if (i->buf == membuf)
1063d056fa04SAlexander Leidinger 			blk = i;
1064d056fa04SAlexander Leidinger 	}
1065d056fa04SAlexander Leidinger 	if (blk == NULL)
1066d056fa04SAlexander Leidinger 		return (EINVAL);
1067d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
1068d056fa04SAlexander Leidinger 	printf("emu10kx emu_memfree: freeing %d for %s\n", blk->pte_size, blk->owner);
1069d056fa04SAlexander Leidinger #endif
1070d056fa04SAlexander Leidinger 	SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
1071d056fa04SAlexander Leidinger 	emu_free(mem, membuf);
1072d056fa04SAlexander Leidinger 	tmp = (uint32_t) (mem->silent_page_addr) << 1;
1073d056fa04SAlexander Leidinger 	for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
1074d056fa04SAlexander Leidinger 		mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
1075d056fa04SAlexander Leidinger 		mem->ptb_pages[idx] = tmp | idx;
1076d056fa04SAlexander Leidinger 	}
1077d056fa04SAlexander Leidinger 	free(blk, M_DEVBUF);
1078d056fa04SAlexander Leidinger 	return (0);
1079d056fa04SAlexander Leidinger }
1080d056fa04SAlexander Leidinger 
1081d056fa04SAlexander Leidinger static int
1082d056fa04SAlexander Leidinger emu_memstart(struct emu_mem *mem, void *membuf)
1083d056fa04SAlexander Leidinger {
1084d056fa04SAlexander Leidinger 	struct emu_memblk *blk, *i;
1085d056fa04SAlexander Leidinger 
1086d056fa04SAlexander Leidinger 	blk = NULL;
1087d056fa04SAlexander Leidinger 	SLIST_FOREACH(i, &mem->blocks, link) {
1088d056fa04SAlexander Leidinger 		if (i->buf == membuf)
1089d056fa04SAlexander Leidinger 			blk = i;
1090d056fa04SAlexander Leidinger 	}
1091d056fa04SAlexander Leidinger 	if (blk == NULL)
1092d056fa04SAlexander Leidinger 		return (-1);
1093d056fa04SAlexander Leidinger 	return (blk->pte_start);
1094d056fa04SAlexander Leidinger }
1095d056fa04SAlexander Leidinger 
1096d056fa04SAlexander Leidinger 
1097d056fa04SAlexander Leidinger static uint32_t
1098d056fa04SAlexander Leidinger emu_rate_to_pitch(uint32_t rate)
1099d056fa04SAlexander Leidinger {
1100d056fa04SAlexander Leidinger 	static uint32_t logMagTable[128] = {
1101d056fa04SAlexander Leidinger 		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
1102d056fa04SAlexander Leidinger 		0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
1103d056fa04SAlexander Leidinger 		0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
1104d056fa04SAlexander Leidinger 		0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
1105d056fa04SAlexander Leidinger 		0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
1106d056fa04SAlexander Leidinger 		0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
1107d056fa04SAlexander Leidinger 		0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
1108d056fa04SAlexander Leidinger 		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
1109d056fa04SAlexander Leidinger 		0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
1110d056fa04SAlexander Leidinger 		0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
1111d056fa04SAlexander Leidinger 		0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
1112d056fa04SAlexander Leidinger 		0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
1113d056fa04SAlexander Leidinger 		0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
1114d056fa04SAlexander Leidinger 		0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
1115d056fa04SAlexander Leidinger 		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
1116d056fa04SAlexander Leidinger 		0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
1117d056fa04SAlexander Leidinger 	};
1118d056fa04SAlexander Leidinger 	static char logSlopeTable[128] = {
1119d056fa04SAlexander Leidinger 		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
1120d056fa04SAlexander Leidinger 		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
1121d056fa04SAlexander Leidinger 		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
1122d056fa04SAlexander Leidinger 		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
1123d056fa04SAlexander Leidinger 		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
1124d056fa04SAlexander Leidinger 		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
1125d056fa04SAlexander Leidinger 		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
1126d056fa04SAlexander Leidinger 		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
1127d056fa04SAlexander Leidinger 		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
1128d056fa04SAlexander Leidinger 		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
1129d056fa04SAlexander Leidinger 		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
1130d056fa04SAlexander Leidinger 		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
1131d056fa04SAlexander Leidinger 		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
1132d056fa04SAlexander Leidinger 		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
1133d056fa04SAlexander Leidinger 		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
1134d056fa04SAlexander Leidinger 		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
1135d056fa04SAlexander Leidinger 	};
1136d056fa04SAlexander Leidinger 	int i;
1137d056fa04SAlexander Leidinger 
1138d056fa04SAlexander Leidinger 	if (rate == 0)
1139d056fa04SAlexander Leidinger 		return (0);
1140d056fa04SAlexander Leidinger 	rate *= 11185;		/* Scale 48000 to 0x20002380 */
1141d056fa04SAlexander Leidinger 	for (i = 31; i > 0; i--) {
1142d056fa04SAlexander Leidinger 		if (rate & 0x80000000) {	/* Detect leading "1" */
1143d056fa04SAlexander Leidinger 			return (((uint32_t) (i - 15) << 20) +
1144d056fa04SAlexander Leidinger 			    logMagTable[0x7f & (rate >> 24)] +
1145d056fa04SAlexander Leidinger 			    (0x7f & (rate >> 17)) *
1146d056fa04SAlexander Leidinger 			    logSlopeTable[0x7f & (rate >> 24)]);
1147d056fa04SAlexander Leidinger 		}
1148d056fa04SAlexander Leidinger 		rate <<= 1;
1149d056fa04SAlexander Leidinger 	}
1150d056fa04SAlexander Leidinger 	/* NOTREACHED */
1151d056fa04SAlexander Leidinger 	return (0);
1152d056fa04SAlexander Leidinger }
1153d056fa04SAlexander Leidinger 
1154d056fa04SAlexander Leidinger static uint32_t
1155d056fa04SAlexander Leidinger emu_rate_to_linearpitch(uint32_t rate)
1156d056fa04SAlexander Leidinger {
1157d056fa04SAlexander Leidinger 	rate = (rate << 8) / 375;
1158d056fa04SAlexander Leidinger 	return ((rate >> 1) + (rate & 1));
1159d056fa04SAlexander Leidinger }
1160d056fa04SAlexander Leidinger 
1161d056fa04SAlexander Leidinger struct emu_voice *
1162d056fa04SAlexander Leidinger emu_valloc(struct emu_sc_info *sc)
1163d056fa04SAlexander Leidinger {
1164d056fa04SAlexander Leidinger 	struct emu_voice *v;
1165d056fa04SAlexander Leidinger 	int i;
1166d056fa04SAlexander Leidinger 
1167d056fa04SAlexander Leidinger 	v = NULL;
1168d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
1169d056fa04SAlexander Leidinger 	for (i = 0; i < NUM_G && sc->voice[i].busy; i++);
1170d056fa04SAlexander Leidinger 	if (i < NUM_G) {
1171d056fa04SAlexander Leidinger 		v = &sc->voice[i];
1172d056fa04SAlexander Leidinger 		v->busy = 1;
1173d056fa04SAlexander Leidinger 	}
1174d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
1175d056fa04SAlexander Leidinger 	return (v);
1176d056fa04SAlexander Leidinger }
1177d056fa04SAlexander Leidinger 
1178d056fa04SAlexander Leidinger void
1179d056fa04SAlexander Leidinger emu_vfree(struct emu_sc_info *sc, struct emu_voice *v)
1180d056fa04SAlexander Leidinger {
1181d056fa04SAlexander Leidinger 	int i, r;
1182d056fa04SAlexander Leidinger 
1183d056fa04SAlexander Leidinger 	mtx_lock(&sc->lock);
1184d056fa04SAlexander Leidinger 	for (i = 0; i < NUM_G; i++) {
1185d056fa04SAlexander Leidinger 		if (v == &sc->voice[i] && sc->voice[i].busy) {
1186d056fa04SAlexander Leidinger 			v->busy = 0;
1187d056fa04SAlexander Leidinger 			/* XXX What we should do with mono channels?
1188d056fa04SAlexander Leidinger 			 See -pcm.c emupchan_init for other side of
1189d056fa04SAlexander Leidinger 			 this problem */
1190d056fa04SAlexander Leidinger 			if (v->slave != NULL)
1191d056fa04SAlexander Leidinger 				r = emu_memfree(&sc->mem, v->vbuf);
1192d056fa04SAlexander Leidinger 		}
1193d056fa04SAlexander Leidinger 	}
1194d056fa04SAlexander Leidinger 	mtx_unlock(&sc->lock);
1195d056fa04SAlexander Leidinger }
1196d056fa04SAlexander Leidinger 
1197d056fa04SAlexander Leidinger int
1198d056fa04SAlexander Leidinger emu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s,
1199d056fa04SAlexander Leidinger     uint32_t sz, struct snd_dbuf *b)
1200d056fa04SAlexander Leidinger {
1201d056fa04SAlexander Leidinger 	void *vbuf;
1202d056fa04SAlexander Leidinger 	bus_addr_t tmp_addr;
1203d056fa04SAlexander Leidinger 
1204d056fa04SAlexander Leidinger 	vbuf = emu_memalloc(&sc->mem, sz, &tmp_addr, "vinit");
1205d056fa04SAlexander Leidinger 	if (vbuf == NULL)
1206d056fa04SAlexander Leidinger 		return (ENOMEM);
1207d056fa04SAlexander Leidinger 	if (b != NULL)
1208d056fa04SAlexander Leidinger 		sndbuf_setup(b, vbuf, sz);
1209d056fa04SAlexander Leidinger 	m->start = emu_memstart(&sc->mem, vbuf) * EMUPAGESIZE;
1210d056fa04SAlexander Leidinger 	if (m->start == -1) {
1211d056fa04SAlexander Leidinger 		emu_memfree(&sc->mem, vbuf);
1212d056fa04SAlexander Leidinger 		return (ENOMEM);
1213d056fa04SAlexander Leidinger 	}
1214d056fa04SAlexander Leidinger 	m->end = m->start + sz;
1215d056fa04SAlexander Leidinger 	m->speed = 0;
1216d056fa04SAlexander Leidinger 	m->b16 = 0;
1217d056fa04SAlexander Leidinger 	m->stereo = 0;
1218d056fa04SAlexander Leidinger 	m->running = 0;
1219d056fa04SAlexander Leidinger 	m->ismaster = 1;
1220d056fa04SAlexander Leidinger 	m->vol = 0xff;
1221d056fa04SAlexander Leidinger 	m->buf = tmp_addr;
1222d056fa04SAlexander Leidinger 	m->vbuf = vbuf;
1223d056fa04SAlexander Leidinger 	m->slave = s;
1224d056fa04SAlexander Leidinger 	if (s != NULL) {
1225d056fa04SAlexander Leidinger 		s->start = m->start;
1226d056fa04SAlexander Leidinger 		s->end = m->end;
1227d056fa04SAlexander Leidinger 		s->speed = 0;
1228d056fa04SAlexander Leidinger 		s->b16 = 0;
1229d056fa04SAlexander Leidinger 		s->stereo = 0;
1230d056fa04SAlexander Leidinger 		s->running = 0;
1231d056fa04SAlexander Leidinger 		s->ismaster = 0;
1232d056fa04SAlexander Leidinger 		s->vol = m->vol;
1233d056fa04SAlexander Leidinger 		s->buf = m->buf;
1234d056fa04SAlexander Leidinger 		s->vbuf = NULL;
1235d056fa04SAlexander Leidinger 		s->slave = NULL;
1236d056fa04SAlexander Leidinger 	}
1237d056fa04SAlexander Leidinger 	return (0);
1238d056fa04SAlexander Leidinger }
1239d056fa04SAlexander Leidinger 
1240d056fa04SAlexander Leidinger void
1241d056fa04SAlexander Leidinger emu_vsetup(struct emu_voice *v, int fmt, int spd)
1242d056fa04SAlexander Leidinger {
1243d056fa04SAlexander Leidinger 	if (fmt) {
1244d056fa04SAlexander Leidinger 		v->b16 = (fmt & AFMT_16BIT) ? 1 : 0;
1245d056fa04SAlexander Leidinger 		v->stereo = (fmt & AFMT_STEREO) ? 1 : 0;
1246d056fa04SAlexander Leidinger 		if (v->slave != NULL) {
1247d056fa04SAlexander Leidinger 			v->slave->b16 = v->b16;
1248d056fa04SAlexander Leidinger 			v->slave->stereo = v->stereo;
1249d056fa04SAlexander Leidinger 		}
1250d056fa04SAlexander Leidinger 	}
1251d056fa04SAlexander Leidinger 	if (spd) {
1252d056fa04SAlexander Leidinger 		v->speed = spd;
1253d056fa04SAlexander Leidinger 		if (v->slave != NULL)
1254d056fa04SAlexander Leidinger 			v->slave->speed = v->speed;
1255d056fa04SAlexander Leidinger 	}
1256d056fa04SAlexander Leidinger }
1257d056fa04SAlexander Leidinger 
1258d056fa04SAlexander Leidinger void
1259d056fa04SAlexander Leidinger emu_vroute(struct emu_sc_info *sc, struct emu_route *rt,  struct emu_voice *v)
1260d056fa04SAlexander Leidinger {
1261d056fa04SAlexander Leidinger 	unsigned int routing[8], amounts[8];
1262d056fa04SAlexander Leidinger 	int i;
1263d056fa04SAlexander Leidinger 
1264d056fa04SAlexander Leidinger 	for (i = 0; i < 8; i++) {
1265d056fa04SAlexander Leidinger 		routing[i] = rt->routing_left[i];
1266d056fa04SAlexander Leidinger 		amounts[i] = rt->amounts_left[i];
1267d056fa04SAlexander Leidinger 	}
1268d056fa04SAlexander Leidinger 	if ((v->stereo) && (v->ismaster == 0))
1269d056fa04SAlexander Leidinger 		for (i = 0; i < 8; i++) {
1270d056fa04SAlexander Leidinger 			routing[i] = rt->routing_right[i];
1271d056fa04SAlexander Leidinger 			amounts[i] = rt->amounts_right[i];
1272d056fa04SAlexander Leidinger 		}
1273d056fa04SAlexander Leidinger 
1274d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
1275d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, FXRT, ((routing[3] << 12) |
1276d056fa04SAlexander Leidinger 		    (routing[2] << 8) |
1277d056fa04SAlexander Leidinger 		    (routing[1] << 4) |
1278d056fa04SAlexander Leidinger 		    (routing[0] << 0)) << 16);
1279d056fa04SAlexander Leidinger 	} else {
1280d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, A_FXRT1, (routing[3] << 24) |
1281d056fa04SAlexander Leidinger 		    (routing[2] << 16) |
1282d056fa04SAlexander Leidinger 		    (routing[1] << 8) |
1283d056fa04SAlexander Leidinger 		    (routing[0] << 0));
1284d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, A_FXRT2, (routing[7] << 24) |
1285d056fa04SAlexander Leidinger 		    (routing[6] << 16) |
1286d056fa04SAlexander Leidinger 		    (routing[5] << 8) |
1287d056fa04SAlexander Leidinger 		    (routing[4] << 0));
1288d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, (amounts[7] << 24) |
1289d056fa04SAlexander Leidinger 		    (amounts[6] << 26) |
1290d056fa04SAlexander Leidinger 		    (amounts[5] << 8) |
1291d056fa04SAlexander Leidinger 		    (amounts[4] << 0));
1292d056fa04SAlexander Leidinger 	}
1293d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, PTRX, (amounts[0] << 8) | (amounts[1] << 0));
1294d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, DSL, v->ea | (amounts[3] << 24));
1295d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, PSST, v->sa | (amounts[2] << 24));
1296d056fa04SAlexander Leidinger 	if ((v->stereo) && (v->slave != NULL))
1297d056fa04SAlexander Leidinger 		emu_vroute(sc, rt, v->slave);
1298d056fa04SAlexander Leidinger }
1299d056fa04SAlexander Leidinger 
1300d056fa04SAlexander Leidinger void
1301d056fa04SAlexander Leidinger emu_vwrite(struct emu_sc_info *sc, struct emu_voice *v)
1302d056fa04SAlexander Leidinger {
1303d056fa04SAlexander Leidinger 	int s;
1304d056fa04SAlexander Leidinger 	uint32_t am_2, am_3, start, val, silent_page;
1305d056fa04SAlexander Leidinger 
1306d056fa04SAlexander Leidinger 	s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
1307d056fa04SAlexander Leidinger 
1308d056fa04SAlexander Leidinger 	v->sa = v->start >> s;
1309d056fa04SAlexander Leidinger 	v->ea = v->end >> s;
1310d056fa04SAlexander Leidinger 
1311d056fa04SAlexander Leidinger 
1312d056fa04SAlexander Leidinger 	if (v->stereo) {
1313d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK);
1314d056fa04SAlexander Leidinger 	} else {
1315d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CPF, 0);
1316d056fa04SAlexander Leidinger 	}
1317d056fa04SAlexander Leidinger 	val = v->stereo ? 28 : 30;
1318d056fa04SAlexander Leidinger 	val *= v->b16 ? 1 : 2;
1319d056fa04SAlexander Leidinger 	start = v->sa + val;
1320d056fa04SAlexander Leidinger 
1321d056fa04SAlexander Leidinger 	am_3 = emu_rdptr(sc, v->vnum, DSL) & 0xff000000;
1322d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, DSL, v->ea | am_3);
1323d056fa04SAlexander Leidinger 	am_2 = emu_rdptr(sc, v->vnum, PSST) & 0xff000000;
1324d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, PSST, v->sa | am_2);
1325d056fa04SAlexander Leidinger 
1326d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT));
1327d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, Z1, 0);
1328d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, Z2, 0);
1329d056fa04SAlexander Leidinger 
1330d056fa04SAlexander Leidinger 	silent_page = ((uint32_t) (sc->mem.silent_page_addr) << 1) | MAP_PTI_MASK;
1331d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, MAPA, silent_page);
1332d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, MAPB, silent_page);
1333d056fa04SAlexander Leidinger 
1334d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK);
1335d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK);
1336d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, ATKHLDM, 0);
1337d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK);
1338d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000);
1339d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000);
1340d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, FMMOD, 0);
1341d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, TREMFRQ, 0);
1342d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, FM2FRQ2, 0);
1343d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, ENVVAL, 0x8000);
1344d056fa04SAlexander Leidinger 
1345d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, ATKHLDV, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK);
1346d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, ENVVOL, 0x8000);
1347d056fa04SAlexander Leidinger 
1348d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, PEFE_FILTERAMOUNT, 0x7f);
1349d056fa04SAlexander Leidinger 	emu_wrptr(sc, v->vnum, PEFE_PITCHAMOUNT, 0);
1350d056fa04SAlexander Leidinger 	if ((v->stereo) && (v->slave != NULL))
1351d056fa04SAlexander Leidinger 		emu_vwrite(sc, v->slave);
1352d056fa04SAlexander Leidinger }
1353d056fa04SAlexander Leidinger 
1354d056fa04SAlexander Leidinger static void
1355d056fa04SAlexander Leidinger emu_vstop(struct emu_sc_info *sc, char channel, int enable)
1356d056fa04SAlexander Leidinger {
1357d056fa04SAlexander Leidinger 	int reg;
1358d056fa04SAlexander Leidinger 
1359d056fa04SAlexander Leidinger 	reg = (channel & 0x20) ? SOLEH : SOLEL;
1360d056fa04SAlexander Leidinger 	channel &= 0x1f;
1361d056fa04SAlexander Leidinger 	reg |= 1 << 24;
1362d056fa04SAlexander Leidinger 	reg |= channel << 16;
1363d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, reg, enable);
1364d056fa04SAlexander Leidinger }
1365d056fa04SAlexander Leidinger 
1366d056fa04SAlexander Leidinger void
1367d056fa04SAlexander Leidinger emu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go)
1368d056fa04SAlexander Leidinger {
1369d056fa04SAlexander Leidinger 	uint32_t pitch_target, initial_pitch;
1370d056fa04SAlexander Leidinger 	uint32_t cra, cs, ccis;
1371d056fa04SAlexander Leidinger 	uint32_t sample, i;
1372d056fa04SAlexander Leidinger 
1373d056fa04SAlexander Leidinger 	if (go) {
1374d056fa04SAlexander Leidinger 		cra = 64;
1375d056fa04SAlexander Leidinger 		cs = v->stereo ? 4 : 2;
1376d056fa04SAlexander Leidinger 		ccis = v->stereo ? 28 : 30;
1377d056fa04SAlexander Leidinger 		ccis *= v->b16 ? 1 : 2;
1378d056fa04SAlexander Leidinger 		sample = v->b16 ? 0x00000000 : 0x80808080;
1379d056fa04SAlexander Leidinger 		for (i = 0; i < cs; i++)
1380d056fa04SAlexander Leidinger 			emu_wrptr(sc, v->vnum, CD0 + i, sample);
1381d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, 0);
1382d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CCR_READADDRESS, cra);
1383d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, ccis);
1384d056fa04SAlexander Leidinger 
1385d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, IFATN, 0xff00);
1386d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, VTFT, 0xffffffff);
1387d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CVCF, 0xffffffff);
1388d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, DCYSUSV, 0x00007f7f);
1389d056fa04SAlexander Leidinger 		emu_vstop(sc, v->vnum, 0);
1390d056fa04SAlexander Leidinger 
1391d056fa04SAlexander Leidinger 		pitch_target = emu_rate_to_linearpitch(v->speed);
1392d056fa04SAlexander Leidinger 		initial_pitch = emu_rate_to_pitch(v->speed) >> 8;
1393d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target);
1394d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target);
1395d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, IP, initial_pitch);
1396d056fa04SAlexander Leidinger 	} else {
1397d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, 0);
1398d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0);
1399d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, IFATN, 0xffff);
1400d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, VTFT, 0x0000ffff);
1401d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, CVCF, 0x0000ffff);
1402d056fa04SAlexander Leidinger 		emu_wrptr(sc, v->vnum, IP, 0);
1403d056fa04SAlexander Leidinger 		emu_vstop(sc, v->vnum, 1);
1404d056fa04SAlexander Leidinger 	}
1405d056fa04SAlexander Leidinger 	if ((v->stereo) && (v->slave != NULL))
1406d056fa04SAlexander Leidinger 		emu_vtrigger(sc, v->slave, go);
1407d056fa04SAlexander Leidinger }
1408d056fa04SAlexander Leidinger 
1409d056fa04SAlexander Leidinger int
1410d056fa04SAlexander Leidinger emu_vpos(struct emu_sc_info *sc, struct emu_voice *v)
1411d056fa04SAlexander Leidinger {
1412d056fa04SAlexander Leidinger 	int s, ptr;
1413d056fa04SAlexander Leidinger 
1414d056fa04SAlexander Leidinger 	s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0);
1415d056fa04SAlexander Leidinger 	ptr = (emu_rdptr(sc, v->vnum, CCCA_CURRADDR) - (v->start >> s)) << s;
1416d056fa04SAlexander Leidinger 	return (ptr & ~0x0000001f);
1417d056fa04SAlexander Leidinger }
1418d056fa04SAlexander Leidinger 
1419d056fa04SAlexander Leidinger 
1420d056fa04SAlexander Leidinger /* fx */
1421d056fa04SAlexander Leidinger static void
1422d056fa04SAlexander Leidinger emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data)
1423d056fa04SAlexander Leidinger {
1424d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, sc->code_base + pc, data);
1425d056fa04SAlexander Leidinger }
1426d056fa04SAlexander Leidinger 
1427d056fa04SAlexander Leidinger 
1428d056fa04SAlexander Leidinger static void
1429d056fa04SAlexander Leidinger emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc)
1430d056fa04SAlexander Leidinger {
1431d056fa04SAlexander Leidinger 	if ((*pc) + 1 > sc->code_size) {
1432d056fa04SAlexander Leidinger 		device_printf(sc->dev, "DSP CODE OVERRUN: attept to write past code_size (pc=%d)\n", (*pc));
1433d056fa04SAlexander Leidinger 		return;
1434d056fa04SAlexander Leidinger 	}
1435d056fa04SAlexander Leidinger 	emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y);
1436d056fa04SAlexander Leidinger 	emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w);
1437d056fa04SAlexander Leidinger 	(*pc)++;
1438d056fa04SAlexander Leidinger }
1439d056fa04SAlexander Leidinger 
1440d056fa04SAlexander Leidinger static int
1441d056fa04SAlexander Leidinger sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS)
1442d056fa04SAlexander Leidinger {
1443d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
1444d056fa04SAlexander Leidinger 	int	mixer_id;
1445d056fa04SAlexander Leidinger 	int	new_vol;
1446d056fa04SAlexander Leidinger 	int	err;
1447d056fa04SAlexander Leidinger 
1448d056fa04SAlexander Leidinger 	sc = arg1;
1449d056fa04SAlexander Leidinger 	mixer_id = arg2;
1450d056fa04SAlexander Leidinger 
1451d056fa04SAlexander Leidinger 	new_vol = emumix_get_volume(sc, mixer_id);
1452041b706bSDavid Malone 	err = sysctl_handle_int(oidp, &new_vol, 0, req);
1453d056fa04SAlexander Leidinger 
1454d056fa04SAlexander Leidinger 	if (err || req->newptr == NULL)
1455d056fa04SAlexander Leidinger 		return (err);
1456d056fa04SAlexander Leidinger 	if (new_vol < 0 || new_vol > 100)
1457d056fa04SAlexander Leidinger 		return (EINVAL);
1458d056fa04SAlexander Leidinger 	emumix_set_volume(sc, mixer_id, new_vol);
1459d056fa04SAlexander Leidinger 
1460d056fa04SAlexander Leidinger 	return (0);
1461d056fa04SAlexander Leidinger }
1462d056fa04SAlexander Leidinger 
1463d056fa04SAlexander Leidinger static int
1464d056fa04SAlexander Leidinger emu_addefxmixer(struct emu_sc_info *sc, const char *mix_name, const int mix_id, uint32_t defvolume)
1465d056fa04SAlexander Leidinger {
1466d056fa04SAlexander Leidinger 	int volgpr;
14674002c392SAlexander Leidinger 	char	sysctl_name[32];
1468d056fa04SAlexander Leidinger 
1469d056fa04SAlexander Leidinger 	volgpr = emu_rm_gpr_alloc(sc->rm, 1);
1470d056fa04SAlexander Leidinger 	emumix_set_fxvol(sc, volgpr, defvolume);
1471d056fa04SAlexander Leidinger 	/* Mixer controls with NULL mix_name are handled by AC97 emulation
1472d056fa04SAlexander Leidinger 	code or PCM mixer. */
1473d056fa04SAlexander Leidinger 	if (mix_name != NULL) {
14744002c392SAlexander Leidinger 		/* Temporary sysctls should start with underscore,
14754002c392SAlexander Leidinger 		 * see freebsd-current mailing list, emu10kx driver
1476e4c87b14SAlexander Leidinger 		 * discussion around 2006-05-24. */
14774002c392SAlexander Leidinger 		snprintf(sysctl_name, 32, "_%s", mix_name);
1478d056fa04SAlexander Leidinger 		SYSCTL_ADD_PROC(sc->ctx,
1479d056fa04SAlexander Leidinger 			SYSCTL_CHILDREN(sc->root),
14804002c392SAlexander Leidinger 			OID_AUTO, sysctl_name,
1481d056fa04SAlexander Leidinger 			CTLTYPE_INT | CTLFLAG_RW, sc, mix_id,
1482d056fa04SAlexander Leidinger 			sysctl_emu_mixer_control, "I","");
1483d056fa04SAlexander Leidinger 	}
1484d056fa04SAlexander Leidinger 
1485d056fa04SAlexander Leidinger 	return (volgpr);
1486d056fa04SAlexander Leidinger }
1487d056fa04SAlexander Leidinger 
1488d056fa04SAlexander Leidinger /* allocate cache GPRs that will hold mixed output channels
1489d056fa04SAlexander Leidinger  * and clear it on every DSP run.
1490d056fa04SAlexander Leidinger  */
1491d056fa04SAlexander Leidinger #define	EFX_CACHE(CACHE_IDX) do {				\
1492d056fa04SAlexander Leidinger 	sc->cache_gpr[CACHE_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \
1493d056fa04SAlexander Leidinger 	emu_addefxop(sc, ACC3, 					\
1494d056fa04SAlexander Leidinger 		GPR(sc->cache_gpr[CACHE_IDX]), 			\
1495d056fa04SAlexander Leidinger 		DSP_CONST(0), 					\
1496d056fa04SAlexander Leidinger 		DSP_CONST(0), 					\
1497d056fa04SAlexander Leidinger 		DSP_CONST(0), 					\
1498d056fa04SAlexander Leidinger 		&pc);						\
1499d056fa04SAlexander Leidinger } while (0)
1500d056fa04SAlexander Leidinger 
1501d056fa04SAlexander Leidinger /* Allocate GPR for volume control and route sound: OUT = OUT + IN * VOL */
1502d056fa04SAlexander Leidinger #define	EFX_ROUTE(TITLE, INP_NR, IN_GPR_IDX, OUT_CACHE_IDX, DEF) do { 	\
1503d056fa04SAlexander Leidinger 	sc->mixer_gpr[IN_GPR_IDX] = emu_addefxmixer(sc, TITLE, IN_GPR_IDX,  DEF); \
1504d056fa04SAlexander Leidinger 	sc->mixer_volcache[IN_GPR_IDX] = DEF; 			\
1505d056fa04SAlexander Leidinger 	emu_addefxop(sc, MACS, 					\
1506d056fa04SAlexander Leidinger 		GPR(sc->cache_gpr[OUT_CACHE_IDX]), 		\
1507d056fa04SAlexander Leidinger 		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1508d056fa04SAlexander Leidinger 		INP_NR,						\
1509d056fa04SAlexander Leidinger 		GPR(sc->mixer_gpr[IN_GPR_IDX]),			\
1510d056fa04SAlexander Leidinger 		&pc);						\
1511d056fa04SAlexander Leidinger } while (0)
1512d056fa04SAlexander Leidinger 
1513d056fa04SAlexander Leidinger /* allocate GPR, OUT = IN * VOL */
1514d056fa04SAlexander Leidinger #define	EFX_OUTPUT(TITLE,OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR, DEF) do {	\
1515d056fa04SAlexander Leidinger 	sc->mixer_gpr[OUT_GPR_IDX] = emu_addefxmixer(sc, TITLE, OUT_GPR_IDX, DEF); \
1516d056fa04SAlexander Leidinger 	sc->mixer_volcache[OUT_GPR_IDX] = DEF;			\
1517d056fa04SAlexander Leidinger 	emu_addefxop(sc, MACS,					\
1518d056fa04SAlexander Leidinger 		OUTP(OUTP_NR),					\
1519d056fa04SAlexander Leidinger 		DSP_CONST(0),					\
1520d056fa04SAlexander Leidinger 		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1521d056fa04SAlexander Leidinger 		GPR(sc->mixer_gpr[OUT_GPR_IDX]),		\
1522d056fa04SAlexander Leidinger 		&pc);						\
1523d056fa04SAlexander Leidinger } while (0)
1524d056fa04SAlexander Leidinger 
1525d056fa04SAlexander Leidinger /* like EFX_OUTPUT, but don't allocate mixer gpr */
1526d056fa04SAlexander Leidinger #define	EFX_OUTPUTD(OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR) do{	\
1527d056fa04SAlexander Leidinger 	emu_addefxop(sc, MACS,					\
1528d056fa04SAlexander Leidinger 		OUTP(OUTP_NR),					\
1529d056fa04SAlexander Leidinger 		DSP_CONST(0),					\
1530d056fa04SAlexander Leidinger 		GPR(sc->cache_gpr[OUT_CACHE_IDX]),		\
1531d056fa04SAlexander Leidinger 		GPR(sc->mixer_gpr[OUT_GPR_IDX]),		\
1532d056fa04SAlexander Leidinger 		&pc);						\
1533d056fa04SAlexander Leidinger } while(0)
1534d056fa04SAlexander Leidinger 
1535f856af04SAlexander Leidinger /* mute, if FLAG != 0 */
1536f856af04SAlexander Leidinger /* XXX */
1537f856af04SAlexander Leidinger #define EFX_MUTEIF(GPR_IDX, FLAG) do {				\
1538f856af04SAlexander Leidinger } while(0)
1539f856af04SAlexander Leidinger 
1540f856af04SAlexander Leidinger /* allocate dummy GPR. It's content will be used somewhere */
1541f856af04SAlexander Leidinger #define	EFX_DUMMY(DUMMY_IDX, DUMMY_VALUE) do {			\
1542f856af04SAlexander Leidinger 	sc->dummy_gpr[DUMMY_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \
1543f856af04SAlexander Leidinger 	emumix_set_gpr(sc, sc->dummy_gpr[DUMMY_IDX], DUMMY_VALUE);	\
1544f856af04SAlexander Leidinger 	emu_addefxop(sc, ACC3, 					\
1545f856af04SAlexander Leidinger 		FX2(DUMMY_IDX),					\
1546f856af04SAlexander Leidinger 		GPR(sc->dummy_gpr[DUMMY_IDX]),			\
1547f856af04SAlexander Leidinger 		DSP_CONST(0),					\
1548f856af04SAlexander Leidinger 		DSP_CONST(0),					\
1549f856af04SAlexander Leidinger 		&pc);						\
1550f856af04SAlexander Leidinger } while (0)
1551f856af04SAlexander Leidinger 
1552f856af04SAlexander Leidinger 
1553d056fa04SAlexander Leidinger static void
1554d056fa04SAlexander Leidinger emu_initefx(struct emu_sc_info *sc)
1555d056fa04SAlexander Leidinger {
1556f856af04SAlexander Leidinger 	unsigned int i;
1557d056fa04SAlexander Leidinger 	uint32_t pc;
1558d056fa04SAlexander Leidinger 
1559d056fa04SAlexander Leidinger 	/* stop DSP */
1560d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
1561d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, DBG, EMU10K1_DBG_SINGLE_STEP);
1562d056fa04SAlexander Leidinger 	} else {
1563d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
1564d056fa04SAlexander Leidinger 	}
1565d056fa04SAlexander Leidinger 
1566d056fa04SAlexander Leidinger 	/* code size is in instructions */
1567d056fa04SAlexander Leidinger 	pc = 0;
1568f856af04SAlexander Leidinger 	for (i = 0; i < sc->code_size; i++) {
1569d056fa04SAlexander Leidinger 		if (sc->is_emu10k1) {
1570d056fa04SAlexander Leidinger 			emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), &pc);
1571d056fa04SAlexander Leidinger 		} else {
1572d056fa04SAlexander Leidinger 			emu_addefxop(sc, SKIP, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0xf), DSP_CONST(0x0), &pc);
1573d056fa04SAlexander Leidinger 		}
1574d056fa04SAlexander Leidinger 	}
1575d056fa04SAlexander Leidinger 
1576d056fa04SAlexander Leidinger 	pc = 0;
1577d056fa04SAlexander Leidinger 
1578d056fa04SAlexander Leidinger 	/*
1579d056fa04SAlexander Leidinger 	 * DSP code below is not good, because:
1580d056fa04SAlexander Leidinger 	 * 1. It can be written smaller, if it can use DSP accumulator register
1581d056fa04SAlexander Leidinger 	 * instead of cache_gpr[].
1582d056fa04SAlexander Leidinger 	 * 2. It can be more careful when volume is 100%, because in DSP
1583d056fa04SAlexander Leidinger 	 * x*0x7fffffff may not be equal to x !
1584d056fa04SAlexander Leidinger 	 */
1585d056fa04SAlexander Leidinger 
1586d056fa04SAlexander Leidinger 	/* clean outputs */
1587f856af04SAlexander Leidinger 	for (i = 0; i < 16 ; i++) {
1588f856af04SAlexander Leidinger 		emu_addefxop(sc, ACC3, OUTP(i), DSP_CONST(0), DSP_CONST(0), DSP_CONST(0), &pc);
1589d056fa04SAlexander Leidinger 	}
1590d056fa04SAlexander Leidinger 
1591d056fa04SAlexander Leidinger 
1592d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
1593d056fa04SAlexander Leidinger 		EFX_CACHE(C_FRONT_L);
1594d056fa04SAlexander Leidinger 		EFX_CACHE(C_FRONT_R);
1595d056fa04SAlexander Leidinger 		EFX_CACHE(C_REC_L);
1596d056fa04SAlexander Leidinger 		EFX_CACHE(C_REC_R);
1597d056fa04SAlexander Leidinger 
1598d056fa04SAlexander Leidinger 		/* fx0 to front/record, 100%/muted by default */
1599d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_front_l", FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
1600d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_front_r", FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
1601d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_rec_l", FX(0), M_FX0_REC_L, C_REC_L, 0);
1602d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_rec_r", FX(1), M_FX1_REC_R, C_REC_R, 0);
1603d056fa04SAlexander Leidinger 
1604d056fa04SAlexander Leidinger 		/* in0, from AC97 codec output */
1605d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_front_l", INP(IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 0);
1606d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_front_r", INP(IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 0);
1607d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_rec_l", INP(IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
1608d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_rec_r", INP(IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
1609d056fa04SAlexander Leidinger 
1610d056fa04SAlexander Leidinger 		/* in1, from CD S/PDIF */
1611d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_front_l", INP(IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
1612f856af04SAlexander Leidinger 		EFX_MUTEIF(M_IN1_FRONT_L, CDSPDIFMUTE);
1613d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_front_r", INP(IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
1614f856af04SAlexander Leidinger 		EFX_MUTEIF(M_IN1_FRONT_R, CDSPDIFMUTE);
1615d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_rec_l", INP(IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
1616f856af04SAlexander Leidinger 		EFX_MUTEIF(M_IN1_REC_L, CDSPDIFMUTE);
1617d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_rec_r", INP(IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
1618f856af04SAlexander Leidinger 		EFX_MUTEIF(M_IN1_REC_L, CDSPDIFMUTE);
1619f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG_OUTPUTS
1620d056fa04SAlexander Leidinger 		/* in2, ZoomVide (???) */
1621d056fa04SAlexander Leidinger 		EFX_ROUTE("zoom_front_l", INP(IN_ZOOM_L), M_IN2_FRONT_L, C_FRONT_L, 0);
1622d056fa04SAlexander Leidinger 		EFX_ROUTE("zoom_front_r", INP(IN_ZOOM_R), M_IN2_FRONT_R, C_FRONT_R, 0);
1623d056fa04SAlexander Leidinger 		EFX_ROUTE("zoom_rec_l", INP(IN_ZOOM_L), M_IN2_REC_L, C_REC_L, 0);
1624d056fa04SAlexander Leidinger 		EFX_ROUTE("zoom_rec_r", INP(IN_ZOOM_R), M_IN2_REC_R, C_REC_R, 0);
1625d056fa04SAlexander Leidinger #endif
1626f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG_OUTPUTS
1627d056fa04SAlexander Leidinger 		/* in3, TOSLink (???) */
1628d056fa04SAlexander Leidinger 		EFX_ROUTE("toslink_front_l", INP(IN_TOSLINK_L), M_IN3_FRONT_L, C_FRONT_L, 0);
1629d056fa04SAlexander Leidinger 		EFX_ROUTE("toslink_front_r", INP(IN_TOSLINK_R), M_IN3_FRONT_R, C_FRONT_R, 0);
1630d056fa04SAlexander Leidinger 		EFX_ROUTE("toslink_rec_l", INP(IN_TOSLINK_L), M_IN3_REC_L, C_REC_L, 0);
1631d056fa04SAlexander Leidinger 		EFX_ROUTE("toslink_rec_r", INP(IN_TOSLINK_R), M_IN3_REC_R, C_REC_R, 0);
1632d056fa04SAlexander Leidinger #endif
1633d056fa04SAlexander Leidinger 		/* in4, LineIn  */
1634d056fa04SAlexander Leidinger 		EFX_ROUTE("linein_front_l", INP(IN_LINE1_L), M_IN4_FRONT_L, C_FRONT_L, 0);
1635d056fa04SAlexander Leidinger 		EFX_ROUTE("linein_front_r", INP(IN_LINE1_R), M_IN4_FRONT_R, C_FRONT_R, 0);
1636d056fa04SAlexander Leidinger 		EFX_ROUTE("linein_rec_l", INP(IN_LINE1_L), M_IN4_REC_L, C_REC_L, 0);
1637d056fa04SAlexander Leidinger 		EFX_ROUTE("linein_rec_r", INP(IN_LINE1_R), M_IN4_REC_R, C_REC_R, 0);
1638d056fa04SAlexander Leidinger 
1639d056fa04SAlexander Leidinger 		/* in5, on-card S/PDIF */
1640d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_front_l", INP(IN_COAX_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
1641d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_front_r", INP(IN_COAX_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
1642d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_rec_l", INP(IN_COAX_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
1643d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_rec_r", INP(IN_COAX_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
1644d056fa04SAlexander Leidinger 
1645d056fa04SAlexander Leidinger 		/* in6, Line2 on Live!Drive */
1646d056fa04SAlexander Leidinger 		EFX_ROUTE("line2_front_l", INP(IN_LINE2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
1647d056fa04SAlexander Leidinger 		EFX_ROUTE("line2_front_r", INP(IN_LINE2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
1648d056fa04SAlexander Leidinger 		EFX_ROUTE("line2_rec_l", INP(IN_LINE2_L), M_IN6_REC_L, C_REC_L, 0);
1649d056fa04SAlexander Leidinger 		EFX_ROUTE("line2_rec_r", INP(IN_LINE2_R), M_IN6_REC_R, C_REC_R, 0);
1650f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG_OUTPUTS
1651d056fa04SAlexander Leidinger 		/* in7, unknown */
1652d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
1653d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
1654d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
1655d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
1656d056fa04SAlexander Leidinger #endif
1657f856af04SAlexander Leidinger 		/* front output to hedaphones and both analog and digital */
1658d056fa04SAlexander Leidinger 		EFX_OUTPUT("master_front_l", C_FRONT_L, M_MASTER_FRONT_L, OUT_AC97_L, 100);
1659d056fa04SAlexander Leidinger 		EFX_OUTPUT("master_front_r", C_FRONT_R, M_MASTER_FRONT_R, OUT_AC97_R, 100);
1660f856af04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_HEADPHONE_L);
1661f856af04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_HEADPHONE_R);
1662d056fa04SAlexander Leidinger 
1663d056fa04SAlexander Leidinger 		/* rec output to "ADC" */
1664d056fa04SAlexander Leidinger 		EFX_OUTPUT("master_rec_l", C_REC_L, M_MASTER_REC_L, OUT_ADC_REC_L, 100);
1665d056fa04SAlexander Leidinger 		EFX_OUTPUT("master_rec_r", C_REC_R, M_MASTER_REC_R, OUT_ADC_REC_R, 100);
1666d056fa04SAlexander Leidinger #ifdef	SND_EMU10KX_MULTICHANNEL
1667d056fa04SAlexander Leidinger 		/*
1668d056fa04SAlexander Leidinger 		 * Additional channel volume is controlled by mixer in
1669d056fa04SAlexander Leidinger 		 * emu_dspmixer_set() in -pcm.c
1670d056fa04SAlexander Leidinger 		 */
1671d056fa04SAlexander Leidinger 
1672d056fa04SAlexander Leidinger 		/* fx2/3 (pcm1) to rear */
1673d056fa04SAlexander Leidinger 		EFX_CACHE(C_REAR_L);
1674d056fa04SAlexander Leidinger 		EFX_CACHE(C_REAR_R);
1675d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
1676d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
1677d056fa04SAlexander Leidinger 
1678d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, OUT_REAR_L, 100);
1679d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, OUT_REAR_R, 100);
1680f856af04SAlexander Leidinger 		if (sc->has_51) {
1681f856af04SAlexander Leidinger 			/* fx4 (pcm2) to center */
1682f856af04SAlexander Leidinger 			EFX_CACHE(C_CENTER);
1683f856af04SAlexander Leidinger 			EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
1684f856af04SAlexander Leidinger 			EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100);
1685f856af04SAlexander Leidinger #if 0
1686f856af04SAlexander Leidinger 			/* XXX in digital mode (default) this should be muted because
1687f856af04SAlexander Leidinger 			this output is shared with digital out */
1688f856af04SAlexander Leidinger 			EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER);
1689f856af04SAlexander Leidinger #endif
1690f856af04SAlexander Leidinger 			/* fx5 (pcm3) to sub */
1691f856af04SAlexander Leidinger 			EFX_CACHE(C_SUB);
1692f856af04SAlexander Leidinger 			EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
1693f856af04SAlexander Leidinger 			EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100);
1694f856af04SAlexander Leidinger #if 0
1695f856af04SAlexander Leidinger 			/* XXX in digital mode (default) this should be muted because
1696f856af04SAlexander Leidinger 			this output is shared with digital out */
1697f856af04SAlexander Leidinger 			EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB);
1698f856af04SAlexander Leidinger #endif
1699f856af04SAlexander Leidinger 		}
1700f856af04SAlexander Leidinger #ifdef	SND_EMU10KX_MCH_RECORDING
1701f856af04SAlexander Leidinger 	/* MCH RECORDING , hight 16 slots. On 5.1 cards first 4 slots are used
1702f856af04SAlexander Leidinger 	as outputs and already filled with data */
1703f856af04SAlexander Leidinger 	for(i = (sc->has_51 ? 4 : 0); i < 16; i++) {
1704f856af04SAlexander Leidinger 		/* XXX fill with dummy data */
1705f856af04SAlexander Leidinger 		EFX_DUMMY(i,i*0x10000);
1706f856af04SAlexander Leidinger 		emu_addefxop(sc, ACC3,
1707f856af04SAlexander Leidinger 				FX2(i),
1708f856af04SAlexander Leidinger 				DSP_CONST(0),
1709f856af04SAlexander Leidinger 				DSP_CONST(0),
1710f856af04SAlexander Leidinger 				GPR(sc->dummy_gpr[i]),
1711f856af04SAlexander Leidinger 				&pc);
1712f856af04SAlexander Leidinger 
1713f856af04SAlexander Leidinger 		}
1714f856af04SAlexander Leidinger #endif
1715d056fa04SAlexander Leidinger #else	/* !SND_EMU10KX_MULTICHANNEL */
1716d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_REAR_L);
1717d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_REAR_R);
1718d056fa04SAlexander Leidinger #endif
1719d056fa04SAlexander Leidinger 	} else /* emu10k2 and later */ {
1720d056fa04SAlexander Leidinger 		EFX_CACHE(C_FRONT_L);
1721d056fa04SAlexander Leidinger 		EFX_CACHE(C_FRONT_R);
1722d056fa04SAlexander Leidinger 		EFX_CACHE(C_REC_L);
1723d056fa04SAlexander Leidinger 		EFX_CACHE(C_REC_R);
1724d056fa04SAlexander Leidinger 
1725d056fa04SAlexander Leidinger 		/* fx0 to front/record, 100%/muted by default */
1726d056fa04SAlexander Leidinger 		/*
1727d056fa04SAlexander Leidinger 		 * FRONT_[L|R] is controlled by AC97 emulation in
1728d056fa04SAlexander Leidinger 		 * emu_ac97_[read|write]_emulation in -pcm.c
1729d056fa04SAlexander Leidinger 		 */
1730d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
1731d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
1732d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_rec_l", FX(0), M_FX0_REC_L, C_REC_L, 0);
1733d056fa04SAlexander Leidinger 		EFX_ROUTE("pcm_rec_r", FX(1), M_FX1_REC_R, C_REC_R, 0);
1734d056fa04SAlexander Leidinger 
1735d056fa04SAlexander Leidinger 		/* in0, from AC97 codec output */
1736d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_front_l", INP(A_IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 100);
1737d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_front_r", INP(A_IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 100);
1738d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_rec_l", INP(A_IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
1739d056fa04SAlexander Leidinger 		EFX_ROUTE("ac97_rec_r", INP(A_IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
1740d056fa04SAlexander Leidinger 
1741d056fa04SAlexander Leidinger 		/* in1, from CD S/PDIF */
1742d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_front_l", INP(A_IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
1743d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_front_r", INP(A_IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
1744d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_rec_l", INP(A_IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
1745d056fa04SAlexander Leidinger 		EFX_ROUTE("cdspdif_rec_r", INP(A_IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
1746d056fa04SAlexander Leidinger 
1747d056fa04SAlexander Leidinger 		/* in2, optical & coax S/PDIF on AudigyDrive*/
1748f856af04SAlexander Leidinger 		/* XXX Should be muted when GPRSCS valid stream == 0 */
1749d056fa04SAlexander Leidinger 		EFX_ROUTE("ospdif_front_l", INP(A_IN_O_SPDIF_L), M_IN2_FRONT_L, C_FRONT_L, 0);
1750d056fa04SAlexander Leidinger 		EFX_ROUTE("ospdif_front_r", INP(A_IN_O_SPDIF_R), M_IN2_FRONT_R, C_FRONT_R, 0);
1751d056fa04SAlexander Leidinger 		EFX_ROUTE("ospdif_rec_l", INP(A_IN_O_SPDIF_L), M_IN2_REC_L, C_REC_L, 0);
1752d056fa04SAlexander Leidinger 		EFX_ROUTE("ospdif_rec_r", INP(A_IN_O_SPDIF_R), M_IN2_REC_R, C_REC_R, 0);
1753f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG_OUTPUTS
1754d056fa04SAlexander Leidinger 		/* in3, unknown */
1755d056fa04SAlexander Leidinger 		EFX_ROUTE("in3_front_l", INP(0x6), M_IN3_FRONT_L, C_FRONT_L, 0);
1756d056fa04SAlexander Leidinger 		EFX_ROUTE("in3_front_r", INP(0x7), M_IN3_FRONT_R, C_FRONT_R, 0);
1757d056fa04SAlexander Leidinger 		EFX_ROUTE("in3_rec_l", INP(0x6), M_IN3_REC_L, C_REC_L, 0);
1758d056fa04SAlexander Leidinger 		EFX_ROUTE("in3_rec_r", INP(0x7), M_IN3_REC_R, C_REC_R, 0);
1759d056fa04SAlexander Leidinger #endif
1760d056fa04SAlexander Leidinger 		/* in4, LineIn 2 on AudigyDrive */
1761d056fa04SAlexander Leidinger 		EFX_ROUTE("linein2_front_l", INP(A_IN_LINE2_L), M_IN4_FRONT_L, C_FRONT_L, 0);
1762d056fa04SAlexander Leidinger 		EFX_ROUTE("linein2_front_r", INP(A_IN_LINE2_R), M_IN4_FRONT_R, C_FRONT_R, 0);
1763d056fa04SAlexander Leidinger 		EFX_ROUTE("linein2_rec_l", INP(A_IN_LINE2_L), M_IN4_REC_L, C_REC_L, 0);
1764d056fa04SAlexander Leidinger 		EFX_ROUTE("linein2_rec_r", INP(A_IN_LINE2_R), M_IN4_REC_R, C_REC_R, 0);
1765d056fa04SAlexander Leidinger 
1766d056fa04SAlexander Leidinger 		/* in5, on-card S/PDIF */
1767d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_front_l", INP(A_IN_R_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
1768d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_front_r", INP(A_IN_R_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
1769d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_rec_l", INP(A_IN_R_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
1770d056fa04SAlexander Leidinger 		EFX_ROUTE("spdif_rec_r", INP(A_IN_R_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
1771d056fa04SAlexander Leidinger 
1772d056fa04SAlexander Leidinger 		/* in6, AUX2 on AudigyDrive */
1773d056fa04SAlexander Leidinger 		EFX_ROUTE("aux2_front_l", INP(A_IN_AUX2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
1774d056fa04SAlexander Leidinger 		EFX_ROUTE("aux2_front_r", INP(A_IN_AUX2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
1775d056fa04SAlexander Leidinger 		EFX_ROUTE("aux2_rec_l", INP(A_IN_AUX2_L), M_IN6_REC_L, C_REC_L, 0);
1776d056fa04SAlexander Leidinger 		EFX_ROUTE("aux2_rec_r", INP(A_IN_AUX2_R), M_IN6_REC_R, C_REC_R, 0);
1777f856af04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG_OUTPUTS
1778d056fa04SAlexander Leidinger 		/* in7, unknown */
1779d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
1780d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
1781d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
1782d056fa04SAlexander Leidinger 		EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
1783d056fa04SAlexander Leidinger #endif
1784d056fa04SAlexander Leidinger 		/* front output to headphones and  alog and digital *front */
1785d056fa04SAlexander Leidinger 		/* volume controlled by AC97 emulation */
1786d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_FRONT_L, 100);
1787d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_FRONT_R, 100);
1788d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_FRONT_L);
1789d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_FRONT_R);
1790d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_HPHONE_L);
1791d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_HPHONE_R);
1792d056fa04SAlexander Leidinger 
1793d056fa04SAlexander Leidinger 		/* rec output to "ADC" */
1794d056fa04SAlexander Leidinger 		/* volume controlled by AC97 emulation */
1795d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REC_L, M_MASTER_REC_L, A_OUT_ADC_REC_L, 100);
1796507ec6d5SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REC_R, M_MASTER_REC_R, A_OUT_ADC_REC_R, 100);
1797d056fa04SAlexander Leidinger #ifdef	SND_EMU10KX_MULTICHANNEL
1798d056fa04SAlexander Leidinger 		/*
1799d056fa04SAlexander Leidinger 		 * Additional channel volume is controlled by mixer in
1800d056fa04SAlexander Leidinger 		 * emu_dspmixer_set() in -pcm.c
1801d056fa04SAlexander Leidinger 		 */
1802d056fa04SAlexander Leidinger 
1803d056fa04SAlexander Leidinger 		/* fx2/3 (pcm1) to rear */
1804d056fa04SAlexander Leidinger 		EFX_CACHE(C_REAR_L);
1805d056fa04SAlexander Leidinger 		EFX_CACHE(C_REAR_R);
1806d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
1807d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
1808d056fa04SAlexander Leidinger 
1809d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, A_OUT_A_REAR_L, 100);
1810d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, A_OUT_A_REAR_R, 100);
1811d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_REAR_L, M_MASTER_REAR_L, A_OUT_D_REAR_L);
1812507ec6d5SAlexander Leidinger 		EFX_OUTPUTD(C_REAR_R, M_MASTER_REAR_R, A_OUT_D_REAR_R);
1813d056fa04SAlexander Leidinger 
1814d056fa04SAlexander Leidinger 		/* fx4 (pcm2) to center */
1815d056fa04SAlexander Leidinger 		EFX_CACHE(C_CENTER);
1816d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
1817d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100);
1818d056fa04SAlexander Leidinger #if 0
1819d056fa04SAlexander Leidinger 		/* XXX in digital mode (default) this should be muted because
1820d056fa04SAlexander Leidinger 		this output is shared with digital out */
1821d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER);
1822d056fa04SAlexander Leidinger #endif
1823d056fa04SAlexander Leidinger 		/* fx5 (pcm3) to sub */
1824d056fa04SAlexander Leidinger 		EFX_CACHE(C_SUB);
1825d056fa04SAlexander Leidinger 		EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
1826d056fa04SAlexander Leidinger 		EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100);
1827d056fa04SAlexander Leidinger #if 0
1828d056fa04SAlexander Leidinger 		/* XXX in digital mode (default) this should be muted because
1829d056fa04SAlexander Leidinger 		this output is shared with digital out */
1830d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB);
1831d056fa04SAlexander Leidinger #endif
1832d056fa04SAlexander Leidinger 		if (sc->has_71) {
1833d056fa04SAlexander Leidinger 			/* XXX this will broke headphones on AudigyDrive */
1834d056fa04SAlexander Leidinger 			/* fx6/7 (pcm4) to side */
1835d056fa04SAlexander Leidinger 			EFX_CACHE(C_SIDE_L);
1836d056fa04SAlexander Leidinger 			EFX_CACHE(C_SIDE_R);
1837d056fa04SAlexander Leidinger 			EFX_ROUTE(NULL, FX(6), M_FX6_SIDE_L, C_SIDE_L, 100);
1838d056fa04SAlexander Leidinger 			EFX_ROUTE(NULL, FX(7), M_FX7_SIDE_R, C_SIDE_R, 100);
1839d056fa04SAlexander Leidinger 			EFX_OUTPUT(NULL, C_SIDE_L, M_MASTER_SIDE_L, A_OUT_A_SIDE_L, 100);
1840d056fa04SAlexander Leidinger 			EFX_OUTPUT(NULL, C_SIDE_R, M_MASTER_SIDE_R, A_OUT_A_SIDE_R, 100);
1841d056fa04SAlexander Leidinger 			EFX_OUTPUTD(C_SIDE_L, M_MASTER_SIDE_L, A_OUT_D_SIDE_L);
1842d056fa04SAlexander Leidinger 			EFX_OUTPUTD(C_SIDE_R, M_MASTER_SIDE_R, A_OUT_D_SIDE_R);
1843d056fa04SAlexander Leidinger 		}
1844f856af04SAlexander Leidinger #ifdef	SND_EMU10KX_MCH_RECORDING
1845f856af04SAlexander Leidinger 	/* MCH RECORDING, high 32 slots */
1846f856af04SAlexander Leidinger 	for(i = 0; i < 32; i++) {
1847f856af04SAlexander Leidinger 		/* XXX fill with dummy data */
1848f856af04SAlexander Leidinger 		EFX_DUMMY(i,i*0x10000);
1849f856af04SAlexander Leidinger 		emu_addefxop(sc, ACC3,
1850f856af04SAlexander Leidinger 				FX2(i),
1851f856af04SAlexander Leidinger 				DSP_CONST(0),
1852f856af04SAlexander Leidinger 				DSP_CONST(0),
1853f856af04SAlexander Leidinger 				GPR(sc->dummy_gpr[i]),
1854f856af04SAlexander Leidinger 				&pc);
1855f856af04SAlexander Leidinger 		}
1856f856af04SAlexander Leidinger #endif
1857d056fa04SAlexander Leidinger #else	/* !SND_EMU10KX_MULTICHANNEL */
1858d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_REAR_L);
1859d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_REAR_R);
1860d056fa04SAlexander Leidinger 
1861d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_REAR_L);
1862d056fa04SAlexander Leidinger 		EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_REAR_R);
1863d056fa04SAlexander Leidinger #endif
1864d056fa04SAlexander Leidinger 	}
1865d056fa04SAlexander Leidinger 
1866d056fa04SAlexander Leidinger 	sc->routing_code_end = pc;
1867d056fa04SAlexander Leidinger 
1868d056fa04SAlexander Leidinger 	/* start DSP */
1869d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
1870d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, DBG, 0);
1871d056fa04SAlexander Leidinger 	} else {
1872d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, A_DBG, 0);
1873d056fa04SAlexander Leidinger 	}
1874d056fa04SAlexander Leidinger }
1875d056fa04SAlexander Leidinger 
1876d056fa04SAlexander Leidinger /* /dev/em10kx */
1877d056fa04SAlexander Leidinger static d_open_t		emu10kx_open;
1878d056fa04SAlexander Leidinger static d_close_t	emu10kx_close;
1879d056fa04SAlexander Leidinger static d_read_t		emu10kx_read;
1880d056fa04SAlexander Leidinger 
1881d056fa04SAlexander Leidinger static struct cdevsw emu10kx_cdevsw = {
1882d056fa04SAlexander Leidinger 	.d_open = 	emu10kx_open,
1883d056fa04SAlexander Leidinger 	.d_close =	emu10kx_close,
1884d056fa04SAlexander Leidinger 	.d_read = 	emu10kx_read,
1885d056fa04SAlexander Leidinger 	.d_name = 	"emu10kx",
1886d056fa04SAlexander Leidinger 	.d_version = 	D_VERSION,
1887d056fa04SAlexander Leidinger };
1888d056fa04SAlexander Leidinger 
1889d056fa04SAlexander Leidinger 
1890d056fa04SAlexander Leidinger static int
1891d056fa04SAlexander Leidinger emu10kx_open(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
1892d056fa04SAlexander Leidinger {
1893d056fa04SAlexander Leidinger 	int error;
1894d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
1895d056fa04SAlexander Leidinger 
1896d056fa04SAlexander Leidinger 	sc = i_dev->si_drv1;
1897d056fa04SAlexander Leidinger 	mtx_lock(&sc->emu10kx_lock);
1898d056fa04SAlexander Leidinger 	if (sc->emu10kx_isopen) {
1899d056fa04SAlexander Leidinger 		mtx_unlock(&sc->emu10kx_lock);
1900d056fa04SAlexander Leidinger 		return (EBUSY);
1901d056fa04SAlexander Leidinger 	}
1902d056fa04SAlexander Leidinger 	sc->emu10kx_isopen = 1;
1903d056fa04SAlexander Leidinger 	mtx_unlock(&sc->emu10kx_lock);
1904d056fa04SAlexander Leidinger 	if (sbuf_new(&sc->emu10kx_sbuf, NULL, 4096, 0) == NULL) {
1905d056fa04SAlexander Leidinger 		error = ENXIO;
1906d056fa04SAlexander Leidinger 		goto out;
1907d056fa04SAlexander Leidinger 	}
1908d056fa04SAlexander Leidinger 	sc->emu10kx_bufptr = 0;
1909d056fa04SAlexander Leidinger 	error = (emu10kx_prepare(sc, &sc->emu10kx_sbuf) > 0) ? 0 : ENOMEM;
1910d056fa04SAlexander Leidinger out:
1911d056fa04SAlexander Leidinger 	if (error) {
1912d056fa04SAlexander Leidinger 		mtx_lock(&sc->emu10kx_lock);
1913d056fa04SAlexander Leidinger 		sc->emu10kx_isopen = 0;
1914d056fa04SAlexander Leidinger 		mtx_unlock(&sc->emu10kx_lock);
1915d056fa04SAlexander Leidinger 	}
1916d056fa04SAlexander Leidinger 	return (error);
1917d056fa04SAlexander Leidinger }
1918d056fa04SAlexander Leidinger 
1919d056fa04SAlexander Leidinger static int
1920d056fa04SAlexander Leidinger emu10kx_close(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
1921d056fa04SAlexander Leidinger {
1922d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
1923d056fa04SAlexander Leidinger 
1924d056fa04SAlexander Leidinger 	sc = i_dev->si_drv1;
1925d056fa04SAlexander Leidinger 
1926d056fa04SAlexander Leidinger 	mtx_lock(&sc->emu10kx_lock);
1927d056fa04SAlexander Leidinger 	if (!(sc->emu10kx_isopen)) {
1928d056fa04SAlexander Leidinger 		mtx_unlock(&sc->emu10kx_lock);
1929d056fa04SAlexander Leidinger 		return (EBADF);
1930d056fa04SAlexander Leidinger 	}
1931d056fa04SAlexander Leidinger 	sbuf_delete(&sc->emu10kx_sbuf);
1932d056fa04SAlexander Leidinger 	sc->emu10kx_isopen = 0;
1933d056fa04SAlexander Leidinger 	mtx_unlock(&sc->emu10kx_lock);
1934d056fa04SAlexander Leidinger 
1935d056fa04SAlexander Leidinger 	return (0);
1936d056fa04SAlexander Leidinger }
1937d056fa04SAlexander Leidinger 
1938d056fa04SAlexander Leidinger static int
1939d056fa04SAlexander Leidinger emu10kx_read(struct cdev *i_dev, struct uio *buf, int flag __unused)
1940d056fa04SAlexander Leidinger {
1941d056fa04SAlexander Leidinger 	int l, err;
1942d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
1943d056fa04SAlexander Leidinger 
1944d056fa04SAlexander Leidinger 	sc = i_dev->si_drv1;
1945d056fa04SAlexander Leidinger 	mtx_lock(&sc->emu10kx_lock);
1946d056fa04SAlexander Leidinger 	if (!(sc->emu10kx_isopen)) {
1947d056fa04SAlexander Leidinger 		mtx_unlock(&sc->emu10kx_lock);
1948d056fa04SAlexander Leidinger 		return (EBADF);
1949d056fa04SAlexander Leidinger 	}
1950d056fa04SAlexander Leidinger 	mtx_unlock(&sc->emu10kx_lock);
1951d056fa04SAlexander Leidinger 
1952d056fa04SAlexander Leidinger 	l = min(buf->uio_resid, sbuf_len(&sc->emu10kx_sbuf) - sc->emu10kx_bufptr);
1953d056fa04SAlexander Leidinger 	err = (l > 0) ? uiomove(sbuf_data(&sc->emu10kx_sbuf) + sc->emu10kx_bufptr, l, buf) : 0;
1954d056fa04SAlexander Leidinger 	sc->emu10kx_bufptr += l;
1955d056fa04SAlexander Leidinger 
1956d056fa04SAlexander Leidinger 	return (err);
1957d056fa04SAlexander Leidinger }
1958d056fa04SAlexander Leidinger 
1959d056fa04SAlexander Leidinger static int
1960d056fa04SAlexander Leidinger emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s)
1961d056fa04SAlexander Leidinger {
1962d056fa04SAlexander Leidinger 	int i;
1963d056fa04SAlexander Leidinger 
1964d056fa04SAlexander Leidinger 	sbuf_printf(s, "FreeBSD EMU10Kx Audio Driver\n");
1965d056fa04SAlexander Leidinger 	sbuf_printf(s, "\nHardware resource usage:\n");
1966d056fa04SAlexander Leidinger 	sbuf_printf(s, "DSP General Purpose Registers: %d used, %d total\n", sc->rm->num_used, sc->rm->num_gprs);
1967d056fa04SAlexander Leidinger 	sbuf_printf(s, "DSP Instruction Registers: %d used, %d total\n", sc->routing_code_end, sc->code_size);
1968d056fa04SAlexander Leidinger 	sbuf_printf(s, "Card supports");
1969d056fa04SAlexander Leidinger 	if (sc->has_ac97) {
1970d056fa04SAlexander Leidinger 		sbuf_printf(s, " AC97 codec");
1971d056fa04SAlexander Leidinger 	} else {
1972d056fa04SAlexander Leidinger 		sbuf_printf(s, " NO AC97 codec");
1973d056fa04SAlexander Leidinger 	}
1974d056fa04SAlexander Leidinger 	if (sc->has_51) {
1975d056fa04SAlexander Leidinger 		if (sc->has_71)
1976d056fa04SAlexander Leidinger 			sbuf_printf(s, " and 7.1 output");
1977d056fa04SAlexander Leidinger 		else
1978d056fa04SAlexander Leidinger 			sbuf_printf(s, " and 5.1 output");
1979d056fa04SAlexander Leidinger 	}
1980d056fa04SAlexander Leidinger 	if (sc->is_emu10k1)
1981d056fa04SAlexander Leidinger 		sbuf_printf(s, ", SBLive! DSP code");
1982d056fa04SAlexander Leidinger 	if (sc->is_emu10k2)
1983d056fa04SAlexander Leidinger 		sbuf_printf(s, ", Audigy DSP code");
1984d056fa04SAlexander Leidinger 	if (sc->is_ca0102)
1985d056fa04SAlexander Leidinger 		sbuf_printf(s, ", Audigy DSP code with Audigy2 hacks");
1986d056fa04SAlexander Leidinger 	if (sc->is_ca0108)
1987d056fa04SAlexander Leidinger 		sbuf_printf(s, ", Audigy DSP code with Audigy2Value hacks");
1988d056fa04SAlexander Leidinger 	sbuf_printf(s, "\n");
1989d056fa04SAlexander Leidinger 	if (sc->broken_digital)
1990d056fa04SAlexander Leidinger 		sbuf_printf(s, "Digital mode unsupported\n");
1991d056fa04SAlexander Leidinger 	sbuf_printf(s, "\nInstalled devices:\n");
1992f856af04SAlexander Leidinger 	for (i = 0; i < RT_COUNT; i++)
1993d056fa04SAlexander Leidinger 		if (sc->pcm[i] != NULL)
1994d056fa04SAlexander Leidinger 			if (device_is_attached(sc->pcm[i])) {
1995d056fa04SAlexander Leidinger 				sbuf_printf(s, "%s on %s\n", device_get_desc(sc->pcm[i]), device_get_nameunit(sc->pcm[i]));
1996d056fa04SAlexander Leidinger 			}
1997d056fa04SAlexander Leidinger 	if (sc->midi[0] != NULL)
1998d056fa04SAlexander Leidinger 		if (device_is_attached(sc->midi[0])) {
1999d056fa04SAlexander Leidinger 			sbuf_printf(s, "EMU10Kx MIDI Interface\n");
2000d056fa04SAlexander Leidinger 			sbuf_printf(s, "\tOn-card connector on %s\n", device_get_nameunit(sc->midi[0]));
2001d056fa04SAlexander Leidinger 		}
2002d056fa04SAlexander Leidinger 	if (sc->midi[1] != NULL)
2003d056fa04SAlexander Leidinger 		if (device_is_attached(sc->midi[1])) {
2004d056fa04SAlexander Leidinger 			sbuf_printf(s, "\tOn-Drive connector on %s\n", device_get_nameunit(sc->midi[1]));
2005d056fa04SAlexander Leidinger 		}
2006d056fa04SAlexander Leidinger 	if (sc->midi[0] != NULL)
2007d056fa04SAlexander Leidinger 		if (device_is_attached(sc->midi[0])) {
2008d056fa04SAlexander Leidinger 			sbuf_printf(s, "\tIR reciever MIDI events %s\n", sc->enable_ir ? "enabled" : "disabled");
2009d056fa04SAlexander Leidinger 		}
2010d056fa04SAlexander Leidinger 	sbuf_finish(s);
2011d056fa04SAlexander Leidinger 	return (sbuf_len(s));
2012d056fa04SAlexander Leidinger }
2013d056fa04SAlexander Leidinger 
2014d056fa04SAlexander Leidinger /* INIT & UNINIT */
2015d056fa04SAlexander Leidinger static int
2016d056fa04SAlexander Leidinger emu10kx_dev_init(struct emu_sc_info *sc)
2017d056fa04SAlexander Leidinger {
2018d056fa04SAlexander Leidinger 	int unit;
2019d056fa04SAlexander Leidinger 
2020d056fa04SAlexander Leidinger 	mtx_init(&sc->emu10kx_lock, "kxdevlock", NULL, 0);
2021d056fa04SAlexander Leidinger 	unit = device_get_unit(sc->dev);
2022d056fa04SAlexander Leidinger 
2023d056fa04SAlexander Leidinger 	sc->cdev = make_dev(&emu10kx_cdevsw, unit2minor(unit), UID_ROOT, GID_WHEEL, 0640, "emu10kx%d", unit);
2024d056fa04SAlexander Leidinger 	if (sc->cdev != NULL) {
2025d056fa04SAlexander Leidinger 		sc->cdev->si_drv1 = sc;
2026d056fa04SAlexander Leidinger 		return (0);
2027d056fa04SAlexander Leidinger 	}
2028d056fa04SAlexander Leidinger 	return (ENXIO);
2029d056fa04SAlexander Leidinger }
2030d056fa04SAlexander Leidinger 
2031d056fa04SAlexander Leidinger static int
2032d056fa04SAlexander Leidinger emu10kx_dev_uninit(struct emu_sc_info *sc)
2033d056fa04SAlexander Leidinger {
2034d056fa04SAlexander Leidinger 	intrmask_t s;
2035d056fa04SAlexander Leidinger 
2036d056fa04SAlexander Leidinger 	s = spltty();
2037d056fa04SAlexander Leidinger 	mtx_lock(&sc->emu10kx_lock);
2038d056fa04SAlexander Leidinger 	if (sc->emu10kx_isopen) {
2039d056fa04SAlexander Leidinger 		mtx_unlock(&sc->emu10kx_lock);
2040d056fa04SAlexander Leidinger 		splx(s);
2041d056fa04SAlexander Leidinger 		return (EBUSY);
2042d056fa04SAlexander Leidinger 	}
2043d056fa04SAlexander Leidinger 	if (sc->cdev)
2044d056fa04SAlexander Leidinger 		destroy_dev(sc->cdev);
2045d056fa04SAlexander Leidinger 	sc->cdev = 0;
2046d056fa04SAlexander Leidinger 
2047d056fa04SAlexander Leidinger 	splx(s);
2048d056fa04SAlexander Leidinger 	mtx_destroy(&sc->emu10kx_lock);
2049d056fa04SAlexander Leidinger 	return (0);
2050d056fa04SAlexander Leidinger }
2051d056fa04SAlexander Leidinger 
2052d056fa04SAlexander Leidinger /* resource manager */
2053d056fa04SAlexander Leidinger int
2054d056fa04SAlexander Leidinger emu_rm_init(struct emu_sc_info *sc)
2055d056fa04SAlexander Leidinger {
2056d056fa04SAlexander Leidinger 	int i;
2057d056fa04SAlexander Leidinger 	int maxcount;
2058d056fa04SAlexander Leidinger 	struct emu_rm *rm;
2059d056fa04SAlexander Leidinger 
2060d056fa04SAlexander Leidinger 	rm = malloc(sizeof(struct emu_rm), M_DEVBUF, M_NOWAIT | M_ZERO);
2061d056fa04SAlexander Leidinger 	if (rm == NULL) {
2062d056fa04SAlexander Leidinger 		return (ENOMEM);
2063d056fa04SAlexander Leidinger 	}
2064d056fa04SAlexander Leidinger 	sc->rm = rm;
2065d056fa04SAlexander Leidinger 	rm->card = sc;
2066d056fa04SAlexander Leidinger 	maxcount = sc->num_gprs;
2067d056fa04SAlexander Leidinger 	rm->num_used = 0;
2068d056fa04SAlexander Leidinger 	mtx_init(&(rm->gpr_lock), "emu10k", "gpr alloc", MTX_DEF);
2069d056fa04SAlexander Leidinger 	rm->num_gprs = (maxcount < EMU_MAX_GPR ? maxcount : EMU_MAX_GPR);
2070d056fa04SAlexander Leidinger 	for (i = 0; i < rm->num_gprs; i++)
2071d056fa04SAlexander Leidinger 		rm->allocmap[i] = 0;
2072d056fa04SAlexander Leidinger 	rm->last_free_gpr = 0;
2073d056fa04SAlexander Leidinger 
2074d056fa04SAlexander Leidinger 	return (0);
2075d056fa04SAlexander Leidinger }
2076d056fa04SAlexander Leidinger 
2077d056fa04SAlexander Leidinger int
2078d056fa04SAlexander Leidinger emu_rm_uninit(struct emu_sc_info *sc)
2079d056fa04SAlexander Leidinger {
2080d056fa04SAlexander Leidinger #ifdef SND_EMU10KX_DEBUG
2081d056fa04SAlexander Leidinger 	int i;
2082d056fa04SAlexander Leidinger 
2083d056fa04SAlexander Leidinger 	mtx_lock(&(sc->rm->gpr_lock));
2084d056fa04SAlexander Leidinger 	for (i = 0; i < sc->rm->last_free_gpr; i++)
2085d056fa04SAlexander Leidinger 		if (sc->rm->allocmap[i] > 0)
2086d056fa04SAlexander Leidinger 			device_printf(sc->dev, "rm: gpr %d not free before uninit\n", i);
2087d056fa04SAlexander Leidinger 	mtx_unlock(&(sc->rm->gpr_lock));
2088d056fa04SAlexander Leidinger #endif
2089d056fa04SAlexander Leidinger 	mtx_destroy(&(sc->rm->gpr_lock));
2090d056fa04SAlexander Leidinger 	free(sc->rm, M_DEVBUF);
2091d056fa04SAlexander Leidinger 	return (0);
2092d056fa04SAlexander Leidinger }
2093d056fa04SAlexander Leidinger 
2094d056fa04SAlexander Leidinger static int
2095d056fa04SAlexander Leidinger emu_rm_gpr_alloc(struct emu_rm *rm, int count)
2096d056fa04SAlexander Leidinger {
2097d056fa04SAlexander Leidinger 	int i, j;
2098d056fa04SAlexander Leidinger 	int allocated_gpr;
2099d056fa04SAlexander Leidinger 
2100d056fa04SAlexander Leidinger 	allocated_gpr = rm->num_gprs;
2101d056fa04SAlexander Leidinger 	/* try fast way first */
2102d056fa04SAlexander Leidinger 	mtx_lock(&(rm->gpr_lock));
2103d056fa04SAlexander Leidinger 	if (rm->last_free_gpr + count <= rm->num_gprs) {
2104d056fa04SAlexander Leidinger 		allocated_gpr = rm->last_free_gpr;
2105d056fa04SAlexander Leidinger 		rm->last_free_gpr += count;
2106d056fa04SAlexander Leidinger 		rm->allocmap[allocated_gpr] = count;
2107d056fa04SAlexander Leidinger 		for (i = 1; i < count; i++)
2108d056fa04SAlexander Leidinger 			rm->allocmap[allocated_gpr + i] = -(count - i);
2109d056fa04SAlexander Leidinger 	} else {
2110d056fa04SAlexander Leidinger 		/* longer */
2111d056fa04SAlexander Leidinger 		i = 0;
2112d056fa04SAlexander Leidinger 		allocated_gpr = rm->num_gprs;
2113d056fa04SAlexander Leidinger 		while (i < rm->last_free_gpr - count) {
2114d056fa04SAlexander Leidinger 			if (rm->allocmap[i] > 0) {
2115d056fa04SAlexander Leidinger 				i += rm->allocmap[i];
2116d056fa04SAlexander Leidinger 			} else {
2117d056fa04SAlexander Leidinger 				allocated_gpr = i;
2118d056fa04SAlexander Leidinger 				for (j = 1; j < count; j++) {
2119d056fa04SAlexander Leidinger 					if (rm->allocmap[i + j] != 0)
2120d056fa04SAlexander Leidinger 						allocated_gpr = rm->num_gprs;
2121d056fa04SAlexander Leidinger 				}
2122d056fa04SAlexander Leidinger 				if (allocated_gpr == i)
2123d056fa04SAlexander Leidinger 					break;
2124d056fa04SAlexander Leidinger 			}
2125d056fa04SAlexander Leidinger 		}
2126d056fa04SAlexander Leidinger 		if (allocated_gpr + count < rm->last_free_gpr) {
2127d056fa04SAlexander Leidinger 			rm->allocmap[allocated_gpr] = count;
2128d056fa04SAlexander Leidinger 			for (i = 1; i < count; i++)
2129d056fa04SAlexander Leidinger 				rm->allocmap[allocated_gpr + i] = -(count - i);
2130d056fa04SAlexander Leidinger 
2131d056fa04SAlexander Leidinger 		}
2132d056fa04SAlexander Leidinger 	}
2133d056fa04SAlexander Leidinger 	if (allocated_gpr == rm->num_gprs)
2134d056fa04SAlexander Leidinger 		allocated_gpr = (-1);
2135d056fa04SAlexander Leidinger 	if (allocated_gpr >= 0)
2136d056fa04SAlexander Leidinger 		rm->num_used += count;
2137d056fa04SAlexander Leidinger 	mtx_unlock(&(rm->gpr_lock));
2138d056fa04SAlexander Leidinger 	return (allocated_gpr);
2139d056fa04SAlexander Leidinger }
2140d056fa04SAlexander Leidinger 
2141d056fa04SAlexander Leidinger /* mixer */
2142d056fa04SAlexander Leidinger void
2143d056fa04SAlexander Leidinger emumix_set_mode(struct emu_sc_info *sc, int mode)
2144d056fa04SAlexander Leidinger {
2145d056fa04SAlexander Leidinger 	uint32_t a_iocfg;
2146d056fa04SAlexander Leidinger 	uint32_t hcfg;
2147d056fa04SAlexander Leidinger 	uint32_t tmp;
2148d056fa04SAlexander Leidinger 
2149d056fa04SAlexander Leidinger 	switch (mode) {
2150d056fa04SAlexander Leidinger 	case MODE_DIGITAL:
2151d056fa04SAlexander Leidinger 		/* FALLTHROUGH */
2152d056fa04SAlexander Leidinger 	case MODE_ANALOG:
2153d056fa04SAlexander Leidinger 		break;
2154d056fa04SAlexander Leidinger 	default:
2155d056fa04SAlexander Leidinger 		return;
2156d056fa04SAlexander Leidinger 	}
2157d056fa04SAlexander Leidinger 
2158d056fa04SAlexander Leidinger 	hcfg = HCFG_AUDIOENABLE | HCFG_AUTOMUTE;
2159d056fa04SAlexander Leidinger 	a_iocfg = 0;
2160d056fa04SAlexander Leidinger 
2161d056fa04SAlexander Leidinger 	if (sc->rev >= 6)
2162d056fa04SAlexander Leidinger 		hcfg |= HCFG_JOYENABLE;
2163d056fa04SAlexander Leidinger 
2164d056fa04SAlexander Leidinger 	if (sc->is_emu10k1)
2165d056fa04SAlexander Leidinger 		hcfg |= HCFG_LOCKTANKCACHE_MASK;
2166d056fa04SAlexander Leidinger 	else
2167d056fa04SAlexander Leidinger 		hcfg |= HCFG_CODECFORMAT_I2S | HCFG_JOYENABLE;
2168d056fa04SAlexander Leidinger 
2169d056fa04SAlexander Leidinger 
2170d056fa04SAlexander Leidinger 	if (mode == MODE_DIGITAL) {
2171d056fa04SAlexander Leidinger 		if (sc->broken_digital) {
2172d056fa04SAlexander Leidinger 			device_printf(sc->dev, "Digital mode is reported as broken on this card,\n");
2173d056fa04SAlexander Leidinger 		}
2174d056fa04SAlexander Leidinger 		a_iocfg |= A_IOCFG_ENABLE_DIGITAL;
2175d056fa04SAlexander Leidinger 		hcfg |= HCFG_GPOUT0;
2176d056fa04SAlexander Leidinger 	}
2177d056fa04SAlexander Leidinger 
2178d056fa04SAlexander Leidinger 	if (mode == MODE_ANALOG)
2179d056fa04SAlexander Leidinger 		emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
2180d056fa04SAlexander Leidinger 
2181d056fa04SAlexander Leidinger 	if (sc->is_emu10k2)
2182d056fa04SAlexander Leidinger 		a_iocfg |= 0x80; /* XXX */
2183d056fa04SAlexander Leidinger 
2184d056fa04SAlexander Leidinger 	if ((sc->is_ca0102) || (sc->is_ca0108))
2185d056fa04SAlexander Leidinger 		a_iocfg |= A_IOCFG_DISABLE_ANALOG; /* means "don't disable"
2186d056fa04SAlexander Leidinger 		on this two cards. Means "disable" on emu10k2. */
2187d056fa04SAlexander Leidinger 
2188d056fa04SAlexander Leidinger 	if (sc->is_ca0108)
2189d056fa04SAlexander Leidinger 		a_iocfg |= 0x20; /* XXX */
2190d056fa04SAlexander Leidinger 
2191d056fa04SAlexander Leidinger 	emu_wr(sc, HCFG, hcfg, 4);
2192d056fa04SAlexander Leidinger 
2193d056fa04SAlexander Leidinger 	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2194d056fa04SAlexander Leidinger 		tmp = emu_rd(sc, A_IOCFG, 2);
2195d056fa04SAlexander Leidinger 		tmp = a_iocfg;
2196d056fa04SAlexander Leidinger 		emu_wr(sc, A_IOCFG, tmp, 2);
2197d056fa04SAlexander Leidinger 	}
2198d056fa04SAlexander Leidinger 
2199d056fa04SAlexander Leidinger 	/*
2200d056fa04SAlexander Leidinger 	 * XXX Mute center/sub if we go digital on Audigy or later card.
2201d056fa04SAlexander Leidinger 	 * Route to analog center / sub in emu_initef should be disabled
2202d056fa04SAlexander Leidinger 	 * until this problem is fixed.
2203d056fa04SAlexander Leidinger 	 */
2204d056fa04SAlexander Leidinger }
2205d056fa04SAlexander Leidinger 
2206d056fa04SAlexander Leidinger void
2207d056fa04SAlexander Leidinger emumix_set_spdif_mode(struct emu_sc_info *sc, int mode)
2208d056fa04SAlexander Leidinger {
2209d056fa04SAlexander Leidinger 	uint32_t spcs;
2210d056fa04SAlexander Leidinger 
2211d056fa04SAlexander Leidinger 	switch (mode) {
2212d056fa04SAlexander Leidinger 	case SPDIF_MODE_PCM:
2213d056fa04SAlexander Leidinger 		break;
2214d056fa04SAlexander Leidinger 	case SPDIF_MODE_AC3:
2215d056fa04SAlexander Leidinger 		device_printf(sc->dev, "AC3 mode does not work and disabled\n");
2216d056fa04SAlexander Leidinger 		return;
2217d056fa04SAlexander Leidinger 	default:
2218d056fa04SAlexander Leidinger 		return;
2219d056fa04SAlexander Leidinger 	}
2220d056fa04SAlexander Leidinger 
2221d056fa04SAlexander Leidinger 	spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
2222d056fa04SAlexander Leidinger 	    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
2223d056fa04SAlexander Leidinger 	    SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 |
2224d056fa04SAlexander Leidinger 	    SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
2225d056fa04SAlexander Leidinger 
2226d056fa04SAlexander Leidinger 	mode = SPDIF_MODE_PCM;
2227d056fa04SAlexander Leidinger 
2228d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SPCS0, spcs);
2229d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SPCS1, spcs);
2230d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SPCS2, spcs);
2231d056fa04SAlexander Leidinger }
2232d056fa04SAlexander Leidinger 
2233d056fa04SAlexander Leidinger #define	L2L_POINTS	10
2234d056fa04SAlexander Leidinger 
2235d056fa04SAlexander Leidinger static int l2l_df[L2L_POINTS] = {
2236d056fa04SAlexander Leidinger 	0x572C5CA,		/* 100..90 */
2237d056fa04SAlexander Leidinger 	0x3211625,		/* 90..80 */
2238d056fa04SAlexander Leidinger 	0x1CC1A76,		/* 80..70 */
2239d056fa04SAlexander Leidinger 	0x108428F,		/* 70..60 */
2240d056fa04SAlexander Leidinger 	0x097C70A,		/* 60..50 */
2241d056fa04SAlexander Leidinger 	0x0572C5C,		/* 50..40 */
2242d056fa04SAlexander Leidinger 	0x0321162,		/* 40..30 */
2243d056fa04SAlexander Leidinger 	0x01CC1A7,		/* 30..20 */
2244d056fa04SAlexander Leidinger 	0x0108428,		/* 20..10 */
2245d056fa04SAlexander Leidinger 	0x016493D		/* 10..0 */
2246d056fa04SAlexander Leidinger };
2247d056fa04SAlexander Leidinger 
2248d056fa04SAlexander Leidinger static int l2l_f[L2L_POINTS] = {
2249d056fa04SAlexander Leidinger 	0x4984461A,		/* 90 */
2250d056fa04SAlexander Leidinger 	0x2A3968A7,		/* 80 */
2251d056fa04SAlexander Leidinger 	0x18406003,		/* 70 */
2252d056fa04SAlexander Leidinger 	0x0DEDC66D,		/* 60 */
2253d056fa04SAlexander Leidinger 	0x07FFFFFF,		/* 50 */
2254d056fa04SAlexander Leidinger 	0x04984461,		/* 40 */
2255d056fa04SAlexander Leidinger 	0x02A3968A,		/* 30 */
2256d056fa04SAlexander Leidinger 	0x01840600,		/* 20 */
2257d056fa04SAlexander Leidinger 	0x00DEDC66,		/* 10 */
2258d056fa04SAlexander Leidinger 	0x00000000		/* 0 */
2259d056fa04SAlexander Leidinger };
2260d056fa04SAlexander Leidinger 
2261d056fa04SAlexander Leidinger 
2262d056fa04SAlexander Leidinger static int
2263d056fa04SAlexander Leidinger log2lin(int log_t)
2264d056fa04SAlexander Leidinger {
2265d056fa04SAlexander Leidinger 	int lin_t;
2266d056fa04SAlexander Leidinger 	int idx, lin;
2267d056fa04SAlexander Leidinger 
2268d056fa04SAlexander Leidinger 	if (log_t <= 0) {
2269d056fa04SAlexander Leidinger 		lin_t = 0x00000000;
2270d056fa04SAlexander Leidinger 		return (lin_t);
2271d056fa04SAlexander Leidinger 	}
2272d056fa04SAlexander Leidinger 
2273d056fa04SAlexander Leidinger 	if (log_t >= 100) {
2274d056fa04SAlexander Leidinger 		lin_t = 0x7fffffff;
2275d056fa04SAlexander Leidinger 		return (lin_t);
2276d056fa04SAlexander Leidinger 	}
2277d056fa04SAlexander Leidinger 
2278d056fa04SAlexander Leidinger 	idx = (L2L_POINTS - 1) - log_t / (L2L_POINTS);
2279d056fa04SAlexander Leidinger 	lin = log_t % (L2L_POINTS);
2280d056fa04SAlexander Leidinger 	lin_t = l2l_df[idx] * lin + l2l_f[idx];
2281d056fa04SAlexander Leidinger 	return (lin_t);
2282d056fa04SAlexander Leidinger }
2283d056fa04SAlexander Leidinger 
2284d056fa04SAlexander Leidinger 
2285d056fa04SAlexander Leidinger void
2286d056fa04SAlexander Leidinger emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol)
2287d056fa04SAlexander Leidinger {
2288d056fa04SAlexander Leidinger 
2289d056fa04SAlexander Leidinger 	vol = log2lin(vol);
2290d056fa04SAlexander Leidinger 	emumix_set_gpr(sc, gpr, vol);
2291d056fa04SAlexander Leidinger }
2292d056fa04SAlexander Leidinger 
2293d056fa04SAlexander Leidinger void
2294d056fa04SAlexander Leidinger emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val)
2295d056fa04SAlexander Leidinger {
2296d056fa04SAlexander Leidinger 
2297d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, GPR(gpr), val);
2298d056fa04SAlexander Leidinger }
2299d056fa04SAlexander Leidinger 
2300d056fa04SAlexander Leidinger void
2301d056fa04SAlexander Leidinger emumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume)
2302d056fa04SAlexander Leidinger {
2303d056fa04SAlexander Leidinger 
2304d056fa04SAlexander Leidinger 	RANGE(volume, 0, 100);
2305d056fa04SAlexander Leidinger 	if (mixer_idx < NUM_MIXERS) {
2306d056fa04SAlexander Leidinger 		sc->mixer_volcache[mixer_idx] = volume;
2307d056fa04SAlexander Leidinger 		emumix_set_fxvol(sc, sc->mixer_gpr[mixer_idx], volume);
2308d056fa04SAlexander Leidinger 	}
2309d056fa04SAlexander Leidinger }
2310d056fa04SAlexander Leidinger 
2311d056fa04SAlexander Leidinger int
2312d056fa04SAlexander Leidinger emumix_get_volume(struct emu_sc_info *sc, int mixer_idx)
2313d056fa04SAlexander Leidinger {
2314d056fa04SAlexander Leidinger 	if ((mixer_idx < NUM_MIXERS) && (mixer_idx >= 0))
2315d056fa04SAlexander Leidinger 		return (sc->mixer_volcache[mixer_idx]);
2316d056fa04SAlexander Leidinger 	return (-1);
2317d056fa04SAlexander Leidinger }
2318d056fa04SAlexander Leidinger 
2319d056fa04SAlexander Leidinger /* Init CardBus part */
2320d056fa04SAlexander Leidinger static int
2321d056fa04SAlexander Leidinger emu_cardbus_init(struct emu_sc_info *sc)
2322d056fa04SAlexander Leidinger {
2323d056fa04SAlexander Leidinger 
2324d056fa04SAlexander Leidinger 	/*
2325d056fa04SAlexander Leidinger 	 * XXX May not need this if we have IPR3 handler.
2326d056fa04SAlexander Leidinger 	 * Is it a real init calls, or IPR3 interrupt acknowledgments?
2327d056fa04SAlexander Leidinger 	 * Looks much like "(data << 16) | register".
2328d056fa04SAlexander Leidinger 	 */
2329d056fa04SAlexander Leidinger 	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0000);
2330d056fa04SAlexander Leidinger 	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0001);
2331d056fa04SAlexander Leidinger 	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x005f);
2332d056fa04SAlexander Leidinger 	emu_wr_cbptr(sc, (0x00d0 << 16) | 0x007f);
2333d056fa04SAlexander Leidinger 
2334d056fa04SAlexander Leidinger 	emu_wr_cbptr(sc, (0x0090 << 16) | 0x007f);
2335d056fa04SAlexander Leidinger 
2336d056fa04SAlexander Leidinger 	return (0);
2337d056fa04SAlexander Leidinger }
2338d056fa04SAlexander Leidinger 
2339d056fa04SAlexander Leidinger /* Probe and attach the card */
2340d056fa04SAlexander Leidinger static int
234155837609SAriff Abdullah emu_init(struct emu_sc_info *sc)
2342d056fa04SAlexander Leidinger {
2343d056fa04SAlexander Leidinger 	uint32_t ch, tmp;
2344d056fa04SAlexander Leidinger 	uint32_t spdif_sr;
2345d056fa04SAlexander Leidinger 	uint32_t ac97slot;
2346d056fa04SAlexander Leidinger 	int def_mode;
2347d056fa04SAlexander Leidinger 	int i;
2348d056fa04SAlexander Leidinger 
2349d056fa04SAlexander Leidinger 	/* disable audio and lock cache */
2350d056fa04SAlexander Leidinger 	emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
2351d056fa04SAlexander Leidinger 
2352d056fa04SAlexander Leidinger 	/* reset recording buffers */
2353d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
2354d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, MICBA, 0);
2355d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
2356d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, FXBA, 0);
2357d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
2358d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, ADCBA, 0);
2359d056fa04SAlexander Leidinger 
2360d056fa04SAlexander Leidinger 	/* disable channel interrupt */
2361d056fa04SAlexander Leidinger 	emu_wr(sc, INTE, INTE_INTERVALTIMERENB | INTE_SAMPLERATETRACKER | INTE_PCIERRORENABLE, 4);
2362d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, CLIEL, 0);
2363d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, CLIEH, 0);
2364d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SOLEL, 0);
2365d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SOLEH, 0);
2366d056fa04SAlexander Leidinger 
2367d056fa04SAlexander Leidinger 	/* disable P16V and S/PDIF interrupts */
2368d056fa04SAlexander Leidinger 	if ((sc->is_ca0102) || (sc->is_ca0108))
2369d056fa04SAlexander Leidinger 		emu_wr(sc, INTE2, 0, 4);
2370d056fa04SAlexander Leidinger 
2371d056fa04SAlexander Leidinger 	if (sc->is_ca0102)
2372d056fa04SAlexander Leidinger 		emu_wr(sc, INTE3, 0, 4);
2373d056fa04SAlexander Leidinger 
2374d056fa04SAlexander Leidinger 	/* init phys inputs and outputs */
2375d056fa04SAlexander Leidinger 	ac97slot = 0;
2376d056fa04SAlexander Leidinger 	if (sc->has_51)
2377d056fa04SAlexander Leidinger 		ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE;
2378d056fa04SAlexander Leidinger 	if (sc->has_71)
2379d056fa04SAlexander Leidinger 		ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE | AC97SLOT_REAR_LEFT | AC97SLOT_REAR_RIGHT;
2380d056fa04SAlexander Leidinger 	if (sc->is_emu10k2)
2381d056fa04SAlexander Leidinger 		ac97slot |= 0x40;
2382d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, AC97SLOT, ac97slot);
2383d056fa04SAlexander Leidinger 
2384d056fa04SAlexander Leidinger 	if (sc->is_emu10k2)	/* XXX for later cards? */
2385d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, SPBYPASS, 0xf00);	/* What will happen if
2386d056fa04SAlexander Leidinger 							 * we write 1 here? */
2387d056fa04SAlexander Leidinger 
238855837609SAriff Abdullah 	if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(sc->dev),
23890b989078SAlexander Leidinger 	     /* alignment */ 2, /* boundary */ 0,
2390d056fa04SAlexander Leidinger 	     /* lowaddr */ 1 << 31,	/* can only access 0-2gb */
2391d056fa04SAlexander Leidinger 	     /* highaddr */ BUS_SPACE_MAXADDR,
2392d056fa04SAlexander Leidinger 	     /* filter */ NULL, /* filterarg */ NULL,
2393e4c87b14SAlexander Leidinger 	     /* maxsize */ EMU_MAX_BUFSZ, /* nsegments */ 1, /* maxsegz */ 0x3ffff,
2394d056fa04SAlexander Leidinger 	     /* flags */ 0, /* lockfunc */ busdma_lock_mutex,
2395d056fa04SAlexander Leidinger 	     /* lockarg */ &Giant, &(sc->mem.dmat)) != 0) {
2396d056fa04SAlexander Leidinger 		device_printf(sc->dev, "unable to create dma tag\n");
2397d056fa04SAlexander Leidinger 		bus_dma_tag_destroy(sc->mem.dmat);
2398d056fa04SAlexander Leidinger 		return (ENOMEM);
2399d056fa04SAlexander Leidinger 	}
2400d056fa04SAlexander Leidinger 
2401d056fa04SAlexander Leidinger 	SLIST_INIT(&sc->mem.blocks);
2402e4c87b14SAlexander Leidinger 	sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr);
2403d056fa04SAlexander Leidinger 	if (sc->mem.ptb_pages == NULL)
2404d056fa04SAlexander Leidinger 		return (ENOMEM);
2405d056fa04SAlexander Leidinger 
2406d056fa04SAlexander Leidinger 	sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr);
2407d056fa04SAlexander Leidinger 	if (sc->mem.silent_page == NULL) {
2408d056fa04SAlexander Leidinger 		emu_free(&sc->mem, sc->mem.ptb_pages);
2409d056fa04SAlexander Leidinger 		return (ENOMEM);
2410d056fa04SAlexander Leidinger 	}
2411d056fa04SAlexander Leidinger 	/* Clear page with silence & setup all pointers to this page */
2412d056fa04SAlexander Leidinger 	bzero(sc->mem.silent_page, EMUPAGESIZE);
2413d056fa04SAlexander Leidinger 	tmp = (uint32_t) (sc->mem.silent_page_addr) << 1;
2414e4c87b14SAlexander Leidinger 	for (i = 0; i < EMU_MAXPAGES; i++)
2415d056fa04SAlexander Leidinger 		sc->mem.ptb_pages[i] = tmp | i;
2416d056fa04SAlexander Leidinger 
2417d056fa04SAlexander Leidinger 	for (ch = 0; ch < NUM_G; ch++) {
2418d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK);
2419d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK);
2420d056fa04SAlexander Leidinger 	}
2421d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, PTB, (sc->mem.ptb_pages_addr));
2422d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, TCB, 0);	/* taken from original driver */
2423d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, TCBS, 0);	/* taken from original driver */
2424d056fa04SAlexander Leidinger 
2425d056fa04SAlexander Leidinger 	/* init envelope engine */
2426d056fa04SAlexander Leidinger 	for (ch = 0; ch < NUM_G; ch++) {
2427d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, DCYSUSV, 0);
2428d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, IP, 0);
2429d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, VTFT, 0xffff);
2430d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CVCF, 0xffff);
2431d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, PTRX, 0);
2432d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CPF, 0);
2433d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CCR, 0);
2434d056fa04SAlexander Leidinger 
2435d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, PSST, 0);
2436d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, DSL, 0x10);
2437d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CCCA, 0);
2438d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, Z1, 0);
2439d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, Z2, 0);
2440d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, FXRT, 0xd01c0000);
2441d056fa04SAlexander Leidinger 
2442d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, ATKHLDM, 0);
2443d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, DCYSUSM, 0);
2444d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, IFATN, 0xffff);
2445d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, PEFE, 0);
2446d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, FMMOD, 0);
2447d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, TREMFRQ, 24);	/* 1 Hz */
2448d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, FM2FRQ2, 24);	/* 1 Hz */
2449d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, TEMPENV, 0);
2450d056fa04SAlexander Leidinger 
2451d056fa04SAlexander Leidinger 		/*** these are last so OFF prevents writing ***/
2452d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, LFOVAL2, 0);
2453d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, LFOVAL1, 0);
2454d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, ATKHLDV, 0);
2455d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, ENVVOL, 0);
2456d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, ENVVAL, 0);
2457d056fa04SAlexander Leidinger 
2458d056fa04SAlexander Leidinger 		if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2459d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, 0x4c, 0x0);
2460d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, 0x4d, 0x0);
2461d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, 0x4e, 0x0);
2462d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, 0x4f, 0x0);
2463d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, A_FXRT1, 0x3f3f3f3f);
2464d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
2465d056fa04SAlexander Leidinger 			emu_wrptr(sc, ch, A_SENDAMOUNTS, 0x0);
2466d056fa04SAlexander Leidinger 		}
2467d056fa04SAlexander Leidinger 	}
2468d056fa04SAlexander Leidinger 
2469d056fa04SAlexander Leidinger 	emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
2470d056fa04SAlexander Leidinger 
2471d056fa04SAlexander Leidinger 	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
2472d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, A_SPDIF_48000);
2473d056fa04SAlexander Leidinger 
2474d056fa04SAlexander Leidinger 	/*
2475d056fa04SAlexander Leidinger 	 * CAxxxx cards needs additional setup:
2476d056fa04SAlexander Leidinger 	 * 1. Set I2S capture sample rate to 96000
2477d056fa04SAlexander Leidinger 	 * 2. Disable P16v / P17v proceesing
2478d056fa04SAlexander Leidinger 	 * 3. Allow EMU10K DSP inputs
2479d056fa04SAlexander Leidinger 	 */
2480d056fa04SAlexander Leidinger 	if ((sc->is_ca0102) || (sc->is_ca0108)) {
2481d056fa04SAlexander Leidinger 
2482d056fa04SAlexander Leidinger 		spdif_sr = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE);
2483d056fa04SAlexander Leidinger 		spdif_sr &= 0xfffff1ff;
2484d056fa04SAlexander Leidinger 		spdif_sr |= A_I2S_CAPTURE_96000;
2485d056fa04SAlexander Leidinger 		emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, spdif_sr);
2486d056fa04SAlexander Leidinger 
2487d056fa04SAlexander Leidinger 		/* Disable P16v processing */
2488d056fa04SAlexander Leidinger 		emu_wr_p16vptr(sc, 0, SRCSel, 0x14);
2489d056fa04SAlexander Leidinger 
2490d056fa04SAlexander Leidinger 		/* Setup P16v/P17v sound routing */
2491d056fa04SAlexander Leidinger 		if (sc->is_ca0102)
2492d056fa04SAlexander Leidinger 			emu_wr_p16vptr(sc, 0, SRCMULTI_ENABLE, 0xFF00FF00);
2493d056fa04SAlexander Leidinger 		else {
2494d056fa04SAlexander Leidinger 			emu_wr_p16vptr(sc, 0, P17V_MIXER_I2S_ENABLE, 0xFF000000);
2495d056fa04SAlexander Leidinger 			emu_wr_p16vptr(sc, 0, P17V_MIXER_SPDIF_ENABLE, 0xFF000000);
2496d056fa04SAlexander Leidinger 
2497d056fa04SAlexander Leidinger 			tmp = emu_rd(sc, A_IOCFG, 2);
2498d056fa04SAlexander Leidinger 			emu_wr(sc, A_IOCFG, tmp & ~0x8, 2);
2499d056fa04SAlexander Leidinger 		}
2500d056fa04SAlexander Leidinger 	}
2501d056fa04SAlexander Leidinger 	emu_initefx(sc);
2502d056fa04SAlexander Leidinger 
2503d056fa04SAlexander Leidinger 	def_mode = MODE_ANALOG;
2504d056fa04SAlexander Leidinger 	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
2505d056fa04SAlexander Leidinger 		def_mode = MODE_DIGITAL;
2506d056fa04SAlexander Leidinger 	if (((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) && (sc->broken_digital)) {
2507d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Audigy card initialized in analog mode.\n");
2508d056fa04SAlexander Leidinger 		def_mode = MODE_ANALOG;
2509d056fa04SAlexander Leidinger 	}
2510d056fa04SAlexander Leidinger 	emumix_set_mode(sc, def_mode);
2511d056fa04SAlexander Leidinger 
2512d056fa04SAlexander Leidinger 	if (bootverbose) {
2513d056fa04SAlexander Leidinger 		tmp = emu_rd(sc, HCFG, 4);
2514d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Card Configuration (   0x%08x )\n", tmp);
2515d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n",
2516d056fa04SAlexander Leidinger 		    (tmp & 0x80000000 ? "[Legacy MPIC] " : ""),
2517d056fa04SAlexander Leidinger 		    (tmp & 0x40000000 ? "[0x40] " : ""),
2518d056fa04SAlexander Leidinger 		    (tmp & 0x20000000 ? "[0x20] " : ""),
2519d056fa04SAlexander Leidinger 		    (tmp & 0x10000000 ? "[0x10] " : ""),
2520d056fa04SAlexander Leidinger 		    (tmp & 0x08000000 ? "[0x08] " : ""),
2521d056fa04SAlexander Leidinger 		    (tmp & 0x04000000 ? "[0x04] " : ""),
2522d056fa04SAlexander Leidinger 		    (tmp & 0x02000000 ? "[0x02] " : ""),
2523d056fa04SAlexander Leidinger 		    (tmp & 0x01000000 ? "[0x01]" : " "));
2524d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n",
2525d056fa04SAlexander Leidinger 		    (tmp & 0x00800000 ? "[0x80] " : ""),
2526d056fa04SAlexander Leidinger 		    (tmp & 0x00400000 ? "[0x40] " : ""),
2527d056fa04SAlexander Leidinger 		    (tmp & 0x00200000 ? "[Legacy INT] " : ""),
2528d056fa04SAlexander Leidinger 		    (tmp & 0x00100000 ? "[0x10] " : ""),
2529d056fa04SAlexander Leidinger 		    (tmp & 0x00080000 ? "[0x08] " : ""),
2530d056fa04SAlexander Leidinger 		    (tmp & 0x00040000 ? "[Codec4] " : ""),
2531d056fa04SAlexander Leidinger 		    (tmp & 0x00020000 ? "[Codec2] " : ""),
2532d056fa04SAlexander Leidinger 		    (tmp & 0x00010000 ? "[I2S Codec]" : " "));
2533d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n",
2534d056fa04SAlexander Leidinger 		    (tmp & 0x00008000 ? "[0x80] " : ""),
2535d056fa04SAlexander Leidinger 		    (tmp & 0x00004000 ? "[GPINPUT0] " : ""),
2536d056fa04SAlexander Leidinger 		    (tmp & 0x00002000 ? "[GPINPUT1] " : ""),
2537d056fa04SAlexander Leidinger 		    (tmp & 0x00001000 ? "[GPOUT0] " : ""),
2538d056fa04SAlexander Leidinger 		    (tmp & 0x00000800 ? "[GPOUT1] " : ""),
2539d056fa04SAlexander Leidinger 		    (tmp & 0x00000400 ? "[GPOUT2] " : ""),
2540d056fa04SAlexander Leidinger 		    (tmp & 0x00000200 ? "[Joystick] " : ""),
2541d056fa04SAlexander Leidinger 		    (tmp & 0x00000100 ? "[0x01]" : " "));
2542d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n",
2543d056fa04SAlexander Leidinger 		    (tmp & 0x00000080 ? "[0x80] " : ""),
2544d056fa04SAlexander Leidinger 		    (tmp & 0x00000040 ? "[0x40] " : ""),
2545d056fa04SAlexander Leidinger 		    (tmp & 0x00000020 ? "[0x20] " : ""),
2546d056fa04SAlexander Leidinger 		    (tmp & 0x00000010 ? "[AUTOMUTE] " : ""),
2547d056fa04SAlexander Leidinger 		    (tmp & 0x00000008 ? "[LOCKSOUNDCACHE] " : ""),
2548d056fa04SAlexander Leidinger 		    (tmp & 0x00000004 ? "[LOCKTANKCACHE] " : ""),
2549d056fa04SAlexander Leidinger 		    (tmp & 0x00000002 ? "[MUTEBUTTONENABLE] " : ""),
2550d056fa04SAlexander Leidinger 		    (tmp & 0x00000001 ? "[AUDIOENABLE]" : " "));
2551d056fa04SAlexander Leidinger 
2552d056fa04SAlexander Leidinger 		if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2553d056fa04SAlexander Leidinger 			tmp = emu_rd(sc, A_IOCFG, 2);
2554d056fa04SAlexander Leidinger 			device_printf(sc->dev, "Audigy Card Configuration (    0x%04x )\n", tmp);
2555d056fa04SAlexander Leidinger 			device_printf(sc->dev, "Audigy Card Configuration (  & 0xff00 )");
2556d056fa04SAlexander Leidinger 			printf(" : %s%s%s%s%s%s%s%s\n",
2557d056fa04SAlexander Leidinger 			    (tmp & 0x8000 ? "[Rear Speakers] " : ""),
2558d056fa04SAlexander Leidinger 			    (tmp & 0x4000 ? "[Front Speakers] " : ""),
2559d056fa04SAlexander Leidinger 			    (tmp & 0x2000 ? "[0x20] " : ""),
2560d056fa04SAlexander Leidinger 			    (tmp & 0x1000 ? "[0x10] " : ""),
2561d056fa04SAlexander Leidinger 			    (tmp & 0x0800 ? "[0x08] " : ""),
2562d056fa04SAlexander Leidinger 			    (tmp & 0x0400 ? "[0x04] " : ""),
2563d056fa04SAlexander Leidinger 			    (tmp & 0x0200 ? "[0x02] " : ""),
2564d056fa04SAlexander Leidinger 			    (tmp & 0x0100 ? "[AudigyDrive Phones]" : " "));
2565d056fa04SAlexander Leidinger 			device_printf(sc->dev, "Audigy Card Configuration (  & 0x00ff )");
2566d056fa04SAlexander Leidinger 			printf(" : %s%s%s%s%s%s%s%s\n",
2567d056fa04SAlexander Leidinger 			    (tmp & 0x0080 ? "[0x80] " : ""),
2568d056fa04SAlexander Leidinger 			    (tmp & 0x0040 ? "[Mute AnalogOut] " : ""),
2569d056fa04SAlexander Leidinger 			    (tmp & 0x0020 ? "[0x20] " : ""),
2570d056fa04SAlexander Leidinger 			    (tmp & 0x0010 ? "[0x10] " : ""),
2571d056fa04SAlexander Leidinger 			    (tmp & 0x0008 ? "[0x08] " : ""),
2572d056fa04SAlexander Leidinger 			    (tmp & 0x0004 ? "[GPOUT0] " : ""),
2573d056fa04SAlexander Leidinger 			    (tmp & 0x0002 ? "[GPOUT1] " : ""),
2574d056fa04SAlexander Leidinger 			    (tmp & 0x0001 ? "[GPOUT2]" : " "));
2575d056fa04SAlexander Leidinger 		}		/* is_emu10k2 or ca* */
2576d056fa04SAlexander Leidinger 	}			/* bootverbose */
2577d056fa04SAlexander Leidinger 	return (0);
2578d056fa04SAlexander Leidinger }
2579d056fa04SAlexander Leidinger 
2580d056fa04SAlexander Leidinger static int
2581d056fa04SAlexander Leidinger emu_uninit(struct emu_sc_info *sc)
2582d056fa04SAlexander Leidinger {
2583d056fa04SAlexander Leidinger 	uint32_t ch;
2584d056fa04SAlexander Leidinger 	struct emu_memblk *blk;
2585d056fa04SAlexander Leidinger 
2586d056fa04SAlexander Leidinger 	emu_wr(sc, INTE, 0, 4);
2587d056fa04SAlexander Leidinger 	for (ch = 0; ch < NUM_G; ch++)
2588d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, DCYSUSV, 0);
2589d056fa04SAlexander Leidinger 	for (ch = 0; ch < NUM_G; ch++) {
2590d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, VTFT, 0);
2591d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CVCF, 0);
2592d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, PTRX, 0);
2593d056fa04SAlexander Leidinger 		emu_wrptr(sc, ch, CPF, 0);
2594d056fa04SAlexander Leidinger 	}
2595d056fa04SAlexander Leidinger 
2596d056fa04SAlexander Leidinger 	/* disable audio and lock cache */
2597d056fa04SAlexander Leidinger 	emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
2598d056fa04SAlexander Leidinger 
2599d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, PTB, 0);
2600d056fa04SAlexander Leidinger 	/* reset recording buffers */
2601d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
2602d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, MICBA, 0);
2603d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
2604d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, FXBA, 0);
2605d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, FXWC, 0);
2606d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
2607d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, ADCBA, 0);
2608d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, TCB, 0);
2609d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, TCBS, 0);
2610d056fa04SAlexander Leidinger 
2611d056fa04SAlexander Leidinger 	/* disable channel interrupt */
2612d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, CLIEL, 0);
2613d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, CLIEH, 0);
2614d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SOLEL, 0);
2615d056fa04SAlexander Leidinger 	emu_wrptr(sc, 0, SOLEH, 0);
2616d056fa04SAlexander Leidinger 
2617d056fa04SAlexander Leidinger 	if (!SLIST_EMPTY(&sc->mem.blocks))
2618d056fa04SAlexander Leidinger 		device_printf(sc->dev, "warning: memblock list not empty\n");
2619d056fa04SAlexander Leidinger 
2620d056fa04SAlexander Leidinger 	SLIST_FOREACH(blk, &sc->mem.blocks, link)
2621d056fa04SAlexander Leidinger 		if (blk != NULL)
2622d056fa04SAlexander Leidinger 		device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner);
2623d056fa04SAlexander Leidinger 
2624d056fa04SAlexander Leidinger 	emu_free(&sc->mem, sc->mem.ptb_pages);
2625d056fa04SAlexander Leidinger 	emu_free(&sc->mem, sc->mem.silent_page);
2626d056fa04SAlexander Leidinger 
2627d056fa04SAlexander Leidinger 	return (0);
2628d056fa04SAlexander Leidinger }
2629d056fa04SAlexander Leidinger 
2630d056fa04SAlexander Leidinger static int
2631d056fa04SAlexander Leidinger emu_read_ivar(device_t bus, device_t dev, int ivar_index, uintptr_t * result)
2632d056fa04SAlexander Leidinger {
2633d056fa04SAlexander Leidinger 	struct sndcard_func *func = device_get_ivars(dev);
2634d056fa04SAlexander Leidinger 	struct emu_sc_info *sc = device_get_softc(bus);
2635d056fa04SAlexander Leidinger 
2636d056fa04SAlexander Leidinger 	switch (ivar_index) {
2637d056fa04SAlexander Leidinger 	case EMU_VAR_FUNC:
2638d056fa04SAlexander Leidinger 		*result = func->func;
2639d056fa04SAlexander Leidinger 		break;
2640d056fa04SAlexander Leidinger 	case EMU_VAR_ROUTE:
2641d056fa04SAlexander Leidinger 		*result = ((struct emu_pcminfo *)func->varinfo)->route;
2642d056fa04SAlexander Leidinger 		break;
2643d056fa04SAlexander Leidinger 	case EMU_VAR_ISEMU10K1:
2644d056fa04SAlexander Leidinger 		*result = sc->is_emu10k1;
2645d056fa04SAlexander Leidinger 		break;
2646d056fa04SAlexander Leidinger 	default:
2647d056fa04SAlexander Leidinger 		return (ENOENT);
2648d056fa04SAlexander Leidinger 	}
2649d056fa04SAlexander Leidinger 
2650d056fa04SAlexander Leidinger 	return (0);
2651d056fa04SAlexander Leidinger }
2652d056fa04SAlexander Leidinger 
2653d056fa04SAlexander Leidinger static int
2654d056fa04SAlexander Leidinger emu_write_ivar(device_t bus __unused, device_t dev __unused,
2655d056fa04SAlexander Leidinger     int ivar_index, uintptr_t value __unused)
2656d056fa04SAlexander Leidinger {
2657d056fa04SAlexander Leidinger 
2658d056fa04SAlexander Leidinger 	switch (ivar_index) {
2659d056fa04SAlexander Leidinger 		case 0:
2660d056fa04SAlexander Leidinger 		return (EINVAL);
2661d056fa04SAlexander Leidinger 
2662d056fa04SAlexander Leidinger 	default:
2663d056fa04SAlexander Leidinger 		return (ENOENT);
2664d056fa04SAlexander Leidinger 	}
2665d056fa04SAlexander Leidinger }
2666d056fa04SAlexander Leidinger 
2667d056fa04SAlexander Leidinger static int
2668d056fa04SAlexander Leidinger emu_pci_probe(device_t dev)
2669d056fa04SAlexander Leidinger {
2670d056fa04SAlexander Leidinger 	struct sbuf *s;
2671f856af04SAlexander Leidinger 	unsigned int thiscard = 0;
2672d056fa04SAlexander Leidinger 	uint16_t vendor;
2673d056fa04SAlexander Leidinger 
2674d056fa04SAlexander Leidinger 	vendor = pci_read_config(dev, PCIR_DEVVENDOR, /* bytes */ 2);
2675d056fa04SAlexander Leidinger 	if (vendor != 0x1102)
2676d056fa04SAlexander Leidinger 		return (ENXIO);	/* Not Creative */
2677d056fa04SAlexander Leidinger 
2678d056fa04SAlexander Leidinger 	thiscard = emu_getcard(dev);
2679f856af04SAlexander Leidinger 	if (thiscard == 0)
2680d056fa04SAlexander Leidinger 		return (ENXIO);
2681d056fa04SAlexander Leidinger 
2682d056fa04SAlexander Leidinger 	s = sbuf_new(NULL, NULL, 4096, 0);
2683d056fa04SAlexander Leidinger 	if (s == NULL)
2684d056fa04SAlexander Leidinger 		return (ENOMEM);
2685d056fa04SAlexander Leidinger 	sbuf_printf(s, "Creative %s [%s]", emu_cards[thiscard].desc, emu_cards[thiscard].SBcode);
2686d056fa04SAlexander Leidinger 	sbuf_finish(s);
2687d056fa04SAlexander Leidinger 
2688d056fa04SAlexander Leidinger 	device_set_desc_copy(dev, sbuf_data(s));
2689d056fa04SAlexander Leidinger 	return (BUS_PROBE_DEFAULT);
2690d056fa04SAlexander Leidinger }
2691d056fa04SAlexander Leidinger 
2692d056fa04SAlexander Leidinger 
2693d056fa04SAlexander Leidinger static int
2694d056fa04SAlexander Leidinger emu_pci_attach(device_t dev)
2695d056fa04SAlexander Leidinger {
2696d056fa04SAlexander Leidinger 	struct sndcard_func *func;
2697d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
2698d056fa04SAlexander Leidinger 	struct emu_pcminfo *pcminfo;
2699d056fa04SAlexander Leidinger 	struct emu_midiinfo *midiinfo[3];
2700d056fa04SAlexander Leidinger 	uint32_t data;
2701d056fa04SAlexander Leidinger 	int i;
2702d056fa04SAlexander Leidinger 	int device_flags;
2703d056fa04SAlexander Leidinger 	char status[255];
2704d056fa04SAlexander Leidinger 	int error = ENXIO;
2705d056fa04SAlexander Leidinger 
2706d056fa04SAlexander Leidinger 	sc = device_get_softc(dev);
2707d056fa04SAlexander Leidinger 
2708d056fa04SAlexander Leidinger 	/* Fill in the softc. */
2709d056fa04SAlexander Leidinger 	mtx_init(&sc->lock, "emu10kx", "bridge conf", MTX_DEF);
2710d056fa04SAlexander Leidinger 	mtx_init(&sc->rw, "emu10kx", "atomic op", MTX_DEF);
2711d056fa04SAlexander Leidinger 	sc->dev = dev;
2712d056fa04SAlexander Leidinger 	sc->type = pci_get_devid(dev);
2713d056fa04SAlexander Leidinger 	sc->rev = pci_get_revid(dev);
2714d056fa04SAlexander Leidinger 	sc->enable_ir = 0;
2715d056fa04SAlexander Leidinger 	sc->enable_debug = 0;
2716d056fa04SAlexander Leidinger 	sc->has_ac97 = 0;
2717d056fa04SAlexander Leidinger 	sc->has_51 = 0;
2718d056fa04SAlexander Leidinger 	sc->has_71 = 0;
2719d056fa04SAlexander Leidinger 	sc->broken_digital = 0;
2720d056fa04SAlexander Leidinger 	sc->is_emu10k1 = 0;
2721d056fa04SAlexander Leidinger 	sc->is_emu10k2 = 0;
2722d056fa04SAlexander Leidinger 	sc->is_ca0102 = 0;
2723d056fa04SAlexander Leidinger 	sc->is_ca0108 = 0;
2724d056fa04SAlexander Leidinger 	sc->is_cardbus = 0;
2725d056fa04SAlexander Leidinger 
2726d056fa04SAlexander Leidinger 	device_flags = emu_cards[emu_getcard(dev)].flags;
2727d056fa04SAlexander Leidinger 	if (device_flags & HAS_51)
2728d056fa04SAlexander Leidinger 		sc->has_51 = 1;
2729d056fa04SAlexander Leidinger 	if (device_flags & HAS_71) {
2730d056fa04SAlexander Leidinger 		sc->has_51 = 1;
2731d056fa04SAlexander Leidinger 		sc->has_71 = 1;
2732d056fa04SAlexander Leidinger 	}
2733d056fa04SAlexander Leidinger 	if (device_flags & IS_EMU10K1)
2734d056fa04SAlexander Leidinger 		sc->is_emu10k1 = 1;
2735d056fa04SAlexander Leidinger 	if (device_flags & IS_EMU10K2)
2736d056fa04SAlexander Leidinger 		sc->is_emu10k2 = 1;
2737d056fa04SAlexander Leidinger 	if (device_flags & IS_CA0102)
2738d056fa04SAlexander Leidinger 		sc->is_ca0102 = 1;
2739d056fa04SAlexander Leidinger 	if (device_flags & IS_CA0108)
2740d056fa04SAlexander Leidinger 		sc->is_ca0108 = 1;
2741d056fa04SAlexander Leidinger 	if ((sc->is_emu10k2) && (sc->rev == 4)) {
2742d056fa04SAlexander Leidinger 		sc->is_emu10k2 = 0;
2743d056fa04SAlexander Leidinger 		sc->is_ca0102 = 1;	/* for unknown Audigy 2 cards */
2744d056fa04SAlexander Leidinger 	}
2745d056fa04SAlexander Leidinger 	if ((sc->is_ca0102 == 1) || (sc->is_ca0108 == 1))
2746d056fa04SAlexander Leidinger 		if (device_flags & IS_CARDBUS)
2747d056fa04SAlexander Leidinger 			sc->is_cardbus = 1;
2748d056fa04SAlexander Leidinger 
2749d056fa04SAlexander Leidinger 	if ((sc->is_emu10k1 + sc->is_emu10k2 + sc->is_ca0102 + sc->is_ca0108) != 1) {
2750d056fa04SAlexander Leidinger 		device_printf(sc->dev, "Unable to detect HW chipset\n");
2751d056fa04SAlexander Leidinger 		goto bad;
2752d056fa04SAlexander Leidinger 	}
2753d056fa04SAlexander Leidinger 	if (device_flags & BROKEN_DIGITAL)
2754d056fa04SAlexander Leidinger 		sc->broken_digital = 1;
2755d056fa04SAlexander Leidinger 	if (device_flags & HAS_AC97)
2756d056fa04SAlexander Leidinger 		sc->has_ac97 = 1;
2757d056fa04SAlexander Leidinger 
2758d056fa04SAlexander Leidinger 	sc->opcode_shift = 0;
2759d056fa04SAlexander Leidinger 	if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
2760d056fa04SAlexander Leidinger 		sc->opcode_shift = 24;
2761d056fa04SAlexander Leidinger 		sc->high_operand_shift = 12;
2762f856af04SAlexander Leidinger 
2763f856af04SAlexander Leidinger 	/*	DSP map				*/
2764f856af04SAlexander Leidinger 	/*	sc->fx_base = 0x0		*/
2765d056fa04SAlexander Leidinger 		sc->input_base = 0x40;
2766d056fa04SAlexander Leidinger 	/*	sc->p16vinput_base = 0x50;	*/
2767d056fa04SAlexander Leidinger 		sc->output_base = 0x60;
2768d056fa04SAlexander Leidinger 		sc->efxc_base = 0x80;
2769d056fa04SAlexander Leidinger 	/*	sc->output32h_base = 0xa0;	*/
2770d056fa04SAlexander Leidinger 	/*	sc->output32l_base = 0xb0;	*/
2771d056fa04SAlexander Leidinger 		sc->dsp_zero = 0xc0;
2772f856af04SAlexander Leidinger 	/*	0xe0...0x100 are unknown	*/
2773f856af04SAlexander Leidinger 	/*	sc->tram_base = 0x200		*/
2774f856af04SAlexander Leidinger 	/*	sc->tram_addr_base = 0x300	*/
2775f856af04SAlexander Leidinger 		sc->gpr_base = A_FXGPREGBASE;
2776f856af04SAlexander Leidinger 		sc->num_gprs = 0x200;
2777f856af04SAlexander Leidinger 		sc->code_base = A_MICROCODEBASE;
2778f856af04SAlexander Leidinger 		sc->code_size = 0x800 / 2;	/* 0x600-0xdff,  2048 words,
2779f856af04SAlexander Leidinger 						 * 1024 instructions */
2780f856af04SAlexander Leidinger 
2781d056fa04SAlexander Leidinger 		sc->mchannel_fx = 8;
2782d056fa04SAlexander Leidinger 		sc->num_fxbuses = 16;
2783d056fa04SAlexander Leidinger 		sc->num_inputs = 8;
2784d056fa04SAlexander Leidinger 		sc->num_outputs = 16;
2785d056fa04SAlexander Leidinger 		sc->address_mask = A_PTR_ADDRESS_MASK;
2786d056fa04SAlexander Leidinger 	}
2787d056fa04SAlexander Leidinger 	if (sc->is_emu10k1) {
2788d056fa04SAlexander Leidinger 		sc->has_51 = 0;	/* We don't support 5.1 sound Live! 5.1 */
2789d056fa04SAlexander Leidinger 		sc->opcode_shift = 20;
2790d056fa04SAlexander Leidinger 		sc->high_operand_shift = 10;
2791d056fa04SAlexander Leidinger 		sc->code_base = MICROCODEBASE;
2792d056fa04SAlexander Leidinger 		sc->code_size = 0x400 / 2;	/* 0x400-0x7ff,  1024 words,
2793d056fa04SAlexander Leidinger 						 * 512 instructions */
2794d056fa04SAlexander Leidinger 		sc->gpr_base = FXGPREGBASE;
2795d056fa04SAlexander Leidinger 		sc->num_gprs = 0x100;
2796d056fa04SAlexander Leidinger 		sc->input_base = 0x10;
2797d056fa04SAlexander Leidinger 		sc->output_base = 0x20;
2798f856af04SAlexander Leidinger 		/*
2799f856af04SAlexander Leidinger 		 * XXX 5.1 Analog outputs are inside efxc address space!
2800f856af04SAlexander Leidinger 		 * They use ouput+0x11/+0x12 (=efxc+1/+2).
2801f856af04SAlexander Leidinger 		 * Don't use this efx registers for recording on SB Live! 5.1!
2802f856af04SAlexander Leidinger 		 */
2803d056fa04SAlexander Leidinger 		sc->efxc_base = 0x30;
2804d056fa04SAlexander Leidinger 		sc->dsp_zero = 0x40;
2805d056fa04SAlexander Leidinger 		sc->mchannel_fx = 0;
2806d056fa04SAlexander Leidinger 		sc->num_fxbuses = 8;
2807d056fa04SAlexander Leidinger 		sc->num_inputs = 8;
2808d056fa04SAlexander Leidinger 		sc->num_outputs = 16;
2809d056fa04SAlexander Leidinger 		sc->address_mask = PTR_ADDRESS_MASK;
2810d056fa04SAlexander Leidinger 	}
2811d056fa04SAlexander Leidinger 	if (sc->opcode_shift == 0)
2812d056fa04SAlexander Leidinger 		goto bad;
2813d056fa04SAlexander Leidinger 
2814d056fa04SAlexander Leidinger 	data = pci_read_config(dev, PCIR_COMMAND, 2);
2815d056fa04SAlexander Leidinger 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
2816d056fa04SAlexander Leidinger 	pci_write_config(dev, PCIR_COMMAND, data, 2);
2817d056fa04SAlexander Leidinger 	data = pci_read_config(dev, PCIR_COMMAND, 2);
2818d056fa04SAlexander Leidinger 
2819d056fa04SAlexander Leidinger 	pci_enable_busmaster(dev);
2820d056fa04SAlexander Leidinger 
2821d056fa04SAlexander Leidinger 	i = PCIR_BAR(0);
2822d056fa04SAlexander Leidinger 	sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE);
2823d056fa04SAlexander Leidinger 	if (sc->reg == NULL) {
2824d056fa04SAlexander Leidinger 		device_printf(dev, "unable to map register space\n");
2825d056fa04SAlexander Leidinger 		goto bad;
2826d056fa04SAlexander Leidinger 	}
2827d056fa04SAlexander Leidinger 	sc->st = rman_get_bustag(sc->reg);
2828d056fa04SAlexander Leidinger 	sc->sh = rman_get_bushandle(sc->reg);
2829d056fa04SAlexander Leidinger 
2830d056fa04SAlexander Leidinger 	for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
2831d056fa04SAlexander Leidinger 		sc->timer[i] = 0;	/* disable it */
2832d056fa04SAlexander Leidinger 
2833d056fa04SAlexander Leidinger 	i = 0;
2834d056fa04SAlexander Leidinger 	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE);
283555837609SAriff Abdullah 	if ((sc->irq == NULL) || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
2836d056fa04SAlexander Leidinger 		device_printf(dev, "unable to map interrupt\n");
2837d056fa04SAlexander Leidinger 		goto bad;
2838d056fa04SAlexander Leidinger 	}
2839d056fa04SAlexander Leidinger 	if (emu_rm_init(sc) != 0) {
2840d056fa04SAlexander Leidinger 		device_printf(dev, "unable to create resource manager\n");
2841d056fa04SAlexander Leidinger 		goto bad;
2842d056fa04SAlexander Leidinger 	}
2843d056fa04SAlexander Leidinger 	if (sc->is_cardbus)
2844d056fa04SAlexander Leidinger 		if (emu_cardbus_init(sc) != 0) {
2845d056fa04SAlexander Leidinger 			device_printf(dev, "unable to initialize CardBus interface\n");
2846d056fa04SAlexander Leidinger 			goto bad;
2847d056fa04SAlexander Leidinger 		}
2848d056fa04SAlexander Leidinger 	sc->ctx = device_get_sysctl_ctx(dev);
2849d056fa04SAlexander Leidinger 	if (sc->ctx == NULL)
2850d056fa04SAlexander Leidinger 		goto bad;
2851d056fa04SAlexander Leidinger 	sc->root = device_get_sysctl_tree(dev);
2852d056fa04SAlexander Leidinger 	if (sc->root == NULL)
2853d056fa04SAlexander Leidinger 		goto bad;
285455837609SAriff Abdullah 	if (emu_init(sc) == -1) {
2855d056fa04SAlexander Leidinger 		device_printf(dev, "unable to initialize the card\n");
2856d056fa04SAlexander Leidinger 		goto bad;
2857d056fa04SAlexander Leidinger 	}
2858d056fa04SAlexander Leidinger 	if (emu10kx_dev_init(sc) == ENXIO) {
2859d056fa04SAlexander Leidinger 		device_printf(dev, "unable to create control device\n");
2860d056fa04SAlexander Leidinger 		goto bad;
2861d056fa04SAlexander Leidinger 	}
2862d056fa04SAlexander Leidinger 	snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq));
2863d056fa04SAlexander Leidinger 
2864d056fa04SAlexander Leidinger 	/* Voices */
2865d056fa04SAlexander Leidinger 	for (i = 0; i < NUM_G; i++) {
2866d056fa04SAlexander Leidinger 		sc->voice[i].vnum = i;
2867d056fa04SAlexander Leidinger 		sc->voice[i].slave = NULL;
2868d056fa04SAlexander Leidinger 		sc->voice[i].busy = 0;
2869d056fa04SAlexander Leidinger 		sc->voice[i].ismaster = 0;
2870d056fa04SAlexander Leidinger 		sc->voice[i].running = 0;
2871d056fa04SAlexander Leidinger 		sc->voice[i].b16 = 0;
2872d056fa04SAlexander Leidinger 		sc->voice[i].stereo = 0;
2873d056fa04SAlexander Leidinger 		sc->voice[i].speed = 0;
2874d056fa04SAlexander Leidinger 		sc->voice[i].start = 0;
2875d056fa04SAlexander Leidinger 		sc->voice[i].end = 0;
2876d056fa04SAlexander Leidinger 	}
2877d056fa04SAlexander Leidinger 
2878d056fa04SAlexander Leidinger 	/* PCM Audio */
2879d056fa04SAlexander Leidinger 	/* FRONT */
2880d056fa04SAlexander Leidinger 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2881d056fa04SAlexander Leidinger 	if (func == NULL) {
2882d056fa04SAlexander Leidinger 		error = ENOMEM;
2883d056fa04SAlexander Leidinger 		goto bad;
2884d056fa04SAlexander Leidinger 	}
2885d056fa04SAlexander Leidinger 	pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2886d056fa04SAlexander Leidinger 	if (pcminfo == NULL) {
2887d056fa04SAlexander Leidinger 		error = ENOMEM;
2888d056fa04SAlexander Leidinger 		goto bad;
2889d056fa04SAlexander Leidinger 	}
2890d056fa04SAlexander Leidinger 	pcminfo->card = sc;
2891d056fa04SAlexander Leidinger 	pcminfo->route = RT_FRONT;
2892d056fa04SAlexander Leidinger 
2893d056fa04SAlexander Leidinger 	func->func = SCF_PCM;
2894d056fa04SAlexander Leidinger 	func->varinfo = pcminfo;
2895d056fa04SAlexander Leidinger 	sc->pcm[RT_FRONT] = device_add_child(dev, "pcm", -1);
2896d056fa04SAlexander Leidinger 	device_set_ivars(sc->pcm[RT_FRONT], func);
2897f856af04SAlexander Leidinger 
2898f856af04SAlexander Leidinger #ifdef SND_EMU10KX_MULTICHANNEL
2899d056fa04SAlexander Leidinger 	/* REAR */
2900d056fa04SAlexander Leidinger 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2901d056fa04SAlexander Leidinger 	if (func == NULL) {
2902d056fa04SAlexander Leidinger 		error = ENOMEM;
2903d056fa04SAlexander Leidinger 		goto bad;
2904d056fa04SAlexander Leidinger 	}
2905d056fa04SAlexander Leidinger 	pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2906d056fa04SAlexander Leidinger 	if (pcminfo == NULL) {
2907d056fa04SAlexander Leidinger 		error = ENOMEM;
2908d056fa04SAlexander Leidinger 		goto bad;
2909d056fa04SAlexander Leidinger 	}
2910d056fa04SAlexander Leidinger 	pcminfo->card = sc;
2911d056fa04SAlexander Leidinger 	pcminfo->route = RT_REAR;
2912d056fa04SAlexander Leidinger 
2913d056fa04SAlexander Leidinger 	func->func = SCF_PCM;
2914d056fa04SAlexander Leidinger 	func->varinfo = pcminfo;
2915d056fa04SAlexander Leidinger 	sc->pcm[RT_REAR] = device_add_child(dev, "pcm", -1);
2916d056fa04SAlexander Leidinger 	device_set_ivars(sc->pcm[RT_REAR], func);
2917d056fa04SAlexander Leidinger 	if (sc->has_51) {
2918d056fa04SAlexander Leidinger 		/* CENTER */
2919d056fa04SAlexander Leidinger 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2920d056fa04SAlexander Leidinger 		if (func == NULL) {
2921d056fa04SAlexander Leidinger 			error = ENOMEM;
2922d056fa04SAlexander Leidinger 			goto bad;
2923d056fa04SAlexander Leidinger 		}
2924d056fa04SAlexander Leidinger 		pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2925d056fa04SAlexander Leidinger 		if (pcminfo == NULL) {
2926d056fa04SAlexander Leidinger 			error = ENOMEM;
2927d056fa04SAlexander Leidinger 			goto bad;
2928d056fa04SAlexander Leidinger 		}
2929d056fa04SAlexander Leidinger 		pcminfo->card = sc;
2930d056fa04SAlexander Leidinger 		pcminfo->route = RT_CENTER;
2931d056fa04SAlexander Leidinger 
2932d056fa04SAlexander Leidinger 		func->func = SCF_PCM;
2933d056fa04SAlexander Leidinger 		func->varinfo = pcminfo;
2934d056fa04SAlexander Leidinger 		sc->pcm[RT_CENTER] = device_add_child(dev, "pcm", -1);
2935d056fa04SAlexander Leidinger 		device_set_ivars(sc->pcm[RT_CENTER], func);
2936d056fa04SAlexander Leidinger 		/* SUB */
2937d056fa04SAlexander Leidinger 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2938d056fa04SAlexander Leidinger 		if (func == NULL) {
2939d056fa04SAlexander Leidinger 			error = ENOMEM;
2940d056fa04SAlexander Leidinger 			goto bad;
2941d056fa04SAlexander Leidinger 		}
2942d056fa04SAlexander Leidinger 		pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2943d056fa04SAlexander Leidinger 		if (pcminfo == NULL) {
2944d056fa04SAlexander Leidinger 			error = ENOMEM;
2945d056fa04SAlexander Leidinger 			goto bad;
2946d056fa04SAlexander Leidinger 		}
2947d056fa04SAlexander Leidinger 		pcminfo->card = sc;
2948d056fa04SAlexander Leidinger 		pcminfo->route = RT_SUB;
2949d056fa04SAlexander Leidinger 
2950d056fa04SAlexander Leidinger 		func->func = SCF_PCM;
2951d056fa04SAlexander Leidinger 		func->varinfo = pcminfo;
2952d056fa04SAlexander Leidinger 		sc->pcm[RT_SUB] = device_add_child(dev, "pcm", -1);
2953d056fa04SAlexander Leidinger 		device_set_ivars(sc->pcm[RT_SUB], func);
2954d056fa04SAlexander Leidinger 	}
2955d056fa04SAlexander Leidinger 	if (sc->has_71) {
2956d056fa04SAlexander Leidinger 		/* SIDE */
2957d056fa04SAlexander Leidinger 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2958d056fa04SAlexander Leidinger 		if (func == NULL) {
2959d056fa04SAlexander Leidinger 			error = ENOMEM;
2960d056fa04SAlexander Leidinger 			goto bad;
2961d056fa04SAlexander Leidinger 		}
2962d056fa04SAlexander Leidinger 		pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2963d056fa04SAlexander Leidinger 		if (pcminfo == NULL) {
2964d056fa04SAlexander Leidinger 			error = ENOMEM;
2965d056fa04SAlexander Leidinger 			goto bad;
2966d056fa04SAlexander Leidinger 		}
2967d056fa04SAlexander Leidinger 		pcminfo->card = sc;
2968d056fa04SAlexander Leidinger 		pcminfo->route = RT_SIDE;
2969d056fa04SAlexander Leidinger 
2970d056fa04SAlexander Leidinger 		func->func = SCF_PCM;
2971d056fa04SAlexander Leidinger 		func->varinfo = pcminfo;
2972d056fa04SAlexander Leidinger 		sc->pcm[RT_SIDE] = device_add_child(dev, "pcm", -1);
2973d056fa04SAlexander Leidinger 		device_set_ivars(sc->pcm[RT_SIDE], func);
2974d056fa04SAlexander Leidinger 	};
2975f856af04SAlexander Leidinger #ifdef	SND_EMU10KX_MCH_RECORDING
2976f856af04SAlexander Leidinger 	/* MULTICHANNEL RECORDING */
2977f856af04SAlexander Leidinger 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
2978f856af04SAlexander Leidinger 	if (func == NULL) {
2979f856af04SAlexander Leidinger 		error = ENOMEM;
2980f856af04SAlexander Leidinger 		goto bad;
2981f856af04SAlexander Leidinger 	}
2982f856af04SAlexander Leidinger 	pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
2983f856af04SAlexander Leidinger 	if (pcminfo == NULL) {
2984f856af04SAlexander Leidinger 		error = ENOMEM;
2985f856af04SAlexander Leidinger 		goto bad;
2986f856af04SAlexander Leidinger 	}
2987f856af04SAlexander Leidinger 	pcminfo->card = sc;
2988f856af04SAlexander Leidinger 	pcminfo->route = RT_MCHRECORD;
2989f856af04SAlexander Leidinger 
2990f856af04SAlexander Leidinger 	func->func = SCF_PCM;
2991f856af04SAlexander Leidinger 	func->varinfo = pcminfo;
2992f856af04SAlexander Leidinger 	sc->pcm[RT_MCHRECORD] = device_add_child(dev, "pcm", -1);
2993f856af04SAlexander Leidinger 	device_set_ivars(sc->pcm[RT_MCHRECORD], func);
2994f856af04SAlexander Leidinger 
2995f856af04SAlexander Leidinger #endif	/* SMD_EMU10KX_MCH_RECORDING */
2996d056fa04SAlexander Leidinger #endif	/* SND_EMU10KX_MULTICHANNEL */
2997d056fa04SAlexander Leidinger 
2998d056fa04SAlexander Leidinger 	/* Midi Interface 1: Live!, Audigy, Audigy 2 */
2999d056fa04SAlexander Leidinger 	if ((sc->is_emu10k1) || (sc->is_emu10k2) || (sc->is_ca0102)) {
3000d056fa04SAlexander Leidinger 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3001d056fa04SAlexander Leidinger 		if (func == NULL) {
3002d056fa04SAlexander Leidinger 			error = ENOMEM;
3003d056fa04SAlexander Leidinger 			goto bad;
3004d056fa04SAlexander Leidinger 		}
3005d056fa04SAlexander Leidinger 		midiinfo[0] = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3006d056fa04SAlexander Leidinger 		if (midiinfo[0] == NULL) {
3007d056fa04SAlexander Leidinger 			error = ENOMEM;
3008d056fa04SAlexander Leidinger 			goto bad;
3009d056fa04SAlexander Leidinger 		}
3010d056fa04SAlexander Leidinger 		midiinfo[0]->card = sc;
3011d056fa04SAlexander Leidinger 		if (sc->is_emu10k2 || (sc->is_ca0102)) {
3012d056fa04SAlexander Leidinger 			midiinfo[0]->port = A_MUDATA1;
3013d056fa04SAlexander Leidinger 			midiinfo[0]->portnr = 1;
3014d056fa04SAlexander Leidinger 		}
3015d056fa04SAlexander Leidinger 		if (sc->is_emu10k1) {
3016d056fa04SAlexander Leidinger 			midiinfo[0]->port = MUDATA;
3017d056fa04SAlexander Leidinger 			midiinfo[0]->portnr = 1;
3018d056fa04SAlexander Leidinger 		}
3019d056fa04SAlexander Leidinger 		func->func = SCF_MIDI;
3020d056fa04SAlexander Leidinger 		func->varinfo = midiinfo[0];
3021d056fa04SAlexander Leidinger 		sc->midi[0] = device_add_child(dev, "midi", -1);
3022d056fa04SAlexander Leidinger 		device_set_ivars(sc->midi[0], func);
3023d056fa04SAlexander Leidinger 	}
3024d056fa04SAlexander Leidinger 	/* Midi Interface 2: Audigy, Audigy 2 (on AudigyDrive) */
3025d056fa04SAlexander Leidinger 	if (sc->is_emu10k2 || (sc->is_ca0102)) {
3026d056fa04SAlexander Leidinger 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
3027d056fa04SAlexander Leidinger 		if (func == NULL) {
3028d056fa04SAlexander Leidinger 			error = ENOMEM;
3029d056fa04SAlexander Leidinger 			goto bad;
3030d056fa04SAlexander Leidinger 		}
3031d056fa04SAlexander Leidinger 		midiinfo[1] = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
3032d056fa04SAlexander Leidinger 		if (midiinfo[1] == NULL) {
3033d056fa04SAlexander Leidinger 			error = ENOMEM;
3034d056fa04SAlexander Leidinger 			goto bad;
3035d056fa04SAlexander Leidinger 		}
3036d056fa04SAlexander Leidinger 		midiinfo[1]->card = sc;
3037d056fa04SAlexander Leidinger 
3038d056fa04SAlexander Leidinger 		midiinfo[1]->port = A_MUDATA2;
3039d056fa04SAlexander Leidinger 		midiinfo[1]->portnr = 2;
3040d056fa04SAlexander Leidinger 
3041d056fa04SAlexander Leidinger 		func->func = SCF_MIDI;
3042d056fa04SAlexander Leidinger 		func->varinfo = midiinfo[1];
3043d056fa04SAlexander Leidinger 		sc->midi[1] = device_add_child(dev, "midi", -1);
3044d056fa04SAlexander Leidinger 		device_set_ivars(sc->midi[1], func);
3045d056fa04SAlexander Leidinger 	}
3046d056fa04SAlexander Leidinger 
3047d056fa04SAlexander Leidinger 	return (bus_generic_attach(dev));
3048d056fa04SAlexander Leidinger 
3049d056fa04SAlexander Leidinger bad:
3050d056fa04SAlexander Leidinger 	/* XXX can we just call emu_pci_detach here? */
3051d056fa04SAlexander Leidinger 	if (sc->cdev)
3052d056fa04SAlexander Leidinger 		emu10kx_dev_uninit(sc);
3053d056fa04SAlexander Leidinger 	if (sc->rm != NULL)
3054d056fa04SAlexander Leidinger 		emu_rm_uninit(sc);
3055d056fa04SAlexander Leidinger 	if (sc->reg)
3056d056fa04SAlexander Leidinger 		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
3057d056fa04SAlexander Leidinger 	if (sc->ih)
3058d056fa04SAlexander Leidinger 		bus_teardown_intr(dev, sc->irq, sc->ih);
3059d056fa04SAlexander Leidinger 	if (sc->irq)
3060d056fa04SAlexander Leidinger 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
3061d056fa04SAlexander Leidinger 	mtx_destroy(&sc->lock);
3062d056fa04SAlexander Leidinger 	mtx_destroy(&sc->rw);
3063d056fa04SAlexander Leidinger 	return (error);
3064d056fa04SAlexander Leidinger }
3065d056fa04SAlexander Leidinger 
3066d056fa04SAlexander Leidinger static int
3067d056fa04SAlexander Leidinger emu_pci_detach(device_t dev)
3068d056fa04SAlexander Leidinger {
3069d056fa04SAlexander Leidinger 	struct emu_sc_info *sc;
3070d056fa04SAlexander Leidinger 	int devcount, i;
3071d056fa04SAlexander Leidinger 	device_t *childlist;
3072d056fa04SAlexander Leidinger 	int r = 0;
3073d056fa04SAlexander Leidinger 
3074d056fa04SAlexander Leidinger 	sc = device_get_softc(dev);
3075d056fa04SAlexander Leidinger 
3076f856af04SAlexander Leidinger 	for (i = 0; i < RT_COUNT; i++) {
3077d056fa04SAlexander Leidinger 		if (sc->pcm[i] != NULL)
3078d056fa04SAlexander Leidinger 			r = device_delete_child(dev, sc->pcm[i]);
3079d056fa04SAlexander Leidinger 		if (r)
3080d056fa04SAlexander Leidinger 			return (r);
3081d056fa04SAlexander Leidinger 	}
3082d056fa04SAlexander Leidinger 	if (sc->midi[0] != NULL)
3083d056fa04SAlexander Leidinger 		r = device_delete_child(dev, sc->midi[0]);
3084d056fa04SAlexander Leidinger 	if (r)
3085d056fa04SAlexander Leidinger 		return (r);
3086d056fa04SAlexander Leidinger 	if (sc->midi[1] != NULL)
3087d056fa04SAlexander Leidinger 		r = device_delete_child(dev, sc->midi[1]);
3088d056fa04SAlexander Leidinger 	if (r)
3089d056fa04SAlexander Leidinger 		return (r);
3090d056fa04SAlexander Leidinger 	(void)device_get_children(dev, &childlist, &devcount);
3091d056fa04SAlexander Leidinger 	for (i = 0; i < devcount - 1; i++) {
3092d056fa04SAlexander Leidinger 		device_printf(dev, "removing stale child %d (unit %d)\n", i, device_get_unit(childlist[i]));
3093d056fa04SAlexander Leidinger 		device_delete_child(dev, childlist[i]);
3094d056fa04SAlexander Leidinger 	}
3095d056fa04SAlexander Leidinger 	free(childlist, M_TEMP);
3096d056fa04SAlexander Leidinger 
3097d056fa04SAlexander Leidinger 	/* shutdown chip */
3098d056fa04SAlexander Leidinger 	emu_uninit(sc);
3099d056fa04SAlexander Leidinger 	r = emu10kx_dev_uninit(sc);
3100d056fa04SAlexander Leidinger 	if (r)
3101d056fa04SAlexander Leidinger 		return (r);
3102d056fa04SAlexander Leidinger 	emu_rm_uninit(sc);
310353bc1d83SAriff Abdullah 
310453bc1d83SAriff Abdullah 	if (sc->mem.dmat)
310553bc1d83SAriff Abdullah 		bus_dma_tag_destroy(sc->mem.dmat);
310653bc1d83SAriff Abdullah 
3107d056fa04SAlexander Leidinger 	if (sc->reg)
3108d056fa04SAlexander Leidinger 		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
3109d056fa04SAlexander Leidinger 	bus_teardown_intr(dev, sc->irq, sc->ih);
3110d056fa04SAlexander Leidinger 	bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
3111d056fa04SAlexander Leidinger 	mtx_destroy(&sc->lock);
3112d056fa04SAlexander Leidinger 	mtx_destroy(&sc->rw);
3113d056fa04SAlexander Leidinger 	return (bus_generic_detach(dev));
3114d056fa04SAlexander Leidinger }
3115d056fa04SAlexander Leidinger /* add suspend, resume */
3116d056fa04SAlexander Leidinger static device_method_t emu_methods[] = {
3117d056fa04SAlexander Leidinger 	/* Device interface */
3118d056fa04SAlexander Leidinger 	DEVMETHOD(device_probe, emu_pci_probe),
3119d056fa04SAlexander Leidinger 	DEVMETHOD(device_attach, emu_pci_attach),
3120d056fa04SAlexander Leidinger 	DEVMETHOD(device_detach, emu_pci_detach),
3121d056fa04SAlexander Leidinger 	/* Bus methods */
3122d056fa04SAlexander Leidinger 	DEVMETHOD(bus_read_ivar, emu_read_ivar),
3123d056fa04SAlexander Leidinger 	DEVMETHOD(bus_write_ivar, emu_write_ivar),
3124d056fa04SAlexander Leidinger 
3125d056fa04SAlexander Leidinger 	{0, 0}
3126d056fa04SAlexander Leidinger };
3127d056fa04SAlexander Leidinger 
3128d056fa04SAlexander Leidinger 
3129d056fa04SAlexander Leidinger static driver_t emu_driver = {
3130d056fa04SAlexander Leidinger 	"emu10kx",
3131d056fa04SAlexander Leidinger 	emu_methods,
3132d056fa04SAlexander Leidinger 	sizeof(struct emu_sc_info),
3133d056fa04SAlexander Leidinger 	NULL,
3134d056fa04SAlexander Leidinger 	0,
3135d056fa04SAlexander Leidinger 	NULL
3136d056fa04SAlexander Leidinger };
3137d056fa04SAlexander Leidinger 
3138d056fa04SAlexander Leidinger static int
3139d056fa04SAlexander Leidinger emu_modevent(module_t mod __unused, int cmd, void *data __unused)
3140d056fa04SAlexander Leidinger {
3141d056fa04SAlexander Leidinger 	int err = 0;
3142d056fa04SAlexander Leidinger 
3143d056fa04SAlexander Leidinger 	switch (cmd) {
3144d056fa04SAlexander Leidinger 	case MOD_LOAD:
3145d056fa04SAlexander Leidinger 		break;		/* Success */
3146d056fa04SAlexander Leidinger 
3147d056fa04SAlexander Leidinger 	case MOD_UNLOAD:
3148d056fa04SAlexander Leidinger 	case MOD_SHUTDOWN:
3149d056fa04SAlexander Leidinger 
3150d056fa04SAlexander Leidinger 		/* XXX  Should we check state of pcm & midi subdevices here? */
3151d056fa04SAlexander Leidinger 
3152d056fa04SAlexander Leidinger 		break;		/* Success */
3153d056fa04SAlexander Leidinger 
3154d056fa04SAlexander Leidinger 	default:
3155d056fa04SAlexander Leidinger 		err = EINVAL;
3156d056fa04SAlexander Leidinger 		break;
3157d056fa04SAlexander Leidinger 	}
3158d056fa04SAlexander Leidinger 
3159d056fa04SAlexander Leidinger 	return (err);
3160d056fa04SAlexander Leidinger 
3161d056fa04SAlexander Leidinger }
3162d056fa04SAlexander Leidinger 
3163d056fa04SAlexander Leidinger static devclass_t emu_devclass;
3164d056fa04SAlexander Leidinger 
3165d056fa04SAlexander Leidinger DRIVER_MODULE(snd_emu10kx, pci, emu_driver, emu_devclass, emu_modevent, NULL);
3166d056fa04SAlexander Leidinger DRIVER_MODULE(snd_emu10kx, cardbus, emu_driver, emu_devclass, emu_modevent, NULL);
3167d056fa04SAlexander Leidinger MODULE_VERSION(snd_emu10kx, SND_EMU10KX_PREFVER);
3168