1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Purpose: Driver for the Creative P16X AC97 audio controller 29 */ 30 /* 31 * 32 * Copyright (C) 4Front Technologies 1996-2009. 33 * 34 * This software is released under CDDL 1.0 source license. 35 * See the COPYING file included in the main directory of this source 36 * distribution for the license terms and conditions. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/modctl.h> 41 #include <sys/kmem.h> 42 #include <sys/conf.h> 43 #include <sys/ddi.h> 44 #include <sys/sunddi.h> 45 #include <sys/pci.h> 46 #include <sys/note.h> 47 #include <sys/audio/audio_driver.h> 48 #include <sys/audio/ac97.h> 49 50 #include "audiop16x.h" 51 52 /* 53 * These boards use an AC'97 codec, but don't have all of the 54 * various outputs that the AC'97 codec can offer. We just 55 * suppress them for now. 56 */ 57 static char *p16x_remove_ac97[] = { 58 AUDIO_CTRL_ID_BEEP, 59 AUDIO_CTRL_ID_VIDEO, 60 AUDIO_CTRL_ID_MICSRC, 61 AUDIO_CTRL_ID_SPEAKER, 62 AUDIO_CTRL_ID_SPKSRC, 63 NULL 64 }; 65 66 static struct ddi_device_acc_attr dev_attr = { 67 DDI_DEVICE_ATTR_V0, 68 DDI_STRUCTURE_LE_ACC, 69 DDI_STRICTORDER_ACC 70 }; 71 72 static struct ddi_device_acc_attr buf_attr = { 73 DDI_DEVICE_ATTR_V0, 74 DDI_NEVERSWAP_ACC, 75 DDI_STRICTORDER_ACC 76 }; 77 78 static ddi_dma_attr_t dma_attr_buf = { 79 DMA_ATTR_V0, /* version number */ 80 0x00000000, /* low DMA address range */ 81 0xffffffff, /* high DMA address range */ 82 0xfffffffe, /* DMA counter register */ 83 4, /* DMA address alignment */ 84 0x3c, /* DMA burstsizes */ 85 4, /* min effective DMA size */ 86 0xffffffff, /* max DMA xfer size */ 87 0xffffffff, /* segment boundary */ 88 1, /* s/g length */ 89 4, /* granularity of device */ 90 0 /* Bus specific DMA flags */ 91 }; 92 93 static int p16x_attach(dev_info_t *); 94 static int p16x_resume(dev_info_t *); 95 static int p16x_detach(p16x_dev_t *); 96 static int p16x_suspend(p16x_dev_t *); 97 98 static int p16x_open(void *, int, unsigned *, unsigned *, caddr_t *); 99 static void p16x_close(void *); 100 static int p16x_start(void *); 101 static void p16x_stop(void *); 102 static int p16x_format(void *); 103 static int p16x_channels(void *); 104 static int p16x_rate(void *); 105 static uint64_t p16x_count(void *); 106 static void p16x_sync(void *, unsigned); 107 static size_t p16x_qlen(void *); 108 static void p16x_chinfo(void *, int, unsigned *, unsigned *); 109 110 static uint16_t p16x_read_ac97(void *, uint8_t); 111 static void p16x_write_ac97(void *, uint8_t, uint16_t); 112 static int p16x_alloc_port(p16x_dev_t *, int); 113 static void p16x_update_port(p16x_port_t *); 114 static void p16x_start_port(p16x_port_t *); 115 static void p16x_stop_port(p16x_port_t *); 116 static void p16x_destroy(p16x_dev_t *); 117 static int p16x_setup_intrs(p16x_dev_t *); 118 static void p16x_hwinit(p16x_dev_t *); 119 static uint_t p16x_intr(caddr_t, caddr_t); 120 121 static audio_engine_ops_t p16x_engine_ops = { 122 AUDIO_ENGINE_VERSION, 123 p16x_open, 124 p16x_close, 125 p16x_start, 126 p16x_stop, 127 p16x_count, 128 p16x_format, 129 p16x_channels, 130 p16x_rate, 131 p16x_sync, 132 p16x_qlen, 133 p16x_chinfo, 134 }; 135 136 static unsigned int 137 read_reg(p16x_dev_t *dev, int reg, int chn) 138 { 139 unsigned int val; 140 141 mutex_enter(&dev->low_mutex); 142 OUTL(dev, (reg << 16) | (chn & 0xffff), PTR); /* Pointer */ 143 val = INL(dev, DR); /* Data */ 144 mutex_exit(&dev->low_mutex); 145 146 return (val); 147 } 148 149 static void 150 write_reg(p16x_dev_t *dev, int reg, int chn, unsigned int value) 151 { 152 153 mutex_enter(&dev->low_mutex); 154 OUTL(dev, (reg << 16) | (chn & 0xffff), PTR); /* Pointer */ 155 OUTL(dev, value, DR); /* Data */ 156 mutex_exit(&dev->low_mutex); 157 } 158 159 static uint16_t 160 p16x_read_ac97(void *arg, uint8_t index) 161 { 162 p16x_dev_t *dev = arg; 163 uint16_t value; 164 int i; 165 166 mutex_enter(&dev->low_mutex); 167 OUTB(dev, index, AC97A); 168 for (i = 0; i < 10000; i++) 169 if (INB(dev, AC97A) & 0x80) 170 break; 171 value = INW(dev, AC97D); 172 mutex_exit(&dev->low_mutex); 173 return (value); 174 } 175 176 static void 177 p16x_write_ac97(void *arg, uint8_t index, uint16_t data) 178 { 179 p16x_dev_t *dev = arg; 180 unsigned int i; 181 182 mutex_enter(&dev->low_mutex); 183 OUTB(dev, index, AC97A); 184 for (i = 0; i < 10000; i++) 185 if (INB(dev, AC97A) & 0x80) 186 break; 187 OUTW(dev, data, AC97D); 188 mutex_exit(&dev->low_mutex); 189 } 190 191 static uint_t 192 p16x_intr(caddr_t argp, caddr_t nocare) 193 { 194 p16x_dev_t *dev = (void *)argp; 195 unsigned int status; 196 audio_engine_t *consume = NULL; 197 audio_engine_t *produce = NULL; 198 199 _NOTE(ARGUNUSED(nocare)); 200 201 mutex_enter(&dev->mutex); 202 if (dev->suspended) { 203 mutex_exit(&dev->mutex); 204 return (DDI_INTR_UNCLAIMED); 205 } 206 /* Read the interrupt status */ 207 status = INL(dev, IP); 208 OUTL(dev, status, IP); /* Acknowledge */ 209 210 if (!(status & INTR_ALL)) { 211 mutex_exit(&dev->mutex); 212 return (DDI_INTR_UNCLAIMED); 213 } 214 215 if (status & INTR_PCI) { 216 audio_dev_warn(dev->adev, "PCI error triggered, PCI status %x", 217 pci_config_get16(dev->pcih, PCI_CONF_STAT)); 218 } 219 220 if ((status & (INTR_PFF | INTR_PFH)) && 221 (dev->port[P16X_PLAY]->started)) { 222 consume = dev->port[P16X_PLAY]->engine; 223 } 224 225 if ((status & (INTR_RFF | INTR_RFH)) && 226 (dev->port[P16X_REC]->started)) { 227 produce = dev->port[P16X_REC]->engine; 228 } 229 230 mutex_exit(&dev->mutex); 231 232 if (consume) { 233 audio_engine_consume(consume); 234 } 235 236 if (produce) { 237 audio_engine_produce(produce); 238 } 239 240 return (DDI_INTR_CLAIMED); 241 } 242 243 /* 244 * Audio routines 245 */ 246 247 static void 248 p16x_init_port(p16x_port_t *port) 249 { 250 p16x_dev_t *dev = port->dev; 251 252 if (port->suspended) 253 return; 254 255 if (port->port_num == P16X_REC) { 256 write_reg(dev, CRFA, 0, 0); 257 write_reg(dev, CRCAV, 0, 0); 258 259 } else { 260 for (int i = 0; i < 3; i++) { 261 write_reg(dev, PTBA, i, 0); 262 write_reg(dev, PTBS, i, 0); 263 write_reg(dev, PTCA, i, 0); 264 write_reg(dev, PFEA, i, 0); 265 write_reg(dev, CPFA, i, 0); 266 write_reg(dev, CPCAV, i, 0); 267 } 268 269 } 270 } 271 272 273 static int 274 p16x_open(void *arg, int flag, uint_t *fragfrp, uint_t *nfp, caddr_t *bufp) 275 { 276 p16x_port_t *port = arg; 277 p16x_dev_t *dev = port->dev; 278 279 _NOTE(ARGUNUSED(flag)); 280 281 mutex_enter(&dev->mutex); 282 283 port->started = B_FALSE; 284 port->count = 0; 285 port->offset = 0; 286 287 p16x_init_port(port); 288 289 *fragfrp = port->fragfr; 290 *nfp = port->nfrags; 291 *bufp = port->buf_kaddr; 292 mutex_exit(&dev->mutex); 293 294 return (0); 295 } 296 297 void 298 p16x_close(void *arg) 299 { 300 p16x_port_t *port = arg; 301 p16x_dev_t *dev = port->dev; 302 303 mutex_enter(&dev->mutex); 304 p16x_stop_port(port); 305 port->started = B_FALSE; 306 mutex_exit(&dev->mutex); 307 } 308 309 int 310 p16x_start(void *arg) 311 { 312 p16x_port_t *port = arg; 313 p16x_dev_t *dev = port->dev; 314 315 mutex_enter(&dev->mutex); 316 if (!port->started) { 317 p16x_start_port(port); 318 port->started = B_TRUE; 319 } 320 mutex_exit(&dev->mutex); 321 return (0); 322 } 323 324 void 325 p16x_stop(void *arg) 326 { 327 p16x_port_t *port = arg; 328 p16x_dev_t *dev = port->dev; 329 330 mutex_enter(&dev->mutex); 331 if (port->started) { 332 p16x_stop_port(port); 333 port->started = B_FALSE; 334 } 335 mutex_exit(&dev->mutex); 336 } 337 338 int 339 p16x_format(void *arg) 340 { 341 _NOTE(ARGUNUSED(arg)); 342 343 return (AUDIO_FORMAT_S16_LE); 344 } 345 346 int 347 p16x_channels(void *arg) 348 { 349 p16x_port_t *port = arg; 350 351 return (port->nchan); 352 } 353 354 int 355 p16x_rate(void *arg) 356 { 357 _NOTE(ARGUNUSED(arg)); 358 359 return (48000); 360 } 361 362 void 363 p16x_sync(void *arg, unsigned nframes) 364 { 365 p16x_port_t *port = arg; 366 _NOTE(ARGUNUSED(nframes)); 367 368 (void) ddi_dma_sync(port->buf_dmah, 0, 0, port->syncdir); 369 } 370 371 size_t 372 p16x_qlen(void *arg) 373 { 374 _NOTE(ARGUNUSED(arg)); 375 return (0); 376 } 377 378 uint64_t 379 p16x_count(void *arg) 380 { 381 p16x_port_t *port = arg; 382 p16x_dev_t *dev = port->dev; 383 uint64_t val; 384 385 mutex_enter(&dev->mutex); 386 if (port->started && !dev->suspended) 387 p16x_update_port(port); 388 val = port->count; 389 mutex_exit(&dev->mutex); 390 391 return (val); 392 } 393 394 static void 395 p16x_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr) 396 { 397 p16x_port_t *port = arg; 398 unsigned mult; 399 400 if (port->port_num == P16X_PLAY) { 401 switch (chan) { 402 case 0: /* left front */ 403 case 1: /* right front */ 404 mult = 0; 405 break; 406 case 2: /* center */ 407 case 3: /* lfe */ 408 mult = 2; 409 break; 410 case 4: /* left surround */ 411 case 5: /* right surround */ 412 mult = 1; 413 break; 414 } 415 *offset = (port->buf_frames * 2 * mult) + (chan % 2); 416 *incr = 2; 417 } else { 418 *offset = chan; 419 *incr = 2; 420 } 421 } 422 423 /* private implementation bits */ 424 425 void 426 p16x_update_port(p16x_port_t *port) 427 { 428 p16x_dev_t *dev = port->dev; 429 uint32_t offset, n; 430 431 if (dev->suspended) 432 return; 433 434 if (port->port_num == P16X_PLAY) { 435 offset = read_reg(dev, CPFA, 0); 436 } else { 437 offset = read_reg(dev, CRFA, 0); 438 } 439 440 /* get the offset, and switch to frames */ 441 offset /= (2 * sizeof (uint16_t)); 442 443 if (offset >= port->offset) { 444 n = offset - port->offset; 445 } else { 446 n = offset + (port->buf_frames - port->offset); 447 } 448 port->offset = offset; 449 port->count += n; 450 } 451 452 void 453 p16x_start_port(p16x_port_t *port) 454 { 455 p16x_dev_t *dev = port->dev; 456 unsigned int tmp; 457 458 ASSERT(mutex_owned(&dev->mutex)); 459 460 if (dev->suspended) 461 return; 462 463 if (port->port_num == P16X_REC) { 464 /* Enable Rec Channel */ 465 tmp = read_reg(dev, SA, 0); 466 tmp |= 0x100; 467 write_reg(dev, SA, 0, tmp); 468 tmp = INL(dev, IE); 469 tmp |= INTR_REC; 470 OUTL(dev, tmp, IE); 471 } else { 472 /* Enable play channel and go */ 473 tmp = read_reg(dev, SA, 0); 474 tmp |= 7; 475 write_reg(dev, SA, 0, tmp); 476 tmp = INL(dev, IE); 477 tmp |= INTR_PLAY; 478 OUTL(dev, tmp, IE); 479 } 480 } 481 482 void 483 p16x_stop_port(p16x_port_t *port) 484 { 485 p16x_dev_t *dev = port->dev; 486 unsigned int tmp; 487 488 489 if (dev->suspended) 490 return; 491 492 if (port->port_num == P16X_REC) { 493 /* Disable rec channel */ 494 tmp = read_reg(dev, SA, 0); 495 tmp &= ~0x100; 496 write_reg(dev, SA, 0, tmp); 497 tmp = INL(dev, IE); 498 tmp &= ~INTR_REC; 499 OUTL(dev, tmp, IE); 500 501 } else { 502 /* Disable Play channel */ 503 tmp = read_reg(dev, SA, 0); 504 tmp &= ~7; 505 write_reg(dev, SA, 0, tmp); 506 tmp = INL(dev, IE); 507 tmp &= ~INTR_PLAY; 508 OUTL(dev, tmp, IE); 509 } 510 } 511 512 int 513 p16x_alloc_port(p16x_dev_t *dev, int num) 514 { 515 p16x_port_t *port; 516 size_t len; 517 ddi_dma_cookie_t cookie; 518 uint_t count; 519 int dir; 520 char *prop; 521 unsigned caps; 522 audio_dev_t *adev; 523 524 adev = dev->adev; 525 port = kmem_zalloc(sizeof (*port), KM_SLEEP); 526 dev->port[num] = port; 527 port->dev = dev; 528 port->started = B_FALSE; 529 530 switch (num) { 531 case P16X_REC: 532 prop = "record-interrupts"; 533 port->syncdir = DDI_DMA_SYNC_FORKERNEL; 534 caps = ENGINE_INPUT_CAP; 535 dir = DDI_DMA_READ; 536 port->port_num = P16X_REC; 537 port->nchan = 2; 538 break; 539 case P16X_PLAY: 540 prop = "play-interrupts"; 541 port->syncdir = DDI_DMA_SYNC_FORDEV; 542 caps = ENGINE_OUTPUT_CAP; 543 dir = DDI_DMA_WRITE; 544 port->port_num = P16X_PLAY; 545 port->nchan = 6; 546 break; 547 default: 548 return (DDI_FAILURE); 549 } 550 551 /* figure out fragment configuration */ 552 port->intrs = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip, 553 DDI_PROP_DONTPASS, prop, P16X_DEF_INTRS); 554 555 /* make sure the values are good */ 556 if (port->intrs < P16X_MIN_INTRS) { 557 audio_dev_warn(adev, "%s too low, %d, reset to %d", 558 prop, port->intrs, P16X_MIN_INTRS); 559 port->intrs = P16X_MIN_INTRS; 560 } else if (port->intrs > P16X_MAX_INTRS) { 561 audio_dev_warn(adev, "%s too high, %d, reset to %d", 562 prop, port->intrs, P16X_DEF_INTRS); 563 port->intrs = P16X_DEF_INTRS; 564 } 565 566 /* 567 * We choose 6 fragments for a specific reason. Since the 568 * device only has full and half interrupts, and since the 569 * framework will try to queue up 4 frags automatically, this 570 * ensures that we will be able to queue all 4 fragments, and 571 * it avoids a potential underrun that you would get with 8 572 * fragments. (More than 8 fragments is guaranteed to cause 573 * underruns in Boomer.) 574 * 575 * Boomer needs to get smarter about dealing with devices with 576 * fewer fragment counts. This device, for instance, should 577 * really be represented with just two fragments. That wll 578 * cause an infinite loop in Boomer, when Boomer tries to 579 * queue up 4 fragments. 580 */ 581 port->nfrags = 6; 582 port->fragfr = 48000 / port->intrs; 583 /* 584 * The device operates in pairs of dwords at a time, for 585 * performance reasons. So make sure that our buffer is 586 * arranged as a whole number of these. We could probably 587 * fine tune by just ensuring that the overall buffer was 128 588 * (64 for half and 64 for full), but this is simpler. 589 */ 590 port->fragfr = (port->fragfr + 63) & ~(63); 591 port->fragsz = port->fragfr * port->nchan * 2; /* 16 bit frames */ 592 port->buf_size = port->nfrags * port->fragsz; 593 port->buf_frames = port->fragfr * port->nfrags; 594 595 /* now allocate buffers */ 596 if (ddi_dma_alloc_handle(dev->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL, 597 &port->buf_dmah) != DDI_SUCCESS) { 598 audio_dev_warn(adev, "failed to allocate BUF handle"); 599 return (DDI_FAILURE); 600 } 601 602 if (ddi_dma_mem_alloc(port->buf_dmah, port->buf_size, 603 &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 604 &port->buf_kaddr, &len, &port->buf_acch) != DDI_SUCCESS) { 605 audio_dev_warn(adev, "failed to allocate BUF memory"); 606 return (DDI_FAILURE); 607 } 608 609 if (ddi_dma_addr_bind_handle(port->buf_dmah, NULL, port->buf_kaddr, 610 len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie, 611 &count) != DDI_SUCCESS) { 612 audio_dev_warn(adev, "failed binding BUF DMA handle"); 613 return (DDI_FAILURE); 614 } 615 port->buf_paddr = cookie.dmac_address; 616 617 port->engine = audio_engine_alloc(&p16x_engine_ops, caps); 618 if (port->engine == NULL) { 619 audio_dev_warn(adev, "audio_engine_alloc failed"); 620 return (DDI_FAILURE); 621 } 622 623 audio_engine_set_private(port->engine, port); 624 audio_dev_add_engine(adev, port->engine); 625 626 return (DDI_SUCCESS); 627 } 628 629 void 630 p16x_destroy(p16x_dev_t *dev) 631 { 632 if (dev->ih != NULL) { 633 (void) ddi_intr_disable(dev->ih); 634 (void) ddi_intr_remove_handler(dev->ih); 635 (void) ddi_intr_free(dev->ih); 636 mutex_destroy(&dev->mutex); 637 mutex_destroy(&dev->low_mutex); 638 } 639 640 if (dev->ksp) { 641 kstat_delete(dev->ksp); 642 } 643 644 for (int i = 0; i < P16X_NUM_PORT; i++) { 645 p16x_port_t *port = dev->port[i]; 646 if (!port) 647 continue; 648 if (port->engine) { 649 audio_dev_remove_engine(dev->adev, port->engine); 650 audio_engine_free(port->engine); 651 } 652 if (port->buf_paddr) { 653 (void) ddi_dma_unbind_handle(port->buf_dmah); 654 } 655 if (port->buf_acch) { 656 ddi_dma_mem_free(&port->buf_acch); 657 } 658 if (port->buf_dmah) { 659 ddi_dma_free_handle(&port->buf_dmah); 660 } 661 kmem_free(port, sizeof (*port)); 662 } 663 664 if (dev->ac97 != NULL) { 665 ac97_free(dev->ac97); 666 } 667 if (dev->adev != NULL) { 668 audio_dev_free(dev->adev); 669 } 670 if (dev->regsh != NULL) { 671 ddi_regs_map_free(&dev->regsh); 672 } 673 if (dev->pcih != NULL) { 674 pci_config_teardown(&dev->pcih); 675 } 676 kmem_free(dev, sizeof (*dev)); 677 } 678 679 void 680 p16x_hwinit(p16x_dev_t *dev) 681 { 682 p16x_port_t *port; 683 uint32_t paddr; 684 uint32_t chunksz; 685 int i; 686 687 for (i = 0; i < 3; i++) { 688 write_reg(dev, PTBA, i, 0); 689 write_reg(dev, PTBS, i, 0); 690 write_reg(dev, PTCA, i, 0); 691 write_reg(dev, PFEA, i, 0); 692 write_reg(dev, CPFA, i, 0); 693 write_reg(dev, CPCAV, i, 0); 694 write_reg(dev, CRFA, i, 0); 695 write_reg(dev, CRCAV, i, 0); 696 } 697 write_reg(dev, SCS0, 0, 0x02108504); 698 write_reg(dev, SCS1, 0, 0x02108504); 699 write_reg(dev, SCS2, 0, 0x02108504); 700 701 /* set the spdif/analog combo jack to analog out */ 702 write_reg(dev, SPC, 0, 0x00000700); 703 write_reg(dev, EA_aux, 0, 0x0001003f); 704 705 port = dev->port[P16X_REC]; 706 /* Set physical address of the DMA buffer */ 707 write_reg(dev, RFBA, 0, port->buf_paddr); 708 write_reg(dev, RFBS, 0, (port->buf_size) << 16); 709 710 /* Set physical address of the DMA buffer */ 711 port = dev->port[P16X_PLAY]; 712 paddr = port->buf_paddr; 713 chunksz = port->buf_frames * 4; 714 write_reg(dev, PFBA, 0, paddr); 715 write_reg(dev, PFBS, 0, chunksz << 16); 716 paddr += chunksz; 717 write_reg(dev, PFBA, 1, paddr); 718 write_reg(dev, PFBS, 1, chunksz << 16); 719 paddr += chunksz; 720 write_reg(dev, PFBA, 2, paddr); 721 write_reg(dev, PFBS, 2, chunksz << 16); 722 723 OUTL(dev, 0x1080, GPIO); /* GPIO */ 724 /* Clear any pending interrupts */ 725 OUTL(dev, INTR_ALL, IP); 726 OUTL(dev, 0, IE); 727 OUTL(dev, 0x9, HC); /* Enable audio */ 728 } 729 730 int 731 p16x_setup_intrs(p16x_dev_t *dev) 732 { 733 uint_t ipri; 734 int actual; 735 int rv; 736 ddi_intr_handle_t ih[1]; 737 738 rv = ddi_intr_alloc(dev->dip, ih, DDI_INTR_TYPE_FIXED, 739 0, 1, &actual, DDI_INTR_ALLOC_STRICT); 740 if ((rv != DDI_SUCCESS) || (actual != 1)) { 741 audio_dev_warn(dev->adev, 742 "Can't alloc interrupt handle (rv %d actual %d)", 743 rv, actual); 744 return (DDI_FAILURE); 745 } 746 747 if (ddi_intr_get_pri(ih[0], &ipri) != DDI_SUCCESS) { 748 audio_dev_warn(dev->adev, "Can't get interrupt priority"); 749 (void) ddi_intr_free(ih[0]); 750 return (DDI_FAILURE); 751 } 752 753 if (ddi_intr_add_handler(ih[0], p16x_intr, dev, NULL) != 754 DDI_SUCCESS) { 755 audio_dev_warn(dev->adev, "Can't add interrupt handler"); 756 (void) ddi_intr_free(ih[0]); 757 return (DDI_FAILURE); 758 } 759 760 dev->ih = ih[0]; 761 mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 762 mutex_init(&dev->low_mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 763 return (DDI_SUCCESS); 764 } 765 766 int 767 p16x_attach(dev_info_t *dip) 768 { 769 uint16_t vendor, device; 770 p16x_dev_t *dev; 771 ddi_acc_handle_t pcih; 772 773 dev = kmem_zalloc(sizeof (*dev), KM_SLEEP); 774 dev->dip = dip; 775 ddi_set_driver_private(dip, dev); 776 777 /* we don't support high level interrupts in the driver */ 778 if (ddi_intr_hilevel(dip, 0) != 0) { 779 cmn_err(CE_WARN, 780 "!%s%d: unsupported high level interrupt", 781 ddi_driver_name(dip), ddi_get_instance(dip)); 782 return (DDI_FAILURE); 783 } 784 785 if (ddi_get_iblock_cookie(dip, 0, &dev->iblock) != DDI_SUCCESS) { 786 cmn_err(CE_WARN, 787 "!%s%d: cannot get iblock cookie", 788 ddi_driver_name(dip), ddi_get_instance(dip)); 789 kmem_free(dev, sizeof (*dev)); 790 return (DDI_FAILURE); 791 } 792 mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, dev->iblock); 793 mutex_init(&dev->low_mutex, NULL, MUTEX_DRIVER, dev->iblock); 794 795 if ((dev->adev = audio_dev_alloc(dip, 0)) == NULL) { 796 cmn_err(CE_WARN, "audio_dev_alloc failed"); 797 goto error; 798 } 799 800 if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) { 801 audio_dev_warn(dev->adev, "pci_config_setup failed"); 802 goto error; 803 } 804 dev->pcih = pcih; 805 806 vendor = pci_config_get16(pcih, PCI_CONF_VENID); 807 device = pci_config_get16(pcih, PCI_CONF_DEVID); 808 if (vendor != CREATIVE_VENDOR_ID || 809 device != SB_P16X_ID) { 810 audio_dev_warn(dev->adev, "Hardware not recognized " 811 "(vendor=%x, dev=%x)", vendor, device); 812 goto error; 813 } 814 815 /* set PCI command register */ 816 pci_config_put16(pcih, PCI_CONF_COMM, 817 pci_config_get16(pcih, PCI_CONF_COMM) | 818 PCI_COMM_MAE | PCI_COMM_IO); 819 820 821 if ((ddi_regs_map_setup(dip, 1, &dev->base, 0, 0, &dev_attr, 822 &dev->regsh)) != DDI_SUCCESS) { 823 audio_dev_warn(dev->adev, "failed to map registers"); 824 goto error; 825 } 826 827 audio_dev_set_description(dev->adev, "Creative Sound Blaster Live!"); 828 audio_dev_set_version(dev->adev, "SBO200"); 829 830 if ((p16x_alloc_port(dev, P16X_PLAY) != DDI_SUCCESS) || 831 (p16x_alloc_port(dev, P16X_REC) != DDI_SUCCESS)) { 832 goto error; 833 } 834 835 p16x_hwinit(dev); 836 837 /* set up the interrupt handler */ 838 if (p16x_setup_intrs(dev) != DDI_SUCCESS) { 839 goto error; 840 } 841 842 /* Enable PCI interrupts */ 843 OUTL(dev, INTR_PCI, IE); 844 845 dev->ac97 = ac97_allocate(dev->adev, dip, 846 p16x_read_ac97, p16x_write_ac97, dev); 847 if (dev->ac97 == NULL) { 848 audio_dev_warn(dev->adev, "failed to allocate ac97 handle"); 849 goto error; 850 } 851 852 ac97_probe_controls(dev->ac97); 853 854 /* remove the AC'97 controls we don't want to expose */ 855 for (int i = 0; p16x_remove_ac97[i]; i++) { 856 ac97_ctrl_t *ctrl; 857 ctrl = ac97_control_find(dev->ac97, p16x_remove_ac97[i]); 858 if (ctrl != NULL) { 859 ac97_control_unregister(ctrl); 860 } 861 } 862 863 ac97_register_controls(dev->ac97); 864 865 /* set up kernel statistics */ 866 if ((dev->ksp = kstat_create(P16X_NAME, ddi_get_instance(dip), 867 P16X_NAME, "controller", KSTAT_TYPE_INTR, 1, 868 KSTAT_FLAG_PERSISTENT)) != NULL) { 869 kstat_install(dev->ksp); 870 } 871 872 if (audio_dev_register(dev->adev) != DDI_SUCCESS) { 873 audio_dev_warn(dev->adev, "unable to register with framework"); 874 goto error; 875 } 876 877 (void) ddi_intr_enable(dev->ih); 878 ddi_report_dev(dip); 879 880 return (DDI_SUCCESS); 881 882 error: 883 p16x_destroy(dev); 884 return (DDI_FAILURE); 885 } 886 887 int 888 p16x_resume(dev_info_t *dip) 889 { 890 p16x_dev_t *dev; 891 892 dev = ddi_get_driver_private(dip); 893 894 p16x_hwinit(dev); 895 896 /* allow ac97 operations again */ 897 ac97_resume(dev->ac97); 898 899 mutex_enter(&dev->mutex); 900 dev->suspended = B_FALSE; 901 902 for (int i = 0; i < P16X_NUM_PORT; i++) { 903 904 p16x_port_t *port = dev->port[i]; 905 906 if (port->engine != NULL) 907 audio_engine_reset(port->engine); 908 909 /* reset the port */ 910 p16x_init_port(port); 911 912 if (port->started) { 913 p16x_start_port(port); 914 } else { 915 p16x_stop_port(port); 916 } 917 } 918 mutex_exit(&dev->mutex); 919 return (DDI_SUCCESS); 920 } 921 922 int 923 p16x_detach(p16x_dev_t *dev) 924 { 925 if (audio_dev_unregister(dev->adev) != DDI_SUCCESS) 926 return (DDI_FAILURE); 927 928 p16x_destroy(dev); 929 return (DDI_SUCCESS); 930 } 931 932 int 933 p16x_suspend(p16x_dev_t *dev) 934 { 935 ac97_suspend(dev->ac97); 936 937 mutex_enter(&dev->mutex); 938 for (int i = 0; i < P16X_NUM_PORT; i++) { 939 940 p16x_port_t *port = dev->port[i]; 941 p16x_stop_port(port); 942 } 943 944 write_reg(dev, SA, 0, 0); 945 OUTL(dev, 0x00, IE); /* Interrupt disable */ 946 OUTL(dev, 0x01, HC); 947 948 dev->suspended = B_TRUE; 949 mutex_exit(&dev->mutex); 950 return (DDI_SUCCESS); 951 } 952 953 static int p16x_ddi_attach(dev_info_t *, ddi_attach_cmd_t); 954 static int p16x_ddi_detach(dev_info_t *, ddi_detach_cmd_t); 955 static int p16x_ddi_quiesce(dev_info_t *); 956 957 static struct dev_ops p16x_dev_ops = { 958 DEVO_REV, /* rev */ 959 0, /* refcnt */ 960 NULL, /* getinfo */ 961 nulldev, /* identify */ 962 nulldev, /* probe */ 963 p16x_ddi_attach, /* attach */ 964 p16x_ddi_detach, /* detach */ 965 nodev, /* reset */ 966 NULL, /* cb_ops */ 967 NULL, /* bus_ops */ 968 NULL, /* power */ 969 p16x_ddi_quiesce, /* quiesce */ 970 }; 971 972 static struct modldrv p16x_modldrv = { 973 &mod_driverops, /* drv_modops */ 974 "Creative P16X Audio", /* linkinfo */ 975 &p16x_dev_ops, /* dev_ops */ 976 }; 977 978 static struct modlinkage modlinkage = { 979 MODREV_1, 980 { &p16x_modldrv, NULL } 981 }; 982 983 int 984 _init(void) 985 { 986 int rv; 987 988 audio_init_ops(&p16x_dev_ops, P16X_NAME); 989 if ((rv = mod_install(&modlinkage)) != 0) { 990 audio_fini_ops(&p16x_dev_ops); 991 } 992 return (rv); 993 } 994 995 int 996 _fini(void) 997 { 998 int rv; 999 1000 if ((rv = mod_remove(&modlinkage)) == 0) { 1001 audio_fini_ops(&p16x_dev_ops); 1002 } 1003 return (rv); 1004 } 1005 1006 int 1007 _info(struct modinfo *modinfop) 1008 { 1009 return (mod_info(&modlinkage, modinfop)); 1010 } 1011 1012 int 1013 p16x_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1014 { 1015 switch (cmd) { 1016 case DDI_ATTACH: 1017 return (p16x_attach(dip)); 1018 1019 case DDI_RESUME: 1020 return (p16x_resume(dip)); 1021 1022 default: 1023 return (DDI_FAILURE); 1024 } 1025 } 1026 1027 int 1028 p16x_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1029 { 1030 p16x_dev_t *dev; 1031 1032 dev = ddi_get_driver_private(dip); 1033 1034 switch (cmd) { 1035 case DDI_DETACH: 1036 return (p16x_detach(dev)); 1037 1038 case DDI_SUSPEND: 1039 return (p16x_suspend(dev)); 1040 1041 default: 1042 return (DDI_FAILURE); 1043 } 1044 } 1045 1046 int 1047 p16x_ddi_quiesce(dev_info_t *dip) 1048 { 1049 p16x_dev_t *dev; 1050 1051 dev = ddi_get_driver_private(dip); 1052 1053 for (int i = 0; i < P16X_NUM_PORT; i++) { 1054 1055 p16x_port_t *port = dev->port[i]; 1056 p16x_stop_port(port); 1057 } 1058 1059 write_reg(dev, SA, 0, 0); 1060 OUTL(dev, 0x00, IE); /* Interrupt disable */ 1061 OUTL(dev, 0x01, HC); 1062 1063 return (DDI_SUCCESS); 1064 } 1065