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