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