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