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