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