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