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