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