1 /*- 2 * Copyright (c) 2001 Orion Hodson <oho@acm.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * als4000.c - driver for the Avance Logic ALS 4000 chipset. 29 * 30 * The ALS4000 is effectively an SB16 with a PCI interface. 31 * 32 * This driver derives from ALS4000a.PDF, Bart Hartgers alsa driver, and 33 * SB16 register descriptions. 34 */ 35 36 #ifdef HAVE_KERNEL_OPTION_HEADERS 37 #include "opt_snd.h" 38 #endif 39 40 #include <dev/sound/pcm/sound.h> 41 #include <dev/sound/pci/sb.h> 42 #include <dev/sound/pci/als4000.h> 43 44 #include <bus/pci/pcireg.h> 45 #include <bus/pci/pcivar.h> 46 47 #include "mixer_if.h" 48 49 SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/als4000.c 274035 2014-11-03 11:11:45Z bapt $"); 50 51 /* Debugging macro's */ 52 #undef DEB 53 #ifndef DEB 54 #define DEB(x) /* x */ 55 #endif /* DEB */ 56 57 #define ALS_DEFAULT_BUFSZ 16384 58 59 /* ------------------------------------------------------------------------- */ 60 /* Structures */ 61 62 struct sc_info; 63 64 struct sc_chinfo { 65 struct sc_info *parent; 66 struct pcm_channel *channel; 67 struct snd_dbuf *buffer; 68 u_int32_t format, speed, phys_buf, bps; 69 u_int32_t dma_active:1, dma_was_active:1; 70 u_int8_t gcr_fifo_status; 71 int dir; 72 }; 73 74 struct sc_info { 75 device_t dev; 76 bus_space_tag_t st; 77 bus_space_handle_t sh; 78 bus_dma_tag_t parent_dmat; 79 struct resource *reg, *irq; 80 int regid, irqid; 81 void *ih; 82 struct lock *lock; 83 84 unsigned int bufsz; 85 struct sc_chinfo pch, rch; 86 }; 87 88 /* Channel caps */ 89 90 static u_int32_t als_format[] = { 91 SND_FORMAT(AFMT_U8, 1, 0), 92 SND_FORMAT(AFMT_U8, 2, 0), 93 SND_FORMAT(AFMT_S16_LE, 1, 0), 94 SND_FORMAT(AFMT_S16_LE, 2, 0), 95 0 96 }; 97 98 /* 99 * I don't believe this rotten soundcard can do 48k, really, 100 * trust me. 101 */ 102 static struct pcmchan_caps als_caps = { 4000, 44100, als_format, 0 }; 103 104 /* ------------------------------------------------------------------------- */ 105 /* Register Utilities */ 106 107 static u_int32_t 108 als_gcr_rd(struct sc_info *sc, int index) 109 { 110 bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index); 111 return bus_space_read_4(sc->st, sc->sh, ALS_GCR_DATA); 112 } 113 114 static void 115 als_gcr_wr(struct sc_info *sc, int index, int data) 116 { 117 bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index); 118 bus_space_write_4(sc->st, sc->sh, ALS_GCR_DATA, data); 119 } 120 121 static u_int8_t 122 als_intr_rd(struct sc_info *sc) 123 { 124 return bus_space_read_1(sc->st, sc->sh, ALS_SB_MPU_IRQ); 125 } 126 127 static void 128 als_intr_wr(struct sc_info *sc, u_int8_t data) 129 { 130 bus_space_write_1(sc->st, sc->sh, ALS_SB_MPU_IRQ, data); 131 } 132 133 static u_int8_t 134 als_mix_rd(struct sc_info *sc, u_int8_t index) 135 { 136 bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index); 137 return bus_space_read_1(sc->st, sc->sh, ALS_MIXER_DATA); 138 } 139 140 static void 141 als_mix_wr(struct sc_info *sc, u_int8_t index, u_int8_t data) 142 { 143 bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index); 144 bus_space_write_1(sc->st, sc->sh, ALS_MIXER_DATA, data); 145 } 146 147 static void 148 als_esp_wr(struct sc_info *sc, u_int8_t data) 149 { 150 u_int32_t tries, v; 151 152 tries = 1000; 153 do { 154 v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_WR_STATUS); 155 if (~v & 0x80) 156 break; 157 DELAY(20); 158 } while (--tries != 0); 159 160 if (tries == 0) 161 device_printf(sc->dev, "als_esp_wr timeout"); 162 163 bus_space_write_1(sc->st, sc->sh, ALS_ESP_WR_DATA, data); 164 } 165 166 static int 167 als_esp_reset(struct sc_info *sc) 168 { 169 u_int32_t tries, u, v; 170 171 bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 1); 172 DELAY(10); 173 bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 0); 174 DELAY(30); 175 176 tries = 1000; 177 do { 178 u = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_STATUS8); 179 if (u & 0x80) { 180 v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_DATA); 181 if (v == 0xaa) 182 return 0; 183 else 184 break; 185 } 186 DELAY(20); 187 } while (--tries != 0); 188 189 if (tries == 0) 190 device_printf(sc->dev, "als_esp_reset timeout"); 191 return 1; 192 } 193 194 static u_int8_t 195 als_ack_read(struct sc_info *sc, u_int8_t addr) 196 { 197 u_int8_t r = bus_space_read_1(sc->st, sc->sh, addr); 198 return r; 199 } 200 201 /* ------------------------------------------------------------------------- */ 202 /* Common pcm channel implementation */ 203 204 static void * 205 alschan_init(kobj_t obj, void *devinfo, 206 struct snd_dbuf *b, struct pcm_channel *c, int dir) 207 { 208 struct sc_info *sc = devinfo; 209 struct sc_chinfo *ch; 210 211 snd_mtxlock(sc->lock); 212 if (dir == PCMDIR_PLAY) { 213 ch = &sc->pch; 214 ch->gcr_fifo_status = ALS_GCR_FIFO0_STATUS; 215 } else { 216 ch = &sc->rch; 217 ch->gcr_fifo_status = ALS_GCR_FIFO1_STATUS; 218 } 219 ch->dir = dir; 220 ch->parent = sc; 221 ch->channel = c; 222 ch->bps = 1; 223 ch->format = SND_FORMAT(AFMT_U8, 1, 0); 224 ch->speed = DSP_DEFAULT_SPEED; 225 ch->buffer = b; 226 snd_mtxunlock(sc->lock); 227 228 if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) 229 return NULL; 230 231 return ch; 232 } 233 234 static int 235 alschan_setformat(kobj_t obj, void *data, u_int32_t format) 236 { 237 struct sc_chinfo *ch = data; 238 239 ch->format = format; 240 return 0; 241 } 242 243 static u_int32_t 244 alschan_setspeed(kobj_t obj, void *data, u_int32_t speed) 245 { 246 struct sc_chinfo *ch = data, *other; 247 struct sc_info *sc = ch->parent; 248 249 other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch; 250 251 /* Deny request if other dma channel is active */ 252 if (other->dma_active) { 253 ch->speed = other->speed; 254 return other->speed; 255 } 256 257 ch->speed = speed; 258 return speed; 259 } 260 261 static u_int32_t 262 alschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 263 { 264 struct sc_chinfo *ch = data; 265 struct sc_info *sc = ch->parent; 266 267 if (blocksize > sc->bufsz / 2) { 268 blocksize = sc->bufsz / 2; 269 } 270 sndbuf_resize(ch->buffer, 2, blocksize); 271 return blocksize; 272 } 273 274 static u_int32_t 275 alschan_getptr(kobj_t obj, void *data) 276 { 277 struct sc_chinfo *ch = data; 278 struct sc_info *sc = ch->parent; 279 int32_t pos, sz; 280 281 snd_mtxlock(sc->lock); 282 pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff; 283 snd_mtxunlock(sc->lock); 284 sz = sndbuf_getsize(ch->buffer); 285 return (2 * sz - pos - 1) % sz; 286 } 287 288 static struct pcmchan_caps* 289 alschan_getcaps(kobj_t obj, void *data) 290 { 291 return &als_caps; 292 } 293 294 static void 295 als_set_speed(struct sc_chinfo *ch) 296 { 297 struct sc_info *sc = ch->parent; 298 struct sc_chinfo *other; 299 300 other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch; 301 if (other->dma_active == 0) { 302 als_esp_wr(sc, ALS_ESP_SAMPLE_RATE); 303 als_esp_wr(sc, ch->speed >> 8); 304 als_esp_wr(sc, ch->speed & 0xff); 305 } else { 306 DEB(printf("speed locked at %d (tried %d)\n", 307 other->speed, ch->speed)); 308 } 309 } 310 311 /* ------------------------------------------------------------------------- */ 312 /* Playback channel implementation */ 313 314 #define ALS_8BIT_CMD(x, y) { (x), (y), DSP_DMA8, DSP_CMD_DMAPAUSE_8 } 315 #define ALS_16BIT_CMD(x, y) { (x), (y), DSP_DMA16, DSP_CMD_DMAPAUSE_16 } 316 317 struct playback_command { 318 u_int32_t pcm_format; /* newpcm format */ 319 u_int8_t format_val; /* sb16 format value */ 320 u_int8_t dma_prog; /* sb16 dma program */ 321 u_int8_t dma_stop; /* sb16 stop register */ 322 }; 323 324 static const struct playback_command playback_cmds[] = { 325 ALS_8BIT_CMD(SND_FORMAT(AFMT_U8, 1, 0), DSP_MODE_U8MONO), 326 ALS_8BIT_CMD(SND_FORMAT(AFMT_U8, 2, 0), DSP_MODE_U8STEREO), 327 ALS_16BIT_CMD(SND_FORMAT(AFMT_S16_LE, 1, 0), DSP_MODE_S16MONO), 328 ALS_16BIT_CMD(SND_FORMAT(AFMT_S16_LE, 2, 0), DSP_MODE_S16STEREO), 329 }; 330 331 static const struct playback_command* 332 als_get_playback_command(u_int32_t format) 333 { 334 u_int32_t i, n; 335 336 n = sizeof(playback_cmds) / sizeof(playback_cmds[0]); 337 for (i = 0; i < n; i++) { 338 if (playback_cmds[i].pcm_format == format) { 339 return &playback_cmds[i]; 340 } 341 } 342 DEB(printf("als_get_playback_command: invalid format 0x%08x\n", 343 format)); 344 return &playback_cmds[0]; 345 } 346 347 static void 348 als_playback_start(struct sc_chinfo *ch) 349 { 350 const struct playback_command *p; 351 struct sc_info *sc = ch->parent; 352 u_int32_t buf, bufsz, count, dma_prog; 353 354 buf = sndbuf_getbufaddr(ch->buffer); 355 bufsz = sndbuf_getsize(ch->buffer); 356 count = bufsz / 2; 357 if (ch->format & AFMT_16BIT) 358 count /= 2; 359 count--; 360 361 als_esp_wr(sc, DSP_CMD_SPKON); 362 als_set_speed(ch); 363 364 als_gcr_wr(sc, ALS_GCR_DMA0_START, buf); 365 als_gcr_wr(sc, ALS_GCR_DMA0_MODE, (bufsz - 1) | 0x180000); 366 367 p = als_get_playback_command(ch->format); 368 dma_prog = p->dma_prog | DSP_F16_DAC | DSP_F16_AUTO | DSP_F16_FIFO_ON; 369 370 als_esp_wr(sc, dma_prog); 371 als_esp_wr(sc, p->format_val); 372 als_esp_wr(sc, count & 0xff); 373 als_esp_wr(sc, count >> 8); 374 375 ch->dma_active = 1; 376 } 377 378 static int 379 als_playback_stop(struct sc_chinfo *ch) 380 { 381 const struct playback_command *p; 382 struct sc_info *sc = ch->parent; 383 u_int32_t active; 384 385 active = ch->dma_active; 386 if (active) { 387 p = als_get_playback_command(ch->format); 388 als_esp_wr(sc, p->dma_stop); 389 } 390 ch->dma_active = 0; 391 return active; 392 } 393 394 static int 395 alspchan_trigger(kobj_t obj, void *data, int go) 396 { 397 struct sc_chinfo *ch = data; 398 struct sc_info *sc = ch->parent; 399 400 if (!PCMTRIG_COMMON(go)) 401 return 0; 402 403 snd_mtxlock(sc->lock); 404 switch(go) { 405 case PCMTRIG_START: 406 als_playback_start(ch); 407 break; 408 case PCMTRIG_STOP: 409 case PCMTRIG_ABORT: 410 als_playback_stop(ch); 411 break; 412 default: 413 break; 414 } 415 snd_mtxunlock(sc->lock); 416 return 0; 417 } 418 419 static kobj_method_t alspchan_methods[] = { 420 KOBJMETHOD(channel_init, alschan_init), 421 KOBJMETHOD(channel_setformat, alschan_setformat), 422 KOBJMETHOD(channel_setspeed, alschan_setspeed), 423 KOBJMETHOD(channel_setblocksize, alschan_setblocksize), 424 KOBJMETHOD(channel_trigger, alspchan_trigger), 425 KOBJMETHOD(channel_getptr, alschan_getptr), 426 KOBJMETHOD(channel_getcaps, alschan_getcaps), 427 KOBJMETHOD_END 428 }; 429 CHANNEL_DECLARE(alspchan); 430 431 /* ------------------------------------------------------------------------- */ 432 /* Capture channel implementation */ 433 434 static u_int8_t 435 als_get_fifo_format(struct sc_info *sc, u_int32_t format) 436 { 437 switch (format) { 438 case SND_FORMAT(AFMT_U8, 1, 0): 439 return ALS_FIFO1_8BIT; 440 case SND_FORMAT(AFMT_U8, 2, 0): 441 return ALS_FIFO1_8BIT | ALS_FIFO1_STEREO; 442 case SND_FORMAT(AFMT_S16_LE, 1, 0): 443 return ALS_FIFO1_SIGNED; 444 case SND_FORMAT(AFMT_S16_LE, 2, 0): 445 return ALS_FIFO1_SIGNED | ALS_FIFO1_STEREO; 446 } 447 device_printf(sc->dev, "format not found: 0x%08x\n", format); 448 return ALS_FIFO1_8BIT; 449 } 450 451 static void 452 als_capture_start(struct sc_chinfo *ch) 453 { 454 struct sc_info *sc = ch->parent; 455 u_int32_t buf, bufsz, count, dma_prog; 456 457 buf = sndbuf_getbufaddr(ch->buffer); 458 bufsz = sndbuf_getsize(ch->buffer); 459 count = bufsz / 2; 460 if (ch->format & AFMT_16BIT) 461 count /= 2; 462 count--; 463 464 als_esp_wr(sc, DSP_CMD_SPKON); 465 als_set_speed(ch); 466 467 als_gcr_wr(sc, ALS_GCR_FIFO1_START, buf); 468 als_gcr_wr(sc, ALS_GCR_FIFO1_COUNT, (bufsz - 1)); 469 470 als_mix_wr(sc, ALS_FIFO1_LENGTH_LO, count & 0xff); 471 als_mix_wr(sc, ALS_FIFO1_LENGTH_HI, count >> 8); 472 473 dma_prog = ALS_FIFO1_RUN | als_get_fifo_format(sc, ch->format); 474 als_mix_wr(sc, ALS_FIFO1_CONTROL, dma_prog); 475 476 ch->dma_active = 1; 477 } 478 479 static int 480 als_capture_stop(struct sc_chinfo *ch) 481 { 482 struct sc_info *sc = ch->parent; 483 u_int32_t active; 484 485 active = ch->dma_active; 486 if (active) { 487 als_mix_wr(sc, ALS_FIFO1_CONTROL, ALS_FIFO1_STOP); 488 } 489 ch->dma_active = 0; 490 return active; 491 } 492 493 static int 494 alsrchan_trigger(kobj_t obj, void *data, int go) 495 { 496 struct sc_chinfo *ch = data; 497 struct sc_info *sc = ch->parent; 498 499 snd_mtxlock(sc->lock); 500 switch(go) { 501 case PCMTRIG_START: 502 als_capture_start(ch); 503 break; 504 case PCMTRIG_STOP: 505 case PCMTRIG_ABORT: 506 als_capture_stop(ch); 507 break; 508 } 509 snd_mtxunlock(sc->lock); 510 return 0; 511 } 512 513 static kobj_method_t alsrchan_methods[] = { 514 KOBJMETHOD(channel_init, alschan_init), 515 KOBJMETHOD(channel_setformat, alschan_setformat), 516 KOBJMETHOD(channel_setspeed, alschan_setspeed), 517 KOBJMETHOD(channel_setblocksize, alschan_setblocksize), 518 KOBJMETHOD(channel_trigger, alsrchan_trigger), 519 KOBJMETHOD(channel_getptr, alschan_getptr), 520 KOBJMETHOD(channel_getcaps, alschan_getcaps), 521 KOBJMETHOD_END 522 }; 523 CHANNEL_DECLARE(alsrchan); 524 525 /* ------------------------------------------------------------------------- */ 526 /* Mixer related */ 527 528 /* 529 * ALS4000 has an sb16 mixer, with some additional controls that we do 530 * not yet a means to support. 531 */ 532 533 struct sb16props { 534 u_int8_t lreg; 535 u_int8_t rreg; 536 u_int8_t bits; 537 u_int8_t oselect; 538 u_int8_t iselect; /* left input mask */ 539 }; 540 541 static const struct sb16props amt[SOUND_MIXER_NRDEVICES] = { 542 [SOUND_MIXER_VOLUME] = { 0x30, 0x31, 5, 0x00, 0x00 }, 543 [SOUND_MIXER_PCM] = { 0x32, 0x33, 5, 0x00, 0x00 }, 544 [SOUND_MIXER_SYNTH] = { 0x34, 0x35, 5, 0x60, 0x40 }, 545 [SOUND_MIXER_CD] = { 0x36, 0x37, 5, 0x06, 0x04 }, 546 [SOUND_MIXER_LINE] = { 0x38, 0x39, 5, 0x18, 0x10 }, 547 [SOUND_MIXER_MIC] = { 0x3a, 0x00, 5, 0x01, 0x01 }, 548 [SOUND_MIXER_SPEAKER] = { 0x3b, 0x00, 2, 0x00, 0x00 }, 549 [SOUND_MIXER_IGAIN] = { 0x3f, 0x40, 2, 0x00, 0x00 }, 550 [SOUND_MIXER_OGAIN] = { 0x41, 0x42, 2, 0x00, 0x00 }, 551 /* The following have register values but no h/w implementation */ 552 [SOUND_MIXER_TREBLE] = { 0x44, 0x45, 4, 0x00, 0x00 }, 553 [SOUND_MIXER_BASS] = { 0x46, 0x47, 4, 0x00, 0x00 } 554 }; 555 556 static int 557 alsmix_init(struct snd_mixer *m) 558 { 559 u_int32_t i, v; 560 561 for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { 562 if (amt[i].bits) v |= 1 << i; 563 } 564 mix_setdevs(m, v); 565 566 for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { 567 if (amt[i].iselect) v |= 1 << i; 568 } 569 mix_setrecdevs(m, v); 570 return 0; 571 } 572 573 static int 574 alsmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 575 { 576 struct sc_info *sc = mix_getdevinfo(m); 577 u_int32_t r, l, v, mask; 578 579 /* Fill upper n bits in mask with 1's */ 580 mask = ((1 << amt[dev].bits) - 1) << (8 - amt[dev].bits); 581 582 l = (left * mask / 100) & mask; 583 v = als_mix_rd(sc, amt[dev].lreg) & ~mask; 584 als_mix_wr(sc, amt[dev].lreg, l | v); 585 586 if (amt[dev].rreg) { 587 r = (right * mask / 100) & mask; 588 v = als_mix_rd(sc, amt[dev].rreg) & ~mask; 589 als_mix_wr(sc, amt[dev].rreg, r | v); 590 } else { 591 r = 0; 592 } 593 594 /* Zero gain does not mute channel from output, but this does. */ 595 v = als_mix_rd(sc, SB16_OMASK); 596 if (l == 0 && r == 0) { 597 v &= ~amt[dev].oselect; 598 } else { 599 v |= amt[dev].oselect; 600 } 601 als_mix_wr(sc, SB16_OMASK, v); 602 return 0; 603 } 604 605 static u_int32_t 606 alsmix_setrecsrc(struct snd_mixer *m, u_int32_t src) 607 { 608 struct sc_info *sc = mix_getdevinfo(m); 609 u_int32_t i, l, r; 610 611 for (i = l = r = 0; i < SOUND_MIXER_NRDEVICES; i++) { 612 if (src & (1 << i)) { 613 if (amt[i].iselect == 1) { /* microphone */ 614 l |= amt[i].iselect; 615 r |= amt[i].iselect; 616 } else { 617 l |= amt[i].iselect; 618 r |= amt[i].iselect >> 1; 619 } 620 } 621 } 622 623 als_mix_wr(sc, SB16_IMASK_L, l); 624 als_mix_wr(sc, SB16_IMASK_R, r); 625 return src; 626 } 627 628 static kobj_method_t als_mixer_methods[] = { 629 KOBJMETHOD(mixer_init, alsmix_init), 630 KOBJMETHOD(mixer_set, alsmix_set), 631 KOBJMETHOD(mixer_setrecsrc, alsmix_setrecsrc), 632 KOBJMETHOD_END 633 }; 634 MIXER_DECLARE(als_mixer); 635 636 /* ------------------------------------------------------------------------- */ 637 /* Interrupt Handler */ 638 639 static void 640 als_intr(void *p) 641 { 642 struct sc_info *sc = (struct sc_info *)p; 643 u_int8_t intr, sb_status; 644 645 snd_mtxlock(sc->lock); 646 intr = als_intr_rd(sc); 647 648 if (intr & 0x80) { 649 snd_mtxunlock(sc->lock); 650 chn_intr(sc->pch.channel); 651 snd_mtxlock(sc->lock); 652 } 653 654 if (intr & 0x40) { 655 snd_mtxunlock(sc->lock); 656 chn_intr(sc->rch.channel); 657 snd_mtxlock(sc->lock); 658 } 659 660 /* ACK interrupt in PCI core */ 661 als_intr_wr(sc, intr); 662 663 /* ACK interrupt in SB core */ 664 sb_status = als_mix_rd(sc, IRQ_STAT); 665 666 if (sb_status & ALS_IRQ_STATUS8) 667 als_ack_read(sc, ALS_ESP_RD_STATUS8); 668 if (sb_status & ALS_IRQ_STATUS16) 669 als_ack_read(sc, ALS_ESP_RD_STATUS16); 670 if (sb_status & ALS_IRQ_MPUIN) 671 als_ack_read(sc, ALS_MIDI_DATA); 672 if (sb_status & ALS_IRQ_CR1E) 673 als_ack_read(sc, ALS_CR1E_ACK_PORT); 674 675 snd_mtxunlock(sc->lock); 676 return; 677 } 678 679 /* ------------------------------------------------------------------------- */ 680 /* H/W initialization */ 681 682 static int 683 als_init(struct sc_info *sc) 684 { 685 u_int32_t i, v; 686 687 /* Reset Chip */ 688 if (als_esp_reset(sc)) { 689 return 1; 690 } 691 692 /* Enable write on DMA_SETUP register */ 693 v = als_mix_rd(sc, ALS_SB16_CONFIG); 694 als_mix_wr(sc, ALS_SB16_CONFIG, v | 0x80); 695 696 /* Select DMA0 */ 697 als_mix_wr(sc, ALS_SB16_DMA_SETUP, 0x01); 698 699 /* Disable write on DMA_SETUP register */ 700 als_mix_wr(sc, ALS_SB16_CONFIG, v & 0x7f); 701 702 /* Enable interrupts */ 703 v = als_gcr_rd(sc, ALS_GCR_MISC); 704 als_gcr_wr(sc, ALS_GCR_MISC, v | 0x28000); 705 706 /* Black out GCR DMA registers */ 707 for (i = 0x91; i <= 0x96; i++) { 708 als_gcr_wr(sc, i, 0); 709 } 710 711 /* Emulation mode */ 712 v = als_gcr_rd(sc, ALS_GCR_DMA_EMULATION); 713 als_gcr_wr(sc, ALS_GCR_DMA_EMULATION, v); 714 DEB(printf("GCR_DMA_EMULATION 0x%08x\n", v)); 715 return 0; 716 } 717 718 static void 719 als_uninit(struct sc_info *sc) 720 { 721 /* Disable interrupts */ 722 als_gcr_wr(sc, ALS_GCR_MISC, 0); 723 } 724 725 /* ------------------------------------------------------------------------- */ 726 /* Probe and attach card */ 727 728 static int 729 als_pci_probe(device_t dev) 730 { 731 if (pci_get_devid(dev) == ALS_PCI_ID0) { 732 device_set_desc(dev, "Avance Logic ALS4000"); 733 return BUS_PROBE_DEFAULT; 734 } 735 return ENXIO; 736 } 737 738 static void 739 als_resource_free(device_t dev, struct sc_info *sc) 740 { 741 if (sc->reg) { 742 bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg); 743 sc->reg = 0; 744 } 745 if (sc->ih) { 746 bus_teardown_intr(dev, sc->irq, sc->ih); 747 sc->ih = 0; 748 } 749 if (sc->irq) { 750 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 751 sc->irq = 0; 752 } 753 if (sc->parent_dmat) { 754 bus_dma_tag_destroy(sc->parent_dmat); 755 sc->parent_dmat = 0; 756 } 757 if (sc->lock) { 758 snd_mtxfree(sc->lock); 759 sc->lock = NULL; 760 } 761 } 762 763 static int 764 als_resource_grab(device_t dev, struct sc_info *sc) 765 { 766 sc->regid = PCIR_BAR(0); 767 sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->regid, 0, ~0, 768 ALS_CONFIG_SPACE_BYTES, RF_ACTIVE); 769 if (sc->reg == 0) { 770 device_printf(dev, "unable to allocate register space\n"); 771 goto bad; 772 } 773 sc->st = rman_get_bustag(sc->reg); 774 sc->sh = rman_get_bushandle(sc->reg); 775 776 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 777 RF_ACTIVE | RF_SHAREABLE); 778 if (sc->irq == 0) { 779 device_printf(dev, "unable to allocate interrupt\n"); 780 goto bad; 781 } 782 783 if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, als_intr, 784 sc, &sc->ih)) { 785 device_printf(dev, "unable to setup interrupt\n"); 786 goto bad; 787 } 788 789 sc->bufsz = pcm_getbuffersize(dev, 4096, ALS_DEFAULT_BUFSZ, 65536); 790 791 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), 792 /*alignment*/2, /*boundary*/0, 793 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 794 /*highaddr*/BUS_SPACE_MAXADDR, 795 /*filter*/NULL, /*filterarg*/NULL, 796 /*maxsize*/sc->bufsz, 797 /*nsegments*/1, /*maxsegz*/0x3ffff, 798 /*flags*/0, 799 &sc->parent_dmat) != 0) { 800 device_printf(dev, "unable to create dma tag\n"); 801 goto bad; 802 } 803 return 0; 804 bad: 805 als_resource_free(dev, sc); 806 return ENXIO; 807 } 808 809 static int 810 als_pci_attach(device_t dev) 811 { 812 struct sc_info *sc; 813 char status[SND_STATUSLEN]; 814 815 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 816 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_als4000 softc"); 817 sc->dev = dev; 818 819 pci_enable_busmaster(dev); 820 /* 821 * By default the power to the various components on the 822 * ALS4000 is entirely controlled by the pci powerstate. We 823 * could attempt finer grained control by setting GCR6.31. 824 */ 825 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 826 /* Reset the power state. */ 827 device_printf(dev, "chip is in D%d power mode " 828 "-- setting to D0\n", pci_get_powerstate(dev)); 829 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 830 } 831 832 if (als_resource_grab(dev, sc)) { 833 device_printf(dev, "failed to allocate resources\n"); 834 goto bad_attach; 835 } 836 837 if (als_init(sc)) { 838 device_printf(dev, "failed to initialize hardware\n"); 839 goto bad_attach; 840 } 841 842 if (mixer_init(dev, &als_mixer_class, sc)) { 843 device_printf(dev, "failed to initialize mixer\n"); 844 goto bad_attach; 845 } 846 847 if (pcm_register(dev, sc, 1, 1)) { 848 device_printf(dev, "failed to register pcm entries\n"); 849 goto bad_attach; 850 } 851 852 pcm_addchan(dev, PCMDIR_PLAY, &alspchan_class, sc); 853 pcm_addchan(dev, PCMDIR_REC, &alsrchan_class, sc); 854 855 ksnprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", 856 rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_als4000)); 857 pcm_setstatus(dev, status); 858 return 0; 859 860 bad_attach: 861 als_resource_free(dev, sc); 862 kfree(sc, M_DEVBUF); 863 return ENXIO; 864 } 865 866 static int 867 als_pci_detach(device_t dev) 868 { 869 struct sc_info *sc; 870 int r; 871 872 r = pcm_unregister(dev); 873 if (r) 874 return r; 875 876 sc = pcm_getdevinfo(dev); 877 als_uninit(sc); 878 als_resource_free(dev, sc); 879 kfree(sc, M_DEVBUF); 880 return 0; 881 } 882 883 static int 884 als_pci_suspend(device_t dev) 885 { 886 struct sc_info *sc = pcm_getdevinfo(dev); 887 888 snd_mtxlock(sc->lock); 889 sc->pch.dma_was_active = als_playback_stop(&sc->pch); 890 sc->rch.dma_was_active = als_capture_stop(&sc->rch); 891 als_uninit(sc); 892 snd_mtxunlock(sc->lock); 893 return 0; 894 } 895 896 static int 897 als_pci_resume(device_t dev) 898 { 899 struct sc_info *sc = pcm_getdevinfo(dev); 900 901 902 snd_mtxlock(sc->lock); 903 if (als_init(sc) != 0) { 904 device_printf(dev, "unable to reinitialize the card\n"); 905 snd_mtxunlock(sc->lock); 906 return ENXIO; 907 } 908 909 if (mixer_reinit(dev) != 0) { 910 device_printf(dev, "unable to reinitialize the mixer\n"); 911 snd_mtxunlock(sc->lock); 912 return ENXIO; 913 } 914 915 if (sc->pch.dma_was_active) { 916 als_playback_start(&sc->pch); 917 } 918 919 if (sc->rch.dma_was_active) { 920 als_capture_start(&sc->rch); 921 } 922 snd_mtxunlock(sc->lock); 923 924 return 0; 925 } 926 927 static device_method_t als_methods[] = { 928 /* Device interface */ 929 DEVMETHOD(device_probe, als_pci_probe), 930 DEVMETHOD(device_attach, als_pci_attach), 931 DEVMETHOD(device_detach, als_pci_detach), 932 DEVMETHOD(device_suspend, als_pci_suspend), 933 DEVMETHOD(device_resume, als_pci_resume), 934 { 0, 0 } 935 }; 936 937 static driver_t als_driver = { 938 "pcm", 939 als_methods, 940 PCM_SOFTC_SIZE, 941 }; 942 943 DRIVER_MODULE(snd_als4000, pci, als_driver, pcm_devclass, 0, 0); 944 MODULE_DEPEND(snd_als4000, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 945 MODULE_VERSION(snd_als4000, 1); 946