1 /* 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <dev/sound/pcm/sound.h> 28 #include <dev/sound/pcm/ac97.h> 29 #include <dev/sound/pci/t4dwave.h> 30 31 #include <dev/pci/pcireg.h> 32 #include <dev/pci/pcivar.h> 33 34 SND_DECLARE_FILE("$FreeBSD$"); 35 36 /* -------------------------------------------------------------------- */ 37 38 #define TDX_PCI_ID 0x20001023 39 #define TNX_PCI_ID 0x20011023 40 #define ALI_PCI_ID 0x545110b9 41 #define SPA_PCI_ID 0x70181039 42 43 #define TR_DEFAULT_BUFSZ 0x1000 44 #define TR_TIMEOUT_CDC 0xffff 45 #define TR_MAXPLAYCH 4 46 47 struct tr_info; 48 49 /* channel registers */ 50 struct tr_chinfo { 51 u_int32_t cso, alpha, fms, fmc, ec; 52 u_int32_t lba; 53 u_int32_t eso, delta; 54 u_int32_t rvol, cvol; 55 u_int32_t gvsel, pan, vol, ctrl; 56 u_int32_t active:1, was_active:1; 57 int index, bufhalf; 58 struct snd_dbuf *buffer; 59 struct pcm_channel *channel; 60 struct tr_info *parent; 61 }; 62 63 struct tr_rchinfo { 64 u_int32_t delta; 65 u_int32_t active:1, was_active:1; 66 struct snd_dbuf *buffer; 67 struct pcm_channel *channel; 68 struct tr_info *parent; 69 }; 70 71 /* device private data */ 72 struct tr_info { 73 u_int32_t type; 74 u_int32_t rev; 75 76 bus_space_tag_t st; 77 bus_space_handle_t sh; 78 bus_dma_tag_t parent_dmat; 79 80 struct resource *reg, *irq; 81 int regtype, regid, irqid; 82 void *ih; 83 84 struct mtx *lock; 85 86 u_int32_t playchns; 87 unsigned int bufsz; 88 89 struct tr_chinfo chinfo[TR_MAXPLAYCH]; 90 struct tr_rchinfo recchinfo; 91 }; 92 93 /* -------------------------------------------------------------------- */ 94 95 static u_int32_t tr_recfmt[] = { 96 AFMT_U8, 97 AFMT_STEREO | AFMT_U8, 98 AFMT_S8, 99 AFMT_STEREO | AFMT_S8, 100 AFMT_S16_LE, 101 AFMT_STEREO | AFMT_S16_LE, 102 AFMT_U16_LE, 103 AFMT_STEREO | AFMT_U16_LE, 104 0 105 }; 106 static struct pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0}; 107 108 static u_int32_t tr_playfmt[] = { 109 AFMT_U8, 110 AFMT_STEREO | AFMT_U8, 111 AFMT_S8, 112 AFMT_STEREO | AFMT_S8, 113 AFMT_S16_LE, 114 AFMT_STEREO | AFMT_S16_LE, 115 AFMT_U16_LE, 116 AFMT_STEREO | AFMT_U16_LE, 117 0 118 }; 119 static struct pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0}; 120 121 /* -------------------------------------------------------------------- */ 122 123 /* Hardware */ 124 125 static u_int32_t 126 tr_rd(struct tr_info *tr, int regno, int size) 127 { 128 switch(size) { 129 case 1: 130 return bus_space_read_1(tr->st, tr->sh, regno); 131 case 2: 132 return bus_space_read_2(tr->st, tr->sh, regno); 133 case 4: 134 return bus_space_read_4(tr->st, tr->sh, regno); 135 default: 136 return 0xffffffff; 137 } 138 } 139 140 static void 141 tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size) 142 { 143 switch(size) { 144 case 1: 145 bus_space_write_1(tr->st, tr->sh, regno, data); 146 break; 147 case 2: 148 bus_space_write_2(tr->st, tr->sh, regno, data); 149 break; 150 case 4: 151 bus_space_write_4(tr->st, tr->sh, regno, data); 152 break; 153 } 154 } 155 156 /* -------------------------------------------------------------------- */ 157 /* ac97 codec */ 158 159 static int 160 tr_rdcd(kobj_t obj, void *devinfo, int regno) 161 { 162 struct tr_info *tr = (struct tr_info *)devinfo; 163 int i, j, treg, trw; 164 165 switch (tr->type) { 166 case SPA_PCI_ID: 167 treg=SPA_REG_CODECRD; 168 trw=SPA_CDC_RWSTAT; 169 break; 170 case ALI_PCI_ID: 171 if (tr->rev > 0x01) 172 treg=TDX_REG_CODECWR; 173 else 174 treg=TDX_REG_CODECRD; 175 trw=TDX_CDC_RWSTAT; 176 break; 177 case TDX_PCI_ID: 178 treg=TDX_REG_CODECRD; 179 trw=TDX_CDC_RWSTAT; 180 break; 181 case TNX_PCI_ID: 182 treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; 183 trw=TNX_CDC_RWSTAT; 184 break; 185 default: 186 printf("!!! tr_rdcd defaulted !!!\n"); 187 return -1; 188 } 189 190 i = j = 0; 191 192 regno &= 0x7f; 193 snd_mtxlock(tr->lock); 194 if (tr->type == ALI_PCI_ID) { 195 u_int32_t chk1, chk2; 196 j = trw; 197 for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) 198 j = tr_rd(tr, treg, 4); 199 if (i > 0) { 200 chk1 = tr_rd(tr, 0xc8, 4); 201 chk2 = tr_rd(tr, 0xc8, 4); 202 for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2); 203 i--) 204 chk2 = tr_rd(tr, 0xc8, 4); 205 } 206 } 207 if (tr->type != ALI_PCI_ID || i > 0) { 208 tr_wr(tr, treg, regno | trw, 4); 209 j=trw; 210 for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) 211 j=tr_rd(tr, treg, 4); 212 } 213 snd_mtxunlock(tr->lock); 214 if (i == 0) printf("codec timeout during read of register %x\n", regno); 215 return (j >> TR_CDC_DATA) & 0xffff; 216 } 217 218 static int 219 tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) 220 { 221 struct tr_info *tr = (struct tr_info *)devinfo; 222 int i, j, treg, trw; 223 224 switch (tr->type) { 225 case SPA_PCI_ID: 226 treg=SPA_REG_CODECWR; 227 trw=SPA_CDC_RWSTAT; 228 break; 229 case ALI_PCI_ID: 230 case TDX_PCI_ID: 231 treg=TDX_REG_CODECWR; 232 trw=TDX_CDC_RWSTAT; 233 break; 234 case TNX_PCI_ID: 235 treg=TNX_REG_CODECWR; 236 trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); 237 break; 238 default: 239 printf("!!! tr_wrcd defaulted !!!"); 240 return -1; 241 } 242 243 i = 0; 244 245 regno &= 0x7f; 246 #if 0 247 printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno)); 248 #endif 249 j=trw; 250 snd_mtxlock(tr->lock); 251 if (tr->type == ALI_PCI_ID) { 252 j = trw; 253 for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) 254 j = tr_rd(tr, treg, 4); 255 if (i > 0) { 256 u_int32_t chk1, chk2; 257 chk1 = tr_rd(tr, 0xc8, 4); 258 chk2 = tr_rd(tr, 0xc8, 4); 259 for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2); 260 i--) 261 chk2 = tr_rd(tr, 0xc8, 4); 262 } 263 } 264 if (tr->type != ALI_PCI_ID || i > 0) { 265 for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--) 266 j=tr_rd(tr, treg, 4); 267 if (tr->type == ALI_PCI_ID && tr->rev > 0x01) 268 trw |= 0x0100; 269 tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4); 270 } 271 #if 0 272 printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno)); 273 #endif 274 snd_mtxunlock(tr->lock); 275 if (i==0) printf("codec timeout writing %x, data %x\n", regno, data); 276 return (i > 0)? 0 : -1; 277 } 278 279 static kobj_method_t tr_ac97_methods[] = { 280 KOBJMETHOD(ac97_read, tr_rdcd), 281 KOBJMETHOD(ac97_write, tr_wrcd), 282 { 0, 0 } 283 }; 284 AC97_DECLARE(tr_ac97); 285 286 /* -------------------------------------------------------------------- */ 287 /* playback channel interrupts */ 288 289 #if 0 290 static u_int32_t 291 tr_testint(struct tr_chinfo *ch) 292 { 293 struct tr_info *tr = ch->parent; 294 int bank, chan; 295 296 bank = (ch->index & 0x20) ? 1 : 0; 297 chan = ch->index & 0x1f; 298 return tr_rd(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 4) & (1 << chan); 299 } 300 #endif 301 302 static void 303 tr_clrint(struct tr_chinfo *ch) 304 { 305 struct tr_info *tr = ch->parent; 306 int bank, chan; 307 308 bank = (ch->index & 0x20) ? 1 : 0; 309 chan = ch->index & 0x1f; 310 tr_wr(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4); 311 } 312 313 static void 314 tr_enaint(struct tr_chinfo *ch, int enable) 315 { 316 struct tr_info *tr = ch->parent; 317 u_int32_t i, reg; 318 int bank, chan; 319 320 snd_mtxlock(tr->lock); 321 bank = (ch->index & 0x20) ? 1 : 0; 322 chan = ch->index & 0x1f; 323 reg = bank? TR_REG_INTENB : TR_REG_INTENA; 324 325 i = tr_rd(tr, reg, 4); 326 i &= ~(1 << chan); 327 i |= (enable? 1 : 0) << chan; 328 329 tr_clrint(ch); 330 tr_wr(tr, reg, i, 4); 331 snd_mtxunlock(tr->lock); 332 } 333 334 /* playback channels */ 335 336 static void 337 tr_selch(struct tr_chinfo *ch) 338 { 339 struct tr_info *tr = ch->parent; 340 int i; 341 342 i = tr_rd(tr, TR_REG_CIR, 4); 343 i &= ~TR_CIR_MASK; 344 i |= ch->index & 0x3f; 345 tr_wr(tr, TR_REG_CIR, i, 4); 346 } 347 348 static void 349 tr_startch(struct tr_chinfo *ch) 350 { 351 struct tr_info *tr = ch->parent; 352 int bank, chan; 353 354 bank = (ch->index & 0x20) ? 1 : 0; 355 chan = ch->index & 0x1f; 356 tr_wr(tr, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4); 357 } 358 359 static void 360 tr_stopch(struct tr_chinfo *ch) 361 { 362 struct tr_info *tr = ch->parent; 363 int bank, chan; 364 365 bank = (ch->index & 0x20) ? 1 : 0; 366 chan = ch->index & 0x1f; 367 tr_wr(tr, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4); 368 } 369 370 static void 371 tr_wrch(struct tr_chinfo *ch) 372 { 373 struct tr_info *tr = ch->parent; 374 u_int32_t cr[TR_CHN_REGS], i; 375 376 ch->gvsel &= 0x00000001; 377 ch->fmc &= 0x00000003; 378 ch->fms &= 0x0000000f; 379 ch->ctrl &= 0x0000000f; 380 ch->pan &= 0x0000007f; 381 ch->rvol &= 0x0000007f; 382 ch->cvol &= 0x0000007f; 383 ch->vol &= 0x000000ff; 384 ch->ec &= 0x00000fff; 385 ch->alpha &= 0x00000fff; 386 ch->delta &= 0x0000ffff; 387 ch->lba &= 0x3fffffff; 388 389 cr[1]=ch->lba; 390 cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol); 391 cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec); 392 393 switch (tr->type) { 394 case SPA_PCI_ID: 395 case ALI_PCI_ID: 396 case TDX_PCI_ID: 397 ch->cso &= 0x0000ffff; 398 ch->eso &= 0x0000ffff; 399 cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); 400 cr[2]=(ch->eso<<16) | (ch->delta); 401 break; 402 case TNX_PCI_ID: 403 ch->cso &= 0x00ffffff; 404 ch->eso &= 0x00ffffff; 405 cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); 406 cr[2]=((ch->delta>>8)<<24) | (ch->eso); 407 cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); 408 break; 409 } 410 snd_mtxlock(tr->lock); 411 tr_selch(ch); 412 for (i=0; i<TR_CHN_REGS; i++) 413 tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4); 414 snd_mtxunlock(tr->lock); 415 } 416 417 static void 418 tr_rdch(struct tr_chinfo *ch) 419 { 420 struct tr_info *tr = ch->parent; 421 u_int32_t cr[5], i; 422 423 snd_mtxlock(tr->lock); 424 tr_selch(ch); 425 for (i=0; i<5; i++) 426 cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4); 427 snd_mtxunlock(tr->lock); 428 429 430 ch->lba= (cr[1] & 0x3fffffff); 431 ch->fmc= (cr[3] & 0x0000c000) >> 14; 432 ch->rvol= (cr[3] & 0x00003f80) >> 7; 433 ch->cvol= (cr[3] & 0x0000007f); 434 ch->gvsel= (cr[4] & 0x80000000) >> 31; 435 ch->pan= (cr[4] & 0x7f000000) >> 24; 436 ch->vol= (cr[4] & 0x00ff0000) >> 16; 437 ch->ctrl= (cr[4] & 0x0000f000) >> 12; 438 ch->ec= (cr[4] & 0x00000fff); 439 switch(tr->type) { 440 case SPA_PCI_ID: 441 case ALI_PCI_ID: 442 case TDX_PCI_ID: 443 ch->cso= (cr[0] & 0xffff0000) >> 16; 444 ch->alpha= (cr[0] & 0x0000fff0) >> 4; 445 ch->fms= (cr[0] & 0x0000000f); 446 ch->eso= (cr[2] & 0xffff0000) >> 16; 447 ch->delta= (cr[2] & 0x0000ffff); 448 break; 449 case TNX_PCI_ID: 450 ch->cso= (cr[0] & 0x00ffffff); 451 ch->eso= (cr[2] & 0x00ffffff); 452 ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24); 453 ch->alpha= (cr[3] & 0xfff00000) >> 20; 454 ch->fms= (cr[3] & 0x000f0000) >> 16; 455 break; 456 } 457 } 458 459 static u_int32_t 460 tr_fmttobits(u_int32_t fmt) 461 { 462 u_int32_t bits; 463 464 bits = 0; 465 bits |= (fmt & AFMT_SIGNED)? 0x2 : 0; 466 bits |= (fmt & AFMT_STEREO)? 0x4 : 0; 467 bits |= (fmt & AFMT_16BIT)? 0x8 : 0; 468 469 return bits; 470 } 471 472 /* -------------------------------------------------------------------- */ 473 /* channel interface */ 474 475 static void * 476 trpchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 477 { 478 struct tr_info *tr = devinfo; 479 struct tr_chinfo *ch; 480 481 KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction")); 482 ch = &tr->chinfo[tr->playchns]; 483 ch->index = tr->playchns++; 484 ch->buffer = b; 485 ch->parent = tr; 486 ch->channel = c; 487 if (sndbuf_alloc(ch->buffer, tr->parent_dmat, tr->bufsz) == -1) 488 return NULL; 489 490 return ch; 491 } 492 493 static int 494 trpchan_setformat(kobj_t obj, void *data, u_int32_t format) 495 { 496 struct tr_chinfo *ch = data; 497 498 ch->ctrl = tr_fmttobits(format) | 0x01; 499 500 return 0; 501 } 502 503 static int 504 trpchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 505 { 506 struct tr_chinfo *ch = data; 507 508 ch->delta = (speed << 12) / 48000; 509 return (ch->delta * 48000) >> 12; 510 } 511 512 static int 513 trpchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 514 { 515 struct tr_chinfo *ch = data; 516 517 sndbuf_resize(ch->buffer, 2, blocksize); 518 return blocksize; 519 } 520 521 static int 522 trpchan_trigger(kobj_t obj, void *data, int go) 523 { 524 struct tr_chinfo *ch = data; 525 526 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 527 return 0; 528 529 if (go == PCMTRIG_START) { 530 ch->fmc = 3; 531 ch->fms = 0; 532 ch->ec = 0; 533 ch->alpha = 0; 534 ch->lba = sndbuf_getbufaddr(ch->buffer); 535 ch->cso = 0; 536 ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1; 537 ch->rvol = ch->cvol = 0x7f; 538 ch->gvsel = 0; 539 ch->pan = 0; 540 ch->vol = 0; 541 ch->bufhalf = 0; 542 tr_wrch(ch); 543 tr_enaint(ch, 1); 544 tr_startch(ch); 545 ch->active = 1; 546 } else { 547 tr_stopch(ch); 548 ch->active = 0; 549 } 550 551 return 0; 552 } 553 554 static int 555 trpchan_getptr(kobj_t obj, void *data) 556 { 557 struct tr_chinfo *ch = data; 558 559 tr_rdch(ch); 560 return ch->cso * sndbuf_getbps(ch->buffer); 561 } 562 563 static struct pcmchan_caps * 564 trpchan_getcaps(kobj_t obj, void *data) 565 { 566 return &tr_playcaps; 567 } 568 569 static kobj_method_t trpchan_methods[] = { 570 KOBJMETHOD(channel_init, trpchan_init), 571 KOBJMETHOD(channel_setformat, trpchan_setformat), 572 KOBJMETHOD(channel_setspeed, trpchan_setspeed), 573 KOBJMETHOD(channel_setblocksize, trpchan_setblocksize), 574 KOBJMETHOD(channel_trigger, trpchan_trigger), 575 KOBJMETHOD(channel_getptr, trpchan_getptr), 576 KOBJMETHOD(channel_getcaps, trpchan_getcaps), 577 { 0, 0 } 578 }; 579 CHANNEL_DECLARE(trpchan); 580 581 /* -------------------------------------------------------------------- */ 582 /* rec channel interface */ 583 584 static void * 585 trrchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 586 { 587 struct tr_info *tr = devinfo; 588 struct tr_rchinfo *ch; 589 590 KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction")); 591 ch = &tr->recchinfo; 592 ch->buffer = b; 593 ch->parent = tr; 594 ch->channel = c; 595 if (sndbuf_alloc(ch->buffer, tr->parent_dmat, tr->bufsz) == -1) 596 return NULL; 597 598 return ch; 599 } 600 601 static int 602 trrchan_setformat(kobj_t obj, void *data, u_int32_t format) 603 { 604 struct tr_rchinfo *ch = data; 605 struct tr_info *tr = ch->parent; 606 u_int32_t i, bits; 607 608 bits = tr_fmttobits(format); 609 /* set # of samples between interrupts */ 610 i = (sndbuf_runsz(ch->buffer) >> ((bits & 0x08)? 1 : 0)) - 1; 611 tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4); 612 /* set sample format */ 613 i = 0x18 | (bits << 4); 614 tr_wr(tr, TR_REG_SBCTRL, i, 1); 615 616 return 0; 617 618 } 619 620 static int 621 trrchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 622 { 623 struct tr_rchinfo *ch = data; 624 struct tr_info *tr = ch->parent; 625 626 /* setup speed */ 627 ch->delta = (48000 << 12) / speed; 628 tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2); 629 630 /* return closest possible speed */ 631 return (48000 << 12) / ch->delta; 632 } 633 634 static int 635 trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 636 { 637 struct tr_rchinfo *ch = data; 638 639 sndbuf_resize(ch->buffer, 2, blocksize); 640 641 return blocksize; 642 } 643 644 static int 645 trrchan_trigger(kobj_t obj, void *data, int go) 646 { 647 struct tr_rchinfo *ch = data; 648 struct tr_info *tr = ch->parent; 649 u_int32_t i; 650 651 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 652 return 0; 653 654 if (go == PCMTRIG_START) { 655 /* set up dma mode regs */ 656 tr_wr(tr, TR_REG_DMAR15, 0, 1); 657 i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03; 658 tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1); 659 /* set up base address */ 660 tr_wr(tr, TR_REG_DMAR0, sndbuf_getbufaddr(ch->buffer), 4); 661 /* set up buffer size */ 662 i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff; 663 tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_runsz(ch->buffer) - 1), 4); 664 /* start */ 665 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) | 1, 1); 666 ch->active = 1; 667 } else { 668 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) & ~7, 1); 669 ch->active = 0; 670 } 671 672 /* return 0 if ok */ 673 return 0; 674 } 675 676 static int 677 trrchan_getptr(kobj_t obj, void *data) 678 { 679 struct tr_rchinfo *ch = data; 680 struct tr_info *tr = ch->parent; 681 682 /* return current byte offset of channel */ 683 return tr_rd(tr, TR_REG_DMAR0, 4) - sndbuf_getbufaddr(ch->buffer); 684 } 685 686 static struct pcmchan_caps * 687 trrchan_getcaps(kobj_t obj, void *data) 688 { 689 return &tr_reccaps; 690 } 691 692 static kobj_method_t trrchan_methods[] = { 693 KOBJMETHOD(channel_init, trrchan_init), 694 KOBJMETHOD(channel_setformat, trrchan_setformat), 695 KOBJMETHOD(channel_setspeed, trrchan_setspeed), 696 KOBJMETHOD(channel_setblocksize, trrchan_setblocksize), 697 KOBJMETHOD(channel_trigger, trrchan_trigger), 698 KOBJMETHOD(channel_getptr, trrchan_getptr), 699 KOBJMETHOD(channel_getcaps, trrchan_getcaps), 700 { 0, 0 } 701 }; 702 CHANNEL_DECLARE(trrchan); 703 704 /* -------------------------------------------------------------------- */ 705 /* The interrupt handler */ 706 707 static void 708 tr_intr(void *p) 709 { 710 struct tr_info *tr = (struct tr_info *)p; 711 struct tr_chinfo *ch; 712 u_int32_t active, mask, bufhalf, chnum, intsrc; 713 int tmp; 714 715 intsrc = tr_rd(tr, TR_REG_MISCINT, 4); 716 if (intsrc & TR_INT_ADDR) { 717 chnum = 0; 718 while (chnum < 64) { 719 mask = 0x00000001; 720 active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4); 721 bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4); 722 if (active) { 723 do { 724 if (active & mask) { 725 tmp = (bufhalf & mask)? 1 : 0; 726 if (chnum < tr->playchns) { 727 ch = &tr->chinfo[chnum]; 728 /* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */ 729 if (ch->bufhalf != tmp) { 730 chn_intr(ch->channel); 731 ch->bufhalf = tmp; 732 } 733 } 734 } 735 chnum++; 736 mask <<= 1; 737 } while (chnum & 31); 738 } else 739 chnum += 32; 740 741 tr_wr(tr, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4); 742 } 743 } 744 if (intsrc & TR_INT_SB) { 745 chn_intr(tr->recchinfo.channel); 746 tr_rd(tr, TR_REG_SBR9, 1); 747 tr_rd(tr, TR_REG_SBR10, 1); 748 } 749 } 750 751 /* -------------------------------------------------------------------- */ 752 753 /* 754 * Probe and attach the card 755 */ 756 757 static int 758 tr_init(struct tr_info *tr) 759 { 760 switch (tr->type) { 761 case SPA_PCI_ID: 762 tr_wr(tr, SPA_REG_GPIO, 0, 4); 763 tr_wr(tr, SPA_REG_CODECST, SPA_RST_OFF, 4); 764 break; 765 case TDX_PCI_ID: 766 tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4); 767 break; 768 case TNX_PCI_ID: 769 tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4); 770 break; 771 } 772 773 tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); 774 return 0; 775 } 776 777 static int 778 tr_pci_probe(device_t dev) 779 { 780 switch (pci_get_devid(dev)) { 781 case SPA_PCI_ID: 782 device_set_desc(dev, "SiS 7018"); 783 return 0; 784 case ALI_PCI_ID: 785 device_set_desc(dev, "Acer Labs M5451"); 786 return 0; 787 case TDX_PCI_ID: 788 device_set_desc(dev, "Trident 4DWave DX"); 789 return 0; 790 case TNX_PCI_ID: 791 device_set_desc(dev, "Trident 4DWave NX"); 792 return 0; 793 } 794 795 return ENXIO; 796 } 797 798 static int 799 tr_pci_attach(device_t dev) 800 { 801 u_int32_t data; 802 struct tr_info *tr; 803 struct ac97_info *codec = 0; 804 int i; 805 char status[SND_STATUSLEN]; 806 807 if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 808 device_printf(dev, "cannot allocate softc\n"); 809 return ENXIO; 810 } 811 812 tr->type = pci_get_devid(dev); 813 tr->rev = pci_get_revid(dev); 814 tr->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); 815 816 data = pci_read_config(dev, PCIR_COMMAND, 2); 817 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 818 pci_write_config(dev, PCIR_COMMAND, data, 2); 819 data = pci_read_config(dev, PCIR_COMMAND, 2); 820 821 tr->regid = PCIR_BAR(0); 822 tr->regtype = SYS_RES_IOPORT; 823 tr->reg = bus_alloc_resource_any(dev, tr->regtype, &tr->regid, 824 RF_ACTIVE); 825 if (tr->reg) { 826 tr->st = rman_get_bustag(tr->reg); 827 tr->sh = rman_get_bushandle(tr->reg); 828 } else { 829 device_printf(dev, "unable to map register space\n"); 830 goto bad; 831 } 832 833 tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, 65536); 834 835 if (tr_init(tr) == -1) { 836 device_printf(dev, "unable to initialize the card\n"); 837 goto bad; 838 } 839 tr->playchns = 0; 840 841 codec = AC97_CREATE(dev, tr, tr_ac97); 842 if (codec == NULL) goto bad; 843 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; 844 845 tr->irqid = 0; 846 tr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &tr->irqid, 847 RF_ACTIVE | RF_SHAREABLE); 848 if (!tr->irq || snd_setup_intr(dev, tr->irq, 0, tr_intr, tr, &tr->ih)) { 849 device_printf(dev, "unable to map interrupt\n"); 850 goto bad; 851 } 852 853 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 854 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 855 /*highaddr*/BUS_SPACE_MAXADDR, 856 /*filter*/NULL, /*filterarg*/NULL, 857 /*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 858 /*flags*/0, /*lockfunc*/busdma_lock_mutex, 859 /*lockarg*/&Giant, &tr->parent_dmat) != 0) { 860 device_printf(dev, "unable to create dma tag\n"); 861 goto bad; 862 } 863 864 snprintf(status, 64, "at io 0x%lx irq %ld %s", 865 rman_get_start(tr->reg), rman_get_start(tr->irq),PCM_KLDSTRING(snd_t4dwave)); 866 867 if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad; 868 pcm_addchan(dev, PCMDIR_REC, &trrchan_class, tr); 869 for (i = 0; i < TR_MAXPLAYCH; i++) 870 pcm_addchan(dev, PCMDIR_PLAY, &trpchan_class, tr); 871 pcm_setstatus(dev, status); 872 873 return 0; 874 875 bad: 876 if (codec) ac97_destroy(codec); 877 if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 878 if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih); 879 if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 880 if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat); 881 if (tr->lock) snd_mtxfree(tr->lock); 882 free(tr, M_DEVBUF); 883 return ENXIO; 884 } 885 886 static int 887 tr_pci_detach(device_t dev) 888 { 889 int r; 890 struct tr_info *tr; 891 892 r = pcm_unregister(dev); 893 if (r) 894 return r; 895 896 tr = pcm_getdevinfo(dev); 897 bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 898 bus_teardown_intr(dev, tr->irq, tr->ih); 899 bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 900 bus_dma_tag_destroy(tr->parent_dmat); 901 snd_mtxfree(tr->lock); 902 free(tr, M_DEVBUF); 903 904 return 0; 905 } 906 907 static int 908 tr_pci_suspend(device_t dev) 909 { 910 int i; 911 struct tr_info *tr; 912 913 tr = pcm_getdevinfo(dev); 914 915 for (i = 0; i < tr->playchns; i++) { 916 tr->chinfo[i].was_active = tr->chinfo[i].active; 917 if (tr->chinfo[i].active) { 918 trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_STOP); 919 } 920 } 921 922 tr->recchinfo.was_active = tr->recchinfo.active; 923 if (tr->recchinfo.active) { 924 trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_STOP); 925 } 926 927 return 0; 928 } 929 930 static int 931 tr_pci_resume(device_t dev) 932 { 933 int i; 934 struct tr_info *tr; 935 936 tr = pcm_getdevinfo(dev); 937 938 if (tr_init(tr) == -1) { 939 device_printf(dev, "unable to initialize the card\n"); 940 return ENXIO; 941 } 942 943 if (mixer_reinit(dev) == -1) { 944 device_printf(dev, "unable to initialize the mixer\n"); 945 return ENXIO; 946 } 947 948 for (i = 0; i < tr->playchns; i++) { 949 if (tr->chinfo[i].was_active) { 950 trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_START); 951 } 952 } 953 954 if (tr->recchinfo.was_active) { 955 trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_START); 956 } 957 958 return 0; 959 } 960 961 static device_method_t tr_methods[] = { 962 /* Device interface */ 963 DEVMETHOD(device_probe, tr_pci_probe), 964 DEVMETHOD(device_attach, tr_pci_attach), 965 DEVMETHOD(device_detach, tr_pci_detach), 966 DEVMETHOD(device_suspend, tr_pci_suspend), 967 DEVMETHOD(device_resume, tr_pci_resume), 968 { 0, 0 } 969 }; 970 971 static driver_t tr_driver = { 972 "pcm", 973 tr_methods, 974 PCM_SOFTC_SIZE, 975 }; 976 977 DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0); 978 MODULE_DEPEND(snd_t4dwave, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 979 MODULE_VERSION(snd_t4dwave, 1); 980