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