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