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