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