xref: /openbsd/sys/dev/pci/envy.c (revision 91f110e0)
1 /*	$OpenBSD: envy.c,v 1.56 2013/05/24 07:58:46 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*
19  * TODO:
20  *
21  * - add nspdin, nspdout, to struct envy_card
22  *
23  * - use eeprom version rather isht flag
24  *
25  * - implement HT mixer, midi uart, spdif, init ADC/DACs for >48kHz modes
26  *
27  */
28 
29 #include "midi.h"
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/device.h>
33 #include <sys/ioctl.h>
34 #include <sys/audioio.h>
35 #include <sys/malloc.h>
36 #include <sys/kernel.h>
37 #include <dev/audio_if.h>
38 #include <dev/midi_if.h>
39 #include <dev/ic/ac97.h>
40 #include <dev/pci/pcivar.h>
41 #include <dev/pci/pcidevs.h>
42 #include <dev/pci/envyvar.h>
43 #include <dev/pci/envyreg.h>
44 #include <machine/bus.h>
45 #include <uvm/uvm.h>
46 
47 #ifdef ENVY_DEBUG
48 #define DPRINTF(...) do { if (envydebug) printf(__VA_ARGS__); } while(0)
49 #define DPRINTFN(n, ...) do { if (envydebug > (n)) printf(__VA_ARGS__); } while(0)
50 int envydebug = 1;
51 #else
52 #define DPRINTF(...) do {} while(0)
53 #define DPRINTFN(n, ...) do {} while(0)
54 #endif
55 #define DEVNAME(sc) ((sc)->dev.dv_xname)
56 
57 int  envymatch(struct device *, void *, void *);
58 void envyattach(struct device *, struct device *, void *);
59 int  envydetach(struct device *, int);
60 
61 int  envy_ccs_read(struct envy_softc *, int);
62 void envy_ccs_write(struct envy_softc *, int, int);
63 int  envy_mt_read_1(struct envy_softc *, int);
64 void envy_mt_write_1(struct envy_softc *, int, int);
65 int  envy_mt_read_2(struct envy_softc *, int);
66 void envy_mt_write_2(struct envy_softc *, int, int);
67 int  envy_mt_read_4(struct envy_softc *, int);
68 void envy_mt_write_4(struct envy_softc *, int, int);
69 int  envy_cci_read(struct envy_softc *, int);
70 void envy_cci_write(struct envy_softc *, int, int);
71 void envy_i2c_wait(struct envy_softc *);
72 int  envy_i2c_read(struct envy_softc *, int, int);
73 void envy_i2c_write(struct envy_softc *, int, int, int);
74 int  envy_gpio_getstate(struct envy_softc *);
75 void envy_gpio_setstate(struct envy_softc *, int);
76 int  envy_gpio_getmask(struct envy_softc *);
77 void envy_gpio_setmask(struct envy_softc *, int);
78 int  envy_gpio_getdir(struct envy_softc *);
79 void envy_gpio_setdir(struct envy_softc *, int);
80 void envy_gpio_i2c_start_bit(struct envy_softc *, int, int);
81 void envy_gpio_i2c_stop_bit(struct envy_softc *, int, int);
82 void envy_gpio_i2c_byte_out(struct envy_softc *, int, int, int);
83 int  envy_eeprom_gpioxxx(struct envy_softc *, int);
84 void envy_midi_wait(struct envy_softc *);
85 void envy_reset(struct envy_softc *);
86 int  envy_codec_read(struct envy_softc *, int, int);
87 void envy_codec_write(struct envy_softc *, int, int, int);
88 void envy_pintr(struct envy_softc *);
89 int  envy_intr(void *);
90 
91 int envy_lineout_getsrc(struct envy_softc *, int);
92 void envy_lineout_setsrc(struct envy_softc *, int, int);
93 int envy_spdout_getsrc(struct envy_softc *, int);
94 void envy_spdout_setsrc(struct envy_softc *, int, int);
95 void envy_mon_getvol(struct envy_softc *, int, int, int *);
96 void envy_mon_setvol(struct envy_softc *, int, int, int);
97 
98 int envy_open(void *, int);
99 void envy_close(void *);
100 void *envy_allocm(void *, int, size_t, int, int);
101 void envy_freem(void *, void *, int);
102 int envy_query_encoding(void *, struct audio_encoding *);
103 int envy_set_params(void *, int, int, struct audio_params *,
104     struct audio_params *);
105 int envy_round_blocksize(void *, int);
106 size_t envy_round_buffersize(void *, int, size_t);
107 int envy_trigger_output(void *, void *, void *, int,
108     void (*)(void *), void *, struct audio_params *);
109 int envy_trigger_input(void *, void *, void *, int,
110     void (*)(void *), void *, struct audio_params *);
111 int envy_halt_output(void *);
112 int envy_halt_input(void *);
113 int envy_getdev(void *, struct audio_device *);
114 int envy_query_devinfo(void *, struct mixer_devinfo *);
115 int envy_get_port(void *, struct mixer_ctrl *);
116 int envy_set_port(void *, struct mixer_ctrl *);
117 int envy_get_props(void *);
118 #if NMIDI > 0
119 int envy_midi_open(void *, int, void (*)(void *, int),
120     void (*)(void *), void *);
121 void envy_midi_close(void *);
122 int envy_midi_output(void *, int);
123 void envy_midi_getinfo(void *, struct midi_info *);
124 #endif
125 
126 int  envy_ac97_wait(struct envy_softc *);
127 int  envy_ac97_attach_codec(void *, struct ac97_codec_if *);
128 int  envy_ac97_read_codec(void *, u_int8_t, u_int16_t *);
129 int  envy_ac97_write_codec(void *, u_int8_t, u_int16_t);
130 void envy_ac97_reset_codec(void *);
131 enum ac97_host_flags envy_ac97_flags_codec(void *);
132 
133 void delta_init(struct envy_softc *);
134 void delta_codec_write(struct envy_softc *, int, int, int);
135 
136 void ap192k_init(struct envy_softc *);
137 void ap192k_codec_write(struct envy_softc *, int, int, int);
138 
139 void ewx_codec_write(struct envy_softc *, int, int, int);
140 
141 void revo51_init(struct envy_softc *);
142 void revo51_codec_write(struct envy_softc *, int, int, int);
143 
144 void envy_ac97_init(struct envy_softc *);
145 void dynex_sc51_init(struct envy_softc *);
146 
147 void julia_init(struct envy_softc *);
148 void julia_codec_write(struct envy_softc *, int, int, int);
149 
150 void unkenvy_init(struct envy_softc *);
151 void unkenvy_codec_write(struct envy_softc *, int, int, int);
152 int unkenvy_codec_ndev(struct envy_softc *);
153 
154 int ak4524_dac_ndev(struct envy_softc *);
155 void ak4524_dac_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
156 void ak4524_dac_get(struct envy_softc *, struct mixer_ctrl *, int);
157 int ak4524_dac_set(struct envy_softc *, struct mixer_ctrl *, int);
158 int ak4524_adc_ndev(struct envy_softc *);
159 void ak4524_adc_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
160 void ak4524_adc_get(struct envy_softc *, struct mixer_ctrl *, int);
161 int ak4524_adc_set(struct envy_softc *, struct mixer_ctrl *, int);
162 
163 int ak4358_dac_ndev(struct envy_softc *);
164 void ak4358_dac_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
165 void ak4358_dac_get(struct envy_softc *, struct mixer_ctrl *, int);
166 int ak4358_dac_set(struct envy_softc *, struct mixer_ctrl *, int);
167 
168 int ak5365_adc_ndev(struct envy_softc *);
169 void ak5365_adc_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
170 void ak5365_adc_get(struct envy_softc *, struct mixer_ctrl *, int);
171 int ak5365_adc_set(struct envy_softc *, struct mixer_ctrl *, int);
172 
173 struct cfattach envy_ca = {
174 	sizeof(struct envy_softc), envymatch, envyattach, envydetach
175 };
176 
177 struct cfdriver envy_cd = {
178 	NULL, "envy", DV_DULL
179 };
180 
181 struct audio_hw_if envy_hw_if = {
182 	envy_open,		/* open */
183 	envy_close,		/* close */
184 	NULL,			/* drain */
185 	envy_query_encoding,	/* query_encoding */
186 	envy_set_params,	/* set_params */
187 	envy_round_blocksize,	/* round_blocksize */
188 	NULL,			/* commit_settings */
189 	NULL,			/* init_output */
190 	NULL,			/* init_input */
191 	NULL,			/* start_output */
192 	NULL,			/* start_input */
193 	envy_halt_output,	/* halt_output */
194 	envy_halt_input,	/* halt_input */
195 	NULL,			/* speaker_ctl */
196 	envy_getdev,		/* getdev */
197 	NULL,			/* setfd */
198 	envy_set_port,		/* set_port */
199 	envy_get_port,		/* get_port */
200 	envy_query_devinfo,	/* query_devinfo */
201 	envy_allocm,		/* malloc */
202 	envy_freem,		/* free */
203 	envy_round_buffersize,	/* round_buffersize */
204 	NULL,			/* mappage */
205 	envy_get_props,		/* get_props */
206 	envy_trigger_output,	/* trigger_output */
207 	envy_trigger_input,	/* trigger_input */
208 	NULL
209 };
210 
211 #if NMIDI > 0
212 struct midi_hw_if envy_midi_hw_if = {
213 	envy_midi_open,
214 	envy_midi_close,
215 	envy_midi_output,
216 	NULL,				/* flush */
217 	envy_midi_getinfo,
218 	NULL				/* ioctl */
219 };
220 #endif
221 
222 struct pci_matchid envy_matchids[] = {
223 	{ PCI_VENDOR_ICENSEMBLE, PCI_PRODUCT_ICENSEMBLE_ICE1712 },
224 	{ PCI_VENDOR_ICENSEMBLE, PCI_PRODUCT_ICENSEMBLE_VT172x }
225 };
226 
227 /*
228  * correspondence between rates (in frames per second)
229  * and values of rate register
230  */
231 struct {
232 	int rate, reg;
233 } envy_rates[] = {
234 	{ 8000, 0x6}, { 9600, 0x3}, {11025, 0xa}, {12000, 2}, {16000, 5},
235 	{22050, 0x9}, {24000, 0x1}, {32000, 0x4}, {44100, 8}, {48000, 0},
236 	{64000, 0xf}, {88200, 0xb}, {96000, 0x7}, {-1, -1}
237 };
238 
239 /*
240  * ESI Julia cards don't have EEPROM, use this copy
241  */
242 static unsigned char julia_eeprom[ENVY_EEPROM_MAXSZ] = {
243 	/* gpio mask/dir/state is from linux */
244 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 	0x20, 0x80, 0xf8, 0xc3,
246 	0x9f, 0xff, 0x7f,
247 	0x90, 0xff, 0x7f,
248 	0x66, 0x00, 0x00
249 };
250 
251 struct envy_codec ak4524_dac = {
252 	"ak4524 dac", ak4524_dac_ndev, ak4524_dac_devinfo, ak4524_dac_get, ak4524_dac_set
253 }, ak4524_adc = {
254 	"ak4524 adc", ak4524_adc_ndev, ak4524_adc_devinfo, ak4524_adc_get, ak4524_adc_set
255 }, ak4358_dac = {
256 	"ak4358 dac", ak4358_dac_ndev, ak4358_dac_devinfo, ak4358_dac_get, ak4358_dac_set
257 }, ak5365_adc = {
258 	"ak5365 adc", ak5365_adc_ndev, ak5365_adc_devinfo, ak5365_adc_get, ak5365_adc_set
259 }, unkenvy_codec = {
260 	"unknown codec", unkenvy_codec_ndev, NULL, NULL, NULL
261 };
262 
263 /*
264  * array with vendor/product sub-IDs to card info
265  */
266 struct envy_card envy_cards[] = {
267 	{
268 		PCI_ID_CODE(0x1412, 0xd630),
269 		"M-Audio Delta 1010",
270 		8, &ak4524_adc, 8, &ak4524_dac,
271 		delta_init,
272 		delta_codec_write,
273 		NULL
274 	}, {
275 		PCI_ID_CODE(0x1412, 0xd632),
276 		"M-Audio Delta 66",
277 		4, &ak4524_adc, 4, &ak4524_dac,
278 		delta_init,
279 		delta_codec_write,
280 		NULL
281 	}, {
282 		PCI_ID_CODE(0x1412, 0xd633),
283 		"M-Audio Delta 44",
284 		4, &ak4524_adc, 4, &ak4524_dac,
285 		delta_init,
286 		delta_codec_write,
287 		NULL
288 	}, {
289 		PCI_ID_CODE(0x1412, 0xd63b),
290 		"M-Audio Delta 1010LT",
291 		8, &ak4524_adc, 8, &ak4524_dac,
292 		delta_init,
293 		delta_codec_write,
294 		NULL
295 	}, {
296 		PCI_ID_CODE(0x1412, 0xd634),
297 		"M-Audio Audiophile 2496",
298 		2, &ak4524_adc, 2, &ak4524_dac,
299 		delta_init,
300 		delta_codec_write,
301 		NULL
302 	}, {
303 		PCI_ID_CODE(0x153b, 0x1130),
304 		"Terratec EWX 24/96",
305 		2, &ak4524_adc, 2, &ak4524_dac,
306 		delta_init,
307 		ewx_codec_write,
308 		NULL
309 	}, {
310 		0,
311 		"unknown 1712-based card",
312 		8, &unkenvy_codec, 8, &unkenvy_codec,
313 		unkenvy_init,
314 		unkenvy_codec_write
315 	}
316 }, envy_cards_ht[] = {
317 	{
318 		PCI_ID_CODE(0x3031, 0x4553),
319 		"ESI Julia",
320 		2, &unkenvy_codec, 2, &ak4358_dac,
321 		julia_init,
322 		julia_codec_write,
323 		julia_eeprom
324 	}, {
325 		PCI_ID_CODE(0x1412, 0x3632),
326 		"M-Audio Audiophile 192k",
327 		2, &unkenvy_codec, 2, &ak4358_dac,
328 		ap192k_init,
329 		ap192k_codec_write
330 	}, {
331 		PCI_ID_CODE(0x1412, 0x3631),
332 		"M-Audio Revolution 5.1",
333 		2, &ak5365_adc, 6, &ak4358_dac,
334 		revo51_init,
335 		revo51_codec_write
336 	}, {
337 		PCI_ID_CODE(0x1412, 0x2403),
338 		"VIA Tremor 5.1",
339 		2, &unkenvy_codec, 6, &unkenvy_codec,
340 		envy_ac97_init,
341 		unkenvy_codec_write
342 	}, {
343 		PCI_ID_CODE(0x14c3, 0x1705),
344 		"Dynex DX-SC51",
345 		2, &unkenvy_codec, 6, &unkenvy_codec,
346 		dynex_sc51_init,
347 		unkenvy_codec_write
348 	}, {
349 		0,
350 		"unknown 1724-based card",
351 		2, &unkenvy_codec, 8, &unkenvy_codec,
352 		unkenvy_init,
353 		unkenvy_codec_write
354 	}
355 };
356 
357 
358 /*
359  * M-Audio Delta specific code
360  */
361 
362 /*
363  * GPIO pin numbers
364  */
365 #define DELTA_GPIO_CLK		0x2
366 #define DELTA_GPIO_DOUT		0x8
367 #define DELTA_GPIO_CSMASK	0x70
368 #define DELTA_GPIO_CS(dev)	((dev) << 4)
369 
370 void
371 delta_init(struct envy_softc *sc)
372 {
373 	int dev;
374 
375 	for (dev = 0; dev < sc->card->noch / 2; dev++) {
376 		envy_codec_write(sc, dev, AK4524_RST, 0x0);
377 		delay(300);
378 		envy_codec_write(sc, dev, AK4524_RST,
379 		    AK4524_RST_AD | AK4524_RST_DA);
380 		envy_codec_write(sc, dev, AK4524_FMT,
381 		    AK4524_FMT_IIS24);
382 		sc->shadow[dev][AK4524_DEEMVOL] = AK4524_DEEM_OFF;
383 		sc->shadow[dev][AK4524_ADC_GAIN0] = 0x7f;
384 		sc->shadow[dev][AK4524_ADC_GAIN1] = 0x7f;
385 		sc->shadow[dev][AK4524_DAC_GAIN0] = 0x7f;
386 		sc->shadow[dev][AK4524_DAC_GAIN1] = 0x7f;
387 	}
388 }
389 
390 void
391 delta_codec_write(struct envy_softc *sc, int dev, int addr, int data)
392 {
393 	int bits, i, reg;
394 
395 	reg = envy_gpio_getstate(sc);
396 	reg &= ~DELTA_GPIO_CSMASK;
397 	reg |=  DELTA_GPIO_CS(dev);
398 	envy_gpio_setstate(sc, reg);
399 	delay(1);
400 
401 	bits  = 0xa000 | (addr << 8) | data;
402 	for (i = 0; i < 16; i++) {
403 		reg &= ~(DELTA_GPIO_CLK | DELTA_GPIO_DOUT);
404 		reg |= (bits & 0x8000) ? DELTA_GPIO_DOUT : 0;
405 		envy_gpio_setstate(sc, reg);
406 		delay(1);
407 
408 		reg |= DELTA_GPIO_CLK;
409 		envy_gpio_setstate(sc, reg);
410 		delay(1);
411 		bits <<= 1;
412 	}
413 
414 	reg |= DELTA_GPIO_CSMASK;
415 	envy_gpio_setstate(sc, reg);
416 	delay(1);
417 }
418 
419 /*
420  * M-Audio Audiophile 192 specific code
421  */
422 
423 /*
424  * GPIO pin numbers
425  */
426 #define AP192K_GPIO_CLK		0x2
427 #define AP192K_GPIO_DOUT	0x8
428 #define AP192K_GPIO_CSMASK	0x30
429 #define AP192K_GPIO_CS(dev)	((dev) << 4)
430 #define AP192K_GPIO_ADC_PWR	0x800
431 #define AP192K_GPIO_ADC_DFSMASK	(3 << 9)
432 #define AP192K_GPIO_ADC_DFS(v)	((v) << 9)
433 #define AP192K_GPIO_MUTE	0x400000
434 
435 void
436 ap192k_init(struct envy_softc *sc)
437 {
438 	int i, reg;
439 
440 	/* AK4358 */
441 	envy_codec_write(sc, 0, 0, 0);	/* reset */
442 	delay(300);
443 	envy_codec_write(sc, 0, 0, 0x87);	/* i2s mode */
444 	delay(1);
445 	for (i = 0; i < sc->card->noch; i++) {
446 		sc->shadow[0][AK4358_ATT(i)] = 0xff;
447 	}
448 
449 	/* AK5385 */
450 	delay(1);
451 	reg = envy_gpio_getstate(sc);
452 	reg &= ~(AP192K_GPIO_ADC_PWR | AP192K_GPIO_ADC_DFSMASK);
453 	reg |= AP192K_GPIO_ADC_DFS(0);
454 	envy_gpio_setstate(sc, reg);
455 	reg |= AP192K_GPIO_ADC_PWR;
456 	envy_gpio_setstate(sc, reg);
457 }
458 
459 void
460 ap192k_codec_write(struct envy_softc *sc, int dev, int addr, int data)
461 {
462 	int bits, i, reg;
463 
464 	reg = envy_gpio_getstate(sc);
465 	reg &= ~AP192K_GPIO_CSMASK;
466 	reg |=  AP192K_GPIO_CS(dev);
467 	envy_gpio_setstate(sc, reg);
468 	delay(1);
469 
470 	bits  = 0xa000 | (addr << 8) | data;
471 	for (i = 0; i < 16; i++) {
472 		reg &= ~(AP192K_GPIO_CLK | AP192K_GPIO_DOUT);
473 		reg |= (bits & 0x8000) ? AP192K_GPIO_DOUT : 0;
474 		envy_gpio_setstate(sc, reg);
475 		delay(1);
476 
477 		reg |= AP192K_GPIO_CLK;
478 		envy_gpio_setstate(sc, reg);
479 		delay(1);
480 		bits <<= 1;
481 	}
482 
483 	reg |= AP192K_GPIO_CSMASK;
484 	envy_gpio_setstate(sc, reg);
485 	delay(1);
486 }
487 
488 /*
489  * Terratec EWX specific code
490  */
491 
492 /*
493  * GPIO pin numbers
494  */
495 #define EWX_GPIO_CSMASK		0x01
496 #define EWX_GPIO_DOUT		0x10
497 #define EWX_GPIO_CLK		0x20
498 
499 void
500 ewx_codec_write(struct envy_softc *sc, int dev, int addr, int data)
501 {
502 	int bits, i, reg;
503 
504 	reg = envy_gpio_getstate(sc);
505 	reg |= (EWX_GPIO_CSMASK | EWX_GPIO_CLK);
506 	envy_gpio_setstate(sc, reg);
507 	delay(1);
508 
509 	bits = 0xa000 | (addr << 8) | data;
510 	for (i = 0; i < 16; i++) {
511 		reg &= ~(EWX_GPIO_CLK | EWX_GPIO_DOUT);
512 		reg |= (bits & 0x8000) ? EWX_GPIO_DOUT : 0;
513 		envy_gpio_setstate(sc, reg);
514 		delay(1);
515 
516 		reg |= EWX_GPIO_CLK;
517 		envy_gpio_setstate(sc, reg);
518 		delay(1);
519 		bits <<= 1;
520 	}
521 
522 	reg &= ~EWX_GPIO_CSMASK;
523 	envy_gpio_setstate(sc, reg);
524 	delay(1);
525 
526 	reg |= EWX_GPIO_CSMASK;
527 	envy_gpio_setstate(sc, reg);
528 	delay(1);
529 }
530 
531 
532 /*
533  * M-Audio Revolution 5.1 specific code
534  */
535 
536 #define REVO51_GPIO_CLK		0x2
537 #define REVO51_GPIO_DOUT	0x8
538 #define REVO51_GPIO_CSMASK	0x30
539 #define REVO51_GPIO_CS(dev)	((dev) ? 0x10 : 0x20)
540 #define REVO51_MUTE		0x400000
541 #define REVO51_PT2258S_SDA	0x40
542 #define REVO51_PT2258S_SCL	0x80
543 #define REVO51_PT2258S_ADDR	0x80
544 #define REVO51_PT2258S_MUTE	6
545 
546 void
547 revo51_init(struct envy_softc *sc)
548 {
549 	int i, reg;
550 
551 	/* AK4358 */
552 	envy_codec_write(sc, 0, 0, 0);	/* reset */
553 	delay(300);
554 	envy_codec_write(sc, 0, 0, 0x87);	/* i2s mode */
555 	for (i = 0; i < sc->card->noch; i++) {
556 		sc->shadow[0][AK4358_ATT(i)] = 0xff;
557 	}
558 
559 	/* AK5365 */
560 	envy_codec_write(sc, 1, AK5365_RST, 0);	/* reset */
561 	delay(300);
562 	envy_codec_write(sc, 1, AK5365_CTRL, AK5365_CTRL_I2S);	/* i2s mode */
563 	envy_codec_write(sc, 1, AK5365_RST , AK5365_RST_NORM);
564 	sc->shadow[1][AK5365_ATT(0)] = 0x7f;
565 	sc->shadow[1][AK5365_ATT(1)] = 0x7f;
566 
567 	/* PT2258S */
568 	envy_codec_write(sc, 2, REVO51_PT2258S_MUTE, 0xc0);	/* reset */
569 	envy_codec_write(sc, 2, REVO51_PT2258S_MUTE, 0xf9);	/* mute */
570 
571 	reg = envy_gpio_getstate(sc);
572 	reg |= REVO51_MUTE;
573 	envy_gpio_setstate(sc, reg);
574 }
575 
576 void
577 revo51_codec_write(struct envy_softc *sc, int dev, int addr, int data)
578 {
579 	int attn, bits, mask, reg;
580 	int xlat[6] = {0x90, 0x50, 0x10, 0x30, 0x70, 0xb0};
581 
582 	/* AK4358 & AK5365 */
583 	if (dev < 2) {
584 		reg = envy_gpio_getstate(sc);
585 		reg &= ~REVO51_GPIO_CSMASK;
586 		reg |=  REVO51_GPIO_CS(dev);
587 		envy_gpio_setstate(sc, reg);
588 		delay(1);
589 
590 		bits  = 0xa000 | (addr << 8) | data;
591 		for (mask = 0x8000; mask != 0; mask >>= 1) {
592 			reg &= ~(REVO51_GPIO_CLK | REVO51_GPIO_DOUT);
593 			reg |= (bits & mask) ? REVO51_GPIO_DOUT : 0;
594 			envy_gpio_setstate(sc, reg);
595 			delay(1);
596 
597 			reg |= REVO51_GPIO_CLK;
598 			envy_gpio_setstate(sc, reg);
599 			delay(1);
600 		}
601 
602 		reg |= REVO51_GPIO_CSMASK;
603 		envy_gpio_setstate(sc, reg);
604 		delay(1);
605 		return;
606 	}
607 
608 	/* PT2258S */
609 	envy_gpio_i2c_start_bit(sc, REVO51_PT2258S_SDA, REVO51_PT2258S_SCL);
610 	envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA, REVO51_PT2258S_SCL,
611 	    REVO51_PT2258S_ADDR);
612 
613 	if (addr == REVO51_PT2258S_MUTE) {
614 		envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA,
615 		    REVO51_PT2258S_SCL, data);
616 	} else {
617 		/* 1's digit */
618 		attn = data % 10;
619 		attn += xlat[addr];
620 		envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA,
621 		    REVO51_PT2258S_SCL, attn);
622 
623 		/* 10's digit */
624 		attn = data / 10;
625 		attn += xlat[addr] - 0x10;
626 		envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA,
627 		    REVO51_PT2258S_SCL, attn);
628 	}
629 
630 	envy_gpio_i2c_stop_bit(sc, REVO51_PT2258S_SDA, REVO51_PT2258S_SCL);
631 }
632 
633 /*
634  * Generic AC'97 initialization
635  */
636 
637 void
638 envy_ac97_init(struct envy_softc *sc)
639 {
640 	sc->isac97 = 1;
641 	sc->host_if.arg = sc;
642 	sc->host_if.attach = envy_ac97_attach_codec;
643 	sc->host_if.read = envy_ac97_read_codec;
644 	sc->host_if.write = envy_ac97_write_codec;
645 	sc->host_if.reset = envy_ac97_reset_codec;
646 	sc->host_if.flags = envy_ac97_flags_codec;
647 
648 	if (ac97_attach(&sc->host_if) != 0)
649 		printf("%s: can't attach ac97\n", DEVNAME(sc));
650 }
651 
652 /*
653  * Dynex
654  */
655 
656 void
657 dynex_sc51_init(struct envy_softc *sc)
658 {
659 	sc->codec_flags |= AC97_HOST_VT1616_DYNEX;
660 	envy_ac97_init(sc);
661 }
662 
663 /*
664  * ESI Julia specific code
665  */
666 
667 void
668 julia_init(struct envy_softc *sc)
669 {
670 	int i;
671 
672 	envy_codec_write(sc, 0, 0, 0);	/* reset */
673 	delay(300);
674 	envy_codec_write(sc, 0, 0, 0x87);	/* i2s mode */
675 	for (i = 0; i < sc->card->noch; i++) {
676 		sc->shadow[0][AK4358_ATT(i)] = 0xff;
677 	}
678 }
679 
680 void
681 julia_codec_write(struct envy_softc *sc, int dev, int addr, int data)
682 {
683 #define JULIA_AK4358_ADDR	0x11
684 	envy_i2c_write(sc, JULIA_AK4358_ADDR, addr, data);
685 }
686 
687 /*
688  * unknown card, ignore codecs setup and hope it works with the power on
689  * settings
690  */
691 
692 void
693 unkenvy_init(struct envy_softc *sc)
694 {
695 }
696 
697 void
698 unkenvy_codec_write(struct envy_softc *sc, int dev, int addr, int data)
699 {
700 }
701 
702 int
703 unkenvy_codec_ndev(struct envy_softc *sc)
704 {
705 	return 0;
706 }
707 
708 /*
709  * AK 4358 DAC specific code
710  */
711 int
712 ak4358_dac_ndev(struct envy_softc *sc)
713 {
714 	/* 1 volume knob per channel */
715 	return sc->card->noch;
716 }
717 
718 void
719 ak4358_dac_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
720 {
721 	dev->type = AUDIO_MIXER_VALUE;
722 	dev->mixer_class = ENVY_MIX_CLASSOUT;
723 	dev->un.v.delta = 2;
724 	dev->un.v.num_channels = 1;
725 	snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
726 	    AudioNline "%d", idx);
727 	strlcpy(dev->un.v.units.name, AudioNvolume,
728 	    MAX_AUDIO_DEV_LEN);
729 }
730 
731 void
732 ak4358_dac_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
733 {
734 	int val;
735 
736 	val = envy_codec_read(sc, 0, AK4358_ATT(idx)) & ~AK4358_ATT_EN;
737 	ctl->un.value.num_channels = 1;
738 	ctl->un.value.level[0] = 2 * val;
739 }
740 
741 int
742 ak4358_dac_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
743 {
744 	int val;
745 
746 	if (ctl->un.value.num_channels != 1)
747 		return EINVAL;
748 	val = ctl->un.value.level[0] / 2;
749 	envy_codec_write(sc, 0, AK4358_ATT(idx), val | AK4358_ATT_EN);
750 	return 0;
751 }
752 
753 /*
754  * AK 4524 DAC specific code
755  */
756 int
757 ak4524_dac_ndev(struct envy_softc *sc)
758 {
759 	/* 1 mute + 2 volume knobs per channel pair */
760 	return 3 * (sc->card->noch / 2);
761 }
762 
763 void
764 ak4524_dac_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
765 {
766 	int ndev;
767 
768 	ndev = sc->card->noch;
769 	if (idx < ndev) {
770 		dev->type = AUDIO_MIXER_VALUE;
771 		dev->mixer_class = ENVY_MIX_CLASSOUT;
772 		dev->un.v.delta = 2;
773 		dev->un.v.num_channels = 1;
774 		snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
775 		    AudioNline "%d", idx);
776 		strlcpy(dev->un.v.units.name, AudioNvolume,
777 		    MAX_AUDIO_DEV_LEN);
778 	} else {
779 		idx -= ndev;
780 		dev->type = AUDIO_MIXER_ENUM;
781 		dev->mixer_class = ENVY_MIX_CLASSOUT;
782 		dev->un.e.member[0].ord = 0;
783 		strlcpy(dev->un.e.member[0].label.name, AudioNoff,
784 		    MAX_AUDIO_DEV_LEN);
785 		dev->un.e.member[1].ord = 1;
786 		strlcpy(dev->un.e.member[1].label.name, AudioNon,
787 		   MAX_AUDIO_DEV_LEN);
788 		dev->un.e.num_mem = 2;
789 		snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
790 		    AudioNmute "%d-%d", 2 * idx, 2 * idx + 1);
791 	}
792 }
793 
794 void
795 ak4524_dac_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
796 {
797 	int val, ndev;
798 
799 	ndev = sc->card->noch;
800 	if (idx < ndev) {
801 		val = envy_codec_read(sc, idx / 2,
802 		    (idx % 2) + AK4524_DAC_GAIN0);
803 		ctl->un.value.num_channels = 1;
804 		ctl->un.value.level[0] = 2 * val;
805 	} else {
806 		idx -= ndev;
807 		val = envy_codec_read(sc, idx, AK4524_DEEMVOL);
808 		ctl->un.ord = (val & AK4524_MUTE) ? 1 : 0;
809 	}
810 }
811 
812 int
813 ak4524_dac_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
814 {
815 	int val, ndev;
816 
817 	ndev = sc->card->noch;
818 	if (idx < ndev) {
819 		if (ctl->un.value.num_channels != 1)
820 			return EINVAL;
821 		val = ctl->un.value.level[0] / 2;
822 		envy_codec_write(sc, idx / 2,
823 		    (idx % 2) + AK4524_DAC_GAIN0, val);
824 	} else {
825 		idx -= ndev;
826 		if (ctl->un.ord >= 2)
827 			return EINVAL;
828 		val = AK4524_DEEM_OFF | (ctl->un.ord ? AK4524_MUTE : 0);
829 		envy_codec_write(sc, idx, AK4524_DEEMVOL, val);
830 	}
831 	return 0;
832 }
833 
834 /*
835  * AK 4524 ADC specific code
836  */
837 int
838 ak4524_adc_ndev(struct envy_softc *sc)
839 {
840 	/* one volume per channel */
841 	return sc->card->nich;
842 }
843 
844 void
845 ak4524_adc_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
846 {
847 	dev->type = AUDIO_MIXER_VALUE;
848 	dev->mixer_class = ENVY_MIX_CLASSIN;
849 	dev->un.v.delta = 2;
850 	dev->un.v.num_channels = 1;
851 	snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, AudioNline "%d", idx);
852 	strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN);
853 }
854 
855 void
856 ak4524_adc_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
857 {
858 	int val;
859 
860 	val = envy_codec_read(sc, idx / 2, (idx % 2) + AK4524_ADC_GAIN0);
861 	ctl->un.value.num_channels = 1;
862 	ctl->un.value.level[0] = 2 * val;
863 }
864 
865 int
866 ak4524_adc_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
867 {
868 	int val;
869 
870 	if (ctl->un.value.num_channels != 1)
871 		return EINVAL;
872 	val = ctl->un.value.level[0] / 2;
873 	envy_codec_write(sc, idx / 2, (idx % 2) + AK4524_ADC_GAIN0, val);
874 	return 0;
875 }
876 
877 /*
878  * AK 5365 ADC specific code
879  */
880 int
881 ak5365_adc_ndev(struct envy_softc *sc)
882 {
883 	/* 1 source + 2 volume knobs per channel pair */
884 	return (sc->card->nich + 1);
885 }
886 
887 void
888 ak5365_adc_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
889 {
890 	int ndev, i;
891 
892 	ndev = sc->card->nich;
893 	if (idx < ndev) {
894 		dev->type = AUDIO_MIXER_VALUE;
895 		dev->mixer_class = ENVY_MIX_CLASSIN;
896 		dev->un.v.delta = 2;
897 		dev->un.v.num_channels = 1;
898 		snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
899 		    AudioNline "%d", idx);
900 		strlcpy(dev->un.v.units.name, AudioNvolume,
901 		    MAX_AUDIO_DEV_LEN);
902 	} else {
903 		dev->type = AUDIO_MIXER_ENUM;
904 		dev->mixer_class = ENVY_MIX_CLASSIN;
905 		for (i = 0; i < 5; i++) {
906 			dev->un.e.member[i].ord = i;
907 			snprintf(dev->un.e.member[i].label.name,
908 			    MAX_AUDIO_DEV_LEN, AudioNline "%d", i);
909 		}
910 		dev->un.e.num_mem = 5;
911 		strlcpy(dev->label.name, AudioNsource,
912 		    MAX_AUDIO_DEV_LEN);
913 	}
914 }
915 
916 void
917 ak5365_adc_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
918 {
919 	int val, ndev;
920 
921 	ndev = sc->card->nich;
922 	if (idx < ndev) {
923 		val = envy_codec_read(sc, 1, AK5365_ATT(idx));
924 		ctl->un.value.num_channels = 1;
925 		ctl->un.value.level[0] = 2 * val;
926 	} else {
927 		ctl->un.ord = envy_codec_read(sc, 1, AK5365_SRC);
928 	}
929 }
930 
931 int
932 ak5365_adc_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
933 {
934 	int val, ndev;
935 
936 	ndev = sc->card->nich;
937 	if (idx < ndev) {
938 		if (ctl->un.value.num_channels != 1)
939 			return EINVAL;
940 		val = ctl->un.value.level[0] / 2;
941 		envy_codec_write(sc, 1, AK5365_ATT(idx), val);
942 	} else {
943 		if (ctl->un.ord >= 5)
944 			return EINVAL;
945 		val = ctl->un.ord & AK5365_SRC_MASK;
946 		envy_codec_write(sc, 1, AK5365_SRC, val);
947 	}
948 	return 0;
949 }
950 
951 /*
952  * generic Envy24 and Envy24HT code, common to all cards
953  */
954 
955 int
956 envy_ccs_read(struct envy_softc *sc, int reg)
957 {
958 	int val;
959 
960 	val = bus_space_read_1(sc->ccs_iot, sc->ccs_ioh, reg);
961 	bus_space_barrier(sc->ccs_iot, sc->ccs_ioh, 0, sc->ccs_iosz,
962 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
963 	return val;
964 }
965 
966 void
967 envy_ccs_write(struct envy_softc *sc, int reg, int val)
968 {
969 	bus_space_write_1(sc->ccs_iot, sc->ccs_ioh, reg, val);
970 	bus_space_barrier(sc->ccs_iot, sc->ccs_ioh, 0, sc->ccs_iosz,
971 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
972 }
973 
974 int
975 envy_mt_read_1(struct envy_softc *sc, int reg)
976 {
977 	int val;
978 
979 	val = bus_space_read_1(sc->mt_iot, sc->mt_ioh, reg);
980 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
981 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
982 	return val;
983 }
984 
985 void
986 envy_mt_write_1(struct envy_softc *sc, int reg, int val)
987 {
988 	bus_space_write_1(sc->mt_iot, sc->mt_ioh, reg, val);
989 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
990 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
991 }
992 
993 int
994 envy_mt_read_2(struct envy_softc *sc, int reg)
995 {
996 	int val;
997 
998 	val = bus_space_read_2(sc->mt_iot, sc->mt_ioh, reg);
999 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1000 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1001 	return val;
1002 }
1003 
1004 void
1005 envy_mt_write_2(struct envy_softc *sc, int reg, int val)
1006 {
1007 	bus_space_write_2(sc->mt_iot, sc->mt_ioh, reg, val);
1008 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1009 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1010 }
1011 
1012 int
1013 envy_mt_read_4(struct envy_softc *sc, int reg)
1014 {
1015 	int val;
1016 
1017 	val = bus_space_read_4(sc->mt_iot, sc->mt_ioh, reg);
1018 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1019 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1020 	return val;
1021 }
1022 
1023 void
1024 envy_mt_write_4(struct envy_softc *sc, int reg, int val)
1025 {
1026 	bus_space_write_4(sc->mt_iot, sc->mt_ioh, reg, val);
1027 	bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1028 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1029 }
1030 
1031 int
1032 envy_cci_read(struct envy_softc *sc, int index)
1033 {
1034 	int val;
1035 
1036 	envy_ccs_write(sc, ENVY_CCI_INDEX, index);
1037 	val = envy_ccs_read(sc, ENVY_CCI_DATA);
1038 	return val;
1039 }
1040 
1041 void
1042 envy_cci_write(struct envy_softc *sc, int index, int data)
1043 {
1044 	envy_ccs_write(sc, ENVY_CCI_INDEX, index);
1045 	envy_ccs_write(sc, ENVY_CCI_DATA, data);
1046 }
1047 
1048 int
1049 envy_gpio_getstate(struct envy_softc *sc)
1050 {
1051 	if (sc->isht) {
1052 		return envy_ccs_read(sc, ENVY_CCS_GPIODATA0) |
1053 		    (envy_ccs_read(sc, ENVY_CCS_GPIODATA1) << 8) |
1054 		    (envy_ccs_read(sc, ENVY_CCS_GPIODATA2) << 16);
1055 	} else
1056 		return envy_cci_read(sc, ENVY_CCI_GPIODATA);
1057 }
1058 
1059 void
1060 envy_gpio_setstate(struct envy_softc *sc, int reg)
1061 {
1062 	if (sc->isht) {
1063 		envy_ccs_write(sc, ENVY_CCS_GPIODATA0, reg & 0xff);
1064 		envy_ccs_write(sc, ENVY_CCS_GPIODATA1, (reg >> 8) & 0xff);
1065 		envy_ccs_write(sc, ENVY_CCS_GPIODATA2, (reg >> 16) & 0xff);
1066 	} else
1067 		envy_cci_write(sc, ENVY_CCI_GPIODATA, reg);
1068 }
1069 
1070 int
1071 envy_gpio_getmask(struct envy_softc *sc)
1072 {
1073 	if (sc->isht) {
1074 		return envy_ccs_read(sc, ENVY_CCS_GPIOMASK0) |
1075 		    (envy_ccs_read(sc, ENVY_CCS_GPIOMASK1) << 8) |
1076 		    (envy_ccs_read(sc, ENVY_CCS_GPIOMASK2) << 16);
1077 	} else
1078 		return envy_cci_read(sc, ENVY_CCI_GPIOMASK);
1079 }
1080 
1081 void
1082 envy_gpio_setmask(struct envy_softc *sc, int mask)
1083 {
1084 	if (sc->isht) {
1085 		envy_ccs_write(sc, ENVY_CCS_GPIOMASK0, mask & 0xff);
1086 		envy_ccs_write(sc, ENVY_CCS_GPIOMASK1, (mask >> 8) & 0xff);
1087 		envy_ccs_write(sc, ENVY_CCS_GPIOMASK2, (mask >> 16) & 0xff);
1088 	} else
1089 		envy_cci_write(sc, ENVY_CCI_GPIOMASK, mask);
1090 }
1091 
1092 int
1093 envy_gpio_getdir(struct envy_softc *sc)
1094 {
1095 	if (sc->isht) {
1096 		return envy_ccs_read(sc, ENVY_CCS_GPIODIR0) |
1097 		    (envy_ccs_read(sc, ENVY_CCS_GPIODIR1) << 8) |
1098 		    (envy_ccs_read(sc, ENVY_CCS_GPIODIR2) << 16);
1099 	} else
1100 		return envy_cci_read(sc, ENVY_CCI_GPIODIR);
1101 }
1102 
1103 void
1104 envy_gpio_setdir(struct envy_softc *sc, int dir)
1105 {
1106 	if (sc->isht) {
1107 		envy_ccs_write(sc, ENVY_CCS_GPIODIR0, dir & 0xff);
1108 		envy_ccs_write(sc, ENVY_CCS_GPIODIR1, (dir >> 8) & 0xff);
1109 		envy_ccs_write(sc, ENVY_CCS_GPIODIR2, (dir >> 16) & 0xff);
1110 	} else
1111 		envy_cci_write(sc, ENVY_CCI_GPIODIR, dir);
1112 }
1113 
1114 void
1115 envy_gpio_i2c_start_bit(struct envy_softc *sc, int sda, int scl)
1116 {
1117 	int reg;
1118 
1119 	reg = envy_gpio_getstate(sc);
1120 	reg |= (sda | scl);
1121 	envy_gpio_setstate(sc, reg);
1122 	delay(5);
1123 	reg &= ~sda;
1124 	envy_gpio_setstate(sc, reg);
1125 	delay(4);
1126 	reg &= ~scl;
1127 	envy_gpio_setstate(sc, reg);
1128 	delay(5);
1129 }
1130 
1131 void
1132 envy_gpio_i2c_stop_bit(struct envy_softc *sc, int sda, int scl)
1133 {
1134 	int reg;
1135 
1136 	reg = envy_gpio_getstate(sc);
1137 	reg &= ~sda;
1138 	reg |= scl;
1139 	envy_gpio_setstate(sc, reg);
1140 	delay(4);
1141 	reg |= sda;
1142 	envy_gpio_setstate(sc, reg);
1143 }
1144 
1145 void
1146 envy_gpio_i2c_byte_out(struct envy_softc *sc, int sda, int scl, int val)
1147 {
1148 	int mask, reg;
1149 
1150 	reg = envy_gpio_getstate(sc);
1151 
1152 	for (mask = 0x80; mask != 0; mask >>= 1) {
1153 		reg &= ~sda;
1154 		reg |= (val & mask) ? sda : 0;
1155 		envy_gpio_setstate(sc, reg);
1156 		delay(1);
1157 		reg |= scl;
1158 		envy_gpio_setstate(sc, reg);
1159 		delay(4);
1160 		reg &= ~scl;
1161 		envy_gpio_setstate(sc, reg);
1162 		delay(5);
1163 	}
1164 
1165 	reg |= scl;
1166 	envy_gpio_setstate(sc, reg);
1167 	delay(4);
1168 	reg &= ~scl;
1169 	envy_gpio_setstate(sc, reg);
1170 	delay(5);
1171 }
1172 
1173 void
1174 envy_i2c_wait(struct envy_softc *sc)
1175 {
1176 	int timeout = 50, st;
1177 
1178 	for (;;) {
1179 		st = envy_ccs_read(sc, ENVY_I2C_CTL);
1180 		if (!(st & ENVY_I2C_CTL_BUSY))
1181 			break;
1182 		if (timeout == 0) {
1183 			printf("%s: i2c busy timeout\n", DEVNAME(sc));
1184 			break;
1185 		}
1186 		delay(50);
1187 		timeout--;
1188 	}
1189 }
1190 
1191 int
1192 envy_i2c_read(struct envy_softc *sc, int dev, int addr)
1193 {
1194 	envy_i2c_wait(sc);
1195 	envy_ccs_write(sc, ENVY_I2C_ADDR, addr);
1196 	envy_i2c_wait(sc);
1197 	envy_ccs_write(sc, ENVY_I2C_DEV, dev << 1);
1198 	envy_i2c_wait(sc);
1199 	return envy_ccs_read(sc, ENVY_I2C_DATA);
1200 }
1201 
1202 void
1203 envy_i2c_write(struct envy_softc *sc, int dev, int addr, int data)
1204 {
1205 	if (dev == 0x50) {
1206 		printf("%s: writing on eeprom is evil...\n", DEVNAME(sc));
1207 		return;
1208 	}
1209 	envy_i2c_wait(sc);
1210 	envy_ccs_write(sc, ENVY_I2C_ADDR, addr);
1211 	envy_i2c_wait(sc);
1212 	envy_ccs_write(sc, ENVY_I2C_DATA, data);
1213 	envy_i2c_wait(sc);
1214 	envy_ccs_write(sc, ENVY_I2C_DEV, (dev << 1) | 1);
1215 }
1216 
1217 int
1218 envy_codec_read(struct envy_softc *sc, int dev, int addr) {
1219 	return sc->shadow[dev][addr];
1220 }
1221 
1222 void
1223 envy_codec_write(struct envy_softc *sc, int dev, int addr, int data)
1224 {
1225 	DPRINTFN(2, "envy_codec_write: %d, %d, 0x%x\n", dev, addr, data);
1226 	sc->shadow[dev][addr] = data;
1227 	sc->card->codec_write(sc, dev, addr, data);
1228 }
1229 
1230 int
1231 envy_eeprom_gpioxxx(struct envy_softc *sc, int addr)
1232 {
1233 	int val;
1234 
1235 	val = sc->eeprom[addr];
1236 	if (sc->isht) {
1237 		val |= sc->eeprom[++addr] << 8;
1238 		val |= sc->eeprom[++addr] << 16;
1239 	}
1240 	return val;
1241 }
1242 
1243 int
1244 envy_ac97_wait(struct envy_softc *sc)
1245 {
1246 	int timeout = 50, st;
1247 
1248 	for (;;) {
1249 		st = envy_mt_read_1(sc, ENVY_MT_AC97_CMD);
1250 		if ((st & ENVY_MT_AC97_READY) && !(st & ENVY_MT_AC97_CMD_MASK)) {
1251 			st = 0;
1252 			break;
1253 		}
1254 		if (timeout == 0) {
1255 			st = -1;
1256 			break;
1257 		}
1258 		delay(50);
1259 		timeout--;
1260 	}
1261 
1262 	return (st);
1263 }
1264 
1265 int
1266 envy_ac97_attach_codec(void *hdl, struct ac97_codec_if *codec_if)
1267 {
1268 	struct envy_softc *sc = hdl;
1269 
1270 	sc->codec_if = codec_if;
1271 
1272 	return (0);
1273 }
1274 
1275 int
1276 envy_ac97_read_codec(void *hdl, u_int8_t reg, u_int16_t *result)
1277 {
1278 	struct envy_softc *sc = hdl;
1279 
1280 	if (envy_ac97_wait(sc)) {
1281 		printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc));
1282 		return (-1);
1283 	}
1284 
1285 	envy_mt_write_1(sc, ENVY_MT_AC97_IDX, reg & 0x7f);
1286 	envy_mt_write_1(sc, ENVY_MT_AC97_CMD,
1287 	    ENVY_MT_AC97_CMD_RD);
1288 	delay(50);
1289 
1290 	if (envy_ac97_wait(sc)) {
1291 		printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc));
1292 		return (-1);
1293 	}
1294 
1295 	*result = envy_mt_read_2(sc, ENVY_MT_AC97_DATA);
1296 
1297 	return (0);
1298 }
1299 
1300 int
1301 envy_ac97_write_codec(void *hdl, u_int8_t reg, u_int16_t data)
1302 {
1303 	struct envy_softc *sc = hdl;
1304 
1305 	if (envy_ac97_wait(sc)) {
1306 		printf("%s: envy_ac97_write_codec: timed out\n", DEVNAME(sc));
1307 		return (-1);
1308 	}
1309 
1310 	envy_mt_write_1(sc, ENVY_MT_AC97_IDX, reg & 0x7f);
1311 	envy_mt_write_2(sc, ENVY_MT_AC97_DATA, data);
1312 	envy_mt_write_1(sc, ENVY_MT_AC97_CMD,
1313 	    ENVY_MT_AC97_CMD_WR);
1314 	delay(50);
1315 
1316 	return (0);
1317 }
1318 
1319 void
1320 envy_ac97_reset_codec(void *hdl)
1321 {
1322 	struct envy_softc *sc = hdl;
1323 
1324 	envy_mt_write_1(sc, ENVY_MT_AC97_CMD, ENVY_MT_AC97_CMD_RST);
1325 	delay(50);
1326 	envy_mt_write_1(sc, ENVY_MT_AC97_CMD, 0);
1327 	delay(50);
1328 
1329 	if (envy_ac97_wait(sc)) {
1330 		printf("%s: envy_ac97_reset_codec: timed out\n", DEVNAME(sc));
1331 	}
1332 
1333 	return;
1334 }
1335 
1336 enum ac97_host_flags
1337 envy_ac97_flags_codec(void *hdl)
1338 {
1339 	struct envy_softc *sc = hdl;
1340 
1341 	return (sc->codec_flags);
1342 }
1343 
1344 void
1345 envy_midi_wait(struct envy_softc *sc)
1346 {
1347 	int i, st;
1348 
1349 	for (i = 100;; i--) {
1350 		st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0);
1351 		if (!(st & ENVY_MIDISTAT_OBUSY(sc)))
1352 			break;
1353 		if (i == 0) {
1354 			printf("%s: midi wait timeout\n", DEVNAME(sc));
1355 			break;
1356 		}
1357 		delay(10);
1358 	}
1359 }
1360 
1361 void
1362 envy_reset(struct envy_softc *sc)
1363 {
1364 	int i;
1365 
1366 	/*
1367 	 * full reset
1368 	 */
1369 	envy_ccs_write(sc, ENVY_CTL, ENVY_CTL_RESET | ENVY_CTL_NATIVE);
1370 	delay(200);
1371 	envy_ccs_write(sc, ENVY_CTL, ENVY_CTL_NATIVE);
1372 	delay(200);
1373 
1374 	/*
1375 	 * read EEPROM using i2c device or from a static array
1376 	 */
1377 	if (sc->card->eeprom == NULL) {
1378 		for (i = 0; i < ENVY_EEPROM_MAXSZ; i++) {
1379 			sc->eeprom[i] = envy_i2c_read(sc, ENVY_I2C_DEV_EEPROM, i);
1380 		}
1381 #ifdef ENVY_DEBUG
1382 		printf("%s: eeprom: ", DEVNAME(sc));
1383 		for (i = 0; i < ENVY_EEPROM_MAXSZ; i++) {
1384 			printf(" %02x", (unsigned)sc->eeprom[i]);
1385 		}
1386 		printf("\n");
1387 #endif
1388 	} else
1389 		memcpy(sc->eeprom, sc->card->eeprom, ENVY_EEPROM_MAXSZ);
1390 
1391 	/*
1392 	 * write EEPROM values to corresponding registers
1393 	 */
1394 	if (sc->isht) {
1395 		envy_ccs_write(sc, ENVY_CCS_CONF,
1396 		    sc->eeprom[ENVY_EEPROM_CONF]);
1397 		envy_ccs_write(sc, ENVY_CCS_ACLINK,
1398 		    sc->eeprom[ENVY_EEPROM_ACLINK]);
1399 		envy_ccs_write(sc, ENVY_CCS_I2S,
1400 		    sc->eeprom[ENVY_EEPROM_I2S]);
1401 		envy_ccs_write(sc, ENVY_CCS_SPDIF,
1402 		    sc->eeprom[ENVY_EEPROM_SPDIF]);
1403 	} else {
1404 		pci_conf_write(sc->pci_pc, sc->pci_tag, ENVY_CONF,
1405 		    sc->eeprom[ENVY_EEPROM_CONF] |
1406 		    (sc->eeprom[ENVY_EEPROM_ACLINK] << 8) |
1407 		    (sc->eeprom[ENVY_EEPROM_I2S] << 16) |
1408 		    (sc->eeprom[ENVY_EEPROM_SPDIF] << 24));
1409 	}
1410 
1411 	envy_gpio_setmask(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOMASK(sc)));
1412 	envy_gpio_setdir(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIODIR(sc)));
1413 	envy_gpio_setstate(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOST(sc)));
1414 
1415 	DPRINTF("%s: gpio_mask = %02x\n", DEVNAME(sc),
1416 		envy_gpio_getmask(sc));
1417 	DPRINTF("%s: gpio_dir = %02x\n", DEVNAME(sc),
1418 		envy_gpio_getdir(sc));
1419 	DPRINTF("%s: gpio_state = %02x\n", DEVNAME(sc),
1420 		envy_gpio_getstate(sc));
1421 
1422 	if (sc->isht) {
1423 		/*
1424 		 * set water marks so we get an interrupt for each byte
1425 		 */
1426 		envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1);
1427 		envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1 | ENVY_CCS_MIDIWAT_RX);
1428 	}
1429 
1430 	/*
1431 	 * switch to UART mode
1432 	 */
1433 	envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, 0xff);
1434 	envy_midi_wait(sc);
1435 	envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, ENVY_MIDISTAT_UART);
1436 	envy_midi_wait(sc);
1437 	if (!sc->isht)
1438 		(void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA0);
1439 
1440 	/*
1441 	 * clear all interrupts and unmask used ones
1442 	 */
1443 	envy_ccs_write(sc, ENVY_CCS_INTSTAT, 0xff);
1444 	envy_ccs_write(sc, ENVY_CCS_INTMASK,
1445 	    ~(ENVY_CCS_INT_MT | ENVY_CCS_INT_MIDI0));
1446 	if (sc->isht) {
1447 		envy_mt_write_1(sc, ENVY_MT_NSTREAM, 4 - sc->card->noch / 2);
1448 		envy_mt_write_1(sc, ENVY_MT_IMASK, ~(ENVY_MT_IMASK_PDMA0 |
1449 		    ENVY_MT_IMASK_RDMA0 | ENVY_MT_IMASK_ERR));
1450 	}
1451 	sc->iactive = 0;
1452 	sc->oactive = 0;
1453 	sc->card->init(sc);
1454 }
1455 
1456 int
1457 envy_lineout_getsrc(struct envy_softc *sc, int out)
1458 {
1459 	int reg, shift, src;
1460 
1461 	if (sc->isht) {
1462 		reg = envy_mt_read_4(sc, ENVY_MT_HTSRC);
1463 		DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg);
1464 		shift = 3 * (out / 2) + ((out & 1) ? 20 : 8);
1465 		src = (reg >> shift) & ENVY_MT_HTSRC_MASK;
1466 		if (src == ENVY_MT_HTSRC_DMA) {
1467 			return ENVY_MIX_OUTSRC_DMA;
1468 		} else {
1469 			src -= ENVY_MT_HTSRC_LINE;
1470 			return ENVY_MIX_OUTSRC_LINEIN + src;
1471 		}
1472 	}
1473 
1474 	reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC);
1475 	DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg);
1476 	shift = (out  & 1) ? (out & ~1) + 8 : out;
1477 	src = (reg >> shift) & 3;
1478 	if (src == ENVY_MT_OUTSRC_DMA) {
1479 		return ENVY_MIX_OUTSRC_DMA;
1480 	} else if (src == ENVY_MT_OUTSRC_MON) {
1481 		return ENVY_MIX_OUTSRC_MON;
1482 	}
1483 	reg = envy_mt_read_4(sc, ENVY_MT_INSEL);
1484 	DPRINTF("%s: insel=%x\n", DEVNAME(sc), reg);
1485 	reg = (reg >> (out * 4)) & 0xf;
1486 	if (src == ENVY_MT_OUTSRC_LINE)
1487 		return ENVY_MIX_OUTSRC_LINEIN + (reg & 7);
1488 	else
1489 		return ENVY_MIX_OUTSRC_SPDIN + (reg >> 3);
1490 }
1491 
1492 void
1493 envy_lineout_setsrc(struct envy_softc *sc, int out, int src)
1494 {
1495 	int reg, shift, mask, sel;
1496 
1497 	if (sc->isht) {
1498 		if (src < ENVY_MIX_OUTSRC_SPDIN) {
1499 			sel = ENVY_MT_HTSRC_LINE;
1500 			sel += src;
1501 		} else if (src < ENVY_MIX_OUTSRC_DMA) {
1502 			sel = ENVY_MT_HTSRC_SPD;
1503 			sel += src - ENVY_MIX_OUTSRC_SPDIN;
1504 		} else {
1505 			sel = ENVY_MT_HTSRC_DMA;
1506 		}
1507 		shift = 3 * (out / 2) + ((out & 1) ? 20 : 8);
1508 		mask = ENVY_MT_HTSRC_MASK << shift;
1509 		reg = envy_mt_read_4(sc, ENVY_MT_HTSRC);
1510 		reg = (reg & ~mask) | (sel << shift);
1511 		envy_mt_write_4(sc, ENVY_MT_HTSRC, reg);
1512 		DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg);
1513 		return;
1514 	}
1515 
1516 	if (src < ENVY_MIX_OUTSRC_DMA) {
1517 		/*
1518 		 * linein and spdin are used as output source so we
1519 		 * must select the input source channel number
1520 		 */
1521 		if (src < ENVY_MIX_OUTSRC_SPDIN)
1522 			sel = src - ENVY_MIX_OUTSRC_LINEIN;
1523 		else
1524 			sel = (src - ENVY_MIX_OUTSRC_SPDIN) << 3;
1525 
1526 		shift = out * ENVY_MT_INSEL_BITS;
1527 		mask = ENVY_MT_INSEL_MASK << shift;
1528 		reg = envy_mt_read_4(sc, ENVY_MT_INSEL);
1529 		reg = (reg & ~mask) | (sel << shift);
1530 		envy_mt_write_4(sc, ENVY_MT_INSEL, reg);
1531 		DPRINTF("%s: insel <- %x\n", DEVNAME(sc), reg);
1532 	}
1533 
1534 	/*
1535 	 * set the lineout route register
1536 	 */
1537 	if (src < ENVY_MIX_OUTSRC_SPDIN) {
1538 		sel = ENVY_MT_OUTSRC_LINE;
1539 	} else if (src < ENVY_MIX_OUTSRC_DMA) {
1540 		sel = ENVY_MT_OUTSRC_SPD;
1541 	} else if (src == ENVY_MIX_OUTSRC_DMA) {
1542 		sel = ENVY_MT_OUTSRC_DMA;
1543 	} else {
1544 		sel = ENVY_MT_OUTSRC_MON;
1545 	}
1546 	shift = (out  & 1) ? (out & ~1) + 8 : out;
1547 	mask = ENVY_MT_OUTSRC_MASK << shift;
1548 	reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC);
1549 	reg = (reg & ~mask) | (sel << shift);
1550 	envy_mt_write_2(sc, ENVY_MT_OUTSRC, reg);
1551 	DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg);
1552 }
1553 
1554 
1555 int
1556 envy_spdout_getsrc(struct envy_softc *sc, int out)
1557 {
1558 	int reg, src, sel;
1559 
1560 	reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE);
1561 	DPRINTF("%s: spdroute=%x\n", DEVNAME(sc), reg);
1562 	src = (out == 0) ? reg : reg >> 2;
1563 	src &= ENVY_MT_SPDSRC_MASK;
1564 	if (src == ENVY_MT_SPDSRC_DMA) {
1565 		return ENVY_MIX_OUTSRC_DMA;
1566 	} else if (src == ENVY_MT_SPDSRC_MON) {
1567 		return ENVY_MIX_OUTSRC_MON;
1568 	}
1569 
1570 	sel = (out == 0) ? reg >> 8 : reg >> 12;
1571 	sel &= ENVY_MT_SPDSEL_MASK;
1572 	if (src == ENVY_MT_SPDSRC_LINE)
1573 		return ENVY_MIX_OUTSRC_LINEIN + (sel & 7);
1574 	else
1575 		return ENVY_MIX_OUTSRC_SPDIN + (sel >> 3);
1576 }
1577 
1578 void
1579 envy_spdout_setsrc(struct envy_softc *sc, int out, int src)
1580 {
1581 	int reg, shift, mask, sel;
1582 
1583 	reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE);
1584 	if (src < ENVY_MIX_OUTSRC_DMA) {
1585 		/*
1586 		 * linein and spdin are used as output source so we
1587 		 * must select the input source channel number
1588 		 */
1589 		if (src < ENVY_MIX_OUTSRC_SPDIN)
1590 			sel = src - ENVY_MIX_OUTSRC_LINEIN;
1591 		else
1592 			sel = (src - ENVY_MIX_OUTSRC_SPDIN) << 3;
1593 
1594 		shift = 8 + out * ENVY_MT_SPDSEL_BITS;
1595 		mask = ENVY_MT_SPDSEL_MASK << shift;
1596 		reg = (reg & ~mask) | (sel << shift);
1597 	}
1598 
1599 	/*
1600 	 * set the lineout route register
1601 	 */
1602 	if (src < ENVY_MIX_OUTSRC_SPDIN) {
1603 		sel = ENVY_MT_OUTSRC_LINE;
1604 	} else if (src < ENVY_MIX_OUTSRC_DMA) {
1605 		sel = ENVY_MT_OUTSRC_SPD;
1606 	} else if (src == ENVY_MIX_OUTSRC_DMA) {
1607 		sel = ENVY_MT_OUTSRC_DMA;
1608 	} else {
1609 		sel = ENVY_MT_OUTSRC_MON;
1610 	}
1611 	shift = out * 2;
1612 	mask = ENVY_MT_SPDSRC_MASK << shift;
1613 	reg = (reg & ~mask) | (sel << shift);
1614 	envy_mt_write_2(sc, ENVY_MT_SPDROUTE, reg);
1615 	DPRINTF("%s: spdroute <- %x\n", DEVNAME(sc), reg);
1616 }
1617 
1618 void
1619 envy_mon_getvol(struct envy_softc *sc, int idx, int ch, int *val)
1620 {
1621 	int reg;
1622 
1623 	envy_mt_write_2(sc, ENVY_MT_MONIDX, idx);
1624 	reg = envy_mt_read_1(sc, ENVY_MT_MONDATA + ch);
1625 	*val = 0x7f - (reg & 0x7f);
1626 }
1627 
1628 void
1629 envy_mon_setvol(struct envy_softc *sc, int idx, int ch, int val)
1630 {
1631 	int reg;
1632 
1633 	envy_mt_write_2(sc, ENVY_MT_MONIDX, idx);
1634 	reg = 0x7f - val;
1635 	DPRINTF("%s: mon=%d/%d <- %d\n", DEVNAME(sc), reg, ch, val);
1636 	envy_mt_write_1(sc, ENVY_MT_MONDATA + ch, reg);
1637 }
1638 
1639 int
1640 envymatch(struct device *parent, void *match, void *aux)
1641 {
1642 	return pci_matchbyid((struct pci_attach_args *)aux, envy_matchids,
1643 	    sizeof(envy_matchids) / sizeof(envy_matchids[0]));
1644 }
1645 
1646 void
1647 envyattach(struct device *parent, struct device *self, void *aux)
1648 {
1649 	struct envy_softc *sc = (struct envy_softc *)self;
1650 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
1651 	pci_intr_handle_t ih;
1652 	const char *intrstr;
1653 	int subid;
1654 
1655 	sc->pci_tag = pa->pa_tag;
1656 	sc->pci_pc = pa->pa_pc;
1657 	sc->pci_dmat = pa->pa_dmat;
1658 	sc->pci_ih = NULL;
1659 	sc->ibuf.addr = sc->obuf.addr = NULL;
1660 	sc->ccs_iosz = 0;
1661 	sc->mt_iosz = 0;
1662 	sc->isht = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ICENSEMBLE_VT172x);
1663 
1664 	if (pci_mapreg_map(pa, ENVY_CTL_BAR, PCI_MAPREG_TYPE_IO, 0,
1665 		&sc->ccs_iot, &sc->ccs_ioh, NULL, &sc->ccs_iosz, 0)) {
1666 		printf(": can't map ctl i/o space\n");
1667 		sc->ccs_iosz = 0;
1668 		return;
1669 	}
1670 	if (pci_mapreg_map(pa, ENVY_MT_BAR(sc->isht), PCI_MAPREG_TYPE_IO, 0,
1671 		&sc->mt_iot, &sc->mt_ioh, NULL, &sc->mt_iosz, 0)) {
1672 		printf(": can't map mt i/o space\n");
1673 		sc->mt_iosz = 0;
1674 		return;
1675 	}
1676 	if (pci_intr_map(pa, &ih)) {
1677 		printf(": can't map interrupt\n");
1678 	}
1679 	intrstr = pci_intr_string(sc->pci_pc, ih);
1680 	sc->pci_ih = pci_intr_establish(sc->pci_pc, ih, IPL_AUDIO | IPL_MPSAFE,
1681 	    envy_intr, sc, sc->dev.dv_xname);
1682 	if (sc->pci_ih == NULL) {
1683 		printf(": can't establish interrupt");
1684 		if (intrstr)
1685 			printf(" at %s", intrstr);
1686 		printf("\n");
1687 		return;
1688 	}
1689 	printf(": %s\n", intrstr);
1690 	subid = pci_conf_read(sc->pci_pc, sc->pci_tag, PCI_SUBVEND_0);
1691 	sc->card = sc->isht ? envy_cards_ht : envy_cards;
1692 	while (sc->card->subid != subid) {
1693 		if (sc->card->subid == 0)
1694 			break;
1695 		sc->card++;
1696 	}
1697 	printf("%s: %s, %u inputs, %u outputs\n", DEVNAME(sc),
1698 	    sc->card->name, sc->card->nich, sc->card->noch);
1699 	envy_reset(sc);
1700 	sc->audio = audio_attach_mi(&envy_hw_if, sc, &sc->dev);
1701 #if NMIDI > 0
1702 	if (!sc->isht || sc->eeprom[ENVY_EEPROM_CONF] & ENVY_CONF_MIDI)
1703 		sc->midi = midi_attach_mi(&envy_midi_hw_if, sc, &sc->dev);
1704 #endif
1705 
1706 }
1707 
1708 int
1709 envydetach(struct device *self, int flags)
1710 {
1711 	struct envy_softc *sc = (struct envy_softc *)self;
1712 
1713 	if (sc->pci_ih != NULL) {
1714 		pci_intr_disestablish(sc->pci_pc, sc->pci_ih);
1715 		sc->pci_ih = NULL;
1716 	}
1717 	if (sc->ccs_iosz) {
1718 		bus_space_unmap(sc->ccs_iot, sc->ccs_ioh, sc->ccs_iosz);
1719 	}
1720 	if (sc->mt_iosz) {
1721 		bus_space_unmap(sc->mt_iot, sc->mt_ioh, sc->mt_iosz);
1722 	}
1723 	return 0;
1724 }
1725 
1726 int
1727 envy_open(void *self, int flags)
1728 {
1729 	return 0;
1730 }
1731 
1732 void
1733 envy_close(void *self)
1734 {
1735 }
1736 
1737 void *
1738 envy_allocm(void *self, int dir, size_t size, int type, int flags)
1739 {
1740 	struct envy_softc *sc = (struct envy_softc *)self;
1741 	int err, basereg, wait;
1742 	struct envy_buf *buf;
1743 	bus_addr_t dma_addr;
1744 
1745 	if (dir == AUMODE_RECORD) {
1746 		buf = &sc->ibuf;
1747 		basereg = ENVY_MT_RADDR;
1748 	} else {
1749 		buf = &sc->obuf;
1750 		basereg = ENVY_MT_PADDR;
1751 	}
1752 	if (buf->addr != NULL) {
1753 		DPRINTF("%s: multiple alloc, dir = %d\n", DEVNAME(sc), dir);
1754 		return NULL;
1755 	}
1756 	buf->size = size;
1757 	wait = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1758 
1759 #define ENVY_ALIGN	4
1760 #define ENVY_MAXADDR	((1 << 28) - 1)
1761 
1762 	buf->addr = (caddr_t)uvm_km_kmemalloc_pla(kernel_map,
1763 	    uvm.kernel_object, buf->size, 0, UVM_KMF_NOWAIT, 0,
1764 	    (paddr_t)ENVY_MAXADDR, 0, 0, 1);
1765 	if (buf->addr == NULL) {
1766 		DPRINTF("%s: unable to alloc dma segment\n", DEVNAME(sc));
1767 		goto err_ret;
1768 	}
1769 	err = bus_dmamap_create(sc->pci_dmat, buf->size, 1, buf->size, 0,
1770 	    wait, &buf->map);
1771 	if (err) {
1772 		DPRINTF("%s: dmamap_create: failed %d\n", DEVNAME(sc), err);
1773 		goto err_unmap;
1774 	}
1775 	err = bus_dmamap_load(sc->pci_dmat, buf->map, buf->addr,
1776 	    buf->size, NULL, wait);
1777 	if (err) {
1778 		DPRINTF("%s: dmamap_load: failed %d\n", DEVNAME(sc), err);
1779 		goto err_destroy;
1780 	}
1781 	dma_addr = buf->map->dm_segs[0].ds_addr;
1782 	DPRINTF("%s: allocated %zd bytes dir=%d, ka=%p, da=%p\n", DEVNAME(sc),
1783 	    buf->size, dir, buf->addr, dma_addr);
1784 	if (!sc->isht && (dma_addr & ~ENVY_MAXADDR)) {
1785 		printf("%s: DMA address beyond 0x10000000\n", DEVNAME(sc));
1786 		goto err_unload;
1787 	}
1788 	envy_mt_write_4(sc, basereg, dma_addr);
1789 	return buf->addr;
1790  err_unload:
1791 	bus_dmamap_unload(sc->pci_dmat, buf->map);
1792  err_destroy:
1793 	bus_dmamap_destroy(sc->pci_dmat, buf->map);
1794  err_unmap:
1795 	uvm_km_free(kernel_map, (vaddr_t)buf->addr, buf->size);
1796  err_ret:
1797 	return NULL;
1798 }
1799 
1800 void
1801 envy_freem(void *self, void *addr, int type)
1802 {
1803 	struct envy_buf *buf;
1804 	struct envy_softc *sc = (struct envy_softc *)self;
1805 	int dir;
1806 
1807 	if (sc->ibuf.addr == addr) {
1808 		buf = &sc->ibuf;
1809 		dir = AUMODE_RECORD;
1810 	} else if (sc->obuf.addr == addr) {
1811 		buf = &sc->obuf;
1812 		dir = AUMODE_PLAY;
1813 	} else {
1814 		DPRINTF("%s: no buf to free\n", DEVNAME(sc));
1815 		return;
1816 	}
1817 	bus_dmamap_unload(sc->pci_dmat, buf->map);
1818 	bus_dmamap_destroy(sc->pci_dmat, buf->map);
1819 	uvm_km_free(kernel_map, (vaddr_t)&buf->addr, buf->size);
1820 	buf->addr = NULL;
1821 	DPRINTF("%s: freed buffer (mode=%d)\n", DEVNAME(sc), dir);
1822 }
1823 
1824 int
1825 envy_query_encoding(void *self, struct audio_encoding *enc)
1826 {
1827 	if (enc->index == 0) {
1828 		strlcpy(enc->name, AudioEslinear_le, sizeof(enc->name));
1829 		enc->encoding = AUDIO_ENCODING_SLINEAR_LE;
1830 		enc->precision = 24;
1831 		enc->bps = 4;
1832 		enc->msb = 1;
1833 		enc->flags = 0;
1834 		return 0;
1835 	}
1836 	return EINVAL;
1837 }
1838 
1839 int
1840 envy_set_params(void *self, int setmode, int usemode,
1841     struct audio_params *p, struct audio_params *r)
1842 {
1843 	struct envy_softc *sc = (struct envy_softc *)self;
1844 	int i, rate, reg;
1845 
1846 	if (setmode == 0)
1847 		return 0;
1848 	if (setmode == (AUMODE_PLAY | AUMODE_RECORD) &&
1849 	    p->sample_rate != r->sample_rate) {
1850 		DPRINTF("%s: play/rec rates mismatch\n", DEVNAME(sc));
1851 		r->sample_rate = p->sample_rate;
1852 	}
1853 	rate = (setmode & AUMODE_PLAY) ? p->sample_rate : r->sample_rate;
1854 	for (i = 0; envy_rates[i].rate < rate; i++) {
1855 		if (envy_rates[i].rate == -1) {
1856 			i--;
1857 			DPRINTF("%s: rate: %d -> %d\n", DEVNAME(sc), rate, i);
1858 			break;
1859 		}
1860 	}
1861 	reg = envy_mt_read_1(sc, ENVY_MT_RATE);
1862 	reg &= ~ENVY_MT_RATEMASK;
1863 	reg |= envy_rates[i].reg;
1864 	envy_mt_write_1(sc, ENVY_MT_RATE, reg);
1865 	if (setmode & AUMODE_PLAY) {
1866 		p->encoding = AUDIO_ENCODING_SLINEAR_LE;
1867 		p->precision = 24;
1868 		p->bps = 4;
1869 		p->msb = 1;
1870 		p->channels = sc->isht ? sc->card->noch : ENVY_PCHANS;
1871 	}
1872 	if (setmode & AUMODE_RECORD) {
1873 		r->encoding = AUDIO_ENCODING_SLINEAR_LE;
1874 		r->precision = 24;
1875 		r->bps = 4;
1876 		r->msb = 1;
1877 		r->channels = sc->isht ? sc->card->nich : ENVY_RCHANS;
1878 	}
1879 	return 0;
1880 }
1881 
1882 int
1883 envy_round_blocksize(void *self, int blksz)
1884 {
1885 	struct envy_softc *sc = (struct envy_softc *)self;
1886 	int mul, pmult, rmult;
1887 
1888 	/*
1889 	 * XXX: audio(4) layer doesn't round to the sample size
1890 	 * until it's fixed, roll our own rounding
1891 	 */
1892 
1893 	pmult = (sc->isht ? sc->card->noch : ENVY_PCHANS);
1894 	if (pmult == 0)
1895 		pmult = 1;
1896 	rmult = (sc->isht ? sc->card->nich : ENVY_RCHANS);
1897 	if (rmult == 0)
1898 		rmult = 1;
1899 	mul = pmult * rmult;
1900 	while ((mul & 0x1f) != 0)
1901 		mul <<= 1;
1902 	blksz -= blksz % mul;
1903 	if (blksz == 0)
1904 		blksz = mul;
1905 	return blksz;
1906 }
1907 
1908 size_t
1909 envy_round_buffersize(void *self, int dir, size_t bufsz)
1910 {
1911 	return bufsz;
1912 }
1913 
1914 #ifdef ENVY_DEBUG
1915 void
1916 envy_pintr(struct envy_softc *sc)
1917 {
1918 	int i;
1919 
1920 	if (sc->spurious > 0 || envydebug >= 2) {
1921 		printf("%s: spurious = %u, start = %lld.%ld\n",
1922 			DEVNAME(sc), sc->spurious,
1923 			(long long)sc->start_ts.tv_sec, sc->start_ts.tv_nsec);
1924 		for (i = 0; i < sc->nintr; i++) {
1925 			printf("%lld.%09ld: "
1926 			    "active=%d/%d pos=%d/%d st=%x/%x, ctl=%x\n",
1927 			    (long long)sc->intrs[i].ts.tv_sec,
1928 			    sc->intrs[i].ts.tv_nsec,
1929 			    sc->intrs[i].iactive,
1930 			    sc->intrs[i].oactive,
1931 			    sc->intrs[i].ipos,
1932 			    sc->intrs[i].opos,
1933 			    sc->intrs[i].st,
1934 			    sc->intrs[i].mask,
1935 			    sc->intrs[i].ctl);
1936 		}
1937 	}
1938 }
1939 #endif
1940 
1941 int
1942 envy_intr(void *self)
1943 {
1944 	struct envy_softc *sc = (struct envy_softc *)self;
1945 	int mintr, mstat, mdata;
1946 	int st, err, ctl;
1947 	int max;
1948 
1949 	mtx_enter(&audio_lock);
1950 	st = envy_mt_read_1(sc, ENVY_MT_INTR);
1951 	mintr = envy_ccs_read(sc, ENVY_CCS_INTSTAT);
1952 	if (!(st & ENVY_MT_INTR_ALL) && !(mintr & ENVY_CCS_INT_MIDI0)) {
1953 		mtx_leave(&audio_lock);
1954 		return 0;
1955 	}
1956 	if (st & ENVY_MT_INTR_ERR) {
1957 		err = envy_mt_read_1(sc, ENVY_MT_ERR);
1958 		envy_mt_write_1(sc, ENVY_MT_ERR, err);
1959 	}
1960 	envy_mt_write_1(sc, ENVY_MT_INTR, st);
1961 	envy_ccs_write(sc, ENVY_CCS_INTSTAT, mintr);
1962 
1963 #ifdef ENVY_DEBUG
1964 	if (sc->nintr < ENVY_NINTR) {
1965 		sc->intrs[sc->nintr].iactive = sc->iactive;
1966 		sc->intrs[sc->nintr].oactive = sc->oactive;
1967 		sc->intrs[sc->nintr].st = st;
1968 		sc->intrs[sc->nintr].ipos = envy_mt_read_2(sc, ENVY_MT_RBUFSZ);
1969 		sc->intrs[sc->nintr].opos = envy_mt_read_2(sc, ENVY_MT_PBUFSZ);
1970 		sc->intrs[sc->nintr].ctl = envy_mt_read_1(sc, ENVY_MT_CTL);
1971 		sc->intrs[sc->nintr].mask = envy_mt_read_1(sc, ENVY_MT_IMASK);
1972 		nanouptime(&sc->intrs[sc->nintr].ts);
1973 		sc->nintr++;
1974 	}
1975 #endif
1976 	if (mintr & ENVY_CCS_INT_MIDI0) {
1977 		for (max = 128; max > 0; max--) {
1978 			mstat = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0);
1979 			if (mstat & ENVY_MIDISTAT_IEMPTY(sc))
1980 				break;
1981 			mdata = envy_ccs_read(sc, ENVY_CCS_MIDIDATA0);
1982 #if NMIDI > 0
1983 			if (sc->midi_in)
1984 				sc->midi_in(sc->midi_arg, mdata);
1985 #endif
1986 		}
1987 	}
1988 	if (st & ENVY_MT_INTR_PACK) {
1989 		if (sc->oactive)
1990 			sc->ointr(sc->oarg);
1991 		else {
1992 			ctl = envy_mt_read_1(sc, ENVY_MT_CTL);
1993 			if (ctl & ENVY_MT_CTL_PSTART) {
1994 				envy_mt_write_1(sc,
1995 				    ENVY_MT_CTL, ctl & ~ENVY_MT_CTL_PSTART);
1996 				st &= ~ENVY_MT_INTR_PACK;
1997 				sc->obusy = 0;
1998 				wakeup(&sc->obusy);
1999 			}
2000 #ifdef ENVY_DEBUG
2001 			else
2002 				sc->spurious++;
2003 #endif
2004 		}
2005 	}
2006 	if (st & ENVY_MT_INTR_RACK) {
2007 		if (sc->iactive)
2008 			sc->iintr(sc->iarg);
2009 		else {
2010 			ctl = envy_mt_read_1(sc, ENVY_MT_CTL);
2011 			if (ctl & ENVY_MT_CTL_RSTART(sc)) {
2012 				envy_mt_write_1(sc,
2013 				    ENVY_MT_CTL, ctl & ~ENVY_MT_CTL_RSTART(sc));
2014 				st &= ~ENVY_MT_INTR_RACK;
2015 				sc->ibusy = 0;
2016 				wakeup(&sc->ibusy);
2017 			}
2018 #ifdef ENVY_DEBUG
2019 			else
2020 				sc->spurious++;
2021 #endif
2022 		}
2023 	}
2024 	mtx_leave(&audio_lock);
2025 	return 1;
2026 }
2027 
2028 int
2029 envy_trigger_output(void *self, void *start, void *end, int blksz,
2030     void (*intr)(void *), void *arg, struct audio_params *param)
2031 {
2032 	struct envy_softc *sc = (struct envy_softc *)self;
2033 	size_t bufsz;
2034 	int st;
2035 
2036 	bufsz = (char *)end - (char *)start;
2037 #ifdef ENVY_DEBUG
2038 	if (blksz % (sc->isht ? sc->card->noch * 4 : ENVY_PFRAME_SIZE) != 0) {
2039 		printf("%s: %d: bad output blksz\n", DEVNAME(sc), blksz);
2040 		return EINVAL;
2041 	}
2042 	if (bufsz % blksz) {
2043 		printf("%s: %ld: bad output bufsz\n", DEVNAME(sc), bufsz);
2044 		return EINVAL;
2045 	}
2046 #endif
2047 	mtx_enter(&audio_lock);
2048 	envy_mt_write_2(sc, ENVY_MT_PBUFSZ, bufsz / 4 - 1);
2049 	envy_mt_write_2(sc, ENVY_MT_PBLKSZ(sc), blksz / 4 - 1);
2050 
2051 #ifdef ENVY_DEBUG
2052 	if (!sc->iactive) {
2053 		sc->nintr = 0;
2054 		sc->spurious = 0;
2055 		nanouptime(&sc->start_ts);
2056 	}
2057 #endif
2058 	sc->ointr = intr;
2059 	sc->oarg = arg;
2060 	sc->oactive = 1;
2061 	sc->obusy = 1;
2062 	st = ENVY_MT_INTR_PACK;
2063 	envy_mt_write_1(sc, ENVY_MT_INTR, st);
2064 	st = envy_mt_read_1(sc, ENVY_MT_CTL);
2065 	st |= ENVY_MT_CTL_PSTART;
2066 	envy_mt_write_1(sc, ENVY_MT_CTL, st);
2067 	mtx_leave(&audio_lock);
2068 	return 0;
2069 }
2070 
2071 int
2072 envy_trigger_input(void *self, void *start, void *end, int blksz,
2073     void (*intr)(void *), void *arg, struct audio_params *param)
2074 {
2075 	struct envy_softc *sc = (struct envy_softc *)self;
2076 	size_t bufsz;
2077 	int st;
2078 
2079 	bufsz = (char *)end - (char *)start;
2080 #ifdef ENVY_DEBUG
2081 	if (blksz % (sc->isht ? sc->card->nich * 4 : ENVY_RFRAME_SIZE) != 0) {
2082 		printf("%s: %d: bad input blksz\n", DEVNAME(sc), blksz);
2083 		return EINVAL;
2084 	}
2085 	if (bufsz % blksz != 0) {
2086 		printf("%s: %ld: bad input bufsz\n", DEVNAME(sc), bufsz);
2087 		return EINVAL;
2088 	}
2089 #endif
2090 	mtx_enter(&audio_lock);
2091 	envy_mt_write_2(sc, ENVY_MT_RBUFSZ, bufsz / 4 - 1);
2092 	envy_mt_write_2(sc, ENVY_MT_RBLKSZ, blksz / 4 - 1);
2093 
2094 #ifdef ENVY_DEBUG
2095 	if (!sc->oactive) {
2096 		sc->nintr = 0;
2097 		sc->spurious = 0;
2098 		nanouptime(&sc->start_ts);
2099 	}
2100 #endif
2101 	sc->iintr = intr;
2102 	sc->iarg = arg;
2103 	sc->iactive = 1;
2104 	sc->ibusy = 1;
2105 	st = ENVY_MT_INTR_RACK;
2106 	envy_mt_write_1(sc, ENVY_MT_INTR, st);
2107 	st = envy_mt_read_1(sc, ENVY_MT_CTL);
2108 	st |= ENVY_MT_CTL_RSTART(sc);
2109 	envy_mt_write_1(sc, ENVY_MT_CTL, st);
2110 	mtx_leave(&audio_lock);
2111 	return 0;
2112 }
2113 
2114 int
2115 envy_halt_output(void *self)
2116 {
2117 	struct envy_softc *sc = (struct envy_softc *)self;
2118 	int err;
2119 
2120 	mtx_enter(&audio_lock);
2121 	sc->oactive = 0;
2122 	if (sc->obusy) {
2123 		err = msleep(&sc->obusy, &audio_lock, PWAIT, "envyobus", 4 * hz);
2124 		if (err)
2125 			printf("%s: output DMA halt timeout\n", DEVNAME(sc));
2126 	}
2127 #ifdef ENVY_DEBUG
2128 	if (!sc->iactive)
2129 		envy_pintr(sc);
2130 #endif
2131 	mtx_leave(&audio_lock);
2132 	return 0;
2133 }
2134 
2135 int
2136 envy_halt_input(void *self)
2137 {
2138 	struct envy_softc *sc = (struct envy_softc *)self;
2139 	int err;
2140 
2141 	mtx_enter(&audio_lock);
2142 	sc->iactive = 0;
2143 	if (sc->ibusy) {
2144 		err = msleep(&sc->ibusy, &audio_lock, PWAIT, "envyibus", 4 * hz);
2145 		if (err)
2146 			printf("%s: input DMA halt timeout\n", DEVNAME(sc));
2147 	}
2148 #ifdef ENVY_DEBUG
2149 	if (!sc->oactive)
2150 		envy_pintr(sc);
2151 #endif
2152 	mtx_leave(&audio_lock);
2153 	return 0;
2154 }
2155 
2156 int
2157 envy_getdev(void *self, struct audio_device *dev)
2158 {
2159 	struct envy_softc *sc = (struct envy_softc *)self;
2160 
2161 	strlcpy(dev->name, sc->isht ? "Envy24HT" : "Envy24", MAX_AUDIO_DEV_LEN);
2162 	strlcpy(dev->version, "-", MAX_AUDIO_DEV_LEN);
2163 	strlcpy(dev->config, sc->card->name, MAX_AUDIO_DEV_LEN);
2164 	return 0;
2165 }
2166 
2167 int
2168 envy_query_devinfo(void *self, struct mixer_devinfo *dev)
2169 {
2170 	struct envy_softc *sc = (struct envy_softc *)self;
2171 	int i, n, idx, ndev;
2172 	char *classes[] = {
2173 		AudioCinputs, AudioCoutputs, AudioCmonitor
2174 	};
2175 
2176 	if (sc->isac97)
2177 		return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dev));
2178 
2179 	if (dev->index < 0)
2180 		return ENXIO;
2181 
2182 	idx = dev->index;
2183 	ndev = ENVY_MIX_NCLASS;
2184 	dev->prev = dev->next = AUDIO_MIXER_LAST;
2185 
2186 	/*
2187 	 * classes
2188 	 */
2189 	if (idx < ndev) {
2190 		dev->type = AUDIO_MIXER_CLASS;
2191 		dev->mixer_class = idx;
2192 		strlcpy(dev->label.name, classes[idx], MAX_AUDIO_DEV_LEN);
2193 		return 0;
2194 	}
2195 	idx -= ndev;
2196 
2197 	/*
2198 	 * output.lineX_source
2199 	 */
2200 	ndev = sc->card->noch;
2201 	if (idx < ndev) {
2202 		n = 0;
2203 		dev->type = AUDIO_MIXER_ENUM;
2204 		dev->mixer_class = ENVY_MIX_CLASSOUT;
2205 		for (i = 0; i < sc->card->nich; i++) {
2206 			dev->un.e.member[n].ord = n;
2207 			snprintf(dev->un.e.member[n++].label.name,
2208 			    MAX_AUDIO_DEV_LEN, AudioNline "%d", i);
2209 		}
2210 		dev->un.e.member[n].ord = n;
2211 		snprintf(dev->un.e.member[n++].label.name,
2212 			 MAX_AUDIO_DEV_LEN, "play%d", idx);
2213 		if (!sc->isht && idx < 2) {
2214 			dev->un.e.member[n].ord = n;
2215 			snprintf(dev->un.e.member[n++].label.name,
2216 			    MAX_AUDIO_DEV_LEN, "mon%d", idx);
2217 		}
2218 		snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
2219 		    "line%u_" AudioNsource, idx);
2220 		dev->un.s.num_mem = n;
2221 		return 0;
2222 	}
2223 	idx -= ndev;
2224 
2225 	/*
2226 	 * envy monitor level
2227 	 */
2228 	ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR;
2229 	if (idx < ndev) {
2230 		dev->type = AUDIO_MIXER_VALUE;
2231 		dev->mixer_class = ENVY_MIX_CLASSMON;
2232 		dev->un.v.delta = 2;
2233 		dev->un.v.num_channels = 1;
2234 		snprintf(dev->label.name, MAX_AUDIO_DEV_LEN,
2235 			 "%s%d", idx < 10 ? "play" : "rec", idx % 10);
2236 		strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN);
2237 		return 0;
2238 	}
2239 	idx -= ndev;
2240 
2241 	/*
2242 	 * inputs.xxx
2243 	 */
2244 	ndev = sc->card->adc->ndev(sc);
2245 	if (idx < ndev) {
2246 		sc->card->adc->devinfo(sc, dev, idx);
2247 		return 0;
2248 	}
2249 	idx -= ndev;
2250 
2251 	/*
2252 	 * outputs.xxx
2253 	 */
2254 	ndev = sc->card->dac->ndev(sc);
2255 	if (idx < ndev) {
2256 		sc->card->dac->devinfo(sc, dev, idx);
2257 		return 0;
2258 	}
2259 	return ENXIO;
2260 }
2261 
2262 int
2263 envy_get_port(void *self, struct mixer_ctrl *ctl)
2264 {
2265 	struct envy_softc *sc = (struct envy_softc *)self;
2266 	int val, idx, ndev;
2267 
2268 	if (sc->isac97)
2269 		return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, ctl));
2270 
2271 	if (ctl->dev < ENVY_MIX_NCLASS) {
2272 		return EINVAL;
2273 	}
2274 
2275 	idx = ctl->dev - ENVY_MIX_NCLASS;
2276 	ndev = sc->card->noch;
2277 	if (idx < ndev) {
2278 		ctl->un.ord = envy_lineout_getsrc(sc, idx);
2279 		if (ctl->un.ord >= ENVY_MIX_NOUTSRC)
2280 			ctl->un.ord -= ENVY_MIX_NOUTSRC - sc->card->nich;
2281 		return 0;
2282 	}
2283 	idx -= ndev;
2284 	ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR;
2285 	if (idx < ndev) {
2286 		envy_mon_getvol(sc, idx / 2, idx % 2, &val);
2287 		ctl->un.value.num_channels = 1;
2288 		ctl->un.value.level[0] = 2 * val;
2289 		return 0;
2290 	}
2291 	idx -= ndev;
2292 	ndev = sc->card->adc->ndev(sc);
2293 	if (idx < ndev) {
2294 		sc->card->adc->get(sc, ctl, idx);
2295 		return 0;
2296 	}
2297 	idx -= ndev;
2298 	ndev = sc->card->dac->ndev(sc);
2299 	if (idx < ndev) {
2300 		sc->card->dac->get(sc, ctl, idx);
2301 		return 0;
2302 	}
2303 	return ENXIO;
2304 }
2305 
2306 int
2307 envy_set_port(void *self, struct mixer_ctrl *ctl)
2308 {
2309 	struct envy_softc *sc = (struct envy_softc *)self;
2310 	int maxsrc, val, idx, ndev;
2311 
2312 	if (sc->isac97)
2313 		return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, ctl));
2314 
2315 	if (ctl->dev < ENVY_MIX_NCLASS) {
2316 		return EINVAL;
2317 	}
2318 
2319 	idx = ctl->dev - ENVY_MIX_NCLASS;
2320 	ndev = sc->card->noch;
2321 	if (idx < ndev) {
2322 		maxsrc = sc->card->nich + 1;
2323 		if (idx < 2)
2324 			maxsrc++;
2325 		if (ctl->un.ord < 0 || ctl->un.ord >= maxsrc)
2326 			return EINVAL;
2327 		if (ctl->un.ord >= sc->card->nich)
2328 			ctl->un.ord += ENVY_MIX_NOUTSRC - sc->card->nich;
2329 		envy_lineout_setsrc(sc, idx, ctl->un.ord);
2330 		return 0;
2331 	}
2332 	idx -= ndev;
2333 	ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR;
2334 	if (idx < ndev) {
2335 		if (ctl->un.value.num_channels != 1) {
2336 			return EINVAL;
2337 		}
2338 		val = ctl->un.value.level[0] / 2;
2339 		envy_mon_setvol(sc, idx / 2, idx % 2, val);
2340 		return 0;
2341 	}
2342 	idx -= ndev;
2343 	ndev = sc->card->adc->ndev(sc);
2344 	if (idx < ndev)
2345 		return sc->card->adc->set(sc, ctl, idx);
2346 	idx -= ndev;
2347 	ndev = sc->card->dac->ndev(sc);
2348 	if (idx < ndev)
2349 		return sc->card->dac->set(sc, ctl, idx);
2350 	return ENXIO;
2351 }
2352 
2353 int
2354 envy_get_props(void *self)
2355 {
2356 	return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
2357 }
2358 
2359 #if NMIDI > 0
2360 int
2361 envy_midi_open(void *self, int flags,
2362     void (*in)(void *, int),
2363     void (*out)(void *),
2364     void *arg)
2365 {
2366 	struct envy_softc *sc = (struct envy_softc *)self;
2367 
2368 	mtx_enter(&audio_lock);
2369 	sc->midi_in = in;
2370 	sc->midi_out = out;
2371 	sc->midi_arg = arg;
2372 	mtx_leave(&audio_lock);
2373 	return 0;
2374 }
2375 
2376 void
2377 envy_midi_close(void *self)
2378 {
2379 	struct envy_softc *sc = (struct envy_softc *)self;
2380 
2381 	tsleep(sc, PWAIT, "envymid", hz / 10);
2382 	mtx_enter(&audio_lock);
2383 	sc->midi_in = NULL;
2384 	sc->midi_out = NULL;
2385 	mtx_leave(&audio_lock);
2386 }
2387 
2388 int
2389 envy_midi_output(void *self, int data)
2390 {
2391 	struct envy_softc *sc = (struct envy_softc *)self;
2392 	int st;
2393 
2394 	st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0);
2395 	if (st & ENVY_MIDISTAT_OBUSY(sc))
2396 		return 0;
2397 	envy_ccs_write(sc, ENVY_CCS_MIDIDATA0, data);
2398 	return 1;
2399 }
2400 
2401 void
2402 envy_midi_getinfo(void *self, struct midi_info *mi)
2403 {
2404 	mi->props = MIDI_PROP_CAN_INPUT;
2405 	mi->name = "Envy24 MIDI UART";
2406 }
2407 #endif
2408