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