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