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