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