1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 5 * Copyright (c) 1997,1998 Luigi Rizzo 6 * 7 * Derived from files in the Voxware 3.5 distribution, 8 * Copyright by Hannu Savolainen 1994, under the same copyright 9 * conditions. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifdef HAVE_KERNEL_OPTION_HEADERS 35#include "opt_snd.h" 36#endif 37 38#include <dev/sound/pcm/sound.h> 39 40#include <dev/sound/isa/sb.h> 41#include <dev/sound/chip.h> 42 43#include <isa/isavar.h> 44 45#include "mixer_if.h" 46 47SND_DECLARE_FILE("$FreeBSD$"); 48 49#define SB16_BUFFSIZE 4096 50#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) 51 52static u_int32_t sb16_fmt8[] = { 53 SND_FORMAT(AFMT_U8, 1, 0), 54 SND_FORMAT(AFMT_U8, 2, 0), 55 0 56}; 57static struct pcmchan_caps sb16_caps8 = {5000, 45000, sb16_fmt8, 0}; 58 59static u_int32_t sb16_fmt16[] = { 60 SND_FORMAT(AFMT_S16_LE, 1, 0), 61 SND_FORMAT(AFMT_S16_LE, 2, 0), 62 0 63}; 64static struct pcmchan_caps sb16_caps16 = {5000, 45000, sb16_fmt16, 0}; 65 66static u_int32_t sb16x_fmt[] = { 67 SND_FORMAT(AFMT_U8, 1, 0), 68 SND_FORMAT(AFMT_U8, 2, 0), 69 SND_FORMAT(AFMT_S16_LE, 1, 0), 70 SND_FORMAT(AFMT_S16_LE, 2, 0), 71 0 72}; 73static struct pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0}; 74 75struct sb_info; 76 77struct sb_chinfo { 78 struct sb_info *parent; 79 struct pcm_channel *channel; 80 struct snd_dbuf *buffer; 81 int dir, run, dch; 82 u_int32_t fmt, spd, blksz; 83}; 84 85struct sb_info { 86 struct resource *io_base; /* I/O address for the board */ 87 struct resource *irq; 88 struct resource *drq1; 89 struct resource *drq2; 90 void *ih; 91 bus_dma_tag_t parent_dmat; 92 93 unsigned int bufsize; 94 int bd_id; 95 u_long bd_flags; /* board-specific flags */ 96 int prio, prio16; 97 struct sb_chinfo pch, rch; 98 device_t parent_dev; 99}; 100 101#if 0 102static void sb_lock(struct sb_info *sb); 103static void sb_unlock(struct sb_info *sb); 104static int sb_rd(struct sb_info *sb, int reg); 105static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); 106static int sb_cmd(struct sb_info *sb, u_char val); 107/* static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); */ 108static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); 109static u_int sb_get_byte(struct sb_info *sb); 110static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); 111static int sb_getmixer(struct sb_info *sb, u_int port); 112static int sb_reset_dsp(struct sb_info *sb); 113 114static void sb_intr(void *arg); 115#endif 116 117/* 118 * Common code for the midi and pcm functions 119 * 120 * sb_cmd write a single byte to the CMD port. 121 * sb_cmd1 write a CMD + 1 byte arg 122 * sb_cmd2 write a CMD + 2 byte arg 123 * sb_get_byte returns a single byte from the DSP data port 124 */ 125 126static void 127sb_lock(struct sb_info *sb) { 128 sbc_lock(device_get_softc(sb->parent_dev)); 129} 130 131static void 132sb_lockassert(struct sb_info *sb) { 133 sbc_lockassert(device_get_softc(sb->parent_dev)); 134} 135 136static void 137sb_unlock(struct sb_info *sb) { 138 sbc_unlock(device_get_softc(sb->parent_dev)); 139} 140 141static int 142port_rd(struct resource *port, int off) 143{ 144 return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); 145} 146 147static void 148port_wr(struct resource *port, int off, u_int8_t data) 149{ 150 bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); 151} 152 153static int 154sb_rd(struct sb_info *sb, int reg) 155{ 156 return port_rd(sb->io_base, reg); 157} 158 159static void 160sb_wr(struct sb_info *sb, int reg, u_int8_t val) 161{ 162 port_wr(sb->io_base, reg, val); 163} 164 165static int 166sb_dspwr(struct sb_info *sb, u_char val) 167{ 168 int i; 169 170 for (i = 0; i < 1000; i++) { 171 if ((sb_rd(sb, SBDSP_STATUS) & 0x80)) 172 DELAY((i > 100)? 1000 : 10); 173 else { 174 sb_wr(sb, SBDSP_CMD, val); 175 return 1; 176 } 177 } 178 if (curthread->td_intr_nesting_level == 0) 179 printf("sb_dspwr(0x%02x) timed out.\n", val); 180 return 0; 181} 182 183static int 184sb_cmd(struct sb_info *sb, u_char val) 185{ 186#if 0 187 printf("sb_cmd: %x\n", val); 188#endif 189 return sb_dspwr(sb, val); 190} 191 192/* 193static int 194sb_cmd1(struct sb_info *sb, u_char cmd, int val) 195{ 196#if 0 197 printf("sb_cmd1: %x, %x\n", cmd, val); 198#endif 199 if (sb_dspwr(sb, cmd)) { 200 return sb_dspwr(sb, val & 0xff); 201 } else return 0; 202} 203*/ 204 205static int 206sb_cmd2(struct sb_info *sb, u_char cmd, int val) 207{ 208 int r; 209 210#if 0 211 printf("sb_cmd2: %x, %x\n", cmd, val); 212#endif 213 sb_lockassert(sb); 214 r = 0; 215 if (sb_dspwr(sb, cmd)) { 216 if (sb_dspwr(sb, val & 0xff)) { 217 if (sb_dspwr(sb, (val >> 8) & 0xff)) { 218 r = 1; 219 } 220 } 221 } 222 223 return r; 224} 225 226/* 227 * in the SB, there is a set of indirect "mixer" registers with 228 * address at offset 4, data at offset 5 229 */ 230static void 231sb_setmixer(struct sb_info *sb, u_int port, u_int value) 232{ 233 sb_lock(sb); 234 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 235 DELAY(10); 236 sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); 237 DELAY(10); 238 sb_unlock(sb); 239} 240 241static int 242sb_getmixer(struct sb_info *sb, u_int port) 243{ 244 int val; 245 246 sb_lockassert(sb); 247 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ 248 DELAY(10); 249 val = sb_rd(sb, SB_MIX_DATA); 250 DELAY(10); 251 252 return val; 253} 254 255static u_int 256sb_get_byte(struct sb_info *sb) 257{ 258 int i; 259 260 for (i = 1000; i > 0; i--) { 261 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) 262 return sb_rd(sb, DSP_READ); 263 else 264 DELAY(20); 265 } 266 return 0xffff; 267} 268 269static int 270sb_reset_dsp(struct sb_info *sb) 271{ 272 u_char b; 273 274 sb_lockassert(sb); 275 sb_wr(sb, SBDSP_RST, 3); 276 DELAY(100); 277 sb_wr(sb, SBDSP_RST, 0); 278 b = sb_get_byte(sb); 279 if (b != 0xAA) { 280 DEB(printf("sb_reset_dsp 0x%lx failed\n", 281 rman_get_start(sb->io_base))); 282 return ENXIO; /* Sorry */ 283 } 284 return 0; 285} 286 287/************************************************************/ 288 289struct sb16_mixent { 290 int reg; 291 int bits; 292 int ofs; 293 int stereo; 294}; 295 296static const struct sb16_mixent sb16_mixtab[32] = { 297 [SOUND_MIXER_VOLUME] = { 0x30, 5, 3, 1 }, 298 [SOUND_MIXER_PCM] = { 0x32, 5, 3, 1 }, 299 [SOUND_MIXER_SYNTH] = { 0x34, 5, 3, 1 }, 300 [SOUND_MIXER_CD] = { 0x36, 5, 3, 1 }, 301 [SOUND_MIXER_LINE] = { 0x38, 5, 3, 1 }, 302 [SOUND_MIXER_MIC] = { 0x3a, 5, 3, 0 }, 303 [SOUND_MIXER_SPEAKER] = { 0x3b, 5, 3, 0 }, 304 [SOUND_MIXER_IGAIN] = { 0x3f, 2, 6, 1 }, 305 [SOUND_MIXER_OGAIN] = { 0x41, 2, 6, 1 }, 306 [SOUND_MIXER_TREBLE] = { 0x44, 4, 4, 1 }, 307 [SOUND_MIXER_BASS] = { 0x46, 4, 4, 1 }, 308 [SOUND_MIXER_LINE1] = { 0x52, 5, 3, 1 } 309}; 310 311static int 312sb16mix_init(struct snd_mixer *m) 313{ 314 struct sb_info *sb = mix_getdevinfo(m); 315 316 mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | 317 SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | 318 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 | 319 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE); 320 321 mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE | 322 SOUND_MASK_LINE1 | SOUND_MASK_MIC | SOUND_MASK_CD); 323 324 sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ 325 326 sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ 327 sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ 328 329 return 0; 330} 331 332static int 333rel2abs_volume(int x, int max) 334{ 335 int temp; 336 337 temp = ((x * max) + 50) / 100; 338 if (temp > max) 339 temp = max; 340 else if (temp < 0) 341 temp = 0; 342 return (temp); 343} 344 345static int 346sb16mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 347{ 348 struct sb_info *sb = mix_getdevinfo(m); 349 const struct sb16_mixent *e; 350 int max; 351 352 e = &sb16_mixtab[dev]; 353 max = (1 << e->bits) - 1; 354 355 left = rel2abs_volume(left, max); 356 right = rel2abs_volume(right, max); 357 358 sb_setmixer(sb, e->reg, left << e->ofs); 359 if (e->stereo) 360 sb_setmixer(sb, e->reg + 1, right << e->ofs); 361 else 362 right = left; 363 364 left = (left * 100) / max; 365 right = (right * 100) / max; 366 367 return left | (right << 8); 368} 369 370static u_int32_t 371sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 372{ 373 struct sb_info *sb = mix_getdevinfo(m); 374 u_char recdev_l, recdev_r; 375 376 recdev_l = 0; 377 recdev_r = 0; 378 if (src & SOUND_MASK_MIC) { 379 recdev_l |= 0x01; /* mono mic */ 380 recdev_r |= 0x01; 381 } 382 383 if (src & SOUND_MASK_CD) { 384 recdev_l |= 0x04; /* l cd */ 385 recdev_r |= 0x02; /* r cd */ 386 } 387 388 if (src & SOUND_MASK_LINE) { 389 recdev_l |= 0x10; /* l line */ 390 recdev_r |= 0x08; /* r line */ 391 } 392 393 if (src & SOUND_MASK_SYNTH) { 394 recdev_l |= 0x40; /* l midi */ 395 recdev_r |= 0x20; /* r midi */ 396 } 397 398 sb_setmixer(sb, SB16_IMASK_L, recdev_l); 399 sb_setmixer(sb, SB16_IMASK_R, recdev_r); 400 401 /* Switch on/off FM tuner source */ 402 if (src & SOUND_MASK_LINE1) 403 sb_setmixer(sb, 0x4a, 0x0c); 404 else 405 sb_setmixer(sb, 0x4a, 0x00); 406 407 /* 408 * since the same volume controls apply to the input and 409 * output sections, the best approach to have a consistent 410 * behaviour among cards would be to disable the output path 411 * on devices which are used to record. 412 * However, since users like to have feedback, we only disable 413 * the mic -- permanently. 414 */ 415 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); 416 417 return src; 418} 419 420static kobj_method_t sb16mix_mixer_methods[] = { 421 KOBJMETHOD(mixer_init, sb16mix_init), 422 KOBJMETHOD(mixer_set, sb16mix_set), 423 KOBJMETHOD(mixer_setrecsrc, sb16mix_setrecsrc), 424 KOBJMETHOD_END 425}; 426MIXER_DECLARE(sb16mix_mixer); 427 428/************************************************************/ 429 430static void 431sb16_release_resources(struct sb_info *sb, device_t dev) 432{ 433 if (sb->irq) { 434 if (sb->ih) 435 bus_teardown_intr(dev, sb->irq, sb->ih); 436 bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); 437 sb->irq = NULL; 438 } 439 if (sb->drq2) { 440 if (sb->drq2 != sb->drq1) { 441 isa_dma_release(rman_get_start(sb->drq2)); 442 bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2); 443 } 444 sb->drq2 = NULL; 445 } 446 if (sb->drq1) { 447 isa_dma_release(rman_get_start(sb->drq1)); 448 bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1); 449 sb->drq1 = NULL; 450 } 451 if (sb->io_base) { 452 bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); 453 sb->io_base = NULL; 454 } 455 if (sb->parent_dmat) { 456 bus_dma_tag_destroy(sb->parent_dmat); 457 sb->parent_dmat = 0; 458 } 459 free(sb, M_DEVBUF); 460} 461 462static int 463sb16_alloc_resources(struct sb_info *sb, device_t dev) 464{ 465 int rid; 466 467 rid = 0; 468 if (!sb->io_base) 469 sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 470 &rid, RF_ACTIVE); 471 472 rid = 0; 473 if (!sb->irq) 474 sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 475 RF_ACTIVE); 476 477 rid = 0; 478 if (!sb->drq1) 479 sb->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, 480 RF_ACTIVE); 481 482 rid = 1; 483 if (!sb->drq2) 484 sb->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, 485 RF_ACTIVE); 486 487 if (sb->io_base && sb->drq1 && sb->irq) { 488 isa_dma_acquire(rman_get_start(sb->drq1)); 489 isa_dmainit(rman_get_start(sb->drq1), sb->bufsize); 490 491 if (sb->drq2) { 492 isa_dma_acquire(rman_get_start(sb->drq2)); 493 isa_dmainit(rman_get_start(sb->drq2), sb->bufsize); 494 } else { 495 sb->drq2 = sb->drq1; 496 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 497 } 498 return 0; 499 } else return ENXIO; 500} 501 502/* sbc does locking for us */ 503static void 504sb_intr(void *arg) 505{ 506 struct sb_info *sb = (struct sb_info *)arg; 507 int reason, c; 508 509 /* 510 * The Vibra16X has separate flags for 8 and 16 bit transfers, but 511 * I have no idea how to tell capture from playback interrupts... 512 */ 513 514 reason = 0; 515 sb_lock(sb); 516 c = sb_getmixer(sb, IRQ_STAT); 517 if (c & 1) 518 sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */ 519 520 if (c & 2) 521 sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ 522 sb_unlock(sb); 523 524 /* 525 * this tells us if the source is 8-bit or 16-bit dma. We 526 * have to check the io channel to map it to read or write... 527 */ 528 529 if (sb->bd_flags & BD_F_SB16X) { 530 if (c & 1) { /* 8-bit format */ 531 if (sb->pch.fmt & AFMT_8BIT) 532 reason |= 1; 533 if (sb->rch.fmt & AFMT_8BIT) 534 reason |= 2; 535 } 536 if (c & 2) { /* 16-bit format */ 537 if (sb->pch.fmt & AFMT_16BIT) 538 reason |= 1; 539 if (sb->rch.fmt & AFMT_16BIT) 540 reason |= 2; 541 } 542 } else { 543 if (c & 1) { /* 8-bit dma */ 544 if (sb->pch.dch == 1) 545 reason |= 1; 546 if (sb->rch.dch == 1) 547 reason |= 2; 548 } 549 if (c & 2) { /* 16-bit dma */ 550 if (sb->pch.dch == 2) 551 reason |= 1; 552 if (sb->rch.dch == 2) 553 reason |= 2; 554 } 555 } 556#if 0 557 printf("sb_intr: reason=%d c=0x%x\n", reason, c); 558#endif 559 if ((reason & 1) && (sb->pch.run)) 560 chn_intr(sb->pch.channel); 561 562 if ((reason & 2) && (sb->rch.run)) 563 chn_intr(sb->rch.channel); 564} 565 566static int 567sb_setup(struct sb_info *sb) 568{ 569 struct sb_chinfo *ch; 570 u_int8_t v; 571 int l, pprio; 572 573 sb_lock(sb); 574 if (sb->bd_flags & BD_F_DMARUN) 575 sndbuf_dma(sb->pch.buffer, PCMTRIG_STOP); 576 if (sb->bd_flags & BD_F_DMARUN2) 577 sndbuf_dma(sb->rch.buffer, PCMTRIG_STOP); 578 sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2); 579 580 sb_reset_dsp(sb); 581 582 if (sb->bd_flags & BD_F_SB16X) { 583 /* full-duplex doesn't work! */ 584 pprio = sb->pch.run? 1 : 0; 585 sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq1 : sb->drq2); 586 sb->pch.dch = pprio? 1 : 0; 587 sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1); 588 sb->rch.dch = pprio? 2 : 1; 589 } else { 590 if (sb->pch.run && sb->rch.run) { 591 pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1; 592 sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1); 593 sb->pch.dch = pprio? 2 : 1; 594 sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2); 595 sb->rch.dch = pprio? 1 : 2; 596 } else { 597 if (sb->pch.run) { 598 sndbuf_dmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1); 599 sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1; 600 sndbuf_dmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2); 601 sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2; 602 } else if (sb->rch.run) { 603 sndbuf_dmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2); 604 sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2; 605 sndbuf_dmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1); 606 sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1; 607 } 608 } 609 } 610 611 sndbuf_dmasetdir(sb->pch.buffer, PCMDIR_PLAY); 612 sndbuf_dmasetdir(sb->rch.buffer, PCMDIR_REC); 613 614 /* 615 printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n", 616 sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run); 617 */ 618 619 ch = &sb->pch; 620 if (ch->run) { 621 l = ch->blksz; 622 if (ch->fmt & AFMT_16BIT) 623 l >>= 1; 624 l--; 625 626 /* play speed */ 627 RANGE(ch->spd, 5000, 45000); 628 sb_cmd(sb, DSP_CMD_OUT16); 629 sb_cmd(sb, ch->spd >> 8); 630 sb_cmd(sb, ch->spd & 0xff); 631 632 /* play format, length */ 633 v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC; 634 v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8; 635 sb_cmd(sb, v); 636 637 v = (AFMT_CHANNEL(ch->fmt) > 1)? DSP_F16_STEREO : 0; 638 v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0; 639 sb_cmd2(sb, v, l); 640 sndbuf_dma(ch->buffer, PCMTRIG_START); 641 sb->bd_flags |= BD_F_DMARUN; 642 } 643 644 ch = &sb->rch; 645 if (ch->run) { 646 l = ch->blksz; 647 if (ch->fmt & AFMT_16BIT) 648 l >>= 1; 649 l--; 650 651 /* record speed */ 652 RANGE(ch->spd, 5000, 45000); 653 sb_cmd(sb, DSP_CMD_IN16); 654 sb_cmd(sb, ch->spd >> 8); 655 sb_cmd(sb, ch->spd & 0xff); 656 657 /* record format, length */ 658 v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC; 659 v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8; 660 sb_cmd(sb, v); 661 662 v = (AFMT_CHANNEL(ch->fmt) > 1)? DSP_F16_STEREO : 0; 663 v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0; 664 sb_cmd2(sb, v, l); 665 sndbuf_dma(ch->buffer, PCMTRIG_START); 666 sb->bd_flags |= BD_F_DMARUN2; 667 } 668 sb_unlock(sb); 669 670 return 0; 671} 672 673/* channel interface */ 674static void * 675sb16chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 676{ 677 struct sb_info *sb = devinfo; 678 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; 679 680 ch->parent = sb; 681 ch->channel = c; 682 ch->buffer = b; 683 ch->dir = dir; 684 685 if (sndbuf_alloc(ch->buffer, sb->parent_dmat, 0, sb->bufsize) != 0) 686 return NULL; 687 688 return ch; 689} 690 691static int 692sb16chan_setformat(kobj_t obj, void *data, u_int32_t format) 693{ 694 struct sb_chinfo *ch = data; 695 struct sb_info *sb = ch->parent; 696 697 ch->fmt = format; 698 sb->prio = ch->dir; 699 sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 700 701 return 0; 702} 703 704static u_int32_t 705sb16chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 706{ 707 struct sb_chinfo *ch = data; 708 709 ch->spd = speed; 710 return speed; 711} 712 713static u_int32_t 714sb16chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 715{ 716 struct sb_chinfo *ch = data; 717 718 ch->blksz = blocksize; 719 return ch->blksz; 720} 721 722static int 723sb16chan_trigger(kobj_t obj, void *data, int go) 724{ 725 struct sb_chinfo *ch = data; 726 struct sb_info *sb = ch->parent; 727 728 if (!PCMTRIG_COMMON(go)) 729 return 0; 730 731 if (go == PCMTRIG_START) 732 ch->run = 1; 733 else 734 ch->run = 0; 735 736 sb_setup(sb); 737 738 return 0; 739} 740 741static u_int32_t 742sb16chan_getptr(kobj_t obj, void *data) 743{ 744 struct sb_chinfo *ch = data; 745 746 return sndbuf_dmaptr(ch->buffer); 747} 748 749static struct pcmchan_caps * 750sb16chan_getcaps(kobj_t obj, void *data) 751{ 752 struct sb_chinfo *ch = data; 753 struct sb_info *sb = ch->parent; 754 755 if ((sb->prio == 0) || (sb->prio == ch->dir)) 756 return &sb16x_caps; 757 else 758 return sb->prio16? &sb16_caps8 : &sb16_caps16; 759} 760 761static int 762sb16chan_resetdone(kobj_t obj, void *data) 763{ 764 struct sb_chinfo *ch = data; 765 struct sb_info *sb = ch->parent; 766 767 sb->prio = 0; 768 769 return 0; 770} 771 772static kobj_method_t sb16chan_methods[] = { 773 KOBJMETHOD(channel_init, sb16chan_init), 774 KOBJMETHOD(channel_resetdone, sb16chan_resetdone), 775 KOBJMETHOD(channel_setformat, sb16chan_setformat), 776 KOBJMETHOD(channel_setspeed, sb16chan_setspeed), 777 KOBJMETHOD(channel_setblocksize, sb16chan_setblocksize), 778 KOBJMETHOD(channel_trigger, sb16chan_trigger), 779 KOBJMETHOD(channel_getptr, sb16chan_getptr), 780 KOBJMETHOD(channel_getcaps, sb16chan_getcaps), 781 KOBJMETHOD_END 782}; 783CHANNEL_DECLARE(sb16chan); 784 785/************************************************************/ 786 787static int 788sb16_probe(device_t dev) 789{ 790 char buf[64]; 791 uintptr_t func, ver, r, f; 792 793 /* The parent device has already been probed. */ 794 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); 795 if (func != SCF_PCM) 796 return (ENXIO); 797 798 r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); 799 f = (ver & 0xffff0000) >> 16; 800 ver &= 0x0000ffff; 801 if (f & BD_F_SB16) { 802 snprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, 803 (f & BD_F_SB16X)? " (ViBRA16X)" : ""); 804 device_set_desc_copy(dev, buf); 805 return 0; 806 } else 807 return (ENXIO); 808} 809 810static int 811sb16_attach(device_t dev) 812{ 813 struct sb_info *sb; 814 uintptr_t ver; 815 char status[SND_STATUSLEN], status2[SND_STATUSLEN]; 816 817 sb = malloc(sizeof(*sb), M_DEVBUF, M_WAITOK | M_ZERO); 818 sb->parent_dev = device_get_parent(dev); 819 BUS_READ_IVAR(sb->parent_dev, dev, 1, &ver); 820 sb->bd_id = ver & 0x0000ffff; 821 sb->bd_flags = (ver & 0xffff0000) >> 16; 822 sb->bufsize = pcm_getbuffersize(dev, 4096, SB16_BUFFSIZE, 65536); 823 824 if (sb16_alloc_resources(sb, dev)) 825 goto no; 826 sb_lock(sb); 827 if (sb_reset_dsp(sb)) { 828 sb_unlock(sb); 829 goto no; 830 } 831 sb_unlock(sb); 832 if (mixer_init(dev, &sb16mix_mixer_class, sb)) 833 goto no; 834 if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih)) 835 goto no; 836 837 if (sb->bd_flags & BD_F_SB16X) 838 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 839 840 sb->prio = 0; 841 842 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 843 /*boundary*/0, 844 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 845 /*highaddr*/BUS_SPACE_MAXADDR, 846 /*filter*/NULL, /*filterarg*/NULL, 847 /*maxsize*/sb->bufsize, /*nsegments*/1, 848 /*maxsegz*/0x3ffff, /*flags*/0, 849 /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, 850 &sb->parent_dmat) != 0) { 851 device_printf(dev, "unable to create dma tag\n"); 852 goto no; 853 } 854 855 if (!(pcm_getflags(dev) & SD_F_SIMPLEX)) 856 snprintf(status2, SND_STATUSLEN, ":%jd", rman_get_start(sb->drq2)); 857 else 858 status2[0] = '\0'; 859 860 snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s", 861 rman_get_start(sb->io_base), rman_get_start(sb->irq), 862 rman_get_start(sb->drq1), status2, sb->bufsize, 863 PCM_KLDSTRING(snd_sb16)); 864 865 if (pcm_register(dev, sb, 1, 1)) 866 goto no; 867 pcm_addchan(dev, PCMDIR_REC, &sb16chan_class, sb); 868 pcm_addchan(dev, PCMDIR_PLAY, &sb16chan_class, sb); 869 870 pcm_setstatus(dev, status); 871 872 return 0; 873 874no: 875 sb16_release_resources(sb, dev); 876 return ENXIO; 877} 878 879static int 880sb16_detach(device_t dev) 881{ 882 int r; 883 struct sb_info *sb; 884 885 r = pcm_unregister(dev); 886 if (r) 887 return r; 888 889 sb = pcm_getdevinfo(dev); 890 sb16_release_resources(sb, dev); 891 return 0; 892} 893 894static device_method_t sb16_methods[] = { 895 /* Device interface */ 896 DEVMETHOD(device_probe, sb16_probe), 897 DEVMETHOD(device_attach, sb16_attach), 898 DEVMETHOD(device_detach, sb16_detach), 899 { 0, 0 } 900}; 901 902static driver_t sb16_driver = { 903 "pcm", 904 sb16_methods, 905 PCM_SOFTC_SIZE, 906}; 907 908DRIVER_MODULE(snd_sb16, sbc, sb16_driver, pcm_devclass, 0, 0); 909MODULE_DEPEND(snd_sb16, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 910MODULE_DEPEND(snd_sb16, snd_sbc, 1, 1, 1); 911MODULE_VERSION(snd_sb16, 1); 912