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