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