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