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