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