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