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