ds1.c revision 61133
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/sound/pci/ds1.c 61133 2000-05-31 19:04:12Z cg $ 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 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 sc_info; 79 80/* channel registers */ 81struct sc_chinfo { 82 int run, spd, dir, fmt; 83 snd_dbuf *buffer; 84 pcm_channel *channel; 85 volatile struct pbank *lslot, *rslot; 86 int lsnum, rsnum; 87 struct sc_info *parent; 88}; 89 90/* device private data */ 91struct sc_info { 92 device_t dev; 93 u_int32_t type, rev; 94 u_int32_t cd2id, ctrlbase; 95 96 bus_space_tag_t st; 97 bus_space_handle_t sh; 98 bus_dma_tag_t parent_dmat; 99 100 struct resource *reg, *irq; 101 int regid, irqid; 102 void *ih; 103 104 u_int32_t *pbase, pbankbase, pbanksize; 105 volatile struct pbank *pbank[2 * 64]; 106 int pslotfree, currbank, pchn, rchn; 107 108 struct sc_chinfo pch[DS1_CHANS], rch[2]; 109}; 110 111struct { 112 u_int32_t dev, subdev; 113 char *name; 114 u_int32_t *mcode; 115} ds_devs[] = { 116 {0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst}, 117 {0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E}, 118 {0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst}, 119 {0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst}, 120 {0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst}, 121 {0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst}, 122 {0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst}, 123 {0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst}, 124 {0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E}, 125 {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E}, 126 {0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E}, 127 {0, 0, NULL, NULL} 128}; 129 130/* -------------------------------------------------------------------- */ 131 132/* 133 * prototypes 134 */ 135 136/* channel interface */ 137static void *ds1chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 138static int ds1chan_setdir(void *data, int dir); 139static int ds1chan_setformat(void *data, u_int32_t format); 140static int ds1chan_setspeed(void *data, u_int32_t speed); 141static int ds1chan_setblocksize(void *data, u_int32_t blocksize); 142static int ds1chan_trigger(void *data, int go); 143static int ds1chan_getptr(void *data); 144static pcmchan_caps *ds1chan_getcaps(void *data); 145 146/* talk to the codec - called from ac97.c */ 147static u_int32_t ds_rdcd(void *, int); 148static void ds_wrcd(void *, int, u_int32_t); 149 150/* stuff */ 151static int ds_init(struct sc_info *); 152static void ds_intr(void *); 153 154/* talk to the card */ 155static u_int32_t ds_rd(struct sc_info *, int, int); 156static void ds_wr(struct sc_info *, int, u_int32_t, int); 157 158/* -------------------------------------------------------------------- */ 159 160static pcmchan_caps ds_reccaps = { 161 4000, 48000, 162 AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, 163 AFMT_STEREO | AFMT_S16_LE 164}; 165 166static pcmchan_caps ds_playcaps = { 167 4000, 96000, 168 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 169 AFMT_STEREO | AFMT_S16_LE 170}; 171 172static pcm_channel ds_chantemplate = { 173 ds1chan_init, 174 ds1chan_setdir, 175 ds1chan_setformat, 176 ds1chan_setspeed, 177 ds1chan_setblocksize, 178 ds1chan_trigger, 179 ds1chan_getptr, 180 ds1chan_getcaps, 181}; 182 183/* -------------------------------------------------------------------- */ 184/* Hardware */ 185static u_int32_t 186ds_rd(struct sc_info *sc, int regno, int size) 187{ 188 switch (size) { 189 case 1: 190 return bus_space_read_1(sc->st, sc->sh, regno); 191 case 2: 192 return bus_space_read_2(sc->st, sc->sh, regno); 193 case 4: 194 return bus_space_read_4(sc->st, sc->sh, regno); 195 default: 196 return 0xffffffff; 197 } 198} 199 200static void 201ds_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 202{ 203 switch (size) { 204 case 1: 205 bus_space_write_1(sc->st, sc->sh, regno, data); 206 break; 207 case 2: 208 bus_space_write_2(sc->st, sc->sh, regno, data); 209 break; 210 case 4: 211 bus_space_write_4(sc->st, sc->sh, regno, data); 212 break; 213 } 214} 215 216static void 217wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val) 218{ 219 *(volatile u_int32_t *)ptr = val; 220 bus_space_barrier(sc->sh, sc->st, 0, 0, BUS_SPACE_BARRIER_WRITE); 221} 222 223/* ac97 codec */ 224static int 225ds_cdbusy(struct sc_info *sc, int sec) 226{ 227 int i, reg; 228 229 reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; 230 i = YDSXG_AC97TIMEOUT; 231 while (i > 0) { 232 if (!(ds_rd(sc, reg, 2) & 0x8000)) 233 return 0; 234 i--; 235 } 236 return ETIMEDOUT; 237} 238 239static u_int32_t 240ds_initcd(void *devinfo) 241{ 242 struct sc_info *sc = (struct sc_info *)devinfo; 243 u_int32_t x; 244 245 x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1); 246 if (x & 0x03) { 247 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 248 pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1); 249 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 250 } 251 252 return ds_cdbusy(sc, 0); 253} 254 255static u_int32_t 256ds_rdcd(void *devinfo, int regno) 257{ 258 struct sc_info *sc = (struct sc_info *)devinfo; 259 int sec, cid, i; 260 u_int32_t cmd, reg; 261 262 sec = regno & 0x100; 263 regno &= 0xff; 264 cid = sec? (sc->cd2id << 8) : 0; 265 reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA; 266 if (sec && cid == 0) 267 return 0xffffffff; 268 269 cmd = YDSXG_AC97READCMD | cid | regno; 270 ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2); 271 272 if (ds_cdbusy(sc, sec)) 273 return 0xffffffff; 274 275 if (sc->type == 9 && sc->rev < 2) 276 for (i = 0; i < 600; i++) 277 ds_rd(sc, reg, 2); 278 279 return ds_rd(sc, reg, 2); 280} 281 282static void 283ds_wrcd(void *devinfo, int regno, u_int32_t data) 284{ 285 struct sc_info *sc = (struct sc_info *)devinfo; 286 int sec, cid; 287 u_int32_t cmd; 288 289 sec = regno & 0x100; 290 regno &= 0xff; 291 cid = sec? (sc->cd2id << 8) : 0; 292 if (sec && cid == 0) 293 return; 294 295 cmd = YDSXG_AC97WRITECMD | cid | regno; 296 cmd <<= 16; 297 cmd |= data; 298 ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4); 299 300 ds_cdbusy(sc, sec); 301} 302 303static void 304ds_enadsp(struct sc_info *sc, int on) 305{ 306 u_int32_t v, i; 307 308 v = on? 1 : 0; 309 if (on) { 310 ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4); 311 } else { 312 if (ds_rd(sc, YDSXGR_CONFIG, 4)) 313 ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4); 314 i = YDSXG_WORKBITTIMEOUT; 315 while (i > 0) { 316 if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002)) 317 break; 318 i--; 319 } 320 } 321} 322 323static volatile struct pbank * 324ds_allocpslot(struct sc_info *sc) 325{ 326 int slot; 327 328 if (sc->pslotfree > 63) 329 return NULL; 330 slot = sc->pslotfree++; 331 return sc->pbank[slot * 2]; 332} 333 334static int 335ds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, void *base, u_int32_t len) 336{ 337 u_int32_t lv[] = {1, 1, 0, 0, 0}; 338 u_int32_t rv[] = {1, 0, 1, 0, 0}; 339 u_int32_t e1[] = {0, 0, 0, 0, 0}; 340 u_int32_t e2[] = {1, 0, 0, 1, 0}; 341 u_int32_t e3[] = {1, 0, 0, 0, 1}; 342 int ss, i; 343 u_int32_t delta; 344 345 struct { 346 int rate, fK, fQ; 347 } speedinfo[] = { 348 { 100, 0x00570000, 0x35280000}, 349 { 2000, 0x06aa0000, 0x34a70000}, 350 { 8000, 0x18b20000, 0x32020000}, 351 {11025, 0x20930000, 0x31770000}, 352 {16000, 0x2b9a0000, 0x31390000}, 353 {22050, 0x35a10000, 0x31c90000}, 354 {32000, 0x3eaa0000, 0x33d00000}, 355/* {44100, 0x04646000, 0x370a0000}, 356*/ {48000, 0x40000000, 0x40000000}, 357 }; 358 359 ss = b16? 1 : 0; 360 ss += stereo? 1 : 0; 361 delta = (65536 * rate) / 48000; 362 i = 0; 363 while (i < 7 && speedinfo[i].rate < rate) 364 i++; 365 366 pb->Format = stereo? 0x00010000 : 0; 367 pb->Format |= b16? 0 : 0x80000000; 368 pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0; 369 pb->LoopDefault = 0; 370 pb->PgBase = base? vtophys(base) : 0; 371 pb->PgLoop = 0; 372 pb->PgLoopEnd = len >> ss; 373 pb->PgLoopFrac = 0; 374 pb->Status = 0; 375 pb->NumOfFrames = 0; 376 pb->LoopCount = 0; 377 pb->PgStart = 0; 378 pb->PgStartFrac = 0; 379 pb->PgDelta = pb->PgDeltaEnd = delta << 12; 380 pb->LpfQ = speedinfo[i].fQ; 381 pb->LpfK = pb->LpfKEnd = speedinfo[i].fK; 382 pb->LpfD1 = pb->LpfD2 = 0; 383 pb->EgGain = pb->EgGainEnd = 0x40000000; 384 pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000; 385 pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000; 386 pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000; 387 pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000; 388 pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000; 389 390 return 0; 391} 392 393static void 394ds_enapslot(struct sc_info *sc, int slot, int go) 395{ 396 wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); 397 /* printf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */ 398} 399 400static void 401ds_setupch(struct sc_chinfo *ch) 402{ 403 int stereo, b16, c; 404 void *buf; 405 406 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 407 b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 408 c = stereo? 1 : 0; 409 buf = ch->buffer->buf; 410 411 ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, buf, ch->buffer->bufsize); 412 ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, buf, ch->buffer->bufsize); 413 ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, buf, ch->buffer->bufsize); 414 ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, buf, ch->buffer->bufsize); 415} 416 417/* channel interface */ 418void * 419ds1chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 420{ 421 struct sc_info *sc = devinfo; 422 struct sc_chinfo *ch; 423 424 ch = (dir == PCMDIR_PLAY)? &sc->pch[sc->pchn++] : &sc->rch[sc->rchn++]; 425 ch->buffer = b; 426 ch->buffer->bufsize = 4096; 427 ch->parent = sc; 428 ch->channel = c; 429 ch->fmt = AFMT_U8; 430 ch->spd = 8000; 431 ch->run = 0; 432 if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) 433 return NULL; 434 else { 435 ch->lsnum = sc->pslotfree; 436 ch->lslot = ds_allocpslot(sc); 437 ch->rsnum = sc->pslotfree; 438 ch->rslot = ds_allocpslot(sc); 439 ds_setupch(ch); 440 return ch; 441 } 442} 443 444static int 445ds1chan_setdir(void *data, int dir) 446{ 447 return 0; 448} 449 450static int 451ds1chan_setformat(void *data, u_int32_t format) 452{ 453 struct sc_chinfo *ch = data; 454 455 ch->fmt = format; 456 457 return 0; 458} 459 460static int 461ds1chan_setspeed(void *data, u_int32_t speed) 462{ 463 struct sc_chinfo *ch = data; 464 465 ch->spd = speed; 466 467 return speed; 468} 469 470static int 471ds1chan_setblocksize(void *data, u_int32_t blocksize) 472{ 473 return blocksize; 474} 475 476/* semantic note: must start at beginning of buffer */ 477static int 478ds1chan_trigger(void *data, int go) 479{ 480 struct sc_chinfo *ch = data; 481 struct sc_info *sc = ch->parent; 482 int stereo; 483 484 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 485 return 0; 486 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0; 487 if (go == PCMTRIG_START) { 488 ch->run = 1; 489 ds_setupch(ch); 490 ds_enapslot(sc, ch->lsnum, 1); 491 ds_enapslot(sc, ch->rsnum, stereo); 492 ds_wr(sc, YDSXGR_MODE, 0x00000003, 4); 493 } else { 494 ch->run = 0; 495 ds_setupch(ch); 496 ds_enapslot(sc, ch->lsnum, 0); 497 ds_enapslot(sc, ch->rsnum, 0); 498 } 499 500 return 0; 501} 502 503static int 504ds1chan_getptr(void *data) 505{ 506 struct sc_chinfo *ch = data; 507 struct sc_info *sc = ch->parent; 508 volatile struct pbank *bank; 509 int ss; 510 u_int32_t ptr; 511 512 ss = (ch->fmt & AFMT_STEREO)? 1 : 0; 513 ss += (ch->fmt & AFMT_16BIT)? 1 : 0; 514 515 bank = ch->lslot + sc->currbank; 516 /* printf("getptr: %d\n", bank->PgStart << ss); */ 517 ptr = bank->PgStart; 518 ptr <<= ss; 519 return ptr; 520} 521 522static pcmchan_caps * 523ds1chan_getcaps(void *data) 524{ 525 struct sc_chinfo *ch = data; 526 527 return (ch->dir == PCMDIR_PLAY)? &ds_playcaps : &ds_reccaps; 528} 529 530/* The interrupt handler */ 531static void 532ds_intr(void *p) 533{ 534 struct sc_info *sc = (struct sc_info *)p; 535 u_int32_t i, x; 536 537 i = ds_rd(sc, YDSXGR_STATUS, 4); 538 if (i & 0x80008000) { 539 ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4); 540 sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001; 541 542 x = 0; 543 for (i = 0; i < DS1_CHANS; i++) 544 if (sc->pch[i].run) { 545 x = 1; 546 chn_intr(sc->pch[i].channel); 547 } 548 549 i = ds_rd(sc, YDSXGR_MODE, 4); 550 if (x) 551 ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4); 552 553 } 554} 555 556/* -------------------------------------------------------------------- */ 557 558/* 559 * Probe and attach the card 560 */ 561 562static void 563ds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 564{ 565 struct sc_info *sc = arg; 566 567 sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr; 568 569 if (bootverbose) { 570 printf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n", 571 (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 572 nseg, error); 573 } 574} 575 576static int 577ds_init(struct sc_info *sc) 578{ 579 int i; 580 u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb; 581 u_int8_t *t; 582 void *buf; 583 bus_dmamap_t map; 584 585 ci = ds_devs[sc->type].mcode; 586 587 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4); 588 ds_enadsp(sc, 0); 589 ds_wr(sc, YDSXGR_MODE, 0x00010000, 4); 590 ds_wr(sc, YDSXGR_MODE, 0x00000000, 4); 591 ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4); 592 ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4); 593 ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4); 594 ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4); 595 ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4); 596 r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2); 597 ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2); 598 599 for (i = 0; i < YDSXG_DSPLENGTH; i += 4) 600 ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4); 601 602 for (i = 0; i < YDSXG_CTRLLENGTH; i += 4) 603 ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4); 604 605 ds_enadsp(sc, 1); 606 607 pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2; 608 rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2; 609 ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2; 610 ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2; 611 612 memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws; 613 memsz += (64 + 1) * 4; 614 615 if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) 616 return -1; 617 if (bus_dmamap_load(sc->parent_dmat, map, buf, memsz, ds_setmap, sc, 0) 618 || !sc->ctrlbase) { 619 device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n", 620 pcs, rcs, ecs, ws, memsz); 621 return -1; 622 } 623 624 cb = 0; 625 t = buf; 626 ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4); 627 cb += ws; 628 sc->pbase = (u_int32_t *)(t + cb); 629 /* printf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */ 630 ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4); 631 cb += (64 + 1) * 4; 632 ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4); 633 cb += 2 * 2 * rcs; 634 ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4); 635 cb += 5 * 2 * ecs; 636 637 sc->pbankbase = sc->ctrlbase + cb; 638 sc->pbanksize = pcs; 639 for (i = 0; i < 64; i++) { 640 wrl(sc, &sc->pbase[i + 1], 0); 641 sc->pbank[i * 2] = (struct pbank *)(t + cb); 642 /* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 643 cb += pcs; 644 sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb); 645 /* printf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 646 cb += pcs; 647 } 648 wrl(sc, &sc->pbase[0], DS1_CHANS * 2); 649 650 sc->pchn = sc->rchn = 0; 651 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4); 652 return 0; 653} 654 655static int 656ds_finddev(u_int32_t dev, u_int32_t subdev) 657{ 658 int i; 659 660 for (i = 0; ds_devs[i].dev; i++) { 661 if (ds_devs[i].dev == dev && 662 (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0)) 663 return i; 664 } 665 return -1; 666} 667 668static int 669ds_pci_probe(device_t dev) 670{ 671 int i; 672 u_int32_t subdev; 673 674 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 675 i = ds_finddev(pci_get_devid(dev), subdev); 676 if (i >= 0) { 677 device_set_desc(dev, ds_devs[i].name); 678 return 0; 679 } else 680 return ENXIO; 681} 682 683static int 684ds_pci_attach(device_t dev) 685{ 686 snddev_info *d; 687 u_int32_t data; 688 u_int32_t subdev, i; 689 struct sc_info *sc; 690 struct ac97_info *codec; 691 char status[SND_STATUSLEN]; 692 693 d = device_get_softc(dev); 694 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { 695 device_printf(dev, "cannot allocate softc\n"); 696 return ENXIO; 697 } 698 699 bzero(sc, sizeof(*sc)); 700 sc->dev = dev; 701 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 702 sc->type = ds_finddev(pci_get_devid(dev), subdev); 703 sc->rev = pci_get_revid(dev); 704 705 data = pci_read_config(dev, PCIR_COMMAND, 2); 706 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 707 pci_write_config(dev, PCIR_COMMAND, data, 2); 708 data = pci_read_config(dev, PCIR_COMMAND, 2); 709 710 sc->regid = PCIR_MAPS; 711 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, 712 0, ~0, 1, RF_ACTIVE); 713 if (!sc->reg) { 714 device_printf(dev, "unable to map register space\n"); 715 goto bad; 716 } 717 718 sc->st = rman_get_bustag(sc->reg); 719 sc->sh = rman_get_bushandle(sc->reg); 720 721 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 722 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 723 /*highaddr*/BUS_SPACE_MAXADDR, 724 /*filter*/NULL, /*filterarg*/NULL, 725 /*maxsize*/65536, /*nsegments*/1, /*maxsegz*/0x3ffff, 726 /*flags*/0, &sc->parent_dmat) != 0) { 727 device_printf(dev, "unable to create dma tag\n"); 728 goto bad; 729 } 730 731 if (ds_init(sc) == -1) { 732 device_printf(dev, "unable to initialize the card\n"); 733 goto bad; 734 } 735 736 codec = ac97_create(dev, sc, ds_initcd, ds_rdcd, ds_wrcd); 737 if (codec == NULL) 738 goto bad; 739 mixer_init(d, &ac97_mixer, codec); 740 741 sc->irqid = 0; 742 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 743 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 744 if (!sc->irq || 745 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ds_intr, sc, &sc->ih)) { 746 device_printf(dev, "unable to map interrupt\n"); 747 goto bad; 748 } 749 750 snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld", 751 rman_get_start(sc->reg), rman_get_start(sc->irq)); 752 753 if (pcm_register(dev, sc, DS1_CHANS, 0)) 754 goto bad; 755 for (i = 0; i < DS1_CHANS; i++) 756 pcm_addchan(dev, PCMDIR_PLAY, &ds_chantemplate, sc); 757 /* 758 pcm_addchan(dev, PCMDIR_REC, &ds_chantemplate, sc); 759 */ 760 pcm_setstatus(dev, status); 761 762 return 0; 763 764bad: 765 if (sc->reg) 766 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 767 if (sc->ih) 768 bus_teardown_intr(dev, sc->irq, sc->ih); 769 if (sc->irq) 770 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 771 free(sc, M_DEVBUF); 772 return ENXIO; 773} 774 775static device_method_t ds1_methods[] = { 776 /* Device interface */ 777 DEVMETHOD(device_probe, ds_pci_probe), 778 DEVMETHOD(device_attach, ds_pci_attach), 779 780 { 0, 0 } 781}; 782 783static driver_t ds1_driver = { 784 "pcm", 785 ds1_methods, 786 sizeof(snddev_info), 787}; 788 789static devclass_t pcm_devclass; 790 791DRIVER_MODULE(ds1, pci, ds1_driver, pcm_devclass, 0, 0); 792