1 /* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 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 <pci/pcireg.h> 32 #include <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_BUFFSIZE 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 int index, bufhalf; 57 struct snd_dbuf *buffer; 58 struct pcm_channel *channel; 59 struct tr_info *parent; 60 }; 61 62 struct tr_rchinfo { 63 u_int32_t delta; 64 struct snd_dbuf *buffer; 65 struct pcm_channel *channel; 66 struct tr_info *parent; 67 }; 68 69 /* device private data */ 70 struct tr_info { 71 u_int32_t type; 72 73 bus_space_tag_t st; 74 bus_space_handle_t sh; 75 bus_dma_tag_t parent_dmat; 76 77 struct resource *reg, *irq; 78 int regtype, regid, irqid; 79 void *ih; 80 81 void *lock; 82 83 u_int32_t playchns; 84 struct tr_chinfo chinfo[TR_MAXPLAYCH]; 85 struct tr_rchinfo recchinfo; 86 }; 87 88 /* -------------------------------------------------------------------- */ 89 90 static u_int32_t tr_recfmt[] = { 91 AFMT_U8, 92 AFMT_STEREO | AFMT_U8, 93 AFMT_S8, 94 AFMT_STEREO | AFMT_S8, 95 AFMT_S16_LE, 96 AFMT_STEREO | AFMT_S16_LE, 97 AFMT_U16_LE, 98 AFMT_STEREO | AFMT_U16_LE, 99 0 100 }; 101 static struct pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0}; 102 103 static u_int32_t tr_playfmt[] = { 104 AFMT_U8, 105 AFMT_STEREO | AFMT_U8, 106 AFMT_S8, 107 AFMT_STEREO | AFMT_S8, 108 AFMT_S16_LE, 109 AFMT_STEREO | AFMT_S16_LE, 110 AFMT_U16_LE, 111 AFMT_STEREO | AFMT_U16_LE, 112 0 113 }; 114 static struct pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0}; 115 116 /* -------------------------------------------------------------------- */ 117 118 /* Hardware */ 119 120 static u_int32_t 121 tr_rd(struct tr_info *tr, int regno, int size) 122 { 123 switch(size) { 124 case 1: 125 return bus_space_read_1(tr->st, tr->sh, regno); 126 case 2: 127 return bus_space_read_2(tr->st, tr->sh, regno); 128 case 4: 129 return bus_space_read_4(tr->st, tr->sh, regno); 130 default: 131 return 0xffffffff; 132 } 133 } 134 135 static void 136 tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size) 137 { 138 switch(size) { 139 case 1: 140 bus_space_write_1(tr->st, tr->sh, regno, data); 141 break; 142 case 2: 143 bus_space_write_2(tr->st, tr->sh, regno, data); 144 break; 145 case 4: 146 bus_space_write_4(tr->st, tr->sh, regno, data); 147 break; 148 } 149 } 150 151 /* -------------------------------------------------------------------- */ 152 /* ac97 codec */ 153 154 static int 155 tr_rdcd(kobj_t obj, void *devinfo, int regno) 156 { 157 struct tr_info *tr = (struct tr_info *)devinfo; 158 int i, j, treg, trw; 159 160 switch (tr->type) { 161 case SPA_PCI_ID: 162 treg=SPA_REG_CODECRD; 163 trw=SPA_CDC_RWSTAT; 164 break; 165 case ALI_PCI_ID: 166 case TDX_PCI_ID: 167 treg=TDX_REG_CODECRD; 168 trw=TDX_CDC_RWSTAT; 169 break; 170 case TNX_PCI_ID: 171 treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; 172 trw=TNX_CDC_RWSTAT; 173 break; 174 default: 175 printf("!!! tr_rdcd defaulted !!!\n"); 176 return -1; 177 } 178 179 regno &= 0x7f; 180 snd_mtxlock(tr->lock); 181 tr_wr(tr, treg, regno | trw, 4); 182 j=trw; 183 for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) j=tr_rd(tr, treg, 4); 184 snd_mtxunlock(tr->lock); 185 if (i == 0) printf("codec timeout during read of register %x\n", regno); 186 return (j >> TR_CDC_DATA) & 0xffff; 187 } 188 189 static int 190 tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) 191 { 192 struct tr_info *tr = (struct tr_info *)devinfo; 193 int i, j, treg, trw; 194 195 switch (tr->type) { 196 case SPA_PCI_ID: 197 treg=SPA_REG_CODECWR; 198 trw=SPA_CDC_RWSTAT; 199 break; 200 case ALI_PCI_ID: 201 case TDX_PCI_ID: 202 treg=TDX_REG_CODECWR; 203 trw=TDX_CDC_RWSTAT; 204 break; 205 case TNX_PCI_ID: 206 treg=TNX_REG_CODECWR; 207 trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); 208 break; 209 default: 210 printf("!!! tr_wrcd defaulted !!!"); 211 return -1; 212 } 213 214 regno &= 0x7f; 215 #if 0 216 printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno)); 217 #endif 218 j=trw; 219 snd_mtxlock(tr->lock); 220 for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--) j=tr_rd(tr, treg, 4); 221 tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4); 222 #if 0 223 printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno)); 224 #endif 225 snd_mtxunlock(tr->lock); 226 if (i==0) printf("codec timeout writing %x, data %x\n", regno, data); 227 return (i > 0)? 0 : -1; 228 } 229 230 static kobj_method_t tr_ac97_methods[] = { 231 KOBJMETHOD(ac97_read, tr_rdcd), 232 KOBJMETHOD(ac97_write, tr_wrcd), 233 { 0, 0 } 234 }; 235 AC97_DECLARE(tr_ac97); 236 237 /* -------------------------------------------------------------------- */ 238 /* playback channel interrupts */ 239 240 #if 0 241 static u_int32_t 242 tr_testint(struct tr_chinfo *ch) 243 { 244 struct tr_info *tr = ch->parent; 245 int bank, chan; 246 247 bank = (ch->index & 0x20) ? 1 : 0; 248 chan = ch->index & 0x1f; 249 return tr_rd(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 4) & (1 << chan); 250 } 251 #endif 252 253 static void 254 tr_clrint(struct tr_chinfo *ch) 255 { 256 struct tr_info *tr = ch->parent; 257 int bank, chan; 258 259 bank = (ch->index & 0x20) ? 1 : 0; 260 chan = ch->index & 0x1f; 261 tr_wr(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4); 262 } 263 264 static void 265 tr_enaint(struct tr_chinfo *ch, int enable) 266 { 267 struct tr_info *tr = ch->parent; 268 u_int32_t i, reg; 269 int bank, chan; 270 271 snd_mtxlock(tr->lock); 272 bank = (ch->index & 0x20) ? 1 : 0; 273 chan = ch->index & 0x1f; 274 reg = bank? TR_REG_INTENB : TR_REG_INTENA; 275 276 i = tr_rd(tr, reg, 4); 277 i &= ~(1 << chan); 278 i |= (enable? 1 : 0) << chan; 279 280 tr_clrint(ch); 281 tr_wr(tr, reg, i, 4); 282 snd_mtxunlock(tr->lock); 283 } 284 285 /* playback channels */ 286 287 static void 288 tr_selch(struct tr_chinfo *ch) 289 { 290 struct tr_info *tr = ch->parent; 291 int i; 292 293 i = tr_rd(tr, TR_REG_CIR, 4); 294 i &= ~TR_CIR_MASK; 295 i |= ch->index & 0x3f; 296 tr_wr(tr, TR_REG_CIR, i, 4); 297 } 298 299 static void 300 tr_startch(struct tr_chinfo *ch) 301 { 302 struct tr_info *tr = ch->parent; 303 int bank, chan; 304 305 bank = (ch->index & 0x20) ? 1 : 0; 306 chan = ch->index & 0x1f; 307 tr_wr(tr, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4); 308 } 309 310 static void 311 tr_stopch(struct tr_chinfo *ch) 312 { 313 struct tr_info *tr = ch->parent; 314 int bank, chan; 315 316 bank = (ch->index & 0x20) ? 1 : 0; 317 chan = ch->index & 0x1f; 318 tr_wr(tr, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4); 319 } 320 321 static void 322 tr_wrch(struct tr_chinfo *ch) 323 { 324 struct tr_info *tr = ch->parent; 325 u_int32_t cr[TR_CHN_REGS], i; 326 327 ch->gvsel &= 0x00000001; 328 ch->fmc &= 0x00000003; 329 ch->fms &= 0x0000000f; 330 ch->ctrl &= 0x0000000f; 331 ch->pan &= 0x0000007f; 332 ch->rvol &= 0x0000007f; 333 ch->cvol &= 0x0000007f; 334 ch->vol &= 0x000000ff; 335 ch->ec &= 0x00000fff; 336 ch->alpha &= 0x00000fff; 337 ch->delta &= 0x0000ffff; 338 ch->lba &= 0x3fffffff; 339 340 cr[1]=ch->lba; 341 cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol); 342 cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec); 343 344 switch (tr->type) { 345 case SPA_PCI_ID: 346 case ALI_PCI_ID: 347 case TDX_PCI_ID: 348 ch->cso &= 0x0000ffff; 349 ch->eso &= 0x0000ffff; 350 cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); 351 cr[2]=(ch->eso<<16) | (ch->delta); 352 break; 353 case TNX_PCI_ID: 354 ch->cso &= 0x00ffffff; 355 ch->eso &= 0x00ffffff; 356 cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); 357 cr[2]=((ch->delta>>8)<<24) | (ch->eso); 358 cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); 359 break; 360 } 361 snd_mtxlock(tr->lock); 362 tr_selch(ch); 363 for (i=0; i<TR_CHN_REGS; i++) 364 tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4); 365 snd_mtxunlock(tr->lock); 366 } 367 368 static void 369 tr_rdch(struct tr_chinfo *ch) 370 { 371 struct tr_info *tr = ch->parent; 372 u_int32_t cr[5], i; 373 374 snd_mtxlock(tr->lock); 375 tr_selch(ch); 376 for (i=0; i<5; i++) 377 cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4); 378 snd_mtxunlock(tr->lock); 379 380 381 ch->lba= (cr[1] & 0x3fffffff); 382 ch->fmc= (cr[3] & 0x0000c000) >> 14; 383 ch->rvol= (cr[3] & 0x00003f80) >> 7; 384 ch->cvol= (cr[3] & 0x0000007f); 385 ch->gvsel= (cr[4] & 0x80000000) >> 31; 386 ch->pan= (cr[4] & 0x7f000000) >> 24; 387 ch->vol= (cr[4] & 0x00ff0000) >> 16; 388 ch->ctrl= (cr[4] & 0x0000f000) >> 12; 389 ch->ec= (cr[4] & 0x00000fff); 390 switch(tr->type) { 391 case SPA_PCI_ID: 392 case ALI_PCI_ID: 393 case TDX_PCI_ID: 394 ch->cso= (cr[0] & 0xffff0000) >> 16; 395 ch->alpha= (cr[0] & 0x0000fff0) >> 4; 396 ch->fms= (cr[0] & 0x0000000f); 397 ch->eso= (cr[2] & 0xffff0000) >> 16; 398 ch->delta= (cr[2] & 0x0000ffff); 399 break; 400 case TNX_PCI_ID: 401 ch->cso= (cr[0] & 0x00ffffff); 402 ch->eso= (cr[2] & 0x00ffffff); 403 ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24); 404 ch->alpha= (cr[3] & 0xfff00000) >> 20; 405 ch->fms= (cr[3] & 0x000f0000) >> 16; 406 break; 407 } 408 } 409 410 static u_int32_t 411 tr_fmttobits(u_int32_t fmt) 412 { 413 u_int32_t bits; 414 415 bits = 0; 416 bits |= (fmt & AFMT_SIGNED)? 0x2 : 0; 417 bits |= (fmt & AFMT_STEREO)? 0x4 : 0; 418 bits |= (fmt & AFMT_16BIT)? 0x8 : 0; 419 420 return bits; 421 } 422 423 /* -------------------------------------------------------------------- */ 424 /* channel interface */ 425 426 static void * 427 trpchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 428 { 429 struct tr_info *tr = devinfo; 430 struct tr_chinfo *ch; 431 432 KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction")); 433 ch = &tr->chinfo[tr->playchns]; 434 ch->index = tr->playchns++; 435 ch->buffer = b; 436 ch->parent = tr; 437 ch->channel = c; 438 if (sndbuf_alloc(ch->buffer, tr->parent_dmat, TR_BUFFSIZE) == -1) 439 return NULL; 440 441 return ch; 442 } 443 444 static int 445 trpchan_setformat(kobj_t obj, void *data, u_int32_t format) 446 { 447 struct tr_chinfo *ch = data; 448 449 ch->ctrl = tr_fmttobits(format) | 0x01; 450 451 return 0; 452 } 453 454 static int 455 trpchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 456 { 457 struct tr_chinfo *ch = data; 458 459 ch->delta = (speed << 12) / 48000; 460 return (ch->delta * 48000) >> 12; 461 } 462 463 static int 464 trpchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 465 { 466 struct tr_chinfo *ch = data; 467 468 sndbuf_resize(ch->buffer, 2, blocksize); 469 return blocksize; 470 } 471 472 static int 473 trpchan_trigger(kobj_t obj, void *data, int go) 474 { 475 struct tr_chinfo *ch = data; 476 477 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 478 return 0; 479 480 if (go == PCMTRIG_START) { 481 ch->fmc = 3; 482 ch->fms = 0; 483 ch->ec = 0; 484 ch->alpha = 0; 485 ch->lba = vtophys(sndbuf_getbuf(ch->buffer)); 486 ch->cso = 0; 487 ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1; 488 ch->rvol = ch->cvol = 0x7f; 489 ch->gvsel = 0; 490 ch->pan = 0; 491 ch->vol = 0; 492 ch->bufhalf = 0; 493 tr_wrch(ch); 494 tr_enaint(ch, 1); 495 tr_startch(ch); 496 } else 497 tr_stopch(ch); 498 499 return 0; 500 } 501 502 static int 503 trpchan_getptr(kobj_t obj, void *data) 504 { 505 struct tr_chinfo *ch = data; 506 507 tr_rdch(ch); 508 return ch->cso * sndbuf_getbps(ch->buffer); 509 } 510 511 static struct pcmchan_caps * 512 trpchan_getcaps(kobj_t obj, void *data) 513 { 514 return &tr_playcaps; 515 } 516 517 static kobj_method_t trpchan_methods[] = { 518 KOBJMETHOD(channel_init, trpchan_init), 519 KOBJMETHOD(channel_setformat, trpchan_setformat), 520 KOBJMETHOD(channel_setspeed, trpchan_setspeed), 521 KOBJMETHOD(channel_setblocksize, trpchan_setblocksize), 522 KOBJMETHOD(channel_trigger, trpchan_trigger), 523 KOBJMETHOD(channel_getptr, trpchan_getptr), 524 KOBJMETHOD(channel_getcaps, trpchan_getcaps), 525 { 0, 0 } 526 }; 527 CHANNEL_DECLARE(trpchan); 528 529 /* -------------------------------------------------------------------- */ 530 /* rec channel interface */ 531 532 static void * 533 trrchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 534 { 535 struct tr_info *tr = devinfo; 536 struct tr_rchinfo *ch; 537 538 KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction")); 539 ch = &tr->recchinfo; 540 ch->buffer = b; 541 ch->parent = tr; 542 ch->channel = c; 543 if (sndbuf_alloc(ch->buffer, tr->parent_dmat, TR_BUFFSIZE) == -1) 544 return NULL; 545 546 return ch; 547 } 548 549 static int 550 trrchan_setformat(kobj_t obj, void *data, u_int32_t format) 551 { 552 struct tr_rchinfo *ch = data; 553 struct tr_info *tr = ch->parent; 554 u_int32_t i, bits; 555 556 bits = tr_fmttobits(format); 557 /* set # of samples between interrupts */ 558 i = (sndbuf_runsz(ch->buffer) >> ((bits & 0x08)? 1 : 0)) - 1; 559 tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4); 560 /* set sample format */ 561 i = 0x18 | (bits << 4); 562 tr_wr(tr, TR_REG_SBCTRL, i, 1); 563 564 return 0; 565 566 } 567 568 static int 569 trrchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 570 { 571 struct tr_rchinfo *ch = data; 572 struct tr_info *tr = ch->parent; 573 574 /* setup speed */ 575 ch->delta = (48000 << 12) / speed; 576 tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2); 577 578 /* return closest possible speed */ 579 return (48000 << 12) / ch->delta; 580 } 581 582 static int 583 trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 584 { 585 struct tr_rchinfo *ch = data; 586 587 sndbuf_resize(ch->buffer, 2, blocksize); 588 589 return blocksize; 590 } 591 592 static int 593 trrchan_trigger(kobj_t obj, void *data, int go) 594 { 595 struct tr_rchinfo *ch = data; 596 struct tr_info *tr = ch->parent; 597 u_int32_t i; 598 599 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 600 return 0; 601 602 if (go == PCMTRIG_START) { 603 /* set up dma mode regs */ 604 tr_wr(tr, TR_REG_DMAR15, 0, 1); 605 i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03; 606 tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1); 607 /* set up base address */ 608 tr_wr(tr, TR_REG_DMAR0, vtophys(sndbuf_getbuf(ch->buffer)), 4); 609 /* set up buffer size */ 610 i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff; 611 tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_runsz(ch->buffer) - 1), 4); 612 /* start */ 613 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) | 1, 1); 614 } else 615 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) & ~7, 1); 616 617 /* return 0 if ok */ 618 return 0; 619 } 620 621 static int 622 trrchan_getptr(kobj_t obj, void *data) 623 { 624 struct tr_rchinfo *ch = data; 625 struct tr_info *tr = ch->parent; 626 627 /* return current byte offset of channel */ 628 return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(sndbuf_getbuf(ch->buffer)); 629 } 630 631 static struct pcmchan_caps * 632 trrchan_getcaps(kobj_t obj, void *data) 633 { 634 return &tr_reccaps; 635 } 636 637 static kobj_method_t trrchan_methods[] = { 638 KOBJMETHOD(channel_init, trrchan_init), 639 KOBJMETHOD(channel_setformat, trrchan_setformat), 640 KOBJMETHOD(channel_setspeed, trrchan_setspeed), 641 KOBJMETHOD(channel_setblocksize, trrchan_setblocksize), 642 KOBJMETHOD(channel_trigger, trrchan_trigger), 643 KOBJMETHOD(channel_getptr, trrchan_getptr), 644 KOBJMETHOD(channel_getcaps, trrchan_getcaps), 645 { 0, 0 } 646 }; 647 CHANNEL_DECLARE(trrchan); 648 649 /* -------------------------------------------------------------------- */ 650 /* The interrupt handler */ 651 652 static void 653 tr_intr(void *p) 654 { 655 struct tr_info *tr = (struct tr_info *)p; 656 struct tr_chinfo *ch; 657 u_int32_t active, mask, bufhalf, chnum, intsrc; 658 int tmp; 659 660 intsrc = tr_rd(tr, TR_REG_MISCINT, 4); 661 if (intsrc & TR_INT_ADDR) { 662 chnum = 0; 663 while (chnum < 64) { 664 mask = 0x00000001; 665 active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4); 666 bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4); 667 if (active) { 668 do { 669 if (active & mask) { 670 tmp = (bufhalf & mask)? 1 : 0; 671 if (chnum < tr->playchns) { 672 ch = &tr->chinfo[chnum]; 673 /* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */ 674 if (ch->bufhalf != tmp) { 675 chn_intr(ch->channel); 676 ch->bufhalf = tmp; 677 } 678 } 679 } 680 chnum++; 681 mask <<= 1; 682 } while (chnum & 31); 683 } else 684 chnum += 32; 685 686 tr_wr(tr, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4); 687 } 688 } 689 if (intsrc & TR_INT_SB) { 690 chn_intr(tr->recchinfo.channel); 691 tr_rd(tr, TR_REG_SBR9, 1); 692 tr_rd(tr, TR_REG_SBR10, 1); 693 } 694 } 695 696 /* -------------------------------------------------------------------- */ 697 698 /* 699 * Probe and attach the card 700 */ 701 702 static int 703 tr_init(struct tr_info *tr) 704 { 705 switch (tr->type) { 706 case SPA_PCI_ID: 707 tr_wr(tr, SPA_REG_GPIO, 0, 4); 708 tr_wr(tr, SPA_REG_CODECST, SPA_RST_OFF, 4); 709 break; 710 case TDX_PCI_ID: 711 tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4); 712 break; 713 case TNX_PCI_ID: 714 tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4); 715 break; 716 } 717 718 tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); 719 tr->playchns = 0; 720 return 0; 721 } 722 723 static int 724 tr_pci_probe(device_t dev) 725 { 726 switch (pci_get_devid(dev)) { 727 case SPA_PCI_ID: 728 device_set_desc(dev, "SiS 7018"); 729 return 0; 730 case ALI_PCI_ID: 731 device_set_desc(dev, "Acer Labs M5451"); 732 return 0; 733 case TDX_PCI_ID: 734 device_set_desc(dev, "Trident 4DWave DX"); 735 return 0; 736 case TNX_PCI_ID: 737 device_set_desc(dev, "Trident 4DWave NX"); 738 return 0; 739 } 740 741 return ENXIO; 742 } 743 744 static int 745 tr_pci_attach(device_t dev) 746 { 747 u_int32_t data; 748 struct tr_info *tr; 749 struct ac97_info *codec = 0; 750 int i; 751 char status[SND_STATUSLEN]; 752 753 if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 754 device_printf(dev, "cannot allocate softc\n"); 755 return ENXIO; 756 } 757 758 tr->type = pci_get_devid(dev); 759 tr->lock = snd_mtxcreate(device_get_nameunit(dev)); 760 761 data = pci_read_config(dev, PCIR_COMMAND, 2); 762 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 763 pci_write_config(dev, PCIR_COMMAND, data, 2); 764 data = pci_read_config(dev, PCIR_COMMAND, 2); 765 766 tr->regid = PCIR_MAPS; 767 tr->regtype = SYS_RES_IOPORT; 768 tr->reg = bus_alloc_resource(dev, tr->regtype, &tr->regid, 0, ~0, 1, RF_ACTIVE); 769 if (tr->reg) { 770 tr->st = rman_get_bustag(tr->reg); 771 tr->sh = rman_get_bushandle(tr->reg); 772 } else { 773 device_printf(dev, "unable to map register space\n"); 774 goto bad; 775 } 776 777 if (tr_init(tr) == -1) { 778 device_printf(dev, "unable to initialize the card\n"); 779 goto bad; 780 } 781 782 codec = AC97_CREATE(dev, tr, tr_ac97); 783 if (codec == NULL) goto bad; 784 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; 785 786 tr->irqid = 0; 787 tr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &tr->irqid, 788 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 789 if (!tr->irq || snd_setup_intr(dev, tr->irq, INTR_MPSAFE, tr_intr, tr, &tr->ih)) { 790 device_printf(dev, "unable to map interrupt\n"); 791 goto bad; 792 } 793 794 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 795 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 796 /*highaddr*/BUS_SPACE_MAXADDR, 797 /*filter*/NULL, /*filterarg*/NULL, 798 /*maxsize*/TR_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, 799 /*flags*/0, &tr->parent_dmat) != 0) { 800 device_printf(dev, "unable to create dma tag\n"); 801 goto bad; 802 } 803 804 snprintf(status, 64, "at io 0x%lx irq %ld", 805 rman_get_start(tr->reg), rman_get_start(tr->irq)); 806 807 if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad; 808 pcm_addchan(dev, PCMDIR_REC, &trrchan_class, tr); 809 for (i = 0; i < TR_MAXPLAYCH; i++) 810 pcm_addchan(dev, PCMDIR_PLAY, &trpchan_class, tr); 811 pcm_setstatus(dev, status); 812 813 return 0; 814 815 bad: 816 if (codec) ac97_destroy(codec); 817 if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 818 if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih); 819 if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 820 if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat); 821 if (tr->lock) snd_mtxfree(tr->lock); 822 free(tr, M_DEVBUF); 823 return ENXIO; 824 } 825 826 static int 827 tr_pci_detach(device_t dev) 828 { 829 int r; 830 struct tr_info *tr; 831 832 r = pcm_unregister(dev); 833 if (r) 834 return r; 835 836 tr = pcm_getdevinfo(dev); 837 bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); 838 bus_teardown_intr(dev, tr->irq, tr->ih); 839 bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); 840 bus_dma_tag_destroy(tr->parent_dmat); 841 snd_mtxfree(tr->lock); 842 free(tr, M_DEVBUF); 843 844 return 0; 845 } 846 847 static device_method_t tr_methods[] = { 848 /* Device interface */ 849 DEVMETHOD(device_probe, tr_pci_probe), 850 DEVMETHOD(device_attach, tr_pci_attach), 851 DEVMETHOD(device_detach, tr_pci_detach), 852 853 { 0, 0 } 854 }; 855 856 static driver_t tr_driver = { 857 "pcm", 858 tr_methods, 859 PCM_SOFTC_SIZE, 860 }; 861 862 DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0); 863 MODULE_DEPEND(snd_t4dwave, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 864 MODULE_VERSION(snd_t4dwave, 1); 865