1 /* $OpenBSD: envy.c,v 1.70 2017/03/28 05:23:15 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 envy_ccs_write(sc, ENVY_CCI_INDEX, index); 1036 return (envy_ccs_read(sc, ENVY_CCI_DATA)); 1037 } 1038 1039 void 1040 envy_cci_write(struct envy_softc *sc, int index, int data) 1041 { 1042 envy_ccs_write(sc, ENVY_CCI_INDEX, index); 1043 envy_ccs_write(sc, ENVY_CCI_DATA, data); 1044 } 1045 1046 int 1047 envy_gpio_getstate(struct envy_softc *sc) 1048 { 1049 if (sc->isht) { 1050 return envy_ccs_read(sc, ENVY_CCS_GPIODATA0) | 1051 (envy_ccs_read(sc, ENVY_CCS_GPIODATA1) << 8) | 1052 (envy_ccs_read(sc, ENVY_CCS_GPIODATA2) << 16); 1053 } else 1054 return envy_cci_read(sc, ENVY_CCI_GPIODATA); 1055 } 1056 1057 void 1058 envy_gpio_setstate(struct envy_softc *sc, int reg) 1059 { 1060 if (sc->isht) { 1061 envy_ccs_write(sc, ENVY_CCS_GPIODATA0, reg & 0xff); 1062 envy_ccs_write(sc, ENVY_CCS_GPIODATA1, (reg >> 8) & 0xff); 1063 envy_ccs_write(sc, ENVY_CCS_GPIODATA2, (reg >> 16) & 0xff); 1064 } else 1065 envy_cci_write(sc, ENVY_CCI_GPIODATA, reg); 1066 } 1067 1068 int 1069 envy_gpio_getmask(struct envy_softc *sc) 1070 { 1071 if (sc->isht) { 1072 return envy_ccs_read(sc, ENVY_CCS_GPIOMASK0) | 1073 (envy_ccs_read(sc, ENVY_CCS_GPIOMASK1) << 8) | 1074 (envy_ccs_read(sc, ENVY_CCS_GPIOMASK2) << 16); 1075 } else 1076 return envy_cci_read(sc, ENVY_CCI_GPIOMASK); 1077 } 1078 1079 void 1080 envy_gpio_setmask(struct envy_softc *sc, int mask) 1081 { 1082 if (sc->isht) { 1083 envy_ccs_write(sc, ENVY_CCS_GPIOMASK0, mask & 0xff); 1084 envy_ccs_write(sc, ENVY_CCS_GPIOMASK1, (mask >> 8) & 0xff); 1085 envy_ccs_write(sc, ENVY_CCS_GPIOMASK2, (mask >> 16) & 0xff); 1086 } else 1087 envy_cci_write(sc, ENVY_CCI_GPIOMASK, mask); 1088 } 1089 1090 int 1091 envy_gpio_getdir(struct envy_softc *sc) 1092 { 1093 if (sc->isht) { 1094 return envy_ccs_read(sc, ENVY_CCS_GPIODIR0) | 1095 (envy_ccs_read(sc, ENVY_CCS_GPIODIR1) << 8) | 1096 (envy_ccs_read(sc, ENVY_CCS_GPIODIR2) << 16); 1097 } else 1098 return envy_cci_read(sc, ENVY_CCI_GPIODIR); 1099 } 1100 1101 void 1102 envy_gpio_setdir(struct envy_softc *sc, int dir) 1103 { 1104 if (sc->isht) { 1105 envy_ccs_write(sc, ENVY_CCS_GPIODIR0, dir & 0xff); 1106 envy_ccs_write(sc, ENVY_CCS_GPIODIR1, (dir >> 8) & 0xff); 1107 envy_ccs_write(sc, ENVY_CCS_GPIODIR2, (dir >> 16) & 0xff); 1108 } else 1109 envy_cci_write(sc, ENVY_CCI_GPIODIR, dir); 1110 } 1111 1112 void 1113 envy_gpio_i2c_start_bit(struct envy_softc *sc, int sda, int scl) 1114 { 1115 int reg; 1116 1117 reg = envy_gpio_getstate(sc); 1118 reg |= (sda | scl); 1119 envy_gpio_setstate(sc, reg); 1120 delay(5); 1121 reg &= ~sda; 1122 envy_gpio_setstate(sc, reg); 1123 delay(4); 1124 reg &= ~scl; 1125 envy_gpio_setstate(sc, reg); 1126 delay(5); 1127 } 1128 1129 void 1130 envy_gpio_i2c_stop_bit(struct envy_softc *sc, int sda, int scl) 1131 { 1132 int reg; 1133 1134 reg = envy_gpio_getstate(sc); 1135 reg &= ~sda; 1136 reg |= scl; 1137 envy_gpio_setstate(sc, reg); 1138 delay(4); 1139 reg |= sda; 1140 envy_gpio_setstate(sc, reg); 1141 } 1142 1143 void 1144 envy_gpio_i2c_byte_out(struct envy_softc *sc, int sda, int scl, int val) 1145 { 1146 int mask, reg; 1147 1148 reg = envy_gpio_getstate(sc); 1149 1150 for (mask = 0x80; mask != 0; mask >>= 1) { 1151 reg &= ~sda; 1152 reg |= (val & mask) ? sda : 0; 1153 envy_gpio_setstate(sc, reg); 1154 delay(1); 1155 reg |= scl; 1156 envy_gpio_setstate(sc, reg); 1157 delay(4); 1158 reg &= ~scl; 1159 envy_gpio_setstate(sc, reg); 1160 delay(5); 1161 } 1162 1163 reg |= scl; 1164 envy_gpio_setstate(sc, reg); 1165 delay(4); 1166 reg &= ~scl; 1167 envy_gpio_setstate(sc, reg); 1168 delay(5); 1169 } 1170 1171 void 1172 envy_i2c_wait(struct envy_softc *sc) 1173 { 1174 int timeout = 50, st; 1175 1176 for (;;) { 1177 st = envy_ccs_read(sc, ENVY_I2C_CTL); 1178 if (!(st & ENVY_I2C_CTL_BUSY)) 1179 break; 1180 if (timeout == 0) { 1181 printf("%s: i2c busy timeout\n", DEVNAME(sc)); 1182 break; 1183 } 1184 delay(50); 1185 timeout--; 1186 } 1187 } 1188 1189 int 1190 envy_i2c_read(struct envy_softc *sc, int dev, int addr) 1191 { 1192 envy_i2c_wait(sc); 1193 envy_ccs_write(sc, ENVY_I2C_ADDR, addr); 1194 envy_i2c_wait(sc); 1195 envy_ccs_write(sc, ENVY_I2C_DEV, dev << 1); 1196 envy_i2c_wait(sc); 1197 return envy_ccs_read(sc, ENVY_I2C_DATA); 1198 } 1199 1200 void 1201 envy_i2c_write(struct envy_softc *sc, int dev, int addr, int data) 1202 { 1203 if (dev == 0x50) { 1204 printf("%s: writing on eeprom is evil...\n", DEVNAME(sc)); 1205 return; 1206 } 1207 envy_i2c_wait(sc); 1208 envy_ccs_write(sc, ENVY_I2C_ADDR, addr); 1209 envy_i2c_wait(sc); 1210 envy_ccs_write(sc, ENVY_I2C_DATA, data); 1211 envy_i2c_wait(sc); 1212 envy_ccs_write(sc, ENVY_I2C_DEV, (dev << 1) | 1); 1213 } 1214 1215 int 1216 envy_codec_read(struct envy_softc *sc, int dev, int addr) { 1217 return sc->shadow[dev][addr]; 1218 } 1219 1220 void 1221 envy_codec_write(struct envy_softc *sc, int dev, int addr, int data) 1222 { 1223 DPRINTFN(2, "envy_codec_write: %d, %d, 0x%x\n", dev, addr, data); 1224 sc->shadow[dev][addr] = data; 1225 sc->card->codec_write(sc, dev, addr, data); 1226 } 1227 1228 int 1229 envy_eeprom_gpioxxx(struct envy_softc *sc, int addr) 1230 { 1231 int val; 1232 1233 val = sc->eeprom[addr]; 1234 if (sc->isht) { 1235 val |= sc->eeprom[++addr] << 8; 1236 val |= sc->eeprom[++addr] << 16; 1237 } 1238 return val; 1239 } 1240 1241 int 1242 envy_ac97_wait(struct envy_softc *sc) 1243 { 1244 int timeout = 50, st; 1245 1246 for (;;) { 1247 st = envy_mt_read_1(sc, ENVY_MT_AC97_CMD); 1248 if ((st & ENVY_MT_AC97_READY) && !(st & ENVY_MT_AC97_CMD_MASK)) { 1249 st = 0; 1250 break; 1251 } 1252 if (timeout == 0) { 1253 st = -1; 1254 break; 1255 } 1256 delay(50); 1257 timeout--; 1258 } 1259 1260 return (st); 1261 } 1262 1263 int 1264 envy_ac97_attach_codec(void *hdl, struct ac97_codec_if *codec_if) 1265 { 1266 struct envy_softc *sc = hdl; 1267 1268 sc->codec_if = codec_if; 1269 1270 return (0); 1271 } 1272 1273 int 1274 envy_ac97_read_codec(void *hdl, u_int8_t reg, u_int16_t *result) 1275 { 1276 struct envy_softc *sc = hdl; 1277 1278 if (envy_ac97_wait(sc)) { 1279 printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc)); 1280 return (-1); 1281 } 1282 1283 envy_mt_write_1(sc, ENVY_MT_AC97_IDX, reg & 0x7f); 1284 envy_mt_write_1(sc, ENVY_MT_AC97_CMD, 1285 ENVY_MT_AC97_CMD_RD); 1286 delay(50); 1287 1288 if (envy_ac97_wait(sc)) { 1289 printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc)); 1290 return (-1); 1291 } 1292 1293 *result = envy_mt_read_2(sc, ENVY_MT_AC97_DATA); 1294 1295 return (0); 1296 } 1297 1298 int 1299 envy_ac97_write_codec(void *hdl, u_int8_t reg, u_int16_t data) 1300 { 1301 struct envy_softc *sc = hdl; 1302 1303 if (envy_ac97_wait(sc)) { 1304 printf("%s: envy_ac97_write_codec: timed out\n", DEVNAME(sc)); 1305 return (-1); 1306 } 1307 1308 envy_mt_write_1(sc, ENVY_MT_AC97_IDX, reg & 0x7f); 1309 envy_mt_write_2(sc, ENVY_MT_AC97_DATA, data); 1310 envy_mt_write_1(sc, ENVY_MT_AC97_CMD, 1311 ENVY_MT_AC97_CMD_WR); 1312 delay(50); 1313 1314 return (0); 1315 } 1316 1317 void 1318 envy_ac97_reset_codec(void *hdl) 1319 { 1320 struct envy_softc *sc = hdl; 1321 1322 envy_mt_write_1(sc, ENVY_MT_AC97_CMD, ENVY_MT_AC97_CMD_RST); 1323 delay(50); 1324 envy_mt_write_1(sc, ENVY_MT_AC97_CMD, 0); 1325 delay(50); 1326 1327 if (envy_ac97_wait(sc)) { 1328 printf("%s: envy_ac97_reset_codec: timed out\n", DEVNAME(sc)); 1329 } 1330 1331 return; 1332 } 1333 1334 enum ac97_host_flags 1335 envy_ac97_flags_codec(void *hdl) 1336 { 1337 struct envy_softc *sc = hdl; 1338 1339 return (sc->codec_flags); 1340 } 1341 1342 void 1343 envy_midi_wait(struct envy_softc *sc) 1344 { 1345 int i, st; 1346 1347 for (i = 100;; i--) { 1348 st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); 1349 if (!(st & ENVY_MIDISTAT_OBUSY(sc))) 1350 break; 1351 if (i == 0) { 1352 printf("%s: midi wait timeout\n", DEVNAME(sc)); 1353 break; 1354 } 1355 delay(10); 1356 } 1357 } 1358 1359 void 1360 envy_reset(struct envy_softc *sc) 1361 { 1362 int i, reg; 1363 1364 /* 1365 * full reset 1366 */ 1367 envy_ccs_write(sc, ENVY_CTL, ENVY_CTL_RESET | ENVY_CTL_NATIVE); 1368 delay(200); 1369 envy_ccs_write(sc, ENVY_CTL, ENVY_CTL_NATIVE); 1370 delay(200); 1371 1372 /* 1373 * read EEPROM using i2c device or from a static array 1374 */ 1375 if (sc->card->eeprom == NULL) { 1376 for (i = 0; i < ENVY_EEPROM_MAXSZ; i++) { 1377 sc->eeprom[i] = envy_i2c_read(sc, ENVY_I2C_DEV_EEPROM, i); 1378 } 1379 #ifdef ENVY_DEBUG 1380 printf("%s: eeprom: ", DEVNAME(sc)); 1381 for (i = 0; i < ENVY_EEPROM_MAXSZ; i++) { 1382 printf(" %02x", (unsigned)sc->eeprom[i]); 1383 } 1384 printf("\n"); 1385 #endif 1386 } else 1387 memcpy(sc->eeprom, sc->card->eeprom, ENVY_EEPROM_MAXSZ); 1388 1389 /* 1390 * write EEPROM values to corresponding registers 1391 */ 1392 if (sc->isht) { 1393 envy_ccs_write(sc, ENVY_CCS_CONF, 1394 sc->eeprom[ENVY_EEPROM_CONF]); 1395 envy_ccs_write(sc, ENVY_CCS_ACLINK, 1396 sc->eeprom[ENVY_EEPROM_ACLINK]); 1397 envy_ccs_write(sc, ENVY_CCS_I2S, 1398 sc->eeprom[ENVY_EEPROM_I2S]); 1399 envy_ccs_write(sc, ENVY_CCS_SPDIF, 1400 sc->eeprom[ENVY_EEPROM_SPDIF]); 1401 } else { 1402 pci_conf_write(sc->pci_pc, sc->pci_tag, ENVY_CONF, 1403 sc->eeprom[ENVY_EEPROM_CONF] | 1404 (sc->eeprom[ENVY_EEPROM_ACLINK] << 8) | 1405 (sc->eeprom[ENVY_EEPROM_I2S] << 16) | 1406 (sc->eeprom[ENVY_EEPROM_SPDIF] << 24)); 1407 } 1408 1409 envy_gpio_setmask(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOMASK(sc))); 1410 envy_gpio_setdir(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIODIR(sc))); 1411 envy_gpio_setstate(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOST(sc))); 1412 1413 DPRINTF("%s: gpio_mask = %02x\n", DEVNAME(sc), 1414 envy_gpio_getmask(sc)); 1415 DPRINTF("%s: gpio_dir = %02x\n", DEVNAME(sc), 1416 envy_gpio_getdir(sc)); 1417 DPRINTF("%s: gpio_state = %02x\n", DEVNAME(sc), 1418 envy_gpio_getstate(sc)); 1419 1420 if (sc->isht) { 1421 /* 1422 * set water marks so we get an interrupt for each byte 1423 */ 1424 envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1); 1425 envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1 | ENVY_CCS_MIDIWAT_RX); 1426 } 1427 1428 /* 1429 * switch to UART mode 1430 */ 1431 envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, 0xff); 1432 envy_midi_wait(sc); 1433 envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, ENVY_MIDISTAT_UART); 1434 envy_midi_wait(sc); 1435 if (!sc->isht) 1436 (void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA0); 1437 1438 /* 1439 * clear all interrupts and unmask used ones 1440 */ 1441 envy_ccs_write(sc, ENVY_CCS_INTSTAT, 0xff); 1442 reg = ~ENVY_CCS_INT_MT; 1443 if (sc->midi_isopen) 1444 reg &= ~ENVY_CCS_INT_MIDI0; 1445 envy_ccs_write(sc, ENVY_CCS_INTMASK, ~ENVY_CCS_INT_MT); 1446 if (sc->isht) { 1447 envy_mt_write_1(sc, ENVY_MT_NSTREAM, 4 - sc->card->noch / 2); 1448 envy_mt_write_1(sc, ENVY_MT_IMASK, ~(ENVY_MT_IMASK_PDMA0 | 1449 ENVY_MT_IMASK_RDMA0 | ENVY_MT_IMASK_ERR)); 1450 } 1451 sc->iactive = 0; 1452 sc->oactive = 0; 1453 sc->card->init(sc); 1454 } 1455 1456 int 1457 envy_lineout_getsrc(struct envy_softc *sc, int out) 1458 { 1459 int reg, shift, src; 1460 1461 if (sc->isht) { 1462 reg = envy_mt_read_4(sc, ENVY_MT_HTSRC); 1463 DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg); 1464 shift = 3 * (out / 2) + ((out & 1) ? 20 : 8); 1465 src = (reg >> shift) & ENVY_MT_HTSRC_MASK; 1466 if (src == ENVY_MT_HTSRC_DMA) { 1467 return ENVY_MIX_OUTSRC_DMA; 1468 } else { 1469 src -= ENVY_MT_HTSRC_LINE; 1470 return ENVY_MIX_OUTSRC_LINEIN + src; 1471 } 1472 } 1473 1474 reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC); 1475 DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg); 1476 shift = (out & 1) ? (out & ~1) + 8 : out; 1477 src = (reg >> shift) & 3; 1478 if (src == ENVY_MT_OUTSRC_DMA) { 1479 return ENVY_MIX_OUTSRC_DMA; 1480 } else if (src == ENVY_MT_OUTSRC_MON) { 1481 return ENVY_MIX_OUTSRC_MON; 1482 } 1483 reg = envy_mt_read_4(sc, ENVY_MT_INSEL); 1484 DPRINTF("%s: insel=%x\n", DEVNAME(sc), reg); 1485 reg = (reg >> (out * 4)) & 0xf; 1486 if (src == ENVY_MT_OUTSRC_LINE) 1487 return ENVY_MIX_OUTSRC_LINEIN + (reg & 7); 1488 else 1489 return ENVY_MIX_OUTSRC_SPDIN + (reg >> 3); 1490 } 1491 1492 void 1493 envy_lineout_setsrc(struct envy_softc *sc, int out, int src) 1494 { 1495 int reg, shift, mask, sel; 1496 1497 if (sc->isht) { 1498 if (src < ENVY_MIX_OUTSRC_SPDIN) { 1499 sel = ENVY_MT_HTSRC_LINE; 1500 sel += src; 1501 } else if (src < ENVY_MIX_OUTSRC_DMA) { 1502 sel = ENVY_MT_HTSRC_SPD; 1503 sel += src - ENVY_MIX_OUTSRC_SPDIN; 1504 } else { 1505 sel = ENVY_MT_HTSRC_DMA; 1506 } 1507 shift = 3 * (out / 2) + ((out & 1) ? 20 : 8); 1508 mask = ENVY_MT_HTSRC_MASK << shift; 1509 reg = envy_mt_read_4(sc, ENVY_MT_HTSRC); 1510 reg = (reg & ~mask) | (sel << shift); 1511 envy_mt_write_4(sc, ENVY_MT_HTSRC, reg); 1512 DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg); 1513 return; 1514 } 1515 1516 if (src < ENVY_MIX_OUTSRC_DMA) { 1517 /* 1518 * linein and spdin are used as output source so we 1519 * must select the input source channel number 1520 */ 1521 if (src < ENVY_MIX_OUTSRC_SPDIN) 1522 sel = src - ENVY_MIX_OUTSRC_LINEIN; 1523 else 1524 sel = (src - ENVY_MIX_OUTSRC_SPDIN) << 3; 1525 1526 shift = out * ENVY_MT_INSEL_BITS; 1527 mask = ENVY_MT_INSEL_MASK << shift; 1528 reg = envy_mt_read_4(sc, ENVY_MT_INSEL); 1529 reg = (reg & ~mask) | (sel << shift); 1530 envy_mt_write_4(sc, ENVY_MT_INSEL, reg); 1531 DPRINTF("%s: insel <- %x\n", DEVNAME(sc), reg); 1532 } 1533 1534 /* 1535 * set the lineout route register 1536 */ 1537 if (src < ENVY_MIX_OUTSRC_SPDIN) { 1538 sel = ENVY_MT_OUTSRC_LINE; 1539 } else if (src < ENVY_MIX_OUTSRC_DMA) { 1540 sel = ENVY_MT_OUTSRC_SPD; 1541 } else if (src == ENVY_MIX_OUTSRC_DMA) { 1542 sel = ENVY_MT_OUTSRC_DMA; 1543 } else { 1544 sel = ENVY_MT_OUTSRC_MON; 1545 } 1546 shift = (out & 1) ? (out & ~1) + 8 : out; 1547 mask = ENVY_MT_OUTSRC_MASK << shift; 1548 reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC); 1549 reg = (reg & ~mask) | (sel << shift); 1550 envy_mt_write_2(sc, ENVY_MT_OUTSRC, reg); 1551 DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg); 1552 } 1553 1554 1555 int 1556 envy_spdout_getsrc(struct envy_softc *sc, int out) 1557 { 1558 int reg, src, sel; 1559 1560 reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE); 1561 DPRINTF("%s: spdroute=%x\n", DEVNAME(sc), reg); 1562 src = (out == 0) ? reg : reg >> 2; 1563 src &= ENVY_MT_SPDSRC_MASK; 1564 if (src == ENVY_MT_SPDSRC_DMA) { 1565 return ENVY_MIX_OUTSRC_DMA; 1566 } else if (src == ENVY_MT_SPDSRC_MON) { 1567 return ENVY_MIX_OUTSRC_MON; 1568 } 1569 1570 sel = (out == 0) ? reg >> 8 : reg >> 12; 1571 sel &= ENVY_MT_SPDSEL_MASK; 1572 if (src == ENVY_MT_SPDSRC_LINE) 1573 return ENVY_MIX_OUTSRC_LINEIN + (sel & 7); 1574 else 1575 return ENVY_MIX_OUTSRC_SPDIN + (sel >> 3); 1576 } 1577 1578 void 1579 envy_spdout_setsrc(struct envy_softc *sc, int out, int src) 1580 { 1581 int reg, shift, mask, sel; 1582 1583 reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE); 1584 if (src < ENVY_MIX_OUTSRC_DMA) { 1585 /* 1586 * linein and spdin are used as output source so we 1587 * must select the input source channel number 1588 */ 1589 if (src < ENVY_MIX_OUTSRC_SPDIN) 1590 sel = src - ENVY_MIX_OUTSRC_LINEIN; 1591 else 1592 sel = (src - ENVY_MIX_OUTSRC_SPDIN) << 3; 1593 1594 shift = 8 + out * ENVY_MT_SPDSEL_BITS; 1595 mask = ENVY_MT_SPDSEL_MASK << shift; 1596 reg = (reg & ~mask) | (sel << shift); 1597 } 1598 1599 /* 1600 * set the lineout route register 1601 */ 1602 if (src < ENVY_MIX_OUTSRC_SPDIN) { 1603 sel = ENVY_MT_OUTSRC_LINE; 1604 } else if (src < ENVY_MIX_OUTSRC_DMA) { 1605 sel = ENVY_MT_OUTSRC_SPD; 1606 } else if (src == ENVY_MIX_OUTSRC_DMA) { 1607 sel = ENVY_MT_OUTSRC_DMA; 1608 } else { 1609 sel = ENVY_MT_OUTSRC_MON; 1610 } 1611 shift = out * 2; 1612 mask = ENVY_MT_SPDSRC_MASK << shift; 1613 reg = (reg & ~mask) | (sel << shift); 1614 envy_mt_write_2(sc, ENVY_MT_SPDROUTE, reg); 1615 DPRINTF("%s: spdroute <- %x\n", DEVNAME(sc), reg); 1616 } 1617 1618 void 1619 envy_mon_getvol(struct envy_softc *sc, int idx, int ch, int *val) 1620 { 1621 int reg; 1622 1623 envy_mt_write_2(sc, ENVY_MT_MONIDX, idx); 1624 reg = envy_mt_read_1(sc, ENVY_MT_MONDATA + ch); 1625 *val = 0x7f - (reg & 0x7f); 1626 } 1627 1628 void 1629 envy_mon_setvol(struct envy_softc *sc, int idx, int ch, int val) 1630 { 1631 int reg; 1632 1633 envy_mt_write_2(sc, ENVY_MT_MONIDX, idx); 1634 reg = 0x7f - val; 1635 DPRINTF("%s: mon=%d/%d <- %d\n", DEVNAME(sc), reg, ch, val); 1636 envy_mt_write_1(sc, ENVY_MT_MONDATA + ch, reg); 1637 } 1638 1639 int 1640 envymatch(struct device *parent, void *match, void *aux) 1641 { 1642 return pci_matchbyid((struct pci_attach_args *)aux, envy_matchids, 1643 sizeof(envy_matchids) / sizeof(envy_matchids[0])); 1644 } 1645 1646 void 1647 envyattach(struct device *parent, struct device *self, void *aux) 1648 { 1649 struct envy_softc *sc = (struct envy_softc *)self; 1650 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 1651 pci_intr_handle_t ih; 1652 const char *intrstr; 1653 int subid; 1654 1655 #if NMIDI > 0 1656 sc->midi_isopen = 0; 1657 #endif 1658 sc->pci_tag = pa->pa_tag; 1659 sc->pci_pc = pa->pa_pc; 1660 sc->pci_dmat = pa->pa_dmat; 1661 sc->pci_ih = NULL; 1662 sc->ibuf.addr = sc->obuf.addr = NULL; 1663 sc->ccs_iosz = 0; 1664 sc->mt_iosz = 0; 1665 sc->isht = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ICENSEMBLE_VT172x); 1666 1667 if (pci_mapreg_map(pa, ENVY_CTL_BAR, PCI_MAPREG_TYPE_IO, 0, 1668 &sc->ccs_iot, &sc->ccs_ioh, NULL, &sc->ccs_iosz, 0)) { 1669 printf(": can't map ctl i/o space\n"); 1670 sc->ccs_iosz = 0; 1671 return; 1672 } 1673 if (pci_mapreg_map(pa, ENVY_MT_BAR(sc->isht), PCI_MAPREG_TYPE_IO, 0, 1674 &sc->mt_iot, &sc->mt_ioh, NULL, &sc->mt_iosz, 0)) { 1675 printf(": can't map mt i/o space\n"); 1676 sc->mt_iosz = 0; 1677 return; 1678 } 1679 if (pci_intr_map(pa, &ih)) { 1680 printf(": can't map interrupt\n"); 1681 } 1682 intrstr = pci_intr_string(sc->pci_pc, ih); 1683 sc->pci_ih = pci_intr_establish(sc->pci_pc, ih, IPL_AUDIO | IPL_MPSAFE, 1684 envy_intr, sc, sc->dev.dv_xname); 1685 if (sc->pci_ih == NULL) { 1686 printf(": can't establish interrupt"); 1687 if (intrstr) 1688 printf(" at %s", intrstr); 1689 printf("\n"); 1690 return; 1691 } 1692 printf(": %s\n", intrstr); 1693 subid = pci_conf_read(sc->pci_pc, sc->pci_tag, PCI_SUBVEND_0); 1694 sc->card = sc->isht ? envy_cards_ht : envy_cards; 1695 while (sc->card->subid != subid) { 1696 if (sc->card->subid == 0) 1697 break; 1698 sc->card++; 1699 } 1700 printf("%s: %s, %u inputs, %u outputs\n", DEVNAME(sc), 1701 sc->card->name, sc->card->nich, sc->card->noch); 1702 envy_reset(sc); 1703 sc->audio = audio_attach_mi(&envy_hw_if, sc, &sc->dev); 1704 #if NMIDI > 0 1705 if (sc->card->nmidi > 0 && (!sc->isht || 1706 sc->eeprom[ENVY_EEPROM_CONF] & ENVY_CONF_MIDI)) { 1707 sc->midi = midi_attach_mi(&envy_midi_hw_if, sc, &sc->dev); 1708 } 1709 #endif 1710 } 1711 1712 int 1713 envydetach(struct device *self, int flags) 1714 { 1715 struct envy_softc *sc = (struct envy_softc *)self; 1716 1717 if (sc->pci_ih != NULL) { 1718 pci_intr_disestablish(sc->pci_pc, sc->pci_ih); 1719 sc->pci_ih = NULL; 1720 } 1721 if (sc->ccs_iosz) { 1722 bus_space_unmap(sc->ccs_iot, sc->ccs_ioh, sc->ccs_iosz); 1723 } 1724 if (sc->mt_iosz) { 1725 bus_space_unmap(sc->mt_iot, sc->mt_ioh, sc->mt_iosz); 1726 } 1727 return 0; 1728 } 1729 1730 int 1731 envy_open(void *self, int flags) 1732 { 1733 return 0; 1734 } 1735 1736 void 1737 envy_close(void *self) 1738 { 1739 } 1740 1741 void * 1742 envy_allocm(void *self, int dir, size_t size, int type, int flags) 1743 { 1744 struct envy_softc *sc = (struct envy_softc *)self; 1745 int err, basereg, wait; 1746 struct envy_buf *buf; 1747 bus_addr_t dma_addr; 1748 1749 if (dir == AUMODE_RECORD) { 1750 buf = &sc->ibuf; 1751 basereg = ENVY_MT_RADDR; 1752 } else { 1753 buf = &sc->obuf; 1754 basereg = ENVY_MT_PADDR; 1755 } 1756 if (buf->addr != NULL) { 1757 DPRINTF("%s: multiple alloc, dir = %d\n", DEVNAME(sc), dir); 1758 return NULL; 1759 } 1760 buf->size = size; 1761 wait = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 1762 1763 #define ENVY_ALIGN 4 1764 #define ENVY_MAXADDR ((1 << 28) - 1) 1765 1766 buf->addr = (caddr_t)uvm_km_kmemalloc_pla(kernel_map, 1767 uvm.kernel_object, buf->size, 0, UVM_KMF_NOWAIT, 0, 1768 (paddr_t)ENVY_MAXADDR, 0, 0, 1); 1769 if (buf->addr == NULL) { 1770 DPRINTF("%s: unable to alloc dma segment\n", DEVNAME(sc)); 1771 goto err_ret; 1772 } 1773 err = bus_dmamap_create(sc->pci_dmat, buf->size, 1, buf->size, 0, 1774 wait, &buf->map); 1775 if (err) { 1776 DPRINTF("%s: dmamap_create: failed %d\n", DEVNAME(sc), err); 1777 goto err_unmap; 1778 } 1779 err = bus_dmamap_load(sc->pci_dmat, buf->map, buf->addr, 1780 buf->size, NULL, wait); 1781 if (err) { 1782 DPRINTF("%s: dmamap_load: failed %d\n", DEVNAME(sc), err); 1783 goto err_destroy; 1784 } 1785 dma_addr = buf->map->dm_segs[0].ds_addr; 1786 DPRINTF("%s: allocated %zd bytes dir=%d, ka=%p, da=%lx\n", DEVNAME(sc), 1787 buf->size, dir, buf->addr, dma_addr); 1788 if (!sc->isht && (dma_addr & ~ENVY_MAXADDR)) { 1789 printf("%s: DMA address beyond 0x10000000\n", DEVNAME(sc)); 1790 goto err_unload; 1791 } 1792 envy_mt_write_4(sc, basereg, dma_addr); 1793 return buf->addr; 1794 err_unload: 1795 bus_dmamap_unload(sc->pci_dmat, buf->map); 1796 err_destroy: 1797 bus_dmamap_destroy(sc->pci_dmat, buf->map); 1798 err_unmap: 1799 uvm_km_free(kernel_map, (vaddr_t)buf->addr, buf->size); 1800 err_ret: 1801 return NULL; 1802 } 1803 1804 void 1805 envy_freem(void *self, void *addr, int type) 1806 { 1807 struct envy_buf *buf; 1808 struct envy_softc *sc = (struct envy_softc *)self; 1809 int dir; 1810 1811 if (sc->ibuf.addr == addr) { 1812 buf = &sc->ibuf; 1813 dir = AUMODE_RECORD; 1814 } else if (sc->obuf.addr == addr) { 1815 buf = &sc->obuf; 1816 dir = AUMODE_PLAY; 1817 } else { 1818 DPRINTF("%s: no buf to free\n", DEVNAME(sc)); 1819 return; 1820 } 1821 bus_dmamap_unload(sc->pci_dmat, buf->map); 1822 bus_dmamap_destroy(sc->pci_dmat, buf->map); 1823 uvm_km_free(kernel_map, (vaddr_t)&buf->addr, buf->size); 1824 buf->addr = NULL; 1825 DPRINTF("%s: freed buffer (mode=%d)\n", DEVNAME(sc), dir); 1826 } 1827 1828 int 1829 envy_set_params(void *self, int setmode, int usemode, 1830 struct audio_params *p, struct audio_params *r) 1831 { 1832 struct envy_softc *sc = (struct envy_softc *)self; 1833 int i, rate, reg; 1834 1835 if (setmode == 0) 1836 return 0; 1837 if (setmode == (AUMODE_PLAY | AUMODE_RECORD) && 1838 p->sample_rate != r->sample_rate) { 1839 DPRINTF("%s: play/rec rates mismatch\n", DEVNAME(sc)); 1840 r->sample_rate = p->sample_rate; 1841 } 1842 rate = (setmode & AUMODE_PLAY) ? p->sample_rate : r->sample_rate; 1843 for (i = 0; envy_rates[i].rate < rate; i++) { 1844 if (envy_rates[i].rate == -1) { 1845 i--; 1846 DPRINTF("%s: rate: %d -> %d\n", DEVNAME(sc), rate, i); 1847 break; 1848 } 1849 } 1850 reg = envy_mt_read_1(sc, ENVY_MT_RATE); 1851 reg &= ~ENVY_MT_RATEMASK; 1852 reg |= envy_rates[i].reg; 1853 envy_mt_write_1(sc, ENVY_MT_RATE, reg); 1854 if (setmode & AUMODE_PLAY) { 1855 p->sample_rate = envy_rates[i].rate; 1856 p->encoding = AUDIO_ENCODING_SLINEAR_LE; 1857 p->precision = 24; 1858 p->bps = 4; 1859 p->msb = 1; 1860 p->channels = sc->isht ? sc->card->noch : ENVY_PCHANS; 1861 } 1862 if (setmode & AUMODE_RECORD) { 1863 r->sample_rate = envy_rates[i].rate; 1864 r->encoding = AUDIO_ENCODING_SLINEAR_LE; 1865 r->precision = 24; 1866 r->bps = 4; 1867 r->msb = 1; 1868 r->channels = sc->isht ? sc->card->nich : ENVY_RCHANS; 1869 } 1870 return 0; 1871 } 1872 1873 int 1874 envy_round_blocksize(void *self, int blksz) 1875 { 1876 return (blksz + 0x1f) & ~0x1f; 1877 } 1878 1879 size_t 1880 envy_round_buffersize(void *self, int dir, size_t bufsz) 1881 { 1882 return bufsz; 1883 } 1884 1885 #ifdef ENVY_DEBUG 1886 void 1887 envy_pintr(struct envy_softc *sc) 1888 { 1889 int i; 1890 1891 if (sc->spurious > 0 || envydebug >= 2) { 1892 printf("%s: spurious = %u, start = %lld.%ld\n", 1893 DEVNAME(sc), sc->spurious, 1894 (long long)sc->start_ts.tv_sec, sc->start_ts.tv_nsec); 1895 for (i = 0; i < sc->nintr; i++) { 1896 printf("%lld.%09ld: " 1897 "active=%d/%d pos=%d/%d st=%x/%x, ctl=%x\n", 1898 (long long)sc->intrs[i].ts.tv_sec, 1899 sc->intrs[i].ts.tv_nsec, 1900 sc->intrs[i].iactive, 1901 sc->intrs[i].oactive, 1902 sc->intrs[i].ipos, 1903 sc->intrs[i].opos, 1904 sc->intrs[i].st, 1905 sc->intrs[i].mask, 1906 sc->intrs[i].ctl); 1907 } 1908 } 1909 } 1910 #endif 1911 1912 int 1913 envy_intr(void *self) 1914 { 1915 struct envy_softc *sc = (struct envy_softc *)self; 1916 unsigned int reg, hwpos, cnt; 1917 int mintr, mstat, mdata; 1918 int st, err, ctl; 1919 int max; 1920 1921 mtx_enter(&audio_lock); 1922 st = envy_mt_read_1(sc, ENVY_MT_INTR); 1923 mintr = envy_ccs_read(sc, ENVY_CCS_INTSTAT); 1924 if (!(st & ENVY_MT_INTR_ALL) && !(mintr & ENVY_CCS_INT_MIDI0)) { 1925 mtx_leave(&audio_lock); 1926 return 0; 1927 } 1928 if (st & ENVY_MT_INTR_ERR) { 1929 err = envy_mt_read_1(sc, ENVY_MT_ERR); 1930 envy_mt_write_1(sc, ENVY_MT_ERR, err); 1931 } 1932 envy_mt_write_1(sc, ENVY_MT_INTR, st); 1933 envy_ccs_write(sc, ENVY_CCS_INTSTAT, mintr); 1934 1935 #ifdef ENVY_DEBUG 1936 if (sc->nintr < ENVY_NINTR) { 1937 sc->intrs[sc->nintr].iactive = sc->iactive; 1938 sc->intrs[sc->nintr].oactive = sc->oactive; 1939 sc->intrs[sc->nintr].st = st; 1940 sc->intrs[sc->nintr].ipos = envy_mt_read_2(sc, ENVY_MT_RBUFSZ); 1941 sc->intrs[sc->nintr].opos = envy_mt_read_2(sc, ENVY_MT_PBUFSZ); 1942 sc->intrs[sc->nintr].ctl = envy_mt_read_1(sc, ENVY_MT_CTL); 1943 sc->intrs[sc->nintr].mask = envy_mt_read_1(sc, ENVY_MT_IMASK); 1944 nanouptime(&sc->intrs[sc->nintr].ts); 1945 sc->nintr++; 1946 } 1947 #endif 1948 if (mintr & ENVY_CCS_INT_MIDI0) { 1949 for (max = 128; max > 0; max--) { 1950 mstat = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); 1951 if (mstat & ENVY_MIDISTAT_IEMPTY(sc)) 1952 break; 1953 mdata = envy_ccs_read(sc, ENVY_CCS_MIDIDATA0); 1954 #if NMIDI > 0 1955 if (sc->midi_in) 1956 sc->midi_in(sc->midi_arg, mdata); 1957 #endif 1958 } 1959 } 1960 if (st & ENVY_MT_INTR_PACK) { 1961 if (sc->oactive) { 1962 reg = envy_mt_read_2(sc, ENVY_MT_PBUFSZ); 1963 hwpos = sc->obuf.bufsz - 4 * (reg + 1); 1964 if (hwpos >= sc->obuf.bufsz) 1965 hwpos -= sc->obuf.bufsz; 1966 DPRINTFN(2, "%s: play: reg = %u, pos: %u -> %u\n", 1967 DEVNAME(sc), reg, sc->obuf.swpos, hwpos); 1968 cnt = 0; 1969 while (hwpos - sc->obuf.swpos >= sc->obuf.blksz) { 1970 sc->ointr(sc->oarg); 1971 sc->obuf.swpos += sc->obuf.blksz; 1972 if (sc->obuf.swpos == sc->obuf.bufsz) 1973 sc->obuf.swpos = 0; 1974 cnt++; 1975 } 1976 if (cnt != 1) { 1977 DPRINTFN(2, "%s: play: %u intrs\n", 1978 DEVNAME(sc), cnt); 1979 } 1980 } else { 1981 ctl = envy_mt_read_1(sc, ENVY_MT_CTL); 1982 if (ctl & ENVY_MT_CTL_PSTART) { 1983 envy_mt_write_1(sc, 1984 ENVY_MT_CTL, ctl & ~ENVY_MT_CTL_PSTART); 1985 st &= ~ENVY_MT_INTR_PACK; 1986 sc->obusy = 0; 1987 wakeup(&sc->obusy); 1988 } 1989 #ifdef ENVY_DEBUG 1990 else 1991 sc->spurious++; 1992 #endif 1993 } 1994 } 1995 if (st & ENVY_MT_INTR_RACK) { 1996 if (sc->iactive) { 1997 reg = envy_mt_read_2(sc, ENVY_MT_RBUFSZ); 1998 hwpos = sc->ibuf.bufsz - 4 * (reg + 1); 1999 if (hwpos >= sc->ibuf.bufsz) 2000 hwpos -= sc->ibuf.bufsz; 2001 DPRINTFN(2, "%s: rec: reg = %u, pos: %u -> %u\n", 2002 DEVNAME(sc), reg, sc->ibuf.swpos, hwpos); 2003 cnt = 0; 2004 while (hwpos - sc->ibuf.swpos >= sc->ibuf.blksz) { 2005 sc->iintr(sc->iarg); 2006 sc->ibuf.swpos += sc->ibuf.blksz; 2007 if (sc->ibuf.swpos == sc->ibuf.bufsz) 2008 sc->ibuf.swpos = 0; 2009 cnt++; 2010 } 2011 if (cnt != 1) { 2012 DPRINTFN(2, "%s: rec: %u intrs\n", 2013 DEVNAME(sc), cnt); 2014 } 2015 } else { 2016 ctl = envy_mt_read_1(sc, ENVY_MT_CTL); 2017 if (ctl & ENVY_MT_CTL_RSTART(sc)) { 2018 envy_mt_write_1(sc, 2019 ENVY_MT_CTL, ctl & ~ENVY_MT_CTL_RSTART(sc)); 2020 st &= ~ENVY_MT_INTR_RACK; 2021 sc->ibusy = 0; 2022 wakeup(&sc->ibusy); 2023 } 2024 #ifdef ENVY_DEBUG 2025 else 2026 sc->spurious++; 2027 #endif 2028 } 2029 } 2030 mtx_leave(&audio_lock); 2031 return 1; 2032 } 2033 2034 int 2035 envy_trigger_output(void *self, void *start, void *end, int blksz, 2036 void (*intr)(void *), void *arg, struct audio_params *param) 2037 { 2038 struct envy_softc *sc = (struct envy_softc *)self; 2039 size_t bufsz; 2040 int st; 2041 2042 bufsz = (char *)end - (char *)start; 2043 #ifdef ENVY_DEBUG 2044 if (blksz % (sc->isht ? sc->card->noch * 4 : ENVY_PFRAME_SIZE) != 0) { 2045 printf("%s: %d: bad output blksz\n", DEVNAME(sc), blksz); 2046 return EINVAL; 2047 } 2048 if (bufsz % blksz) { 2049 printf("%s: %ld: bad output bufsz\n", DEVNAME(sc), bufsz); 2050 return EINVAL; 2051 } 2052 #endif 2053 mtx_enter(&audio_lock); 2054 envy_mt_write_2(sc, ENVY_MT_PBUFSZ, bufsz / 4 - 1); 2055 envy_mt_write_2(sc, ENVY_MT_PBLKSZ(sc), blksz / 4 - 1); 2056 2057 #ifdef ENVY_DEBUG 2058 if (!sc->iactive) { 2059 sc->nintr = 0; 2060 sc->spurious = 0; 2061 nanouptime(&sc->start_ts); 2062 } 2063 #endif 2064 sc->obuf.bufsz = bufsz; 2065 sc->obuf.blksz = blksz; 2066 sc->obuf.swpos = 0; 2067 sc->ointr = intr; 2068 sc->oarg = arg; 2069 sc->oactive = 1; 2070 sc->obusy = 1; 2071 st = ENVY_MT_INTR_PACK; 2072 envy_mt_write_1(sc, ENVY_MT_INTR, st); 2073 st = envy_mt_read_1(sc, ENVY_MT_CTL); 2074 st |= ENVY_MT_CTL_PSTART; 2075 envy_mt_write_1(sc, ENVY_MT_CTL, st); 2076 mtx_leave(&audio_lock); 2077 return 0; 2078 } 2079 2080 int 2081 envy_trigger_input(void *self, void *start, void *end, int blksz, 2082 void (*intr)(void *), void *arg, struct audio_params *param) 2083 { 2084 struct envy_softc *sc = (struct envy_softc *)self; 2085 size_t bufsz; 2086 int st; 2087 2088 bufsz = (char *)end - (char *)start; 2089 #ifdef ENVY_DEBUG 2090 if (blksz % (sc->isht ? sc->card->nich * 4 : ENVY_RFRAME_SIZE) != 0) { 2091 printf("%s: %d: bad input blksz\n", DEVNAME(sc), blksz); 2092 return EINVAL; 2093 } 2094 if (bufsz % blksz != 0) { 2095 printf("%s: %ld: bad input bufsz\n", DEVNAME(sc), bufsz); 2096 return EINVAL; 2097 } 2098 #endif 2099 mtx_enter(&audio_lock); 2100 envy_mt_write_2(sc, ENVY_MT_RBUFSZ, bufsz / 4 - 1); 2101 envy_mt_write_2(sc, ENVY_MT_RBLKSZ, blksz / 4 - 1); 2102 2103 #ifdef ENVY_DEBUG 2104 if (!sc->oactive) { 2105 sc->nintr = 0; 2106 sc->spurious = 0; 2107 nanouptime(&sc->start_ts); 2108 } 2109 #endif 2110 sc->ibuf.bufsz = bufsz; 2111 sc->ibuf.blksz = blksz; 2112 sc->ibuf.swpos = 0; 2113 sc->iintr = intr; 2114 sc->iarg = arg; 2115 sc->iactive = 1; 2116 sc->ibusy = 1; 2117 st = ENVY_MT_INTR_RACK; 2118 envy_mt_write_1(sc, ENVY_MT_INTR, st); 2119 st = envy_mt_read_1(sc, ENVY_MT_CTL); 2120 st |= ENVY_MT_CTL_RSTART(sc); 2121 envy_mt_write_1(sc, ENVY_MT_CTL, st); 2122 mtx_leave(&audio_lock); 2123 return 0; 2124 } 2125 2126 int 2127 envy_halt_output(void *self) 2128 { 2129 struct envy_softc *sc = (struct envy_softc *)self; 2130 int err; 2131 2132 mtx_enter(&audio_lock); 2133 sc->oactive = 0; 2134 if (sc->obusy) { 2135 err = msleep(&sc->obusy, &audio_lock, PWAIT, "envyobus", 4 * hz); 2136 if (err) 2137 printf("%s: output DMA halt timeout\n", DEVNAME(sc)); 2138 } 2139 #ifdef ENVY_DEBUG 2140 if (!sc->iactive) 2141 envy_pintr(sc); 2142 #endif 2143 mtx_leave(&audio_lock); 2144 return 0; 2145 } 2146 2147 int 2148 envy_halt_input(void *self) 2149 { 2150 struct envy_softc *sc = (struct envy_softc *)self; 2151 int err; 2152 2153 mtx_enter(&audio_lock); 2154 sc->iactive = 0; 2155 if (sc->ibusy) { 2156 err = msleep(&sc->ibusy, &audio_lock, PWAIT, "envyibus", 4 * hz); 2157 if (err) 2158 printf("%s: input DMA halt timeout\n", DEVNAME(sc)); 2159 } 2160 #ifdef ENVY_DEBUG 2161 if (!sc->oactive) 2162 envy_pintr(sc); 2163 #endif 2164 mtx_leave(&audio_lock); 2165 return 0; 2166 } 2167 2168 int 2169 envy_query_devinfo(void *self, struct mixer_devinfo *dev) 2170 { 2171 struct envy_softc *sc = (struct envy_softc *)self; 2172 int i, n, idx, ndev; 2173 char *classes[] = { 2174 AudioCinputs, AudioCoutputs, AudioCmonitor 2175 }; 2176 2177 if (sc->isac97) 2178 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dev)); 2179 2180 if (dev->index < 0) 2181 return ENXIO; 2182 2183 idx = dev->index; 2184 ndev = ENVY_MIX_NCLASS; 2185 dev->prev = dev->next = AUDIO_MIXER_LAST; 2186 2187 /* 2188 * classes 2189 */ 2190 if (idx < ndev) { 2191 dev->type = AUDIO_MIXER_CLASS; 2192 dev->mixer_class = idx; 2193 strlcpy(dev->label.name, classes[idx], MAX_AUDIO_DEV_LEN); 2194 return 0; 2195 } 2196 idx -= ndev; 2197 2198 /* 2199 * output.lineX_source 2200 */ 2201 ndev = sc->card->noch; 2202 if (idx < ndev) { 2203 n = 0; 2204 dev->type = AUDIO_MIXER_ENUM; 2205 dev->mixer_class = ENVY_MIX_CLASSOUT; 2206 for (i = 0; i < sc->card->nich; i++) { 2207 dev->un.e.member[n].ord = n; 2208 snprintf(dev->un.e.member[n++].label.name, 2209 MAX_AUDIO_DEV_LEN, AudioNline "-%d", i); 2210 } 2211 dev->un.e.member[n].ord = n; 2212 snprintf(dev->un.e.member[n++].label.name, 2213 MAX_AUDIO_DEV_LEN, "play-%d", idx); 2214 if (!sc->isht && idx < 2) { 2215 dev->un.e.member[n].ord = n; 2216 snprintf(dev->un.e.member[n++].label.name, 2217 MAX_AUDIO_DEV_LEN, "mon-%d", idx); 2218 } 2219 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, 2220 AudioNline "-%d_" AudioNsource, idx); 2221 dev->un.s.num_mem = n; 2222 return 0; 2223 } 2224 idx -= ndev; 2225 2226 /* 2227 * envy monitor level 2228 */ 2229 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR; 2230 if (idx < ndev) { 2231 dev->type = AUDIO_MIXER_VALUE; 2232 dev->mixer_class = ENVY_MIX_CLASSMON; 2233 dev->un.v.delta = 2; 2234 dev->un.v.num_channels = 1; 2235 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, 2236 "%s-%d", idx < 10 ? "play" : "rec", idx % 10); 2237 strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN); 2238 return 0; 2239 } 2240 idx -= ndev; 2241 2242 /* 2243 * inputs.xxx 2244 */ 2245 ndev = sc->card->adc->ndev(sc); 2246 if (idx < ndev) { 2247 sc->card->adc->devinfo(sc, dev, idx); 2248 return 0; 2249 } 2250 idx -= ndev; 2251 2252 /* 2253 * outputs.xxx 2254 */ 2255 ndev = sc->card->dac->ndev(sc); 2256 if (idx < ndev) { 2257 sc->card->dac->devinfo(sc, dev, idx); 2258 return 0; 2259 } 2260 return ENXIO; 2261 } 2262 2263 int 2264 envy_get_port(void *self, struct mixer_ctrl *ctl) 2265 { 2266 struct envy_softc *sc = (struct envy_softc *)self; 2267 int val, idx, ndev; 2268 2269 if (sc->isac97) 2270 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, ctl)); 2271 2272 if (ctl->dev < ENVY_MIX_NCLASS) { 2273 return EINVAL; 2274 } 2275 2276 idx = ctl->dev - ENVY_MIX_NCLASS; 2277 ndev = sc->card->noch; 2278 if (idx < ndev) { 2279 ctl->un.ord = envy_lineout_getsrc(sc, idx); 2280 if (ctl->un.ord >= ENVY_MIX_NOUTSRC) 2281 ctl->un.ord -= ENVY_MIX_NOUTSRC - sc->card->nich; 2282 return 0; 2283 } 2284 idx -= ndev; 2285 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR; 2286 if (idx < ndev) { 2287 envy_mon_getvol(sc, idx / 2, idx % 2, &val); 2288 ctl->un.value.num_channels = 1; 2289 ctl->un.value.level[0] = 2 * val; 2290 return 0; 2291 } 2292 idx -= ndev; 2293 ndev = sc->card->adc->ndev(sc); 2294 if (idx < ndev) { 2295 sc->card->adc->get(sc, ctl, idx); 2296 return 0; 2297 } 2298 idx -= ndev; 2299 ndev = sc->card->dac->ndev(sc); 2300 if (idx < ndev) { 2301 sc->card->dac->get(sc, ctl, idx); 2302 return 0; 2303 } 2304 return ENXIO; 2305 } 2306 2307 int 2308 envy_set_port(void *self, struct mixer_ctrl *ctl) 2309 { 2310 struct envy_softc *sc = (struct envy_softc *)self; 2311 int maxsrc, val, idx, ndev; 2312 2313 if (sc->isac97) 2314 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, ctl)); 2315 2316 if (ctl->dev < ENVY_MIX_NCLASS) { 2317 return EINVAL; 2318 } 2319 2320 idx = ctl->dev - ENVY_MIX_NCLASS; 2321 ndev = sc->card->noch; 2322 if (idx < ndev) { 2323 maxsrc = sc->card->nich + 1; 2324 if (idx < 2) 2325 maxsrc++; 2326 if (ctl->un.ord < 0 || ctl->un.ord >= maxsrc) 2327 return EINVAL; 2328 if (ctl->un.ord >= sc->card->nich) 2329 ctl->un.ord += ENVY_MIX_NOUTSRC - sc->card->nich; 2330 envy_lineout_setsrc(sc, idx, ctl->un.ord); 2331 return 0; 2332 } 2333 idx -= ndev; 2334 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR; 2335 if (idx < ndev) { 2336 if (ctl->un.value.num_channels != 1) { 2337 return EINVAL; 2338 } 2339 val = ctl->un.value.level[0] / 2; 2340 envy_mon_setvol(sc, idx / 2, idx % 2, val); 2341 return 0; 2342 } 2343 idx -= ndev; 2344 ndev = sc->card->adc->ndev(sc); 2345 if (idx < ndev) 2346 return sc->card->adc->set(sc, ctl, idx); 2347 idx -= ndev; 2348 ndev = sc->card->dac->ndev(sc); 2349 if (idx < ndev) 2350 return sc->card->dac->set(sc, ctl, idx); 2351 return ENXIO; 2352 } 2353 2354 int 2355 envy_get_props(void *self) 2356 { 2357 return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT; 2358 } 2359 2360 #if NMIDI > 0 2361 int 2362 envy_midi_open(void *self, int flags, 2363 void (*in)(void *, int), 2364 void (*out)(void *), 2365 void *arg) 2366 { 2367 struct envy_softc *sc = (struct envy_softc *)self; 2368 unsigned int i, reg; 2369 2370 /* discard pending data */ 2371 for (i = 0; i < 128; i++) { 2372 reg = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); 2373 if (reg & ENVY_MIDISTAT_IEMPTY(sc)) 2374 break; 2375 (void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA0); 2376 } 2377 #ifdef ENVY_DEBUG 2378 if (i > 0) 2379 DPRINTF("%s: midi: discarded %u bytes\n", DEVNAME(sc), i); 2380 #endif 2381 2382 /* clear pending midi interrupt */ 2383 envy_ccs_write(sc, ENVY_CCS_INTSTAT, ENVY_CCS_INT_MIDI0); 2384 2385 /* interrupts are disabled, it safe to manipulate these */ 2386 sc->midi_in = in; 2387 sc->midi_out = out; 2388 sc->midi_arg = arg; 2389 sc->midi_isopen = 1; 2390 2391 /* enable interrupts */ 2392 reg = envy_ccs_read(sc, ENVY_CCS_INTMASK); 2393 reg &= ~ENVY_CCS_INT_MIDI0; 2394 envy_ccs_write(sc, ENVY_CCS_INTMASK, reg); 2395 return 0; 2396 } 2397 2398 void 2399 envy_midi_close(void *self) 2400 { 2401 struct envy_softc *sc = (struct envy_softc *)self; 2402 unsigned int reg; 2403 2404 /* wait for output fifo to drain */ 2405 tsleep(sc, PWAIT, "envymid", hz / 10); 2406 2407 /* disable interrupts */ 2408 reg = envy_ccs_read(sc, ENVY_CCS_INTMASK); 2409 reg |= ENVY_CCS_INT_MIDI0; 2410 envy_ccs_write(sc, ENVY_CCS_INTMASK, reg); 2411 2412 /* interrupts are disabled, it safe to manipulate these */ 2413 sc->midi_in = NULL; 2414 sc->midi_out = NULL; 2415 sc->midi_isopen = 0; 2416 } 2417 2418 int 2419 envy_midi_output(void *self, int data) 2420 { 2421 struct envy_softc *sc = (struct envy_softc *)self; 2422 int st; 2423 2424 st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); 2425 if (st & ENVY_MIDISTAT_OBUSY(sc)) 2426 return 0; 2427 envy_ccs_write(sc, ENVY_CCS_MIDIDATA0, data); 2428 return 1; 2429 } 2430 2431 void 2432 envy_midi_getinfo(void *self, struct midi_info *mi) 2433 { 2434 mi->props = MIDI_PROP_CAN_INPUT; 2435 mi->name = "Envy24 MIDI UART"; 2436 } 2437 #endif 2438