ds1.c revision 70343
1/* 2 * Copyright (c) 2000 Cameron Grant <cg@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/sound/pci/ds1.c 70343 2000-12-25 01:42:13Z cg $ 27 */ 28 29#include <dev/sound/pcm/sound.h> 30#include <dev/sound/pcm/ac97.h> 31 32#include <pci/pcireg.h> 33#include <pci/pcivar.h> 34 35#include <dev/sound/pci/ds1.h> 36#include <dev/sound/pci/ds1-fw.h> 37 38/* -------------------------------------------------------------------- */ 39 40#define DS1_CHANS 4 41#define DS1_RECPRIMARY 0 42#define DS1_IRQHZ ((48000 << 8) / 256) 43 44struct pbank { 45 volatile u_int32_t Format; 46 volatile u_int32_t LoopDefault; 47 volatile u_int32_t PgBase; 48 volatile u_int32_t PgLoop; 49 volatile u_int32_t PgLoopEnd; 50 volatile u_int32_t PgLoopFrac; 51 volatile u_int32_t PgDeltaEnd; 52 volatile u_int32_t LpfKEnd; 53 volatile u_int32_t EgGainEnd; 54 volatile u_int32_t LchGainEnd; 55 volatile u_int32_t RchGainEnd; 56 volatile u_int32_t Effect1GainEnd; 57 volatile u_int32_t Effect2GainEnd; 58 volatile u_int32_t Effect3GainEnd; 59 volatile u_int32_t LpfQ; 60 volatile u_int32_t Status; 61 volatile u_int32_t NumOfFrames; 62 volatile u_int32_t LoopCount; 63 volatile u_int32_t PgStart; 64 volatile u_int32_t PgStartFrac; 65 volatile u_int32_t PgDelta; 66 volatile u_int32_t LpfK; 67 volatile u_int32_t EgGain; 68 volatile u_int32_t LchGain; 69 volatile u_int32_t RchGain; 70 volatile u_int32_t Effect1Gain; 71 volatile u_int32_t Effect2Gain; 72 volatile u_int32_t Effect3Gain; 73 volatile u_int32_t LpfD1; 74 volatile u_int32_t LpfD2; 75}; 76 77struct rbank { 78 volatile u_int32_t PgBase; 79 volatile u_int32_t PgLoopEnd; 80 volatile u_int32_t PgStart; 81 volatile u_int32_t NumOfLoops; 82}; 83 84struct sc_info; 85 86/* channel registers */ 87struct sc_pchinfo { 88 int run, spd, dir, fmt; 89 snd_dbuf *buffer; 90 pcm_channel *channel; 91 volatile struct pbank *lslot, *rslot; 92 int lsnum, rsnum; 93 struct sc_info *parent; 94}; 95 96struct sc_rchinfo { 97 int run, spd, dir, fmt, num; 98 snd_dbuf *buffer; 99 pcm_channel *channel; 100 volatile struct rbank *slot; 101 struct sc_info *parent; 102}; 103 104/* device private data */ 105struct sc_info { 106 device_t dev; 107 u_int32_t type, rev; 108 u_int32_t cd2id, ctrlbase; 109 110 bus_space_tag_t st; 111 bus_space_handle_t sh; 112 bus_dma_tag_t parent_dmat; 113 bus_dmamap_t map; 114 115 struct resource *reg, *irq; 116 int regid, irqid; 117 void *ih; 118 119 void *regbase; 120 u_int32_t *pbase, pbankbase, pbanksize; 121 volatile struct pbank *pbank[2 * 64]; 122 volatile struct rbank *rbank; 123 int pslotfree, currbank, pchn, rchn; 124 125 struct sc_pchinfo pch[DS1_CHANS]; 126 struct sc_rchinfo rch[2]; 127}; 128 129struct { 130 u_int32_t dev, subdev; 131 char *name; 132 u_int32_t *mcode; 133} ds_devs[] = { 134 {0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst}, 135 {0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E}, 136 {0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst}, 137 {0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst}, 138 {0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst}, 139 {0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst}, 140 {0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst}, 141 {0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst}, 142 {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst}, 143 {0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst}, 144 {0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E}, 145 {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E}, 146 {0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E}, 147 {0, 0, NULL, NULL} 148}; 149 150/* -------------------------------------------------------------------- */ 151 152/* 153 * prototypes 154 */ 155 156/* stuff */ 157static int ds_init(struct sc_info *); 158static void ds_intr(void *); 159 160/* talk to the card */ 161static u_int32_t ds_rd(struct sc_info *, int, int); 162static void ds_wr(struct sc_info *, int, u_int32_t, int); 163 164/* -------------------------------------------------------------------- */ 165 166static u_int32_t ds_recfmt[] = { 167 AFMT_U8, 168 AFMT_STEREO | AFMT_U8, 169 AFMT_S8, 170 AFMT_STEREO | AFMT_S8, 171 AFMT_S16_LE, 172 AFMT_STEREO | AFMT_S16_LE, 173 AFMT_U16_LE, 174 AFMT_STEREO | AFMT_U16_LE, 175 0 176}; 177static pcmchan_caps ds_reccaps = {4000, 48000, ds_recfmt, 0}; 178 179static u_int32_t ds_playfmt[] = { 180 AFMT_U8, 181 AFMT_STEREO | AFMT_U8, 182 /* AFMT_S16_LE, */ 183 AFMT_STEREO | AFMT_S16_LE, 184 0 185}; 186static pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0}; 187 188/* -------------------------------------------------------------------- */ 189/* Hardware */ 190static u_int32_t 191ds_rd(struct sc_info *sc, int regno, int size) 192{ 193 switch (size) { 194 case 1: 195 return bus_space_read_1(sc->st, sc->sh, regno); 196 case 2: 197 return bus_space_read_2(sc->st, sc->sh, regno); 198 case 4: 199 return bus_space_read_4(sc->st, sc->sh, regno); 200 default: 201 return 0xffffffff; 202 } 203} 204 205static void 206ds_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 207{ 208 switch (size) { 209 case 1: 210 bus_space_write_1(sc->st, sc->sh, regno, data); 211 break; 212 case 2: 213 bus_space_write_2(sc->st, sc->sh, regno, data); 214 break; 215 case 4: 216 bus_space_write_4(sc->st, sc->sh, regno, data); 217 break; 218 } 219} 220 221static void 222wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val) 223{ 224 *(volatile u_int32_t *)ptr = val; 225 bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE); 226} 227 228/* -------------------------------------------------------------------- */ 229/* ac97 codec */ 230static int 231ds_cdbusy(struct sc_info *sc, int sec) 232{ 233 int i, reg; 234 235 reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; 236 i = YDSXG_AC97TIMEOUT; 237 while (i > 0) { 238 if (!(ds_rd(sc, reg, 2) & 0x8000)) 239 return 0; 240 i--; 241 } 242 return ETIMEDOUT; 243} 244 245static u_int32_t 246ds_initcd(kobj_t obj, void *devinfo) 247{ 248 struct sc_info *sc = (struct sc_info *)devinfo; 249 u_int32_t x; 250 251 x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1); 252 if (x & 0x03) { 253 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 254 pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1); 255 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 256 /* 257 * The YMF740 on some Intel motherboards requires a pretty 258 * hefty delay after this reset for some reason... Otherwise: 259 * "pcm0: ac97 codec init failed" 260 * Maybe this is needed for all YMF740's? 261 * 400ms and 500ms here seem to work, 300ms does not. 262 * 263 * do it for all chips -cg 264 */ 265 DELAY(500000); 266 } 267 268 return ds_cdbusy(sc, 0)? 0 : 1; 269} 270 271static int 272ds_rdcd(kobj_t obj, void *devinfo, int regno) 273{ 274 struct sc_info *sc = (struct sc_info *)devinfo; 275 int sec, cid, i; 276 u_int32_t cmd, reg; 277 278 sec = regno & 0x100; 279 regno &= 0xff; 280 cid = sec? (sc->cd2id << 8) : 0; 281 reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA; 282 if (sec && cid == 0) 283 return 0xffffffff; 284 285 cmd = YDSXG_AC97READCMD | cid | regno; 286 ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2); 287 288 if (ds_cdbusy(sc, sec)) 289 return 0xffffffff; 290 291 if (sc->type == 11 && sc->rev < 2) 292 for (i = 0; i < 600; i++) 293 ds_rd(sc, reg, 2); 294 295 return ds_rd(sc, reg, 2); 296} 297 298static int 299ds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) 300{ 301 struct sc_info *sc = (struct sc_info *)devinfo; 302 int sec, cid; 303 u_int32_t cmd; 304 305 sec = regno & 0x100; 306 regno &= 0xff; 307 cid = sec? (sc->cd2id << 8) : 0; 308 if (sec && cid == 0) 309 return ENXIO; 310 311 cmd = YDSXG_AC97WRITECMD | cid | regno; 312 cmd <<= 16; 313 cmd |= data; 314 ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4); 315 316 return ds_cdbusy(sc, sec); 317} 318 319static kobj_method_t ds_ac97_methods[] = { 320 KOBJMETHOD(ac97_init, ds_initcd), 321 KOBJMETHOD(ac97_read, ds_rdcd), 322 KOBJMETHOD(ac97_write, ds_wrcd), 323 { 0, 0 } 324}; 325AC97_DECLARE(ds_ac97); 326 327/* -------------------------------------------------------------------- */ 328 329static void 330ds_enadsp(struct sc_info *sc, int on) 331{ 332 u_int32_t v, i; 333 334 v = on? 1 : 0; 335 if (on) { 336 ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4); 337 } else { 338 if (ds_rd(sc, YDSXGR_CONFIG, 4)) 339 ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4); 340 i = YDSXG_WORKBITTIMEOUT; 341 while (i > 0) { 342 if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002)) 343 break; 344 i--; 345 } 346 } 347} 348 349static volatile struct pbank * 350ds_allocpslot(struct sc_info *sc) 351{ 352 int slot; 353 354 if (sc->pslotfree > 63) 355 return NULL; 356 slot = sc->pslotfree++; 357 return sc->pbank[slot * 2]; 358} 359 360static int 361ds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, void *base, u_int32_t len) 362{ 363 u_int32_t lv[] = {1, 1, 0, 0, 0}; 364 u_int32_t rv[] = {1, 0, 1, 0, 0}; 365 u_int32_t e1[] = {0, 0, 0, 0, 0}; 366 u_int32_t e2[] = {1, 0, 0, 1, 0}; 367 u_int32_t e3[] = {1, 0, 0, 0, 1}; 368 int ss, i; 369 u_int32_t delta; 370 371 struct { 372 int rate, fK, fQ; 373 } speedinfo[] = { 374 { 100, 0x00570000, 0x35280000}, 375 { 2000, 0x06aa0000, 0x34a70000}, 376 { 8000, 0x18b20000, 0x32020000}, 377 {11025, 0x20930000, 0x31770000}, 378 {16000, 0x2b9a0000, 0x31390000}, 379 {22050, 0x35a10000, 0x31c90000}, 380 {32000, 0x3eaa0000, 0x33d00000}, 381/* {44100, 0x04646000, 0x370a0000}, 382*/ {48000, 0x40000000, 0x40000000}, 383 }; 384 385 ss = b16? 1 : 0; 386 ss += stereo? 1 : 0; 387 delta = (65536 * rate) / 48000; 388 i = 0; 389 while (i < 7 && speedinfo[i].rate < rate) 390 i++; 391 392 pb->Format = stereo? 0x00010000 : 0; 393 pb->Format |= b16? 0 : 0x80000000; 394 pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0; 395 pb->LoopDefault = 0; 396 pb->PgBase = base? vtophys(base) : 0; 397 pb->PgLoop = 0; 398 pb->PgLoopEnd = len >> ss; 399 pb->PgLoopFrac = 0; 400 pb->Status = 0; 401 pb->NumOfFrames = 0; 402 pb->LoopCount = 0; 403 pb->PgStart = 0; 404 pb->PgStartFrac = 0; 405 pb->PgDelta = pb->PgDeltaEnd = delta << 12; 406 pb->LpfQ = speedinfo[i].fQ; 407 pb->LpfK = pb->LpfKEnd = speedinfo[i].fK; 408 pb->LpfD1 = pb->LpfD2 = 0; 409 pb->EgGain = pb->EgGainEnd = 0x40000000; 410 pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000; 411 pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000; 412 pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000; 413 pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000; 414 pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000; 415 416 return 0; 417} 418 419static void 420ds_enapslot(struct sc_info *sc, int slot, int go) 421{ 422 wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); 423 /* printf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */ 424} 425 426static void 427ds_setuppch(struct sc_pchinfo *ch) 428{ 429 int stereo, b16, c, sz; 430 void *buf; 431 432 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 433 b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 434 c = stereo? 1 : 0; 435 buf = sndbuf_getbuf(ch->buffer); 436 sz = sndbuf_getsize(ch->buffer); 437 438 ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, buf, sz); 439 ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, buf, sz); 440 ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, buf, sz); 441 ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, buf, sz); 442} 443 444static void 445ds_setuprch(struct sc_rchinfo *ch) 446{ 447 struct sc_info *sc = ch->parent; 448 int stereo, b16, i, sz, pri; 449 u_int32_t x, y; 450 void *buf; 451 452 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 453 b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 454 buf = sndbuf_getbuf(ch->buffer); 455 sz = sndbuf_getsize(ch->buffer); 456 pri = (ch->num == DS1_RECPRIMARY)? 1 : 0; 457 458 for (i = 0; i < 2; i++) { 459 ch->slot[i].PgBase = vtophys(buf); 460 ch->slot[i].PgLoopEnd = sz; 461 ch->slot[i].PgStart = 0; 462 ch->slot[i].NumOfLoops = 0; 463 } 464 x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00); 465 y = (48000 * 4096) / ch->spd; 466 y--; 467 /* printf("pri = %d, x = %d, y = %d\n", pri, x, y); */ 468 ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4); 469 ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4); 470} 471 472/* -------------------------------------------------------------------- */ 473/* play channel interface */ 474static void * 475ds1pchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 476{ 477 struct sc_info *sc = devinfo; 478 struct sc_pchinfo *ch; 479 480 KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction")); 481 482 ch = &sc->pch[sc->pchn++]; 483 ch->buffer = b; 484 ch->parent = sc; 485 ch->channel = c; 486 ch->dir = dir; 487 ch->fmt = AFMT_U8; 488 ch->spd = 8000; 489 ch->run = 0; 490 if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 4096) == -1) 491 return NULL; 492 else { 493 ch->lsnum = sc->pslotfree; 494 ch->lslot = ds_allocpslot(sc); 495 ch->rsnum = sc->pslotfree; 496 ch->rslot = ds_allocpslot(sc); 497 ds_setuppch(ch); 498 return ch; 499 } 500} 501 502static int 503ds1pchan_setformat(kobj_t obj, void *data, u_int32_t format) 504{ 505 struct sc_pchinfo *ch = data; 506 507 ch->fmt = format; 508 509 return 0; 510} 511 512static int 513ds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 514{ 515 struct sc_pchinfo *ch = data; 516 517 ch->spd = speed; 518 519 return speed; 520} 521 522static int 523ds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 524{ 525 struct sc_pchinfo *ch = data; 526 int drate; 527 528 /* irq rate is fixed at 187.5hz */ 529 drate = ch->spd * sndbuf_getbps(ch->buffer); 530 blocksize = (drate << 8) / DS1_IRQHZ; 531 return blocksize; 532} 533 534/* semantic note: must start at beginning of buffer */ 535static int 536ds1pchan_trigger(kobj_t obj, void *data, int go) 537{ 538 struct sc_pchinfo *ch = data; 539 struct sc_info *sc = ch->parent; 540 int stereo; 541 542 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 543 return 0; 544 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 545 if (go == PCMTRIG_START) { 546 ch->run = 1; 547 ds_setuppch(ch); 548 ds_enapslot(sc, ch->lsnum, 1); 549 ds_enapslot(sc, ch->rsnum, stereo); 550 ds_wr(sc, YDSXGR_MODE, 0x00000003, 4); 551 } else { 552 ch->run = 0; 553 /* ds_setuppch(ch); */ 554 ds_enapslot(sc, ch->lsnum, 0); 555 ds_enapslot(sc, ch->rsnum, 0); 556 } 557 558 return 0; 559} 560 561static int 562ds1pchan_getptr(kobj_t obj, void *data) 563{ 564 struct sc_pchinfo *ch = data; 565 struct sc_info *sc = ch->parent; 566 volatile struct pbank *bank; 567 int ss; 568 u_int32_t ptr; 569 570 ss = (ch->fmt & AFMT_STEREO)? 1 : 0; 571 ss += (ch->fmt & AFMT_16BIT)? 1 : 0; 572 573 bank = ch->lslot + sc->currbank; 574 /* printf("getptr: %d\n", bank->PgStart << ss); */ 575 ptr = bank->PgStart; 576 ptr <<= ss; 577 return ptr; 578} 579 580static pcmchan_caps * 581ds1pchan_getcaps(kobj_t obj, void *data) 582{ 583 return &ds_playcaps; 584} 585 586static kobj_method_t ds1pchan_methods[] = { 587 KOBJMETHOD(channel_init, ds1pchan_init), 588 KOBJMETHOD(channel_setformat, ds1pchan_setformat), 589 KOBJMETHOD(channel_setspeed, ds1pchan_setspeed), 590 KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize), 591 KOBJMETHOD(channel_trigger, ds1pchan_trigger), 592 KOBJMETHOD(channel_getptr, ds1pchan_getptr), 593 KOBJMETHOD(channel_getcaps, ds1pchan_getcaps), 594 { 0, 0 } 595}; 596CHANNEL_DECLARE(ds1pchan); 597 598/* -------------------------------------------------------------------- */ 599/* record channel interface */ 600static void * 601ds1rchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 602{ 603 struct sc_info *sc = devinfo; 604 struct sc_rchinfo *ch; 605 606 KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction")); 607 608 ch = &sc->rch[sc->rchn]; 609 ch->num = sc->rchn++; 610 ch->buffer = b; 611 ch->parent = sc; 612 ch->channel = c; 613 ch->dir = dir; 614 ch->fmt = AFMT_U8; 615 ch->spd = 8000; 616 if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 4096) == -1) 617 return NULL; 618 else { 619 ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank; 620 ds_setuprch(ch); 621 return ch; 622 } 623} 624 625static int 626ds1rchan_setformat(kobj_t obj, void *data, u_int32_t format) 627{ 628 struct sc_rchinfo *ch = data; 629 630 ch->fmt = format; 631 632 return 0; 633} 634 635static int 636ds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 637{ 638 struct sc_rchinfo *ch = data; 639 640 ch->spd = speed; 641 642 return speed; 643} 644 645static int 646ds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 647{ 648 return blocksize; 649} 650 651/* semantic note: must start at beginning of buffer */ 652static int 653ds1rchan_trigger(kobj_t obj, void *data, int go) 654{ 655 struct sc_rchinfo *ch = data; 656 struct sc_info *sc = ch->parent; 657 u_int32_t x; 658 659 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 660 return 0; 661 if (go == PCMTRIG_START) { 662 ch->run = 1; 663 ds_setuprch(ch); 664 x = ds_rd(sc, YDSXGR_MAPOFREC, 4); 665 x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01; 666 ds_wr(sc, YDSXGR_MAPOFREC, x, 4); 667 ds_wr(sc, YDSXGR_MODE, 0x00000003, 4); 668 } else { 669 ch->run = 0; 670 x = ds_rd(sc, YDSXGR_MAPOFREC, 4); 671 x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01); 672 ds_wr(sc, YDSXGR_MAPOFREC, x, 4); 673 } 674 675 return 0; 676} 677 678static int 679ds1rchan_getptr(kobj_t obj, void *data) 680{ 681 struct sc_rchinfo *ch = data; 682 struct sc_info *sc = ch->parent; 683 684 return ch->slot[sc->currbank].PgStart; 685} 686 687static pcmchan_caps * 688ds1rchan_getcaps(kobj_t obj, void *data) 689{ 690 return &ds_reccaps; 691} 692 693static kobj_method_t ds1rchan_methods[] = { 694 KOBJMETHOD(channel_init, ds1rchan_init), 695 KOBJMETHOD(channel_setformat, ds1rchan_setformat), 696 KOBJMETHOD(channel_setspeed, ds1rchan_setspeed), 697 KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize), 698 KOBJMETHOD(channel_trigger, ds1rchan_trigger), 699 KOBJMETHOD(channel_getptr, ds1rchan_getptr), 700 KOBJMETHOD(channel_getcaps, ds1rchan_getcaps), 701 { 0, 0 } 702}; 703CHANNEL_DECLARE(ds1rchan); 704 705/* -------------------------------------------------------------------- */ 706/* The interrupt handler */ 707static void 708ds_intr(void *p) 709{ 710 struct sc_info *sc = (struct sc_info *)p; 711 u_int32_t i, x; 712 713 i = ds_rd(sc, YDSXGR_STATUS, 4); 714 if (i & 0x00008000) 715 device_printf(sc->dev, "timeout irq\n"); 716 if (i & 0x80008000) { 717 ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4); 718 sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001; 719 720 x = 0; 721 for (i = 0; i < DS1_CHANS; i++) { 722 if (sc->pch[i].run) { 723 x = 1; 724 chn_intr(sc->pch[i].channel); 725 } 726 } 727 for (i = 0; i < 2; i++) { 728 if (sc->rch[i].run) { 729 x = 1; 730 chn_intr(sc->rch[i].channel); 731 } 732 } 733 i = ds_rd(sc, YDSXGR_MODE, 4); 734 if (x) 735 ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4); 736 737 } 738} 739 740/* -------------------------------------------------------------------- */ 741 742/* 743 * Probe and attach the card 744 */ 745 746static void 747ds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 748{ 749 struct sc_info *sc = arg; 750 751 sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr; 752 753 if (bootverbose) { 754 printf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n", 755 (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 756 nseg, error); 757 } 758} 759 760static int 761ds_init(struct sc_info *sc) 762{ 763 int i; 764 u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb; 765 u_int8_t *t; 766 void *buf; 767 768 ci = ds_devs[sc->type].mcode; 769 770 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4); 771 ds_enadsp(sc, 0); 772 ds_wr(sc, YDSXGR_MODE, 0x00010000, 4); 773 ds_wr(sc, YDSXGR_MODE, 0x00000000, 4); 774 ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4); 775 ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4); 776 ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4); 777 ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4); 778 ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4); 779 r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2); 780 ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2); 781 782 for (i = 0; i < YDSXG_DSPLENGTH; i += 4) 783 ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4); 784 785 for (i = 0; i < YDSXG_CTRLLENGTH; i += 4) 786 ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4); 787 788 ds_enadsp(sc, 1); 789 790 pcs = 0; 791 for (i = 100; i > 0; i--) { 792 pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2; 793 if (pcs == sizeof(struct pbank)) 794 break; 795 DELAY(1000); 796 } 797 if (pcs != sizeof(struct pbank)) { 798 device_printf(sc->dev, "preposterous playctrlsize (%d)\n", pcs); 799 return -1; 800 } 801 rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2; 802 ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2; 803 ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2; 804 805 memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws; 806 memsz += (64 + 1) * 4; 807 808 if (sc->regbase == NULL) { 809 if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &sc->map)) 810 return -1; 811 if (bus_dmamap_load(sc->parent_dmat, sc->map, buf, memsz, ds_setmap, sc, 0) 812 || !sc->ctrlbase) { 813 device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n", 814 pcs, rcs, ecs, ws, memsz); 815 return -1; 816 } 817 sc->regbase = buf; 818 } else 819 buf = sc->regbase; 820 821 cb = 0; 822 t = buf; 823 ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4); 824 cb += ws; 825 sc->pbase = (u_int32_t *)(t + cb); 826 /* printf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */ 827 ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4); 828 cb += (64 + 1) * 4; 829 sc->rbank = (struct rbank *)(t + cb); 830 ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4); 831 cb += 2 * 2 * rcs; 832 ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4); 833 cb += 5 * 2 * ecs; 834 835 sc->pbankbase = sc->ctrlbase + cb; 836 sc->pbanksize = pcs; 837 for (i = 0; i < 64; i++) { 838 wrl(sc, &sc->pbase[i + 1], 0); 839 sc->pbank[i * 2] = (struct pbank *)(t + cb); 840 /* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 841 cb += pcs; 842 sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb); 843 /* printf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 844 cb += pcs; 845 } 846 wrl(sc, &sc->pbase[0], DS1_CHANS * 2); 847 848 sc->pchn = sc->rchn = 0; 849 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4); 850 ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4); 851 ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4); 852 853 return 0; 854} 855 856static int 857ds_uninit(struct sc_info *sc) 858{ 859 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4); 860 ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4); 861 ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4); 862 ds_enadsp(sc, 0); 863 ds_wr(sc, YDSXGR_MODE, 0x00010000, 4); 864 ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4); 865 ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4); 866 ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4); 867 ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4); 868 ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4); 869 ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2); 870 871 bus_dmamap_unload(sc->parent_dmat, sc->map); 872 bus_dmamem_free(sc->parent_dmat, sc->regbase, sc->map); 873 874 return 0; 875} 876 877static int 878ds_finddev(u_int32_t dev, u_int32_t subdev) 879{ 880 int i; 881 882 for (i = 0; ds_devs[i].dev; i++) { 883 if (ds_devs[i].dev == dev && 884 (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0)) 885 return i; 886 } 887 return -1; 888} 889 890static int 891ds_pci_probe(device_t dev) 892{ 893 int i; 894 u_int32_t subdev; 895 896 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 897 i = ds_finddev(pci_get_devid(dev), subdev); 898 if (i >= 0) { 899 device_set_desc(dev, ds_devs[i].name); 900 return 0; 901 } else 902 return ENXIO; 903} 904 905static int 906ds_pci_attach(device_t dev) 907{ 908 u_int32_t data; 909 u_int32_t subdev, i; 910 struct sc_info *sc; 911 struct ac97_info *codec = NULL; 912 char status[SND_STATUSLEN]; 913 914 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { 915 device_printf(dev, "cannot allocate softc\n"); 916 return ENXIO; 917 } 918 919 bzero(sc, sizeof(*sc)); 920 sc->dev = dev; 921 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 922 sc->type = ds_finddev(pci_get_devid(dev), subdev); 923 sc->rev = pci_get_revid(dev); 924 925 data = pci_read_config(dev, PCIR_COMMAND, 2); 926 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 927 pci_write_config(dev, PCIR_COMMAND, data, 2); 928 data = pci_read_config(dev, PCIR_COMMAND, 2); 929 930 sc->regid = PCIR_MAPS; 931 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, 932 0, ~0, 1, RF_ACTIVE); 933 if (!sc->reg) { 934 device_printf(dev, "unable to map register space\n"); 935 goto bad; 936 } 937 938 sc->st = rman_get_bustag(sc->reg); 939 sc->sh = rman_get_bushandle(sc->reg); 940 941 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 942 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 943 /*highaddr*/BUS_SPACE_MAXADDR, 944 /*filter*/NULL, /*filterarg*/NULL, 945 /*maxsize*/65536, /*nsegments*/1, /*maxsegz*/0x3ffff, 946 /*flags*/0, &sc->parent_dmat) != 0) { 947 device_printf(dev, "unable to create dma tag\n"); 948 goto bad; 949 } 950 951 sc->regbase = NULL; 952 if (ds_init(sc) == -1) { 953 device_printf(dev, "unable to initialize the card\n"); 954 goto bad; 955 } 956 957 codec = AC97_CREATE(dev, sc, ds_ac97); 958 if (codec == NULL) 959 goto bad; 960 mixer_init(dev, ac97_getmixerclass(), codec); 961 962 sc->irqid = 0; 963 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 964 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 965 if (!sc->irq || 966 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ds_intr, sc, &sc->ih)) { 967 device_printf(dev, "unable to map interrupt\n"); 968 goto bad; 969 } 970 971 snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld", 972 rman_get_start(sc->reg), rman_get_start(sc->irq)); 973 974 if (pcm_register(dev, sc, DS1_CHANS, 2)) 975 goto bad; 976 for (i = 0; i < DS1_CHANS; i++) 977 pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc); 978 for (i = 0; i < 2; i++) 979 pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc); 980 pcm_setstatus(dev, status); 981 982 return 0; 983 984bad: 985 if (codec) 986 ac97_destroy(codec); 987 if (sc->reg) 988 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 989 if (sc->ih) 990 bus_teardown_intr(dev, sc->irq, sc->ih); 991 if (sc->irq) 992 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 993 if (sc->parent_dmat) 994 bus_dma_tag_destroy(sc->parent_dmat); 995 free(sc, M_DEVBUF); 996 return ENXIO; 997} 998 999static int 1000ds_pci_resume(device_t dev) 1001{ 1002 struct sc_info *sc; 1003 1004 sc = pcm_getdevinfo(dev); 1005 1006 if (ds_init(sc) == -1) { 1007 device_printf(dev, "unable to reinitialize the card\n"); 1008 return ENXIO; 1009 } 1010 if (mixer_reinit(dev) == -1) { 1011 device_printf(dev, "unable to reinitialize the mixer\n"); 1012 return ENXIO; 1013 } 1014 return 0; 1015} 1016 1017static int 1018ds_pci_detach(device_t dev) 1019{ 1020 int r; 1021 struct sc_info *sc; 1022 1023 r = pcm_unregister(dev); 1024 if (r) 1025 return r; 1026 1027 sc = pcm_getdevinfo(dev); 1028 ds_uninit(sc); 1029 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 1030 bus_teardown_intr(dev, sc->irq, sc->ih); 1031 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1032 bus_dma_tag_destroy(sc->parent_dmat); 1033 free(sc, M_DEVBUF); 1034 return 0; 1035} 1036 1037static device_method_t ds1_methods[] = { 1038 /* Device interface */ 1039 DEVMETHOD(device_probe, ds_pci_probe), 1040 DEVMETHOD(device_attach, ds_pci_attach), 1041 DEVMETHOD(device_detach, ds_pci_detach), 1042 DEVMETHOD(device_resume, ds_pci_resume), 1043 { 0, 0 } 1044}; 1045 1046static driver_t ds1_driver = { 1047 "pcm", 1048 ds1_methods, 1049 sizeof(snddev_info), 1050}; 1051 1052static devclass_t pcm_devclass; 1053 1054DRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0); 1055MODULE_DEPEND(snd_ds1, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 1056MODULE_VERSION(snd_ds1, 1); 1057