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