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