sb16.c revision 62483
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 62483 2000-07-03 20:52:27Z cg $ 32 */ 33 34#include <dev/sound/pcm/sound.h> 35 36#define __SB_MIXER_C__ /* XXX warning... */ 37#include <dev/sound/isa/sb.h> 38#include <dev/sound/chip.h> 39 40#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) 41 42/* channel interface */ 43static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 44static int sbchan_setdir(void *data, int dir); 45static int sbchan_setformat(void *data, u_int32_t format); 46static int sbchan_setspeed(void *data, u_int32_t speed); 47static int sbchan_setblocksize(void *data, u_int32_t blocksize); 48static int sbchan_trigger(void *data, int go); 49static int sbchan_getptr(void *data); 50static pcmchan_caps *sbchan_getcaps(void *data); 51 52static pcmchan_caps sb_playcaps = { 53 4000, 22050, 54 AFMT_U8, 55 AFMT_U8 56}; 57 58static pcmchan_caps sb_reccaps = { 59 4000, 13000, 60 AFMT_U8, 61 AFMT_U8 62}; 63 64static pcmchan_caps sbpro_playcaps = { 65 4000, 45000, 66 AFMT_STEREO | AFMT_U8, 67 AFMT_STEREO | AFMT_U8 68}; 69 70static pcmchan_caps sbpro_reccaps = { 71 4000, 15000, 72 AFMT_STEREO | AFMT_U8, 73 AFMT_STEREO | AFMT_U8 74}; 75 76static pcmchan_caps sb16_hcaps = { 77 5000, 45000, 78 AFMT_STEREO | AFMT_S16_LE, 79 AFMT_STEREO | AFMT_S16_LE 80}; 81 82static pcmchan_caps sb16_lcaps = { 83 5000, 45000, 84 AFMT_STEREO | AFMT_U8, 85 AFMT_STEREO | AFMT_U8 86}; 87 88static pcmchan_caps sb16x_caps = { 89 5000, 49000, 90 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 91 AFMT_STEREO | AFMT_S16_LE 92}; 93 94static pcm_channel sb_chantemplate = { 95 sbchan_init, 96 sbchan_setdir, 97 sbchan_setformat, 98 sbchan_setspeed, 99 sbchan_setblocksize, 100 sbchan_trigger, 101 sbchan_getptr, 102 sbchan_getcaps, 103}; 104 105struct sb_info; 106 107struct sb_chinfo { 108 struct sb_info *parent; 109 pcm_channel *channel; 110 snd_dbuf *buffer; 111 int dir; 112 u_int32_t fmt, spd; 113}; 114 115struct sb_info { 116 struct resource *io_base; /* I/O address for the board */ 117 struct resource *irq; 118 struct resource *drq1; 119 struct resource *drq2; 120 bus_dma_tag_t parent_dmat; 121 122 int bd_id; 123 u_long bd_flags; /* board-specific flags */ 124 struct sb_chinfo pch, rch; 125}; 126 127static int sb_rd(struct sb_info *sb, int reg); 128static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); 129static int sb_dspready(struct sb_info *sb); 130static int sb_cmd(struct sb_info *sb, u_char val); 131static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); 132static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); 133static u_int sb_get_byte(struct sb_info *sb); 134static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); 135static int sb_getmixer(struct sb_info *sb, u_int port); 136static int sb_reset_dsp(struct sb_info *sb); 137 138static void sb_intr(void *arg); 139static int sb_speed(struct sb_chinfo *ch); 140static int sb_start(struct sb_chinfo *ch); 141static int sb_stop(struct sb_chinfo *ch); 142 143static int sbmix_init(snd_mixer *m); 144static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); 145static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src); 146 147static snd_mixer sb_mixer = { 148 "SoundBlaster mixer", 149 sbmix_init, 150 sbmix_set, 151 sbmix_setrecsrc, 152}; 153 154static devclass_t pcm_devclass; 155 156/* 157 * Common code for the midi and pcm functions 158 * 159 * sb_cmd write a single byte to the CMD port. 160 * sb_cmd1 write a CMD + 1 byte arg 161 * sb_cmd2 write a CMD + 2 byte arg 162 * sb_get_byte returns a single byte from the DSP data port 163 * 164 * ess_write is actually sb_cmd1 165 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte 166 */ 167 168static int 169port_rd(struct resource *port, int off) 170{ 171 return bus_space_read_1(rman_get_bustag(port), 172 rman_get_bushandle(port), 173 off); 174} 175 176static void 177port_wr(struct resource *port, int off, u_int8_t data) 178{ 179 return bus_space_write_1(rman_get_bustag(port), 180 rman_get_bushandle(port), 181 off, data); 182} 183 184static int 185sb_rd(struct sb_info *sb, int reg) 186{ 187 return port_rd(sb->io_base, reg); 188} 189 190static void 191sb_wr(struct sb_info *sb, int reg, u_int8_t val) 192{ 193 port_wr(sb->io_base, reg, val); 194} 195 196static int 197sb_dspready(struct sb_info *sb) 198{ 199 return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0); 200} 201 202static int 203sb_dspwr(struct sb_info *sb, u_char val) 204{ 205 int i; 206 207 for (i = 0; i < 1000; i++) { 208 if (sb_dspready(sb)) { 209 sb_wr(sb, SBDSP_CMD, val); 210 return 1; 211 } 212 if (i > 10) DELAY((i > 100)? 1000 : 10); 213 } 214 printf("sb_dspwr(0x%02x) timed out.\n", val); 215 return 0; 216} 217 218static int 219sb_cmd(struct sb_info *sb, u_char val) 220{ 221#if 0 222 printf("sb_cmd: %x\n", val); 223#endif 224 return sb_dspwr(sb, val); 225} 226 227static int 228sb_cmd1(struct sb_info *sb, u_char cmd, int val) 229{ 230#if 0 231 printf("sb_cmd1: %x, %x\n", cmd, val); 232#endif 233 if (sb_dspwr(sb, cmd)) { 234 return sb_dspwr(sb, val & 0xff); 235 } else return 0; 236} 237 238static int 239sb_cmd2(struct sb_info *sb, u_char cmd, int val) 240{ 241#if 0 242 printf("sb_cmd2: %x, %x\n", cmd, val); 243#endif 244 if (sb_dspwr(sb, cmd)) { 245 return sb_dspwr(sb, val & 0xff) && 246 sb_dspwr(sb, (val >> 8) & 0xff); 247 } else return 0; 248} 249 250/* 251 * in the SB, there is a set of indirect "mixer" registers with 252 * address at offset 4, data at offset 5 253 */ 254static void 255sb_setmixer(struct sb_info *sb, u_int port, u_int value) 256{ 257 u_long flags; 258 259 flags = spltty(); 260 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 261 DELAY(10); 262 sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); 263 DELAY(10); 264 splx(flags); 265} 266 267static int 268sb_getmixer(struct sb_info *sb, u_int port) 269{ 270 int val; 271 u_long flags; 272 273 flags = spltty(); 274 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 275 DELAY(10); 276 val = sb_rd(sb, SB_MIX_DATA); 277 DELAY(10); 278 splx(flags); 279 280 return val; 281} 282 283static u_int 284sb_get_byte(struct sb_info *sb) 285{ 286 int i; 287 288 for (i = 1000; i > 0; i--) { 289 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) 290 return sb_rd(sb, DSP_READ); 291 else 292 DELAY(20); 293 } 294 return 0xffff; 295} 296 297static int 298sb_reset_dsp(struct sb_info *sb) 299{ 300 sb_wr(sb, SBDSP_RST, 3); 301 DELAY(100); 302 sb_wr(sb, SBDSP_RST, 0); 303 if (sb_get_byte(sb) != 0xAA) { 304 DEB(printf("sb_reset_dsp 0x%lx failed\n", 305 rman_get_start(d->io_base))); 306 return ENXIO; /* Sorry */ 307 } 308 if (sb->bd_flags & BD_F_ESS) 309 sb_cmd(sb, 0xc6); 310 return 0; 311} 312 313static void 314sb_release_resources(struct sb_info *sb, device_t dev) 315{ 316 /* should we bus_teardown_intr here? */ 317 if (sb->irq) { 318 bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); 319 sb->irq = 0; 320 } 321 if (sb->drq1) { 322 bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1); 323 sb->drq1 = 0; 324 } 325 if (sb->drq2) { 326 bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2); 327 sb->drq2 = 0; 328 } 329 if (sb->io_base) { 330 bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); 331 sb->io_base = 0; 332 } 333 free(sb, M_DEVBUF); 334} 335 336static int 337sb_alloc_resources(struct sb_info *sb, device_t dev) 338{ 339 int rid; 340 341 rid = 0; 342 if (!sb->io_base) 343 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, 344 &rid, 0, ~0, 1, 345 RF_ACTIVE); 346 rid = 0; 347 if (!sb->irq) 348 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ, 349 &rid, 0, ~0, 1, 350 RF_ACTIVE); 351 rid = 0; 352 if (!sb->drq1) 353 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, 354 &rid, 0, ~0, 1, 355 RF_ACTIVE); 356 rid = 1; 357 if (!sb->drq2) 358 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, 359 &rid, 0, ~0, 1, 360 RF_ACTIVE); 361 362 if (sb->io_base && sb->drq1 && sb->irq) { 363 int bs = DSP_BUFFSIZE; 364 365 isa_dma_acquire(rman_get_start(sb->drq1)); 366 isa_dmainit(rman_get_start(sb->drq1), bs); 367 368 if (sb->drq2) { 369 isa_dma_acquire(rman_get_start(sb->drq2)); 370 isa_dmainit(rman_get_start(sb->drq2), bs); 371 } 372 373 return 0; 374 } else return ENXIO; 375} 376 377static void 378sb16_swap(void *v, int dir) 379{ 380 struct sb_info *sb = v; 381 int pb = sb->pch.buffer->dl; 382 int rb = sb->rch.buffer->dl; 383 int pc = sb->pch.buffer->chan; 384 int rc = sb->rch.buffer->chan; 385 int swp = 0; 386 387 if (!pb && !rb) { 388 if (dir == PCMDIR_PLAY && pc < 4) 389 swp = 1; 390 else 391 if (dir == PCMDIR_REC && rc < 4) 392 swp = 1; 393 if (swp) { 394 int t; 395 396 t = sb->pch.buffer->chan; 397 sb->pch.buffer->chan = sb->rch.buffer->chan; 398 sb->rch.buffer->chan = t; 399 sb->pch.buffer->dir = ISADMA_WRITE; 400 sb->rch.buffer->dir = ISADMA_READ; 401 } 402 } 403} 404 405static int 406sb_doattach(device_t dev, struct sb_info *sb) 407{ 408 snddev_info *d = device_get_softc(dev); 409 void *ih; 410 char status[SND_STATUSLEN]; 411 int bs = DSP_BUFFSIZE; 412 413 if (sb_alloc_resources(sb, dev)) 414 goto no; 415 if (sb_reset_dsp(sb)) 416 goto no; 417 mixer_init(d, &sb_mixer, sb); 418 419 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); 420 if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) 421 pcm_setswap(dev, sb16_swap); 422 if (!sb->drq2) 423 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 424 425 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 426 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 427 /*highaddr*/BUS_SPACE_MAXADDR, 428 /*filter*/NULL, /*filterarg*/NULL, 429 /*maxsize*/bs, /*nsegments*/1, 430 /*maxsegz*/0x3ffff, 431 /*flags*/0, &sb->parent_dmat) != 0) { 432 device_printf(dev, "unable to create dma tag\n"); 433 goto no; 434 } 435 436 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld", 437 rman_get_start(sb->io_base), rman_get_start(sb->irq), 438 rman_get_start(sb->drq1)); 439 if (sb->drq2) 440 snprintf(status + strlen(status), SND_STATUSLEN - strlen(status), 441 ":%ld", rman_get_start(sb->drq2)); 442 443 if (pcm_register(dev, sb, 1, 1)) 444 goto no; 445 pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb); 446 pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb); 447 pcm_setstatus(dev, status); 448 449 return 0; 450 451no: 452 sb_release_resources(sb, dev); 453 return ENXIO; 454} 455 456static void 457sb_intr(void *arg) 458{ 459 struct sb_info *sb = (struct sb_info *)arg; 460 int reason = 3, c; 461 462 /* 463 * SB < 4.0 is half duplex and has only 1 bit for int source, 464 * so we fake it. SB 4.x (SB16) has the int source in a separate 465 * register. 466 * The Vibra16X has separate flags for 8 and 16 bit transfers, but 467 * I have no idea how to tell capture from playback interrupts... 468 */ 469 if (sb->bd_flags & BD_F_SB16) { 470 c = sb_getmixer(sb, IRQ_STAT); 471 /* this tells us if the source is 8-bit or 16-bit dma. We 472 * have to check the io channel to map it to read or write... 473 */ 474 reason = 0; 475 if (c & 1) { /* 8-bit dma */ 476 if (sb->pch.fmt & AFMT_U8) 477 reason |= 1; 478 if (sb->rch.fmt & AFMT_U8) 479 reason |= 2; 480 } 481 if (c & 2) { /* 16-bit dma */ 482 if (sb->pch.fmt & AFMT_S16_LE) 483 reason |= 1; 484 if (sb->rch.fmt & AFMT_S16_LE) 485 reason |= 2; 486 } 487 } else c = 1; 488#if 0 489 printf("sb_intr: reason=%d c=0x%x\n", reason, c); 490#endif 491 if ((reason & 1) && (sb->pch.buffer->dl > 0)) 492 chn_intr(sb->pch.channel); 493 if ((reason & 2) && (sb->rch.buffer->dl > 0)) 494 chn_intr(sb->rch.channel); 495 if (c & 1) 496 sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */ 497 if (c & 2) 498 sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ 499} 500 501static int 502sb_speed(struct sb_chinfo *ch) 503{ 504 struct sb_info *sb = ch->parent; 505 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 506 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 507 int speed = ch->spd; 508 509 if (sb->bd_flags & BD_F_SB16) { 510 RANGE(speed, 5000, 45000); 511 sb_cmd(sb, 0x42 - play); 512 sb_cmd(sb, speed >> 8); 513 sb_cmd(sb, speed & 0xff); 514 } else { 515 u_char tconst; 516 int max_speed = 45000, tmp; 517 u_long flags; 518 519 /* here enforce speed limitations - max 22050 on sb 1.x*/ 520 if (sb->bd_id <= 0x200) 521 max_speed = 22050; 522 523 /* 524 * SB models earlier than SB Pro have low limit for the 525 * input rate. Note that this is only for input, but since 526 * we do not support separate values for rec & play.... 527 */ 528 if (!play) { 529 if (sb->bd_id <= 0x200) 530 max_speed = 13000; 531 else 532 if (sb->bd_id < 0x300) 533 max_speed = 15000; 534 } 535 RANGE(speed, 4000, max_speed); 536 if (stereo) 537 speed <<= 1; 538 539 /* 540 * Now the speed should be valid. Compute the value to be 541 * programmed into the board. 542 */ 543 if (speed > 22050) { /* High speed mode on 2.01/3.xx */ 544 tconst = (u_char) 545 ((65536 - ((256000000 + speed / 2) / speed)) 546 >> 8); 547 sb->bd_flags |= BD_F_HISPEED; 548 tmp = 65536 - (tconst << 8); 549 speed = (256000000 + tmp / 2) / tmp; 550 } else { 551 sb->bd_flags &= ~BD_F_HISPEED; 552 tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; 553 tmp = 256 - tconst; 554 speed = (1000000 + tmp / 2) / tmp; 555 } 556 flags = spltty(); 557 sb_cmd1(sb, 0x40, tconst); /* set time constant */ 558 splx(flags); 559 if (stereo) 560 speed >>= 1; 561 } 562 ch->spd = speed; 563 return speed; 564} 565 566static int 567sb_start(struct sb_chinfo *ch) 568{ 569 struct sb_info *sb = ch->parent; 570 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 571 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; 572 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 573 int l = ch->buffer->dl; 574 int dh = ch->buffer->chan > 3; 575 u_char i1, i2; 576 577 if (b16 || dh) 578 l >>= 1; 579 l--; 580 581 if (play) 582 sb_cmd(sb, DSP_CMD_SPKON); 583 584 if (sb->bd_flags & BD_F_SB16) { 585 i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON; 586 i1 |= play? DSP_F16_DAC : DSP_F16_ADC; 587 i1 |= (b16 || dh)? DSP_DMA16 : DSP_DMA8; 588 i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0); 589 sb_cmd(sb, i1); 590 sb_cmd2(sb, i2, l); 591 } else { 592 if (sb->bd_flags & BD_F_HISPEED) 593 i1 = play? 0x90 : 0x98; 594 else 595 i1 = play? 0x1c : 0x2c; 596 sb_setmixer(sb, 0x0e, stereo? 2 : 0); 597 sb_cmd2(sb, 0x48, l); 598 sb_cmd(sb, i1); 599 } 600 sb->bd_flags |= BD_F_DMARUN << b16; 601 return 0; 602} 603 604static int 605sb_stop(struct sb_chinfo *ch) 606{ 607 struct sb_info *sb = ch->parent; 608 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; 609 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0; 610 611 if (sb->bd_flags & BD_F_HISPEED) 612 sb_reset_dsp(sb); 613 else { 614 sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8); 615 /* 616 * The above seems to have the undocumented side effect of 617 * blocking the other side as well. If the other 618 * channel was active (SB16) I have to re-enable it :( 619 */ 620 if (sb->bd_flags & (BD_F_DMARUN << (1 - b16))) 621 sb_cmd(sb, b16? 0xd4 : 0xd6 ); 622 } 623 if (play) 624 sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ 625 sb->bd_flags &= ~(BD_F_DMARUN << b16); 626 return 0; 627} 628 629/* channel interface */ 630static void * 631sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 632{ 633 struct sb_info *sb = devinfo; 634 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; 635 int dch, dl, dh; 636 637 ch->parent = sb; 638 ch->channel = c; 639 ch->buffer = b; 640 ch->buffer->bufsize = DSP_BUFFSIZE; 641 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) 642 return NULL; 643 dch = (dir == PCMDIR_PLAY)? 1 : 0; 644 if (sb->bd_flags & BD_F_SB16X) 645 dch = !dch; 646 dl = rman_get_start(sb->drq1); 647 dh = sb->drq2? rman_get_start(sb->drq2) : dl; 648 ch->buffer->chan = dch? dh : dl; 649 return ch; 650} 651 652static int 653sbchan_setdir(void *data, int dir) 654{ 655 struct sb_chinfo *ch = data; 656 657 ch->dir = dir; 658 return 0; 659} 660 661static int 662sbchan_setformat(void *data, u_int32_t format) 663{ 664 struct sb_chinfo *ch = data; 665 666 ch->fmt = format; 667 return 0; 668} 669 670static int 671sbchan_setspeed(void *data, u_int32_t speed) 672{ 673 struct sb_chinfo *ch = data; 674 675 ch->spd = speed; 676 return sb_speed(ch); 677} 678 679static int 680sbchan_setblocksize(void *data, u_int32_t blocksize) 681{ 682 return blocksize; 683} 684 685static int 686sbchan_trigger(void *data, int go) 687{ 688 struct sb_chinfo *ch = data; 689 690 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 691 return 0; 692 693 buf_isadma(ch->buffer, go); 694 if (go == PCMTRIG_START) 695 sb_start(ch); 696 else 697 sb_stop(ch); 698 return 0; 699} 700 701static int 702sbchan_getptr(void *data) 703{ 704 struct sb_chinfo *ch = data; 705 706 return buf_isadmaptr(ch->buffer); 707} 708 709static pcmchan_caps * 710sbchan_getcaps(void *data) 711{ 712 struct sb_chinfo *ch = data; 713 int p = (ch->dir == PCMDIR_PLAY)? 1 : 0; 714 715 if (ch->parent->bd_id < 0x300) 716 return p? &sb_playcaps : &sb_reccaps; 717 else if (ch->parent->bd_id < 0x400) 718 return p? &sbpro_playcaps : &sbpro_reccaps; 719 else if (ch->parent->bd_flags & BD_F_SB16X) 720 return &sb16x_caps; 721 else 722 return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps; 723} 724 725/************************************************************/ 726 727static int 728sbmix_init(snd_mixer *m) 729{ 730 struct sb_info *sb = mix_getdevinfo(m); 731 732 switch (sb->bd_flags & BD_F_MIX_MASK) { 733 case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */ 734 mix_setdevs(m, SBPRO_MIXER_DEVICES); 735 mix_setrecdevs(m, SBPRO_RECORDING_DEVICES); 736 sb_setmixer(sb, 0, 1); /* reset mixer */ 737 sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */ 738 sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */ 739 sb_setmixer(sb, FM_VOL, 0x0); /* no midi */ 740 break; 741 742 case BD_F_MIX_CT1745: /* SB16 mixer ... */ 743 mix_setdevs(m, SB16_MIXER_DEVICES); 744 mix_setrecdevs(m, SB16_RECORDING_DEVICES); 745 sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ 746 sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ 747 sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ 748 } 749 return 0; 750} 751 752static int 753sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) 754{ 755 struct sb_info *sb = mix_getdevinfo(m); 756 int regoffs; 757 u_char val; 758 mixer_tab *iomap; 759 760 switch (sb->bd_flags & BD_F_MIX_MASK) { 761 case BD_F_MIX_CT1345: 762 iomap = &sbpro_mix; 763 break; 764 765 case BD_F_MIX_CT1745: 766 iomap = &sb16_mix; 767 break; 768 769 default: 770 return -1; 771 } 772 773 /* Change left channel */ 774 regoffs = (*iomap)[dev][LEFT_CHN].regno; 775 if (regoffs != 0) { 776 val = sb_getmixer(sb, regoffs); 777 change_bits(iomap, &val, dev, LEFT_CHN, left); 778 sb_setmixer(sb, regoffs, val); 779 } 780 781 /* Change right channel */ 782 regoffs = (*iomap)[dev][RIGHT_CHN].regno; 783 if (regoffs != 0) { 784 val = sb_getmixer(sb, regoffs); /* Read the new one */ 785 change_bits(iomap, &val, dev, RIGHT_CHN, right); 786 sb_setmixer(sb, regoffs, val); 787 } else 788 right = left; 789 790 return left | (right << 8); 791} 792 793static int 794sbmix_setrecsrc(snd_mixer *m, u_int32_t src) 795{ 796 struct sb_info *sb = mix_getdevinfo(m); 797 u_char recdev; 798 799 switch (sb->bd_flags & BD_F_MIX_MASK) { 800 case BD_F_MIX_CT1345: 801 if (src == SOUND_MASK_LINE) 802 recdev = 0x06; 803 else if (src == SOUND_MASK_CD) 804 recdev = 0x02; 805 else { /* default: mic */ 806 src = SOUND_MASK_MIC; 807 recdev = 0; 808 } 809 sb_setmixer(sb, RECORD_SRC, recdev | 810 (sb_getmixer(sb, RECORD_SRC) & ~0x07)); 811 break; 812 813 case BD_F_MIX_CT1745: /* sb16 */ 814 recdev = 0; 815 if (src & SOUND_MASK_MIC) 816 recdev |= 0x01; /* mono mic */ 817 if (src & SOUND_MASK_CD) 818 recdev |= 0x06; /* l+r cd */ 819 if (src & SOUND_MASK_LINE) 820 recdev |= 0x18; /* l+r line */ 821 if (src & SOUND_MASK_SYNTH) 822 recdev |= 0x60; /* l+r midi */ 823 sb_setmixer(sb, SB16_IMASK_L, recdev); 824 sb_setmixer(sb, SB16_IMASK_R, recdev); 825 /* 826 * since the same volume controls apply to the input and 827 * output sections, the best approach to have a consistent 828 * behaviour among cards would be to disable the output path 829 * on devices which are used to record. 830 * However, since users like to have feedback, we only disable 831 * the mic -- permanently. 832 */ 833 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); 834 break; 835 } 836 return src; 837} 838 839static int 840sbsbc_probe(device_t dev) 841{ 842 char buf[64]; 843 uintptr_t func, ver, r, f; 844 845 /* The parent device has already been probed. */ 846 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); 847 if (func != SCF_PCM) 848 return (ENXIO); 849 850 r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); 851 f = (ver & 0xffff0000) >> 16; 852 ver &= 0x0000ffff; 853 if (f & BD_F_ESS) 854 return (ENXIO); 855 856 snprintf(buf, sizeof buf, "SB DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, 857 (f & BD_F_SB16X)? " (ViBRA16X)" : ""); 858 device_set_desc_copy(dev, buf); 859 860 return 0; 861} 862 863static int 864sbsbc_attach(device_t dev) 865{ 866 struct sb_info *sb; 867 uintptr_t ver; 868 869 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT); 870 if (!sb) 871 return ENXIO; 872 bzero(sb, sizeof *sb); 873 874 BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); 875 sb->bd_id = ver & 0x0000ffff; 876 sb->bd_flags = (ver & 0xffff0000) >> 16; 877 878 return sb_doattach(dev, sb); 879} 880 881static device_method_t sbsbc_methods[] = { 882 /* Device interface */ 883 DEVMETHOD(device_probe, sbsbc_probe), 884 DEVMETHOD(device_attach, sbsbc_attach), 885 886 { 0, 0 } 887}; 888 889static driver_t sbsbc_driver = { 890 "pcm", 891 sbsbc_methods, 892 sizeof(snddev_info), 893}; 894 895DRIVER_MODULE(snd_sb, sbc, sbsbc_driver, pcm_devclass, 0, 0); 896MODULE_DEPEND(snd_sb, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 897MODULE_VERSION(snd_sb, 1); 898 899 900 901 902