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