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