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