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