sb16.c revision 55706
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Copyright 1997,1998 Luigi Rizzo. 4 * 5 * Derived from files in the Voxware 3.5 distribution, 6 * Copyright by Hannu Savolainen 1994, under the same copyright 7 * conditions. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD: head/sys/dev/sound/isa/sb16.c 55706 2000-01-10 03:22:28Z cg $ 32 */ 33 34#include <dev/sound/pcm/sound.h> 35 36#include "sbc.h" 37 38#define __SB_MIXER_C__ /* XXX warning... */ 39#include <dev/sound/isa/sb.h> 40#include <dev/sound/chip.h> 41 42#define ESS_BUFFSIZE (65536 - 256) 43#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) 44 45/* channel interface */ 46static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 47static int sbchan_setdir(void *data, int dir); 48static int sbchan_setformat(void *data, u_int32_t format); 49static int sbchan_setspeed(void *data, u_int32_t speed); 50static int sbchan_setblocksize(void *data, u_int32_t blocksize); 51static int sbchan_trigger(void *data, int go); 52static int sbchan_getptr(void *data); 53static pcmchan_caps *sbchan_getcaps(void *data); 54 55/* channel interface for ESS */ 56static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 57static int esschan_setdir(void *data, int dir); 58static int esschan_setformat(void *data, u_int32_t format); 59static int esschan_setspeed(void *data, u_int32_t speed); 60static int esschan_setblocksize(void *data, u_int32_t blocksize); 61static int esschan_trigger(void *data, int go); 62static int esschan_getptr(void *data); 63static pcmchan_caps *esschan_getcaps(void *data); 64 65static pcmchan_caps sb_playcaps = { 66 4000, 22050, 67 AFMT_U8, 68 AFMT_U8 69}; 70 71static pcmchan_caps sb_reccaps = { 72 4000, 13000, 73 AFMT_U8, 74 AFMT_U8 75}; 76 77static pcmchan_caps sbpro_playcaps = { 78 4000, 45000, 79 AFMT_STEREO | AFMT_U8, 80 AFMT_STEREO | AFMT_U8 81}; 82 83static pcmchan_caps sbpro_reccaps = { 84 4000, 15000, 85 AFMT_STEREO | AFMT_U8, 86 AFMT_STEREO | AFMT_U8 87}; 88 89static pcmchan_caps sb16_hcaps = { 90 5000, 45000, 91 AFMT_STEREO | AFMT_S16_LE, 92 AFMT_STEREO | AFMT_S16_LE 93}; 94 95static pcmchan_caps sb16_lcaps = { 96 5000, 45000, 97 AFMT_STEREO | AFMT_U8, 98 AFMT_STEREO | AFMT_U8 99}; 100 101static pcmchan_caps sb16x_caps = { 102 5000, 49000, 103 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 104 AFMT_STEREO | AFMT_S16_LE 105}; 106 107static pcmchan_caps ess_playcaps = { 108 5000, 49000, 109 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 110 AFMT_STEREO | AFMT_S16_LE 111}; 112 113static pcmchan_caps ess_reccaps = { 114 5000, 49000, 115 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 116 AFMT_STEREO | AFMT_S16_LE 117}; 118 119static pcm_channel sb_chantemplate = { 120 sbchan_init, 121 sbchan_setdir, 122 sbchan_setformat, 123 sbchan_setspeed, 124 sbchan_setblocksize, 125 sbchan_trigger, 126 sbchan_getptr, 127 sbchan_getcaps, 128}; 129 130static pcm_channel ess_chantemplate = { 131 esschan_init, 132 esschan_setdir, 133 esschan_setformat, 134 esschan_setspeed, 135 esschan_setblocksize, 136 esschan_trigger, 137 esschan_getptr, 138 esschan_getcaps, 139}; 140 141struct sb_info; 142 143struct sb_chinfo { 144 struct sb_info *parent; 145 pcm_channel *channel; 146 snd_dbuf *buffer; 147 int dir; 148 u_int32_t fmt, spd; 149 int ess_dma_started; 150}; 151 152struct sb_info { 153 struct resource *io_base; /* I/O address for the board */ 154 struct resource *irq; 155 struct resource *drq1; 156 struct resource *drq2; 157 bus_dma_tag_t parent_dmat; 158 159 int bd_id; 160 u_long bd_flags; /* board-specific flags */ 161 struct sb_chinfo pch, rch; 162}; 163 164static int sb_rd(struct sb_info *sb, int reg); 165static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); 166static int sb_dspready(struct sb_info *sb); 167static int sb_cmd(struct sb_info *sb, u_char val); 168static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); 169static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); 170static u_int sb_get_byte(struct sb_info *sb); 171static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); 172static int sb_getmixer(struct sb_info *sb, u_int port); 173static int sb_reset_dsp(struct sb_info *sb); 174 175static void sb_intr(void *arg); 176static int sb_speed(struct sb_chinfo *ch); 177static int sb_start(struct sb_chinfo *ch); 178static int sb_stop(struct sb_chinfo *ch); 179 180static int ess_write(struct sb_info *sb, u_char reg, int val); 181static int ess_read(struct sb_info *sb, u_char reg); 182static void ess_intr(void *arg); 183static int ess_format(struct sb_chinfo *ch, u_int32_t format); 184static int ess_speed(struct sb_chinfo *ch, int speed); 185static int ess_start(struct sb_chinfo *ch); 186static int ess_stop(struct sb_chinfo *ch); 187static int ess_abort(struct sb_chinfo *ch); 188 189static int sbmix_init(snd_mixer *m); 190static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); 191static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src); 192 193static snd_mixer sb_mixer = { 194 "SoundBlaster mixer", 195 sbmix_init, 196 sbmix_set, 197 sbmix_setrecsrc, 198}; 199 200static devclass_t pcm_devclass; 201 202/* 203 * Common code for the midi and pcm functions 204 * 205 * sb_cmd write a single byte to the CMD port. 206 * sb_cmd1 write a CMD + 1 byte arg 207 * sb_cmd2 write a CMD + 2 byte arg 208 * sb_get_byte returns a single byte from the DSP data port 209 * 210 * ess_write is actually sb_cmd1 211 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte 212 */ 213 214static int 215port_rd(struct resource *port, int off) 216{ 217 return bus_space_read_1(rman_get_bustag(port), 218 rman_get_bushandle(port), 219 off); 220} 221 222static void 223port_wr(struct resource *port, int off, u_int8_t data) 224{ 225 return bus_space_write_1(rman_get_bustag(port), 226 rman_get_bushandle(port), 227 off, data); 228} 229 230static int 231sb_rd(struct sb_info *sb, int reg) 232{ 233 return port_rd(sb->io_base, reg); 234} 235 236static void 237sb_wr(struct sb_info *sb, int reg, u_int8_t val) 238{ 239 port_wr(sb->io_base, reg, val); 240} 241 242static int 243sb_dspready(struct sb_info *sb) 244{ 245 return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0); 246} 247 248static int 249sb_dspwr(struct sb_info *sb, u_char val) 250{ 251 int i; 252 253 for (i = 0; i < 1000; i++) { 254 if (sb_dspready(sb)) { 255 sb_wr(sb, SBDSP_CMD, val); 256 return 1; 257 } 258 if (i > 10) DELAY((i > 100)? 1000 : 10); 259 } 260 printf("sb_dspwr(0x%02x) timed out.\n", val); 261 return 0; 262} 263 264static int 265sb_cmd(struct sb_info *sb, u_char val) 266{ 267#if 0 268 printf("sb_cmd: %x\n", val); 269#endif 270 return sb_dspwr(sb, val); 271} 272 273static int 274sb_cmd1(struct sb_info *sb, u_char cmd, int val) 275{ 276#if 0 277 printf("sb_cmd1: %x, %x\n", cmd, val); 278#endif 279 if (sb_dspwr(sb, cmd)) { 280 return sb_dspwr(sb, val & 0xff); 281 } else return 0; 282} 283 284static int 285sb_cmd2(struct sb_info *sb, u_char cmd, int val) 286{ 287#if 0 288 printf("sb_cmd2: %x, %x\n", cmd, val); 289#endif 290 if (sb_dspwr(sb, cmd)) { 291 return sb_dspwr(sb, val & 0xff) && 292 sb_dspwr(sb, (val >> 8) & 0xff); 293 } else return 0; 294} 295 296/* 297 * in the SB, there is a set of indirect "mixer" registers with 298 * address at offset 4, data at offset 5 299 */ 300static void 301sb_setmixer(struct sb_info *sb, u_int port, u_int value) 302{ 303 u_long flags; 304 305 flags = spltty(); 306 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 307 DELAY(10); 308 sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); 309 DELAY(10); 310 splx(flags); 311} 312 313static int 314sb_getmixer(struct sb_info *sb, u_int port) 315{ 316 int val; 317 u_long flags; 318 319 flags = spltty(); 320 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 321 DELAY(10); 322 val = sb_rd(sb, SB_MIX_DATA); 323 DELAY(10); 324 splx(flags); 325 326 return val; 327} 328 329static u_int 330sb_get_byte(struct sb_info *sb) 331{ 332 int i; 333 334 for (i = 1000; i > 0; i--) { 335 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) 336 return sb_rd(sb, DSP_READ); 337 else 338 DELAY(20); 339 } 340 return 0xffff; 341} 342 343static int 344ess_write(struct sb_info *sb, u_char reg, int val) 345{ 346 return sb_cmd1(sb, reg, val); 347} 348 349static int 350ess_read(struct sb_info *sb, u_char reg) 351{ 352 return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff; 353} 354 355static int 356sb_reset_dsp(struct sb_info *sb) 357{ 358 sb_wr(sb, SBDSP_RST, 3); 359 DELAY(100); 360 sb_wr(sb, SBDSP_RST, 0); 361 if (sb_get_byte(sb) != 0xAA) { 362 DEB(printf("sb_reset_dsp 0x%lx failed\n", 363 rman_get_start(d->io_base))); 364 return ENXIO; /* Sorry */ 365 } 366 if (sb->bd_flags & BD_F_ESS) 367 sb_cmd(sb, 0xc6); 368 return 0; 369} 370 371static void 372sb_release_resources(struct sb_info *sb, device_t dev) 373{ 374 /* should we bus_teardown_intr here? */ 375 if (sb->irq) { 376 bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); 377 sb->irq = 0; 378 } 379 if (sb->drq1) { 380 bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1); 381 sb->drq1 = 0; 382 } 383 if (sb->drq2) { 384 bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2); 385 sb->drq2 = 0; 386 } 387 if (sb->io_base) { 388 bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); 389 sb->io_base = 0; 390 } 391 free(sb, M_DEVBUF); 392} 393 394static int 395sb_alloc_resources(struct sb_info *sb, device_t dev) 396{ 397 int rid; 398 399 rid = 0; 400 if (!sb->io_base) 401 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 402 &rid, 0, ~0, 1, 403 RF_ACTIVE); 404 rid = 0; 405 if (!sb->irq) 406 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ, 407 &rid, 0, ~0, 1, 408 RF_ACTIVE); 409 rid = 0; 410 if (!sb->drq1) 411 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, 412 &rid, 0, ~0, 1, 413 RF_ACTIVE); 414 rid = 1; 415 if (!sb->drq2 && !(sb->bd_flags & BD_F_ESS)) 416 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, 417 &rid, 0, ~0, 1, 418 RF_ACTIVE); 419 420 if (sb->io_base && sb->drq1 && sb->irq) { 421 int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; 422 423 isa_dma_acquire(rman_get_start(sb->drq1)); 424 isa_dmainit(rman_get_start(sb->drq1), bs); 425 426 if (sb->drq2) { 427 isa_dma_acquire(rman_get_start(sb->drq2)); 428 isa_dmainit(rman_get_start(sb->drq2), bs); 429 } 430 431 return 0; 432 } else return ENXIO; 433} 434 435static void 436sb16_swap(void *v, int dir) 437{ 438 struct sb_info *sb = v; 439 int pb = sb->pch.buffer->dl; 440 int rb = sb->rch.buffer->dl; 441 int pc = sb->pch.buffer->chan; 442 int rc = sb->rch.buffer->chan; 443 int swp = 0; 444 445 if (!pb && !rb) { 446 if (dir == PCMDIR_PLAY && pc < 4) 447 swp = 1; 448 else 449 if (dir == PCMDIR_REC && rc < 4) 450 swp = 1; 451 if (sb->bd_flags & BD_F_SB16X) 452 swp = !swp; 453 if (swp) { 454 int t; 455 456 t = sb->pch.buffer->chan; 457 sb->pch.buffer->chan = sb->rch.buffer->chan; 458 sb->rch.buffer->chan = t; 459 sb->pch.buffer->dir = B_WRITE; 460 sb->rch.buffer->dir = B_READ; 461 } 462 } 463} 464 465static int 466sb_doattach(device_t dev, struct sb_info *sb) 467{ 468 snddev_info *d = device_get_softc(dev); 469 void *ih; 470 char status[SND_STATUSLEN]; 471 int bs = (sb->bd_flags & BD_F_ESS)? ESS_BUFFSIZE : DSP_BUFFSIZE; 472 473 if (sb_alloc_resources(sb, dev)) 474 goto no; 475 if (sb_reset_dsp(sb)) 476 goto no; 477 mixer_init(d, &sb_mixer, sb); 478 479 if (sb->bd_flags & BD_F_ESS) 480 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih); 481 else 482 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); 483 if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) 484 pcm_setswap(dev, sb16_swap); 485 if (!sb->drq2) 486 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 487 488 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 489 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 490 /*highaddr*/BUS_SPACE_MAXADDR, 491 /*filter*/NULL, /*filterarg*/NULL, 492 /*maxsize*/bs, /*nsegments*/1, 493 /*maxsegz*/0x3ffff, 494 /*flags*/0, &sb->parent_dmat) != 0) { 495 device_printf(dev, "unable to create dma tag\n"); 496 goto no; 497 } 498 499 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld", 500 rman_get_start(sb->io_base), rman_get_start(sb->irq), 501 rman_get_start(sb->drq1)); 502 if (sb->drq2) 503 snprintf(status + strlen(status), SND_STATUSLEN - strlen(status), 504 ":%ld", rman_get_start(sb->drq2)); 505 506 if (pcm_register(dev, sb, 1, 1)) 507 goto no; 508 if (sb->bd_flags & BD_F_ESS) { 509 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb); 510 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb); 511 } else { 512 pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); 513 pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); 514 } 515 pcm_setstatus(dev, status); 516 517 return 0; 518 519no: 520 sb_release_resources(sb, dev); 521 return ENXIO; 522} 523 524static void 525sb_intr(void *arg) 526{ 527 struct sb_info *sb = (struct sb_info *)arg; 528 int reason = 3, c; 529 530 /* 531 * SB < 4.0 is half duplex and has only 1 bit for int source, 532 * so we fake it. SB 4.x (SB16) has the int source in a separate 533 * register. 534 * The Vibra16X has separate flags for 8 and 16 bit transfers, but 535 * I have no idea how to tell capture from playback interrupts... 536 */ 537 if (sb->bd_flags & BD_F_SB16) { 538 c = sb_getmixer(sb, IRQ_STAT); 539 /* this tells us if the source is 8-bit or 16-bit dma. We 540 * have to check the io channel to map it to read or write... 541 */ 542 reason = 0; 543 if (c & 1) { /* 8-bit dma */ 544 if (sb->pch.fmt & AFMT_U8) 545 reason |= 1; 546 if (sb->rch.fmt & AFMT_U8) 547 reason |= 2; 548 } 549 if (c & 2) { /* 16-bit dma */ 550 if (sb->pch.fmt & AFMT_S16_LE) 551 reason |= 1; 552 if (sb->rch.fmt & AFMT_S16_LE) 553 reason |= 2; 554 } 555 } else c = 1; 556#if 0 557 printf("sb_intr: reason=%d c=0x%x\n", reason, c); 558#endif 559 if ((reason & 1) && (sb->pch.buffer->dl > 0)) 560 chn_intr(sb->pch.channel); 561 if ((reason & 2) && (sb->rch.buffer->dl > 0)) 562 chn_intr(sb->rch.channel); 563 if (c & 1) 564 sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */ 565 if (c & 2) 566 sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ 567} 568 569static void 570ess_intr(void *arg) 571{ 572 struct sb_info *sb = (struct sb_info *)arg; 573 574 sb_rd(sb, DSP_DATA_AVAIL); /* int ack */ 575#ifdef notyet 576 /* 577 * XXX 578 * for full-duplex mode: 579 * should read port 0x6 to identify where interrupt came from. 580 */ 581#endif 582 /* 583 * We are transferring data in DSP normal mode, 584 * so clear the dl to indicate the DMA is stopped. 585 */ 586 if (sb->pch.buffer->dl > 0) { 587 sb->pch.buffer->dl = -1; 588 chn_intr(sb->pch.channel); 589 } 590 if (sb->rch.buffer->dl > 0) { 591 sb->rch.buffer->dl = -1; 592 chn_intr(sb->rch.channel); 593 } 594} 595 596static int 597sb_speed(struct sb_chinfo *ch) 598{ 599 struct sb_info *sb = ch->parent; 600 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 601 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 602 int speed = ch->spd; 603 604 if (sb->bd_flags & BD_F_SB16) { 605 RANGE(speed, 5000, 45000); 606 sb_cmd(sb, 0x42 - play); 607 sb_cmd(sb, speed >> 8); 608 sb_cmd(sb, speed & 0xff); 609 } else { 610 u_char tconst; 611 int max_speed = 45000, tmp; 612 u_long flags; 613 614 /* here enforce speed limitations - max 22050 on sb 1.x*/ 615 if (sb->bd_id <= 0x200) 616 max_speed = 22050; 617 618 /* 619 * SB models earlier than SB Pro have low limit for the 620 * input rate. Note that this is only for input, but since 621 * we do not support separate values for rec & play.... 622 */ 623 if (!play) { 624 if (sb->bd_id <= 0x200) 625 max_speed = 13000; 626 else 627 if (sb->bd_id < 0x300) 628 max_speed = 15000; 629 } 630 RANGE(speed, 4000, max_speed); 631 if (stereo) 632 speed <<= 1; 633 634 /* 635 * Now the speed should be valid. Compute the value to be 636 * programmed into the board. 637 */ 638 if (speed > 22050) { /* High speed mode on 2.01/3.xx */ 639 tconst = (u_char) 640 ((65536 - ((256000000 + speed / 2) / speed)) 641 >> 8); 642 sb->bd_flags |= BD_F_HISPEED; 643 tmp = 65536 - (tconst << 8); 644 speed = (256000000 + tmp / 2) / tmp; 645 } else { 646 sb->bd_flags &= ~BD_F_HISPEED; 647 tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; 648 tmp = 256 - tconst; 649 speed = (1000000 + tmp / 2) / tmp; 650 } 651 flags = spltty(); 652 sb_cmd1(sb, 0x40, tconst); /* set time constant */ 653 splx(flags); 654 if (stereo) 655 speed >>= 1; 656 } 657 ch->spd = speed; 658 return speed; 659} 660 661static int 662sb_start(struct sb_chinfo *ch) 663{ 664 struct sb_info *sb = ch->parent; 665 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 666 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; 667 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 668 int l = ch->buffer->dl; 669 int dh = ch->buffer->chan > 3; 670 u_char i1, i2; 671 672 if (b16 || dh) 673 l >>= 1; 674 l--; 675 676 if (play) 677 sb_cmd(sb, DSP_CMD_SPKON); 678 679 if (sb->bd_flags & BD_F_SB16) { 680 i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON; 681 i1 |= play? DSP_F16_DAC : DSP_F16_ADC; 682 i1 |= (b16 || dh)? DSP_DMA16 : DSP_DMA8; 683 i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0); 684 sb_cmd(sb, i1); 685 sb_cmd2(sb, i2, l); 686 } else { 687 if (sb->bd_flags & BD_F_HISPEED) 688 i1 = play? 0x90 : 0x98; 689 else 690 i1 = play? 0x1c : 0x2c; 691 sb_setmixer(sb, 0x0e, stereo? 2 : 0); 692 sb_cmd2(sb, 0x48, l); 693 sb_cmd(sb, i1); 694 } 695 sb->bd_flags |= BD_F_DMARUN << b16; 696 return 0; 697} 698 699static int 700sb_stop(struct sb_chinfo *ch) 701{ 702 struct sb_info *sb = ch->parent; 703 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 704 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; 705 706 if (sb->bd_flags & BD_F_HISPEED) 707 sb_reset_dsp(sb); 708 else { 709 sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8); 710 /* 711 * The above seems to have the undocumented side effect of 712 * blocking the other side as well. If the other 713 * channel was active (SB16) I have to re-enable it :( 714 */ 715 if (sb->bd_flags & (BD_F_DMARUN << (1 - b16))) 716 sb_cmd(sb, b16? 0xd4 : 0xd6 ); 717 } 718 if (play) 719 sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ 720 sb->bd_flags &= ~(BD_F_DMARUN << b16); 721 return 0; 722} 723 724/* channel interface */ 725static void * 726sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 727{ 728 struct sb_info *sb = devinfo; 729 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; 730 int dch, dl, dh; 731 732 ch->parent = sb; 733 ch->channel = c; 734 ch->buffer = b; 735 ch->buffer->bufsize = DSP_BUFFSIZE; 736 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) 737 return NULL; 738 dch = (dir == PCMDIR_PLAY)? 1 : 0; 739 if (sb->bd_flags & BD_F_SB16X) 740 dch = !dch; 741 dl = rman_get_start(sb->drq1); 742 dh = sb->drq2? rman_get_start(sb->drq2) : dl; 743 ch->buffer->chan = dch? dh : dl; 744 return ch; 745} 746 747static int 748sbchan_setdir(void *data, int dir) 749{ 750 struct sb_chinfo *ch = data; 751 752 ch->dir = dir; 753 return 0; 754} 755 756static int 757sbchan_setformat(void *data, u_int32_t format) 758{ 759 struct sb_chinfo *ch = data; 760 761 ch->fmt = format; 762 return 0; 763} 764 765static int 766sbchan_setspeed(void *data, u_int32_t speed) 767{ 768 struct sb_chinfo *ch = data; 769 770 ch->spd = speed; 771 return sb_speed(ch); 772} 773 774static int 775sbchan_setblocksize(void *data, u_int32_t blocksize) 776{ 777 return blocksize; 778} 779 780static int 781sbchan_trigger(void *data, int go) 782{ 783 struct sb_chinfo *ch = data; 784 785 if (go == PCMTRIG_EMLDMAWR) 786 return 0; 787 788 buf_isadma(ch->buffer, go); 789 if (go == PCMTRIG_START) 790 sb_start(ch); 791 else 792 sb_stop(ch); 793 return 0; 794} 795 796static int 797sbchan_getptr(void *data) 798{ 799 struct sb_chinfo *ch = data; 800 801 return buf_isadmaptr(ch->buffer); 802} 803 804static pcmchan_caps * 805sbchan_getcaps(void *data) 806{ 807 struct sb_chinfo *ch = data; 808 int p = (ch->dir == PCMDIR_PLAY)? 1 : 0; 809 810 if (ch->parent->bd_id < 0x300) 811 return p? &sb_playcaps : &sb_reccaps; 812 else if (ch->parent->bd_id < 0x400) 813 return p? &sbpro_playcaps : &sbpro_reccaps; 814 else if (ch->parent->bd_flags & BD_F_SB16X) 815 return &sb16x_caps; 816 else 817 return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps; 818} 819 820/* utility functions for ESS */ 821static int 822ess_format(struct sb_chinfo *ch, u_int32_t format) 823{ 824 struct sb_info *sb = ch->parent; 825 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 826 int b16 = (format & AFMT_S16_LE)? 1 : 0; 827 int stereo = (format & AFMT_STEREO)? 1 : 0; 828 u_char c; 829 830 ch->fmt = format; 831 sb_reset_dsp(sb); 832 /* auto-init DMA mode */ 833 ess_write(sb, 0xb8, play ? 0x04 : 0x0e); 834 /* mono/stereo */ 835 c = (ess_read(sb, 0xa8) & ~0x03) | 1; 836 if (!stereo) 837 c++; 838 ess_write(sb, 0xa8, c); 839 /* demand mode, 4 bytes/xfer */ 840 ess_write(sb, 0xb9, 2); 841 /* setup dac/adc */ 842 if (play) 843 ess_write(sb, 0xb6, b16? 0x00 : 0x80); 844 ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00)); 845 ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38)); 846 /* irq/drq control */ 847 ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50); 848 ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50); 849 return 0; 850} 851 852static int 853ess_speed(struct sb_chinfo *ch, int speed) 854{ 855 struct sb_info *sb = ch->parent; 856 int t; 857 858 RANGE (speed, 5000, 49000); 859 if (speed > 22000) { 860 t = (795500 + speed / 2) / speed; 861 speed = (795500 + t / 2) / t; 862 t = (256 - t ) | 0x80; 863 } else { 864 t = (397700 + speed / 2) / speed; 865 speed = (397700 + t / 2) / t; 866 t = 128 - t; 867 } 868 ess_write(sb, 0xa1, t); /* set time constant */ 869#if 0 870 d->play_speed = d->rec_speed = speed; 871 speed = (speed * 9 ) / 20; 872#endif 873 t = 256 - 7160000 / ((speed * 9 / 20) * 82); 874 ess_write(sb, 0xa2, t); 875 return speed; 876} 877 878static int 879ess_start(struct sb_chinfo *ch) 880{ 881 struct sb_info *sb = ch->parent; 882 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 883 short c = - ch->buffer->dl; 884 u_char c1; 885 886 /* 887 * clear bit 0 of register B8h 888 */ 889#if 1 890 c1 = play ? 0x04 : 0x0e; 891 ess_write(sb, 0xb8, c1++); 892#else 893 c1 = ess_read(sb, 0xb8) & 0xfe; 894 ess_write(sb, 0xb8, c1++); 895#endif 896 /* 897 * update ESS Transfer Count Register 898 */ 899 ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff)); 900 ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff)); 901 /* 902 * set bit 0 of register B8h 903 */ 904 ess_write(sb, 0xb8, c1); 905 if (play) 906 sb_cmd(sb, DSP_CMD_SPKON); 907 return 0; 908} 909 910static int 911ess_stop(struct sb_chinfo *ch) 912{ 913 struct sb_info *sb = ch->parent; 914 /* 915 * no need to send a stop command if the DMA has already stopped. 916 */ 917 if (ch->buffer->dl > 0) { 918 sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */ 919 } 920 return 0; 921} 922 923static int 924ess_abort(struct sb_chinfo *ch) 925{ 926 struct sb_info *sb = ch->parent; 927 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 928 929 if (play) 930 sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ 931 sb_reset_dsp(sb); 932 ess_format(ch, ch->fmt); 933 ess_speed(ch, ch->channel->speed); 934 return 0; 935} 936 937/* channel interface for ESS18xx */ 938static void * 939esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 940{ 941 struct sb_info *sb = devinfo; 942 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; 943 944 ch->parent = sb; 945 ch->channel = c; 946 ch->buffer = b; 947 ch->buffer->bufsize = ESS_BUFFSIZE; 948 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) 949 return NULL; 950 ch->buffer->chan = rman_get_start(sb->drq1); 951 return ch; 952} 953 954static int 955esschan_setdir(void *data, int dir) 956{ 957 struct sb_chinfo *ch = data; 958 959 ch->dir = dir; 960 return 0; 961} 962 963static int 964esschan_setformat(void *data, u_int32_t format) 965{ 966 struct sb_chinfo *ch = data; 967 968 ess_format(ch, format); 969 return 0; 970} 971 972static int 973esschan_setspeed(void *data, u_int32_t speed) 974{ 975 struct sb_chinfo *ch = data; 976 977 return ess_speed(ch, speed); 978} 979 980static int 981esschan_setblocksize(void *data, u_int32_t blocksize) 982{ 983 return blocksize; 984} 985 986static int 987esschan_trigger(void *data, int go) 988{ 989 struct sb_chinfo *ch = data; 990 991 if (go == PCMTRIG_EMLDMAWR) 992 return 0; 993 switch (go) { 994 case PCMTRIG_START: 995 if (!ch->ess_dma_started) 996 buf_isadma(ch->buffer, go); 997 ch->ess_dma_started = 1; 998 ess_start(ch); 999 break; 1000 case PCMTRIG_STOP: 1001 if (ch->buffer->dl >= 0) { 1002 buf_isadma(ch->buffer, go); 1003 ch->ess_dma_started = 0; 1004 ess_stop(ch); 1005 } 1006 break; 1007 case PCMTRIG_ABORT: 1008 default: 1009 ch->ess_dma_started = 0; 1010 ess_abort(ch); 1011 buf_isadma(ch->buffer, go); 1012 break; 1013 } 1014 return 0; 1015} 1016 1017static int 1018esschan_getptr(void *data) 1019{ 1020 struct sb_chinfo *ch = data; 1021 1022 return buf_isadmaptr(ch->buffer); 1023} 1024 1025static pcmchan_caps * 1026esschan_getcaps(void *data) 1027{ 1028 struct sb_chinfo *ch = data; 1029 1030 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 1031} 1032 1033/************************************************************/ 1034 1035static int 1036sbmix_init(snd_mixer *m) 1037{ 1038 struct sb_info *sb = mix_getdevinfo(m); 1039 1040 switch (sb->bd_flags & BD_F_MIX_MASK) { 1041 case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */ 1042 mix_setdevs(m, SBPRO_MIXER_DEVICES); 1043 mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); 1044 sb_setmixer(sb, 0, 1); /* reset mixer */ 1045 if (!(sb->bd_flags & BD_F_ESS)) 1046 sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ 1047 sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */ 1048 sb_setmixer(sb, FM_VOL, 0x0); /* no midi */ 1049 break; 1050 1051 case BD_F_MIX_CT1745: /* SB16 mixer ... */ 1052 mix_setdevs(m, SB16_MIXER_DEVICES); 1053 mix_setrecdevs(m, SB16_RECORDING_DEVICES); 1054 sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ 1055 sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ 1056 sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ 1057 } 1058 return 0; 1059} 1060 1061static int 1062sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1063{ 1064 struct sb_info *sb = mix_getdevinfo(m); 1065 int regoffs; 1066 u_char val; 1067 mixer_tab *iomap; 1068 1069 switch (sb->bd_flags & BD_F_MIX_MASK) { 1070 case BD_F_MIX_CT1345: 1071 if (sb->bd_flags & BD_F_ESS) 1072 iomap = &ess_mix; 1073 else 1074 iomap = &sbpro_mix; 1075 break; 1076 1077 case BD_F_MIX_CT1745: 1078 iomap = &sb16_mix; 1079 break; 1080 1081 default: 1082 return -1; 1083 } 1084 1085 /* Change left channel */ 1086 regoffs = (*iomap)[dev][LEFT_CHN].regno; 1087 if (regoffs != 0) { 1088 val = sb_getmixer(sb, regoffs); 1089 change_bits(iomap, &val, dev, LEFT_CHN, left); 1090 sb_setmixer(sb, regoffs, val); 1091 } 1092 1093 /* Change right channel */ 1094 regoffs = (*iomap)[dev][RIGHT_CHN].regno; 1095 if (regoffs != 0) { 1096 val = sb_getmixer(sb, regoffs); /* Read the new one */ 1097 change_bits(iomap, &val, dev, RIGHT_CHN, right); 1098 sb_setmixer(sb, regoffs, val); 1099 } else 1100 right = left; 1101 1102 return left | (right << 8); 1103} 1104 1105static int 1106sbmix_setrecsrc(snd_mixer *m, u_int32_t src) 1107{ 1108 struct sb_info *sb = mix_getdevinfo(m); 1109 u_char recdev; 1110 1111 switch (sb->bd_flags & BD_F_MIX_MASK) { 1112 case BD_F_MIX_CT1345: 1113 if (src == SOUND_MASK_LINE) 1114 recdev = 0x06; 1115 else if (src == SOUND_MASK_CD) 1116 recdev = 0x02; 1117 else { /* default: mic */ 1118 src = SOUND_MASK_MIC; 1119 recdev = 0; 1120 } 1121 sb_setmixer(sb, RECORD_SRC, recdev | 1122 (sb_getmixer(sb, RECORD_SRC) & ~0x07)); 1123 break; 1124 1125 case BD_F_MIX_CT1745: /* sb16 */ 1126 recdev = 0; 1127 if (src & SOUND_MASK_MIC) 1128 recdev |= 0x01; /* mono mic */ 1129 if (src & SOUND_MASK_CD) 1130 recdev |= 0x06; /* l+r cd */ 1131 if (src & SOUND_MASK_LINE) 1132 recdev |= 0x18; /* l+r line */ 1133 if (src & SOUND_MASK_SYNTH) 1134 recdev |= 0x60; /* l+r midi */ 1135 sb_setmixer(sb, SB16_IMASK_L, recdev); 1136 sb_setmixer(sb, SB16_IMASK_R, recdev); 1137 /* 1138 * since the same volume controls apply to the input and 1139 * output sections, the best approach to have a consistent 1140 * behaviour among cards would be to disable the output path 1141 * on devices which are used to record. 1142 * However, since users like to have feedback, we only disable 1143 * the mic -- permanently. 1144 */ 1145 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); 1146 break; 1147 } 1148 return src; 1149} 1150 1151static int 1152sbsbc_probe(device_t dev) 1153{ 1154 char buf[64]; 1155 uintptr_t func, ver, r, f; 1156 1157 /* The parent device has already been probed. */ 1158 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); 1159 if (func != SCF_PCM) 1160 return (ENXIO); 1161 1162 r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); 1163 f = (ver & 0xffff0000) >> 16; 1164 ver &= 0x0000ffff; 1165 snprintf(buf, sizeof buf, "SB DSP %d.%02d%s%s", (int) ver >> 8, (int) ver & 0xff, 1166 (f & BD_F_ESS)? " (ESS mode)" : "", 1167 (f & BD_F_SB16X)? " (ViBRA16X)" : ""); 1168 device_set_desc_copy(dev, buf); 1169 1170 return 0; 1171} 1172 1173static int 1174sbsbc_attach(device_t dev) 1175{ 1176 struct sb_info *sb; 1177 uintptr_t ver; 1178 1179 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT); 1180 if (!sb) 1181 return ENXIO; 1182 bzero(sb, sizeof *sb); 1183 1184 BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); 1185 sb->bd_id = ver & 0x0000ffff; 1186 sb->bd_flags = (ver & 0xffff0000) >> 16; 1187 1188 return sb_doattach(dev, sb); 1189} 1190 1191static device_method_t sbsbc_methods[] = { 1192 /* Device interface */ 1193 DEVMETHOD(device_probe, sbsbc_probe), 1194 DEVMETHOD(device_attach, sbsbc_attach), 1195 1196 { 0, 0 } 1197}; 1198 1199static driver_t sbsbc_driver = { 1200 "pcm", 1201 sbsbc_methods, 1202 sizeof(snddev_info), 1203}; 1204 1205DRIVER_MODULE(sbsbc, sbc, sbsbc_driver, pcm_devclass, 0, 0); 1206 1207 1208 1209