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