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