1 /*- 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <dev/sound/pcm/sound.h> 27 28 #include <dev/pci/pcireg.h> 29 #include <dev/pci/pcivar.h> 30 31 #include <dev/sound/isa/sb.h> 32 #include <dev/sound/chip.h> 33 34 #include "mixer_if.h" 35 36 SND_DECLARE_FILE("$FreeBSD$"); 37 38 #define SOLO_DEFAULT_BUFSZ 16384 39 #define ABS(x) (((x) < 0)? -(x) : (x)) 40 41 /* if defined, playback always uses the 2nd channel and full duplex works */ 42 #define ESS18XX_DUPLEX 1 43 44 /* more accurate clocks and split audio1/audio2 rates */ 45 #define ESS18XX_NEWSPEED 46 47 /* 1 = INTR_MPSAFE, 0 = GIANT */ 48 #define ESS18XX_MPSAFE 1 49 50 static u_int32_t ess_playfmt[] = { 51 AFMT_U8, 52 AFMT_STEREO | AFMT_U8, 53 AFMT_S8, 54 AFMT_STEREO | AFMT_S8, 55 AFMT_S16_LE, 56 AFMT_STEREO | AFMT_S16_LE, 57 AFMT_U16_LE, 58 AFMT_STEREO | AFMT_U16_LE, 59 0 60 }; 61 static struct pcmchan_caps ess_playcaps = {6000, 48000, ess_playfmt, 0}; 62 63 /* 64 * Recording output is byte-swapped 65 */ 66 static u_int32_t ess_recfmt[] = { 67 AFMT_U8, 68 AFMT_STEREO | AFMT_U8, 69 AFMT_S8, 70 AFMT_STEREO | AFMT_S8, 71 AFMT_S16_BE, 72 AFMT_STEREO | AFMT_S16_BE, 73 AFMT_U16_BE, 74 AFMT_STEREO | AFMT_U16_BE, 75 0 76 }; 77 static struct pcmchan_caps ess_reccaps = {6000, 48000, ess_recfmt, 0}; 78 79 struct ess_info; 80 81 struct ess_chinfo { 82 struct ess_info *parent; 83 struct pcm_channel *channel; 84 struct snd_dbuf *buffer; 85 int dir, hwch, stopping; 86 u_int32_t fmt, spd, blksz; 87 }; 88 89 struct ess_info { 90 struct resource *io, *sb, *vc, *mpu, *gp; /* I/O address for the board */ 91 struct resource *irq; 92 void *ih; 93 bus_dma_tag_t parent_dmat; 94 95 int simplex_dir, type, duplex:1, newspeed:1, dmasz[2]; 96 unsigned int bufsz; 97 98 struct ess_chinfo pch, rch; 99 #if ESS18XX_MPSAFE == 1 100 struct mtx *lock; 101 #endif 102 }; 103 104 #if ESS18XX_MPSAFE == 1 105 #define ess_lock(_ess) snd_mtxlock((_ess)->lock) 106 #define ess_unlock(_ess) snd_mtxunlock((_ess)->lock) 107 #define ess_lock_assert(_ess) snd_mtxassert((_ess)->lock) 108 #else 109 #define ess_lock(_ess) 110 #define ess_unlock(_ess) 111 #define ess_lock_assert(_ess) 112 #endif 113 114 static int ess_rd(struct ess_info *sc, int reg); 115 static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); 116 static int ess_dspready(struct ess_info *sc); 117 static int ess_cmd(struct ess_info *sc, u_char val); 118 static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); 119 static int ess_get_byte(struct ess_info *sc); 120 static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); 121 static int ess_getmixer(struct ess_info *sc, u_int port); 122 static int ess_reset_dsp(struct ess_info *sc); 123 124 static int ess_write(struct ess_info *sc, u_char reg, int val); 125 static int ess_read(struct ess_info *sc, u_char reg); 126 127 static void ess_intr(void *arg); 128 static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); 129 static int ess_start(struct ess_chinfo *ch); 130 static int ess_stop(struct ess_chinfo *ch); 131 132 static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir); 133 static int ess_dmapos(struct ess_info *sc, int ch); 134 static int ess_dmatrigger(struct ess_info *sc, int ch, int go); 135 136 /* 137 * Common code for the midi and pcm functions 138 * 139 * ess_cmd write a single byte to the CMD port. 140 * ess_cmd1 write a CMD + 1 byte arg 141 * ess_cmd2 write a CMD + 2 byte arg 142 * ess_get_byte returns a single byte from the DSP data port 143 * 144 * ess_write is actually ess_cmd1 145 * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte 146 */ 147 148 static int 149 port_rd(struct resource *port, int regno, int size) 150 { 151 bus_space_tag_t st = rman_get_bustag(port); 152 bus_space_handle_t sh = rman_get_bushandle(port); 153 154 switch (size) { 155 case 1: 156 return bus_space_read_1(st, sh, regno); 157 case 2: 158 return bus_space_read_2(st, sh, regno); 159 case 4: 160 return bus_space_read_4(st, sh, regno); 161 default: 162 return 0xffffffff; 163 } 164 } 165 166 static void 167 port_wr(struct resource *port, int regno, u_int32_t data, int size) 168 { 169 bus_space_tag_t st = rman_get_bustag(port); 170 bus_space_handle_t sh = rman_get_bushandle(port); 171 172 switch (size) { 173 case 1: 174 bus_space_write_1(st, sh, regno, data); 175 break; 176 case 2: 177 bus_space_write_2(st, sh, regno, data); 178 break; 179 case 4: 180 bus_space_write_4(st, sh, regno, data); 181 break; 182 } 183 } 184 185 static int 186 ess_rd(struct ess_info *sc, int reg) 187 { 188 return port_rd(sc->sb, reg, 1); 189 } 190 191 static void 192 ess_wr(struct ess_info *sc, int reg, u_int8_t val) 193 { 194 port_wr(sc->sb, reg, val, 1); 195 } 196 197 static int 198 ess_dspready(struct ess_info *sc) 199 { 200 return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0); 201 } 202 203 static int 204 ess_dspwr(struct ess_info *sc, u_char val) 205 { 206 int i; 207 208 for (i = 0; i < 1000; i++) { 209 if (ess_dspready(sc)) { 210 ess_wr(sc, SBDSP_CMD, val); 211 return 1; 212 } 213 if (i > 10) DELAY((i > 100)? 1000 : 10); 214 } 215 printf("ess_dspwr(0x%02x) timed out.\n", val); 216 return 0; 217 } 218 219 static int 220 ess_cmd(struct ess_info *sc, u_char val) 221 { 222 DEB(printf("ess_cmd: %x\n", val)); 223 return ess_dspwr(sc, val); 224 } 225 226 static int 227 ess_cmd1(struct ess_info *sc, u_char cmd, int val) 228 { 229 DEB(printf("ess_cmd1: %x, %x\n", cmd, val)); 230 if (ess_dspwr(sc, cmd)) { 231 return ess_dspwr(sc, val & 0xff); 232 } else return 0; 233 } 234 235 static void 236 ess_setmixer(struct ess_info *sc, u_int port, u_int value) 237 { 238 DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);) 239 ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 240 DELAY(10); 241 ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff)); 242 DELAY(10); 243 } 244 245 static int 246 ess_getmixer(struct ess_info *sc, u_int port) 247 { 248 int val; 249 250 ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 251 DELAY(10); 252 val = ess_rd(sc, SB_MIX_DATA); 253 DELAY(10); 254 255 return val; 256 } 257 258 static int 259 ess_get_byte(struct ess_info *sc) 260 { 261 int i; 262 263 for (i = 1000; i > 0; i--) { 264 if (ess_rd(sc, 0xc) & 0x40) 265 return ess_rd(sc, DSP_READ); 266 else 267 DELAY(20); 268 } 269 return -1; 270 } 271 272 static int 273 ess_write(struct ess_info *sc, u_char reg, int val) 274 { 275 return ess_cmd1(sc, reg, val); 276 } 277 278 static int 279 ess_read(struct ess_info *sc, u_char reg) 280 { 281 return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1; 282 } 283 284 static int 285 ess_reset_dsp(struct ess_info *sc) 286 { 287 DEB(printf("ess_reset_dsp\n")); 288 ess_wr(sc, SBDSP_RST, 3); 289 DELAY(100); 290 ess_wr(sc, SBDSP_RST, 0); 291 if (ess_get_byte(sc) != 0xAA) { 292 DEB(printf("ess_reset_dsp failed\n")); 293 /* 294 rman_get_start(d->io_base))); 295 */ 296 return ENXIO; /* Sorry */ 297 } 298 ess_cmd(sc, 0xc6); 299 return 0; 300 } 301 302 static void 303 ess_intr(void *arg) 304 { 305 struct ess_info *sc = (struct ess_info *)arg; 306 int src, pirq = 0, rirq = 0; 307 308 ess_lock(sc); 309 src = 0; 310 if (ess_getmixer(sc, 0x7a) & 0x80) 311 src |= 2; 312 if (ess_rd(sc, 0x0c) & 0x01) 313 src |= 1; 314 315 if (src == 0) { 316 ess_unlock(sc); 317 return; 318 } 319 320 if (sc->duplex) { 321 pirq = (src & sc->pch.hwch)? 1 : 0; 322 rirq = (src & sc->rch.hwch)? 1 : 0; 323 } else { 324 if (sc->simplex_dir == PCMDIR_PLAY) 325 pirq = 1; 326 if (sc->simplex_dir == PCMDIR_REC) 327 rirq = 1; 328 if (!pirq && !rirq) 329 printf("solo: IRQ neither playback nor rec!\n"); 330 } 331 332 DEB(printf("ess_intr: pirq:%d rirq:%d\n",pirq,rirq)); 333 334 if (pirq) { 335 if (sc->pch.stopping) { 336 ess_dmatrigger(sc, sc->pch.hwch, 0); 337 sc->pch.stopping = 0; 338 if (sc->pch.hwch == 1) 339 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 340 else 341 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03); 342 } 343 ess_unlock(sc); 344 chn_intr(sc->pch.channel); 345 ess_lock(sc); 346 } 347 348 if (rirq) { 349 if (sc->rch.stopping) { 350 ess_dmatrigger(sc, sc->rch.hwch, 0); 351 sc->rch.stopping = 0; 352 /* XXX: will this stop audio2? */ 353 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 354 } 355 ess_unlock(sc); 356 chn_intr(sc->rch.channel); 357 ess_lock(sc); 358 } 359 360 if (src & 2) 361 ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80); 362 if (src & 1) 363 ess_rd(sc, DSP_DATA_AVAIL); 364 365 ess_unlock(sc); 366 } 367 368 /* utility functions for ESS */ 369 static u_int8_t 370 ess_calcspeed8(int *spd) 371 { 372 int speed = *spd; 373 u_int32_t t; 374 375 if (speed > 22000) { 376 t = (795500 + speed / 2) / speed; 377 speed = (795500 + t / 2) / t; 378 t = (256 - t) | 0x80; 379 } else { 380 t = (397700 + speed / 2) / speed; 381 speed = (397700 + t / 2) / t; 382 t = 128 - t; 383 } 384 *spd = speed; 385 return t & 0x000000ff; 386 } 387 388 static u_int8_t 389 ess_calcspeed9(int *spd) 390 { 391 int speed, s0, s1, use0; 392 u_int8_t t0, t1; 393 394 /* rate = source / (256 - divisor) */ 395 /* divisor = 256 - (source / rate) */ 396 speed = *spd; 397 t0 = 128 - (793800 / speed); 398 s0 = 793800 / (128 - t0); 399 400 t1 = 128 - (768000 / speed); 401 s1 = 768000 / (128 - t1); 402 t1 |= 0x80; 403 404 use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0; 405 406 *spd = use0? s0 : s1; 407 return use0? t0 : t1; 408 } 409 410 static u_int8_t 411 ess_calcfilter(int spd) 412 { 413 int cutoff; 414 415 /* cutoff = 7160000 / (256 - divisor) */ 416 /* divisor = 256 - (7160000 / cutoff) */ 417 cutoff = (spd * 9 * 82) / 20; 418 return (256 - (7160000 / cutoff)); 419 } 420 421 static int 422 ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len) 423 { 424 int play = (dir == PCMDIR_PLAY)? 1 : 0; 425 int b16 = (fmt & AFMT_16BIT)? 1 : 0; 426 int stereo = (fmt & AFMT_STEREO)? 1 : 0; 427 int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE || fmt == AFMT_U16_BE)? 1 : 0; 428 u_int8_t spdval, fmtval; 429 430 DEB(printf("ess_setupch\n")); 431 spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd); 432 433 sc->simplex_dir = play ? PCMDIR_PLAY : PCMDIR_REC ; 434 435 if (ch == 1) { 436 KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad")); 437 len = -len; 438 /* transfer length low */ 439 ess_write(sc, 0xa4, len & 0x00ff); 440 /* transfer length high */ 441 ess_write(sc, 0xa5, (len & 0xff00) >> 8); 442 /* autoinit, dma dir */ 443 ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a)); 444 /* mono/stereo */ 445 ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02)); 446 /* demand mode, 4 bytes/xfer */ 447 ess_write(sc, 0xb9, 0x02); 448 /* sample rate */ 449 ess_write(sc, 0xa1, spdval); 450 /* filter cutoff */ 451 ess_write(sc, 0xa2, ess_calcfilter(spd)); 452 /* setup dac/adc */ 453 /* 454 if (play) 455 ess_write(sc, 0xb6, unsign? 0x80 : 0x00); 456 */ 457 /* mono, b16: signed, load signal */ 458 /* 459 ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20)); 460 */ 461 /* setup fifo */ 462 ess_write(sc, 0xb7, 0x91 | (unsign? 0x00 : 0x20) | 463 (b16? 0x04 : 0x00) | 464 (stereo? 0x08 : 0x40)); 465 /* irq control */ 466 ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50); 467 /* drq control */ 468 ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50); 469 } else if (ch == 2) { 470 KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad")); 471 len >>= 1; 472 len = -len; 473 /* transfer length low */ 474 ess_setmixer(sc, 0x74, len & 0x00ff); 475 /* transfer length high */ 476 ess_setmixer(sc, 0x76, (len & 0xff00) >> 8); 477 /* autoinit, 4 bytes/req */ 478 ess_setmixer(sc, 0x78, 0x10); 479 fmtval = b16 | (stereo << 1) | ((!unsign) << 2); 480 /* enable irq, set format */ 481 ess_setmixer(sc, 0x7a, 0x40 | fmtval); 482 if (sc->newspeed) { 483 /* sample rate */ 484 ess_setmixer(sc, 0x70, spdval); 485 /* filter cutoff */ 486 ess_setmixer(sc, 0x72, ess_calcfilter(spd)); 487 } 488 489 } 490 return 0; 491 } 492 static int 493 ess_start(struct ess_chinfo *ch) 494 { 495 struct ess_info *sc = ch->parent; 496 497 DEB(printf("ess_start\n");); 498 ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz); 499 ch->stopping = 0; 500 if (ch->hwch == 1) { 501 ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01); 502 if (ch->dir == PCMDIR_PLAY) { 503 #if 0 504 DELAY(100000); /* 100 ms */ 505 #endif 506 ess_cmd(sc, 0xd1); 507 } 508 } else 509 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03); 510 return 0; 511 } 512 513 static int 514 ess_stop(struct ess_chinfo *ch) 515 { 516 struct ess_info *sc = ch->parent; 517 518 DEB(printf("ess_stop\n")); 519 ch->stopping = 1; 520 if (ch->hwch == 1) 521 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); 522 else 523 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); 524 DEB(printf("done with stop\n")); 525 return 0; 526 } 527 528 /* -------------------------------------------------------------------- */ 529 /* channel interface for ESS18xx */ 530 static void * 531 esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 532 { 533 struct ess_info *sc = devinfo; 534 struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 535 536 DEB(printf("esschan_init\n")); 537 ch->parent = sc; 538 ch->channel = c; 539 ch->buffer = b; 540 ch->dir = dir; 541 if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) 542 return NULL; 543 ch->hwch = 1; 544 if ((dir == PCMDIR_PLAY) && (sc->duplex)) 545 ch->hwch = 2; 546 return ch; 547 } 548 549 static int 550 esschan_setformat(kobj_t obj, void *data, u_int32_t format) 551 { 552 struct ess_chinfo *ch = data; 553 554 ch->fmt = format; 555 return 0; 556 } 557 558 static int 559 esschan_setspeed(kobj_t obj, void *data, u_int32_t speed) 560 { 561 struct ess_chinfo *ch = data; 562 struct ess_info *sc = ch->parent; 563 564 ch->spd = speed; 565 if (sc->newspeed) 566 ess_calcspeed9(&ch->spd); 567 else 568 ess_calcspeed8(&ch->spd); 569 return ch->spd; 570 } 571 572 static int 573 esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 574 { 575 struct ess_chinfo *ch = data; 576 577 ch->blksz = blocksize; 578 return ch->blksz; 579 } 580 581 static int 582 esschan_trigger(kobj_t obj, void *data, int go) 583 { 584 struct ess_chinfo *ch = data; 585 struct ess_info *sc = ch->parent; 586 587 DEB(printf("esschan_trigger: %d\n",go)); 588 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 589 return 0; 590 591 ess_lock(sc); 592 switch (go) { 593 case PCMTRIG_START: 594 ess_dmasetup(sc, ch->hwch, sndbuf_getbufaddr(ch->buffer), sndbuf_getsize(ch->buffer), ch->dir); 595 ess_dmatrigger(sc, ch->hwch, 1); 596 ess_start(ch); 597 break; 598 599 case PCMTRIG_STOP: 600 case PCMTRIG_ABORT: 601 default: 602 ess_stop(ch); 603 break; 604 } 605 ess_unlock(sc); 606 return 0; 607 } 608 609 static int 610 esschan_getptr(kobj_t obj, void *data) 611 { 612 struct ess_chinfo *ch = data; 613 struct ess_info *sc = ch->parent; 614 int ret; 615 616 ess_lock(sc); 617 ret = ess_dmapos(sc, ch->hwch); 618 ess_unlock(sc); 619 return ret; 620 } 621 622 static struct pcmchan_caps * 623 esschan_getcaps(kobj_t obj, void *data) 624 { 625 struct ess_chinfo *ch = data; 626 627 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 628 } 629 630 static kobj_method_t esschan_methods[] = { 631 KOBJMETHOD(channel_init, esschan_init), 632 KOBJMETHOD(channel_setformat, esschan_setformat), 633 KOBJMETHOD(channel_setspeed, esschan_setspeed), 634 KOBJMETHOD(channel_setblocksize, esschan_setblocksize), 635 KOBJMETHOD(channel_trigger, esschan_trigger), 636 KOBJMETHOD(channel_getptr, esschan_getptr), 637 KOBJMETHOD(channel_getcaps, esschan_getcaps), 638 { 0, 0 } 639 }; 640 CHANNEL_DECLARE(esschan); 641 642 /************************************************************/ 643 644 static int 645 essmix_init(struct snd_mixer *m) 646 { 647 struct ess_info *sc = mix_getdevinfo(m); 648 649 mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | 650 SOUND_MASK_IMIX); 651 652 mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | 653 SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME | 654 SOUND_MASK_LINE1); 655 656 ess_setmixer(sc, 0, 0); /* reset */ 657 658 return 0; 659 } 660 661 static int 662 essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 663 { 664 struct ess_info *sc = mix_getdevinfo(m); 665 int preg = 0, rreg = 0, l, r; 666 667 l = (left * 15) / 100; 668 r = (right * 15) / 100; 669 switch (dev) { 670 case SOUND_MIXER_SYNTH: 671 preg = 0x36; 672 rreg = 0x6b; 673 break; 674 675 case SOUND_MIXER_PCM: 676 preg = 0x14; 677 rreg = 0x7c; 678 break; 679 680 case SOUND_MIXER_LINE: 681 preg = 0x3e; 682 rreg = 0x6e; 683 break; 684 685 case SOUND_MIXER_MIC: 686 preg = 0x1a; 687 rreg = 0x68; 688 break; 689 690 case SOUND_MIXER_LINE1: 691 preg = 0x3a; 692 rreg = 0x6c; 693 break; 694 695 case SOUND_MIXER_CD: 696 preg = 0x38; 697 rreg = 0x6a; 698 break; 699 700 case SOUND_MIXER_VOLUME: 701 l = left? (left * 63) / 100 : 64; 702 r = right? (right * 63) / 100 : 64; 703 ess_setmixer(sc, 0x60, l); 704 ess_setmixer(sc, 0x62, r); 705 left = (l == 64)? 0 : (l * 100) / 63; 706 right = (r == 64)? 0 : (r * 100) / 63; 707 return left | (right << 8); 708 } 709 710 if (preg) 711 ess_setmixer(sc, preg, (l << 4) | r); 712 if (rreg) 713 ess_setmixer(sc, rreg, (l << 4) | r); 714 715 left = (l * 100) / 15; 716 right = (r * 100) / 15; 717 718 return left | (right << 8); 719 } 720 721 static int 722 essmix_setrecsrc(struct snd_mixer *m, u_int32_t src) 723 { 724 struct ess_info *sc = mix_getdevinfo(m); 725 u_char recdev; 726 727 switch (src) { 728 case SOUND_MASK_CD: 729 recdev = 0x02; 730 break; 731 732 case SOUND_MASK_LINE: 733 recdev = 0x06; 734 break; 735 736 case SOUND_MASK_IMIX: 737 recdev = 0x05; 738 break; 739 740 case SOUND_MASK_MIC: 741 default: 742 recdev = 0x00; 743 src = SOUND_MASK_MIC; 744 break; 745 } 746 747 ess_setmixer(sc, 0x1c, recdev); 748 749 return src; 750 } 751 752 static kobj_method_t solomixer_methods[] = { 753 KOBJMETHOD(mixer_init, essmix_init), 754 KOBJMETHOD(mixer_set, essmix_set), 755 KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), 756 { 0, 0 } 757 }; 758 MIXER_DECLARE(solomixer); 759 760 /************************************************************/ 761 762 static int 763 ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir) 764 { 765 KASSERT(ch == 1 || ch == 2, ("bad ch")); 766 sc->dmasz[ch - 1] = cnt; 767 if (ch == 1) { 768 port_wr(sc->vc, 0x8, 0xc4, 1); /* command */ 769 port_wr(sc->vc, 0xd, 0xff, 1); /* reset */ 770 port_wr(sc->vc, 0xf, 0x01, 1); /* mask */ 771 port_wr(sc->vc, 0xb, dir == PCMDIR_PLAY? 0x58 : 0x54, 1); /* mode */ 772 port_wr(sc->vc, 0x0, base, 4); 773 port_wr(sc->vc, 0x4, cnt - 1, 2); 774 775 } else if (ch == 2) { 776 port_wr(sc->io, 0x6, 0x08, 1); /* autoinit */ 777 port_wr(sc->io, 0x0, base, 4); 778 port_wr(sc->io, 0x4, cnt, 2); 779 } 780 return 0; 781 } 782 783 static int 784 ess_dmapos(struct ess_info *sc, int ch) 785 { 786 int p = 0, i = 0, j = 0; 787 788 KASSERT(ch == 1 || ch == 2, ("bad ch")); 789 if (ch == 1) { 790 791 /* 792 * During recording, this register is known to give back 793 * garbage if it's not quiescent while being read. That's 794 * why we spl, stop the DMA, and try over and over until 795 * adjacent reads are "close", in the right order and not 796 * bigger than is otherwise possible. 797 */ 798 ess_dmatrigger(sc, ch, 0); 799 DELAY(20); 800 do { 801 DELAY(10); 802 if (j > 1) 803 printf("DMA count reg bogus: %04x & %04x\n", 804 i, p); 805 i = port_rd(sc->vc, 0x4, 2) + 1; 806 p = port_rd(sc->vc, 0x4, 2) + 1; 807 } while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000); 808 ess_dmatrigger(sc, ch, 1); 809 } 810 else if (ch == 2) 811 p = port_rd(sc->io, 0x4, 2); 812 return sc->dmasz[ch - 1] - p; 813 } 814 815 static int 816 ess_dmatrigger(struct ess_info *sc, int ch, int go) 817 { 818 KASSERT(ch == 1 || ch == 2, ("bad ch")); 819 if (ch == 1) 820 port_wr(sc->vc, 0xf, go? 0x00 : 0x01, 1); /* mask */ 821 else if (ch == 2) 822 port_wr(sc->io, 0x6, 0x08 | (go? 0x02 : 0x00), 1); /* autoinit */ 823 return 0; 824 } 825 826 static void 827 ess_release_resources(struct ess_info *sc, device_t dev) 828 { 829 if (sc->irq) { 830 if (sc->ih) 831 bus_teardown_intr(dev, sc->irq, sc->ih); 832 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 833 sc->irq = 0; 834 } 835 if (sc->io) { 836 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->io); 837 sc->io = 0; 838 } 839 840 if (sc->sb) { 841 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(1), sc->sb); 842 sc->sb = 0; 843 } 844 845 if (sc->vc) { 846 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(2), sc->vc); 847 sc->vc = 0; 848 } 849 850 if (sc->mpu) { 851 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(3), sc->mpu); 852 sc->mpu = 0; 853 } 854 855 if (sc->gp) { 856 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(4), sc->gp); 857 sc->gp = 0; 858 } 859 860 if (sc->parent_dmat) { 861 bus_dma_tag_destroy(sc->parent_dmat); 862 sc->parent_dmat = 0; 863 } 864 865 #if ESS18XX_MPSAFE == 1 866 if (sc->lock) { 867 snd_mtxfree(sc->lock); 868 sc->lock = NULL; 869 } 870 #endif 871 872 free(sc, M_DEVBUF); 873 } 874 875 static int 876 ess_alloc_resources(struct ess_info *sc, device_t dev) 877 { 878 int rid; 879 880 rid = PCIR_BAR(0); 881 sc->io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 882 883 rid = PCIR_BAR(1); 884 sc->sb = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 885 886 rid = PCIR_BAR(2); 887 sc->vc = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 888 889 rid = PCIR_BAR(3); 890 sc->mpu = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 891 892 rid = PCIR_BAR(4); 893 sc->gp = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 894 895 rid = 0; 896 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 897 RF_ACTIVE | RF_SHAREABLE); 898 899 #if ESS18XX_MPSAFE == 1 900 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_solo softc"); 901 902 return (sc->irq && sc->io && sc->sb && sc->vc && 903 sc->mpu && sc->gp && sc->lock)? 0 : ENXIO; 904 #else 905 return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO; 906 #endif 907 } 908 909 static int 910 ess_probe(device_t dev) 911 { 912 char *s = NULL; 913 u_int32_t subdev; 914 915 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 916 switch (pci_get_devid(dev)) { 917 case 0x1969125d: 918 if (subdev == 0x8888125d) 919 s = "ESS Solo-1E"; 920 else if (subdev == 0x1818125d) 921 s = "ESS Solo-1"; 922 else 923 s = "ESS Solo-1 (unknown vendor)"; 924 break; 925 } 926 927 if (s) 928 device_set_desc(dev, s); 929 return s ? BUS_PROBE_DEFAULT : ENXIO; 930 } 931 932 #define ESS_PCI_LEGACYCONTROL 0x40 933 #define ESS_PCI_CONFIG 0x50 934 #define ESS_PCI_DDMACONTROL 0x60 935 936 static int 937 ess_suspend(device_t dev) 938 { 939 return 0; 940 } 941 942 static int 943 ess_resume(device_t dev) 944 { 945 uint16_t ddma; 946 uint32_t data; 947 struct ess_info *sc = pcm_getdevinfo(dev); 948 949 ess_lock(sc); 950 data = pci_read_config(dev, PCIR_COMMAND, 2); 951 data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN; 952 pci_write_config(dev, PCIR_COMMAND, data, 2); 953 data = pci_read_config(dev, PCIR_COMMAND, 2); 954 955 ddma = rman_get_start(sc->vc) | 1; 956 pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2); 957 pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2); 958 pci_write_config(dev, ESS_PCI_CONFIG, 0, 2); 959 960 if (ess_reset_dsp(sc)) { 961 ess_unlock(sc); 962 goto no; 963 } 964 ess_unlock(sc); 965 if (mixer_reinit(dev)) 966 goto no; 967 ess_lock(sc); 968 if (sc->newspeed) 969 ess_setmixer(sc, 0x71, 0x2a); 970 971 port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ 972 ess_unlock(sc); 973 974 return 0; 975 no: 976 return EIO; 977 } 978 979 static int 980 ess_attach(device_t dev) 981 { 982 struct ess_info *sc; 983 char status[SND_STATUSLEN]; 984 u_int16_t ddma; 985 u_int32_t data; 986 987 sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO); 988 if (!sc) 989 return ENXIO; 990 991 data = pci_read_config(dev, PCIR_COMMAND, 2); 992 data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN; 993 pci_write_config(dev, PCIR_COMMAND, data, 2); 994 data = pci_read_config(dev, PCIR_COMMAND, 2); 995 996 if (ess_alloc_resources(sc, dev)) 997 goto no; 998 999 sc->bufsz = pcm_getbuffersize(dev, 4096, SOLO_DEFAULT_BUFSZ, 65536); 1000 1001 ddma = rman_get_start(sc->vc) | 1; 1002 pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2); 1003 pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2); 1004 pci_write_config(dev, ESS_PCI_CONFIG, 0, 2); 1005 1006 port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ 1007 #ifdef ESS18XX_DUPLEX 1008 sc->duplex = 1; 1009 #else 1010 sc->duplex = 0; 1011 #endif 1012 1013 #ifdef ESS18XX_NEWSPEED 1014 sc->newspeed = 1; 1015 #else 1016 sc->newspeed = 0; 1017 #endif 1018 if (snd_setup_intr(dev, sc->irq, 1019 #if ESS18XX_MPSAFE == 1 1020 INTR_MPSAFE 1021 #else 1022 0 1023 #endif 1024 , ess_intr, sc, &sc->ih)) { 1025 device_printf(dev, "unable to map interrupt\n"); 1026 goto no; 1027 } 1028 1029 if (!sc->duplex) 1030 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 1031 1032 #if 0 1033 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/65536, /*boundary*/0, 1034 #endif 1035 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0, 1036 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 1037 /*highaddr*/BUS_SPACE_MAXADDR, 1038 /*filter*/NULL, /*filterarg*/NULL, 1039 /*maxsize*/sc->bufsz, /*nsegments*/1, 1040 /*maxsegz*/0x3ffff, 1041 /*flags*/0, 1042 #if ESS18XX_MPSAFE == 1 1043 /*lockfunc*/NULL, /*lockarg*/NULL, 1044 #else 1045 /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, 1046 #endif 1047 &sc->parent_dmat) != 0) { 1048 device_printf(dev, "unable to create dma tag\n"); 1049 goto no; 1050 } 1051 1052 if (ess_reset_dsp(sc)) 1053 goto no; 1054 1055 if (sc->newspeed) 1056 ess_setmixer(sc, 0x71, 0x2a); 1057 1058 if (mixer_init(dev, &solomixer_class, sc)) 1059 goto no; 1060 1061 snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld %s", 1062 rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc), 1063 rman_get_start(sc->irq),PCM_KLDSTRING(snd_solo)); 1064 1065 if (pcm_register(dev, sc, 1, 1)) 1066 goto no; 1067 pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc); 1068 pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc); 1069 pcm_setstatus(dev, status); 1070 1071 return 0; 1072 1073 no: 1074 ess_release_resources(sc, dev); 1075 return ENXIO; 1076 } 1077 1078 static int 1079 ess_detach(device_t dev) 1080 { 1081 int r; 1082 struct ess_info *sc; 1083 1084 r = pcm_unregister(dev); 1085 if (r) 1086 return r; 1087 1088 sc = pcm_getdevinfo(dev); 1089 ess_release_resources(sc, dev); 1090 return 0; 1091 } 1092 1093 static device_method_t ess_methods[] = { 1094 /* Device interface */ 1095 DEVMETHOD(device_probe, ess_probe), 1096 DEVMETHOD(device_attach, ess_attach), 1097 DEVMETHOD(device_detach, ess_detach), 1098 DEVMETHOD(device_resume, ess_resume), 1099 DEVMETHOD(device_suspend, ess_suspend), 1100 1101 { 0, 0 } 1102 }; 1103 1104 static driver_t ess_driver = { 1105 "pcm", 1106 ess_methods, 1107 PCM_SOFTC_SIZE, 1108 }; 1109 1110 DRIVER_MODULE(snd_solo, pci, ess_driver, pcm_devclass, 0, 0); 1111 MODULE_DEPEND(snd_solo, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 1112 MODULE_VERSION(snd_solo, 1); 1113 1114 1115 1116