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 VIA8233/8235 AC97 audio controller 29 */ 30 /* 31 * This file is part of Open Sound System 32 * 33 * Copyright (C) 4Front Technologies 1996-2008. 34 * 35 * This software is released under CDDL 1.0 source license. 36 * See the COPYING file included in the main directory of this source 37 * distribution for the license terms and conditions. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/modctl.h> 42 #include <sys/kmem.h> 43 #include <sys/conf.h> 44 #include <sys/ddi.h> 45 #include <sys/sunddi.h> 46 #include <sys/pci.h> 47 #include <sys/note.h> 48 #include <sys/audio/audio_driver.h> 49 #include <sys/audio/ac97.h> 50 51 #include "audiovia823x.h" 52 53 static struct ddi_device_acc_attr dev_attr = { 54 DDI_DEVICE_ATTR_V0, 55 DDI_STRUCTURE_LE_ACC, 56 DDI_STRICTORDER_ACC 57 }; 58 59 static struct ddi_device_acc_attr buf_attr = { 60 DDI_DEVICE_ATTR_V0, 61 DDI_NEVERSWAP_ACC, 62 DDI_STRICTORDER_ACC 63 }; 64 65 static ddi_dma_attr_t dma_attr_sgd = { 66 DMA_ATTR_V0, /* version number */ 67 0x00000000, /* low DMA address range */ 68 0xffffffff, /* high DMA address range */ 69 0x0000ffff, /* DMA counter register */ 70 8, /* DMA address alignment */ 71 0x3c, /* DMA burstsizes */ 72 8, /* min effective DMA size */ 73 0xffffffff, /* max DMA xfer size */ 74 0x00000fff, /* segment boundary */ 75 1, /* s/g length */ 76 8, /* granularity of device */ 77 0 /* Bus specific DMA flags */ 78 }; 79 80 static ddi_dma_attr_t dma_attr_buf = { 81 DMA_ATTR_V0, /* version number */ 82 0x00000000, /* low DMA address range */ 83 0xffffffff, /* high DMA address range */ 84 0x0001fffe, /* DMA counter register */ 85 4, /* DMA address alignment */ 86 0x3c, /* DMA burstsizes */ 87 4, /* min effective DMA size */ 88 0x0001ffff, /* max DMA xfer size */ 89 0x0001ffff, /* segment boundary */ 90 1, /* s/g length */ 91 4, /* granularity of device */ 92 0 /* Bus specific DMA flags */ 93 }; 94 95 static int auvia_attach(dev_info_t *); 96 static int auvia_resume(dev_info_t *); 97 static int auvia_detach(auvia_devc_t *); 98 static int auvia_suspend(auvia_devc_t *); 99 100 static int auvia_open(void *, int, unsigned *, unsigned *, caddr_t *); 101 static void auvia_close(void *); 102 static int auvia_start(void *); 103 static void auvia_stop(void *); 104 static int auvia_format(void *); 105 static int auvia_channels(void *); 106 static int auvia_rate(void *); 107 static uint64_t auvia_count(void *); 108 static void auvia_sync(void *, unsigned); 109 110 static uint16_t auvia_read_ac97(void *, uint8_t); 111 static void auvia_write_ac97(void *, uint8_t, uint16_t); 112 static int auvia_alloc_port(auvia_devc_t *, int); 113 static void auvia_start_port(auvia_portc_t *); 114 static void auvia_stop_port(auvia_portc_t *); 115 static void auvia_update_port(auvia_portc_t *); 116 static void auvia_reset_input(auvia_portc_t *); 117 static void auvia_reset_output(auvia_portc_t *); 118 static void auvia_destroy(auvia_devc_t *); 119 static int auvia_setup_intrs(auvia_devc_t *); 120 static void auvia_hwinit(auvia_devc_t *); 121 static uint_t auvia_intr(caddr_t, caddr_t); 122 123 static audio_engine_ops_t auvia_engine_ops = { 124 AUDIO_ENGINE_VERSION, 125 auvia_open, 126 auvia_close, 127 auvia_start, 128 auvia_stop, 129 auvia_count, 130 auvia_format, 131 auvia_channels, 132 auvia_rate, 133 auvia_sync, 134 NULL, 135 NULL, 136 NULL, 137 }; 138 139 static uint16_t 140 auvia_read_ac97(void *arg, uint8_t index) 141 { 142 auvia_devc_t *devc = arg; 143 uint32_t val = 0; 144 int i; 145 146 mutex_enter(&devc->low_mutex); 147 148 val = ((uint32_t)index << 16) | CODEC_RD; 149 OUTL(devc, devc->base + REG_CODEC, val); 150 drv_usecwait(100); 151 152 /* Check AC CODEC access time out */ 153 for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) { 154 155 /* if send command over, break */ 156 if (INL(devc, devc->base + REG_CODEC) & CODEC_STA_VALID) 157 break; 158 drv_usecwait(50); 159 } 160 161 if (i == CODEC_TIMEOUT_COUNT) { 162 goto failed; 163 } 164 165 /* Check if Index still ours? If yes, return data, else return FAIL */ 166 val = INL(devc, devc->base + REG_CODEC); 167 OUTB(devc, devc->base + REG_CODEC + 3, 0x02); 168 if (((val & CODEC_INDEX) >> 16) == index) { 169 mutex_exit(&devc->low_mutex); 170 return (val & CODEC_DATA); 171 } 172 173 failed: 174 mutex_exit(&devc->low_mutex); 175 return (0xffff); 176 } 177 178 static void 179 auvia_write_ac97(void *arg, uint8_t index, uint16_t data) 180 { 181 auvia_devc_t *devc = arg; 182 uint32_t val = 0; 183 int i = 0; 184 185 mutex_enter(&devc->low_mutex); 186 187 val = ((uint32_t)index << 16) | data | CODEC_WR; 188 OUTL(devc, devc->base + REG_CODEC, val); 189 drv_usecwait(100); 190 191 /* Check AC CODEC access time out */ 192 for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) { 193 /* if send command over, break */ 194 if (!(INL(devc, devc->base + REG_CODEC) & CODEC_IN_CMD)) 195 break; 196 drv_usecwait(50); 197 } 198 199 mutex_exit(&devc->low_mutex); 200 } 201 202 static uint_t 203 auvia_intr(caddr_t argp, caddr_t nocare) 204 { 205 auvia_devc_t *devc = (void *)argp; 206 auvia_portc_t *portc; 207 uint8_t status; 208 unsigned intrs = 0; 209 boolean_t claimed = B_FALSE; 210 211 _NOTE(ARGUNUSED(nocare)); 212 213 mutex_enter(&devc->mutex); 214 if (devc->suspended) { 215 mutex_exit(&devc->mutex); 216 return (DDI_INTR_UNCLAIMED); 217 } 218 219 for (int i = 0; i < AUVIA_NUM_PORTC; i++) { 220 221 portc = devc->portc[i]; 222 223 status = INB(devc, portc->base + OFF_STATUS); 224 if ((status & STATUS_INTR) == 0) { 225 /* clear any other interrupts */ 226 continue; 227 } 228 229 /* 230 * NB: The old code did some goofy things to update 231 * the last valid SGD. However, since we don't ever 232 * reach the last valid SGD (because we loop first), I 233 * don't believe we need to do that. It would appear 234 * that NetBSD does the same. 235 */ 236 /* port interrupt */ 237 if (portc->started) { 238 intrs |= (1U << i); 239 } 240 /* let the chip know we are acking the interrupt */ 241 OUTB(devc, portc->base + OFF_STATUS, status); 242 243 claimed = B_TRUE; 244 } 245 246 mutex_exit(&devc->mutex); 247 248 if (!claimed) { 249 return (DDI_INTR_UNCLAIMED); 250 } 251 252 if (intrs & (1U << AUVIA_PLAY_SGD_NUM)) { 253 audio_engine_consume(devc->portc[AUVIA_PLAY_SGD_NUM]->engine); 254 } 255 if (intrs & (1U << AUVIA_REC_SGD_NUM)) { 256 audio_engine_produce(devc->portc[AUVIA_REC_SGD_NUM]->engine); 257 } 258 if (devc->ksp) { 259 AUVIA_KIOP(devc)->intrs[KSTAT_INTR_HARD]++; 260 } 261 262 return (DDI_INTR_CLAIMED); 263 } 264 265 /* 266 * Audio routines 267 */ 268 269 int 270 auvia_open(void *arg, int flag, 271 unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp) 272 { 273 auvia_portc_t *portc = arg; 274 auvia_devc_t *devc = portc->devc; 275 276 _NOTE(ARGUNUSED(flag)); 277 278 portc->started = B_FALSE; 279 portc->count = 0; 280 *fragfrp = portc->fragfr; 281 *nfragsp = AUVIA_NUM_SGD; 282 *bufp = portc->buf_kaddr; 283 284 mutex_enter(&devc->mutex); 285 portc->reset(portc); 286 mutex_exit(&devc->mutex); 287 288 return (0); 289 } 290 291 void 292 auvia_close(void *arg) 293 { 294 auvia_portc_t *portc = arg; 295 auvia_devc_t *devc = portc->devc; 296 297 mutex_enter(&devc->mutex); 298 auvia_stop_port(portc); 299 portc->started = B_FALSE; 300 mutex_exit(&devc->mutex); 301 } 302 303 int 304 auvia_start(void *arg) 305 { 306 auvia_portc_t *portc = arg; 307 auvia_devc_t *devc = portc->devc; 308 309 mutex_enter(&devc->mutex); 310 if (!portc->started) { 311 auvia_start_port(portc); 312 portc->started = B_TRUE; 313 } 314 mutex_exit(&devc->mutex); 315 return (0); 316 } 317 318 void 319 auvia_stop(void *arg) 320 { 321 auvia_portc_t *portc = arg; 322 auvia_devc_t *devc = portc->devc; 323 324 mutex_enter(&devc->mutex); 325 if (portc->started) { 326 auvia_stop_port(portc); 327 portc->started = B_FALSE; 328 } 329 mutex_exit(&devc->mutex); 330 } 331 332 int 333 auvia_format(void *arg) 334 { 335 _NOTE(ARGUNUSED(arg)); 336 337 return (AUDIO_FORMAT_S16_LE); 338 } 339 340 int 341 auvia_channels(void *arg) 342 { 343 auvia_portc_t *portc = arg; 344 345 return (portc->nchan); 346 } 347 348 int 349 auvia_rate(void *arg) 350 { 351 _NOTE(ARGUNUSED(arg)); 352 353 return (48000); 354 } 355 356 void 357 auvia_sync(void *arg, unsigned nframes) 358 { 359 auvia_portc_t *portc = arg; 360 _NOTE(ARGUNUSED(nframes)); 361 362 (void) ddi_dma_sync(portc->buf_dmah, 0, 0, portc->syncdir); 363 } 364 365 uint64_t 366 auvia_count(void *arg) 367 { 368 auvia_portc_t *portc = arg; 369 auvia_devc_t *devc = portc->devc; 370 uint64_t val; 371 372 mutex_enter(&devc->mutex); 373 auvia_update_port(portc); 374 /* 375 * The residual is in bytes. We have to convert to frames, 376 * and then subtract it from the fragment size to get the 377 * number of frames processed. It is somewhat unfortunate thta 378 * this (the division) has to happen under the lock. If we 379 * restricted ourself to stereo out, this would be a simple 380 * shift. 381 */ 382 val = portc->count + 383 (portc->fragfr - (portc->resid / (portc->nchan * 2))); 384 mutex_exit(&devc->mutex); 385 386 return (val); 387 } 388 389 390 /* private implementation bits */ 391 392 void 393 auvia_start_port(auvia_portc_t *portc) 394 { 395 auvia_devc_t *devc = portc->devc; 396 397 ASSERT(mutex_owned(&devc->mutex)); 398 399 if (devc->suspended) 400 return; 401 402 /* 403 * Start with autoinit and SGD flag 404 * interrupts enabled. 405 */ 406 OUTB(devc, portc->base + OFF_CTRL, 407 CTRL_START | CTRL_AUTOSTART | CTRL_FLAG); 408 } 409 410 void 411 auvia_stop_port(auvia_portc_t *portc) 412 { 413 auvia_devc_t *devc = portc->devc; 414 415 if (devc->suspended) 416 return; 417 418 OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE); 419 } 420 421 void 422 auvia_update_port(auvia_portc_t *portc) 423 { 424 auvia_devc_t *devc = portc->devc; 425 uint32_t frag; 426 uint32_t n; 427 428 ASSERT(mutex_owned(&devc->mutex)); 429 if (devc->suspended) { 430 portc->cur_frag = 0; 431 portc->resid = portc->fragsz; 432 n = 0; 433 } else { 434 frag = INL(devc, portc->base + OFF_COUNT); 435 portc->resid = (frag & 0xffffff); 436 frag >>= 24; 437 frag &= 0xff; 438 439 if (frag >= portc->cur_frag) { 440 n = frag - portc->cur_frag; 441 } else { 442 n = frag + AUVIA_NUM_SGD - portc->cur_frag; 443 } 444 portc->count += (n * portc->fragfr); 445 portc->cur_frag = frag; 446 } 447 } 448 449 void 450 auvia_reset_output(auvia_portc_t *portc) 451 { 452 auvia_devc_t *devc = portc->devc; 453 uint32_t cmap; 454 455 portc->cur_frag = 0; 456 portc->resid = portc->fragsz; 457 458 if (devc->suspended) 459 return; 460 461 OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE); /* Stop */ 462 OUTL(devc, portc->base + OFF_DMA, portc->sgd_paddr); 463 464 OUTB(devc, portc->base + OFF_PLAYFMT, 465 PLAYFMT_16BIT | (portc->nchan << 4)); 466 467 /* Select channel assignment - not valid for 8233A */ 468 if (devc->chip_type != CHIP_8233A) { 469 /* 470 * Undocumented slot mapping table: 471 * 472 * slot 3 = 1 (left) 473 * slot 4 = 2 (right) 474 * slot 6 = 5 (center) 475 * slot 9 = 6 (lfe) 476 * slot 7 = 3 (left rear) 477 * slot 8 = 4 (right rear) 478 */ 479 switch (portc->nchan) { 480 case 1: 481 cmap = (1 << 0) | (1 << 4); 482 break; 483 case 2: 484 cmap = (1 << 0) | (2 << 4); 485 break; 486 case 4: 487 cmap = (1 << 0) | (2 << 4) | (3 << 8) | (4 << 12); 488 break; 489 case 6: 490 cmap = (1 << 0) | (2 << 4) | 491 (5 << 8) | (6 << 12) | (3 << 16) | (4 << 20); 492 break; 493 default: 494 cmap = 0; 495 break; 496 } 497 OUTL(devc, portc->base + OFF_CHANNELS, cmap | 0xFF000000U); 498 } 499 } 500 501 static void 502 auvia_reset_input(auvia_portc_t *portc) 503 { 504 auvia_devc_t *devc = portc->devc; 505 uint32_t fmt; 506 507 portc->cur_frag = 0; 508 portc->resid = portc->fragsz; 509 510 if (devc->suspended) 511 return; 512 513 OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE); /* Stop */ 514 OUTL(devc, portc->base + OFF_DMA, portc->sgd_paddr); 515 516 fmt = RECFMT_STEREO | RECFMT_16BIT; 517 518 if (devc->chip_type != CHIP_8233A) { 519 fmt |= RECFMT_48K; 520 } 521 fmt |= (0xffU << 24); 522 OUTB(devc, portc->base + OFF_RECFIFO, RECFIFO_ENABLE); 523 OUTL(devc, portc->base + OFF_RECFMT, fmt); 524 } 525 526 int 527 auvia_alloc_port(auvia_devc_t *devc, int num) 528 { 529 auvia_portc_t *portc; 530 size_t len; 531 ddi_dma_cookie_t cookie; 532 uint_t count; 533 int dir; 534 char *prop; 535 unsigned caps; 536 audio_dev_t *adev; 537 uint32_t *desc; 538 uint32_t paddr; 539 540 adev = devc->adev; 541 portc = kmem_zalloc(sizeof (*portc), KM_SLEEP); 542 devc->portc[num] = portc; 543 portc->devc = devc; 544 portc->started = B_FALSE; 545 546 switch (num) { 547 case AUVIA_REC_SGD_NUM: 548 prop = "record-interrupts"; 549 portc->base = devc->base + REG_RECBASE; 550 portc->syncdir = DDI_DMA_SYNC_FORKERNEL; 551 portc->nchan = 2; 552 portc->reset = auvia_reset_input; 553 caps = ENGINE_INPUT_CAP; 554 dir = DDI_DMA_READ; 555 break; 556 case AUVIA_PLAY_SGD_NUM: 557 prop = "play-interrupts"; 558 portc->base = devc->base + REG_PLAYBASE; 559 portc->syncdir = DDI_DMA_SYNC_FORDEV; 560 portc->nchan = 6; 561 portc->reset = auvia_reset_output; 562 caps = ENGINE_OUTPUT_CAP; 563 dir = DDI_DMA_WRITE; 564 break; 565 default: 566 return (DDI_FAILURE); 567 } 568 569 /* make sure port is shut down */ 570 OUTB(portc->devc, portc->base + OFF_CTRL, CTRL_TERMINATE); 571 572 /* figure out fragment configuration */ 573 portc->intrs = ddi_prop_get_int(DDI_DEV_T_ANY, devc->dip, 574 DDI_PROP_DONTPASS, prop, AUVIA_INTRS); 575 576 /* make sure the values are good */ 577 if (portc->intrs < AUVIA_MIN_INTRS) { 578 audio_dev_warn(adev, "%s too low, %d, reset to %d", 579 prop, portc->intrs, AUVIA_INTRS); 580 portc->intrs = AUVIA_INTRS; 581 } else if (portc->intrs > AUVIA_MAX_INTRS) { 582 audio_dev_warn(adev, "%s too high, %d, reset to %d", 583 prop, portc->intrs, AUVIA_INTRS); 584 portc->intrs = AUVIA_INTRS; 585 } 586 587 portc->fragfr = 48000 / portc->intrs; 588 portc->fragsz = portc->fragfr * portc->nchan * 2; 589 portc->buf_size = portc->fragsz * AUVIA_NUM_SGD; 590 591 /* first allocate up space for SGD list */ 592 if (ddi_dma_alloc_handle(devc->dip, &dma_attr_sgd, 593 DDI_DMA_SLEEP, NULL, &portc->sgd_dmah) != DDI_SUCCESS) { 594 audio_dev_warn(adev, "failed to allocate SGD handle"); 595 return (DDI_FAILURE); 596 } 597 598 if (ddi_dma_mem_alloc(portc->sgd_dmah, 599 AUVIA_NUM_SGD * 2 * sizeof (uint32_t), &dev_attr, 600 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &portc->sgd_kaddr, 601 &len, &portc->sgd_acch) != DDI_SUCCESS) { 602 audio_dev_warn(adev, "failed to allocate SGD memory"); 603 return (DDI_FAILURE); 604 } 605 606 if (ddi_dma_addr_bind_handle(portc->sgd_dmah, NULL, 607 portc->sgd_kaddr, len, DDI_DMA_CONSISTENT | DDI_DMA_WRITE, 608 DDI_DMA_SLEEP, NULL, &cookie, &count) != DDI_SUCCESS) { 609 audio_dev_warn(adev, "failed binding SGD DMA handle"); 610 return (DDI_FAILURE); 611 } 612 portc->sgd_paddr = cookie.dmac_address; 613 614 /* now buffers */ 615 if (ddi_dma_alloc_handle(devc->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL, 616 &portc->buf_dmah) != DDI_SUCCESS) { 617 audio_dev_warn(adev, "failed to allocate BUF handle"); 618 return (DDI_FAILURE); 619 } 620 621 if (ddi_dma_mem_alloc(portc->buf_dmah, portc->buf_size, 622 &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 623 &portc->buf_kaddr, &len, &portc->buf_acch) != DDI_SUCCESS) { 624 audio_dev_warn(adev, "failed to allocate BUF memory"); 625 return (DDI_FAILURE); 626 } 627 628 if (ddi_dma_addr_bind_handle(portc->buf_dmah, NULL, portc->buf_kaddr, 629 len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie, 630 &count) != DDI_SUCCESS) { 631 audio_dev_warn(adev, "failed binding BUF DMA handle"); 632 return (DDI_FAILURE); 633 } 634 portc->buf_paddr = cookie.dmac_address; 635 636 /* now wire descriptors up */ 637 desc = (void *)portc->sgd_kaddr; 638 paddr = portc->buf_paddr; 639 for (int i = 0; i < AUVIA_NUM_SGD; i++) { 640 uint32_t flags; 641 642 flags = AUVIA_SGD_FLAG | portc->fragsz; 643 644 if (i == (AUVIA_NUM_SGD - 1)) { 645 flags |= AUVIA_SGD_EOL; 646 } 647 ddi_put32(portc->sgd_acch, desc++, paddr); 648 ddi_put32(portc->sgd_acch, desc++, flags); 649 paddr += portc->fragsz; 650 } 651 652 (void) ddi_dma_sync(portc->sgd_dmah, 0, 0, DDI_DMA_SYNC_FORDEV); 653 654 portc->engine = audio_engine_alloc(&auvia_engine_ops, caps); 655 if (portc->engine == NULL) { 656 audio_dev_warn(adev, "audio_engine_alloc failed"); 657 return (DDI_FAILURE); 658 } 659 660 audio_engine_set_private(portc->engine, portc); 661 audio_dev_add_engine(adev, portc->engine); 662 663 return (DDI_SUCCESS); 664 } 665 666 int 667 auvia_setup_intrs(auvia_devc_t *devc) 668 { 669 uint_t ipri; 670 int actual; 671 int rv; 672 ddi_intr_handle_t ih[1]; 673 674 rv = ddi_intr_alloc(devc->dip, ih, DDI_INTR_TYPE_FIXED, 675 0, 1, &actual, DDI_INTR_ALLOC_STRICT); 676 if ((rv != DDI_SUCCESS) || (actual != 1)) { 677 audio_dev_warn(devc->adev, 678 "Can't alloc interrupt handle (rv %d actual %d)", 679 rv, actual); 680 return (DDI_FAILURE); 681 } 682 683 if (ddi_intr_get_pri(ih[0], &ipri) != DDI_SUCCESS) { 684 audio_dev_warn(devc->adev, "Can't get interrupt priority"); 685 (void) ddi_intr_free(ih[0]); 686 return (DDI_FAILURE); 687 } 688 689 if (ddi_intr_add_handler(ih[0], auvia_intr, devc, NULL) != 690 DDI_SUCCESS) { 691 audio_dev_warn(devc->adev, "Can't add interrupt handler"); 692 (void) ddi_intr_free(ih[0]); 693 return (DDI_FAILURE); 694 } 695 696 devc->ih = ih[0]; 697 mutex_init(&devc->mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 698 mutex_init(&devc->low_mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 699 return (DDI_SUCCESS); 700 } 701 702 void 703 auvia_destroy(auvia_devc_t *devc) 704 { 705 if (devc->ih != NULL) { 706 (void) ddi_intr_disable(devc->ih); 707 (void) ddi_intr_remove_handler(devc->ih); 708 (void) ddi_intr_free(devc->ih); 709 mutex_destroy(&devc->mutex); 710 mutex_destroy(&devc->low_mutex); 711 } 712 713 if (devc->ksp) { 714 kstat_delete(devc->ksp); 715 } 716 717 for (int i = 0; i < AUVIA_NUM_PORTC; i++) { 718 auvia_portc_t *portc = devc->portc[i]; 719 if (!portc) 720 continue; 721 if (portc->engine) { 722 audio_dev_remove_engine(devc->adev, portc->engine); 723 audio_engine_free(portc->engine); 724 } 725 if (portc->sgd_paddr) { 726 (void) ddi_dma_unbind_handle(portc->sgd_dmah); 727 } 728 if (portc->sgd_acch) { 729 ddi_dma_mem_free(&portc->sgd_acch); 730 } 731 if (portc->sgd_dmah) { 732 ddi_dma_free_handle(&portc->sgd_dmah); 733 } 734 if (portc->buf_paddr) { 735 (void) ddi_dma_unbind_handle(portc->buf_dmah); 736 } 737 if (portc->buf_acch) { 738 ddi_dma_mem_free(&portc->buf_acch); 739 } 740 if (portc->buf_dmah) { 741 ddi_dma_free_handle(&portc->buf_dmah); 742 } 743 kmem_free(portc, sizeof (*portc)); 744 } 745 746 if (devc->ac97 != NULL) { 747 ac97_free(devc->ac97); 748 } 749 if (devc->adev != NULL) { 750 audio_dev_free(devc->adev); 751 } 752 if (devc->regsh != NULL) { 753 ddi_regs_map_free(&devc->regsh); 754 } 755 if (devc->pcih != NULL) { 756 pci_config_teardown(&devc->pcih); 757 } 758 kmem_free(devc, sizeof (*devc)); 759 } 760 761 void 762 auvia_hwinit(auvia_devc_t *devc) 763 { 764 ddi_acc_handle_t pcih = devc->pcih; 765 uint32_t val; 766 767 val = pci_config_get32(pcih, AUVIA_PCICFG); 768 /* we want to disable all legacy */ 769 val &= ~AUVIA_PCICFG_LEGACY; 770 val &= ~(AUVIA_PCICFG_FMEN | AUVIA_PCICFG_SBEN); 771 772 /* enable AC'97 link and clear the reset bit */ 773 val |= (AUVIA_PCICFG_ACLINKEN | AUVIA_PCICFG_NRST); 774 /* disable SRC (we won't use it) */ 775 val &= ~AUVIA_PCICFG_SRCEN; 776 /* enable the SGD engines */ 777 val |= AUVIA_PCICFG_SGDEN; 778 779 pci_config_put32(pcih, AUVIA_PCICFG, val); 780 781 drv_usecwait(10); 782 } 783 784 int 785 auvia_attach(dev_info_t *dip) 786 { 787 uint8_t pci_revision; 788 uint16_t pci_command, vendor, device; 789 auvia_devc_t *devc; 790 ddi_acc_handle_t pcih; 791 const char *version; 792 793 devc = kmem_zalloc(sizeof (*devc), KM_SLEEP); 794 devc->dip = dip; 795 ddi_set_driver_private(dip, devc); 796 797 if ((devc->adev = audio_dev_alloc(dip, 0)) == NULL) { 798 cmn_err(CE_WARN, "audio_dev_alloc failed"); 799 goto error; 800 } 801 802 if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) { 803 audio_dev_warn(devc->adev, "pci_config_setup failed"); 804 goto error; 805 } 806 devc->pcih = pcih; 807 808 vendor = pci_config_get16(pcih, PCI_CONF_VENID); 809 device = pci_config_get16(pcih, PCI_CONF_DEVID); 810 if ((vendor != VIA_VENDOR_ID) || (device != VIA_8233_ID && 811 device != VIA_8233A_ID)) { 812 audio_dev_warn(devc->adev, "Hardware not recognized " 813 "(vendor=%x, dev=%x)", vendor, device); 814 goto error; 815 } 816 817 devc->chip_type = CHIP_8233; 818 devc->chip_name = "VIA VT8233"; 819 version = "8233"; 820 821 pci_revision = pci_config_get8(pcih, PCI_CONF_REVID); 822 823 if (pci_revision == 0x50) { 824 devc->chip_name = "VIA VT8235"; 825 version = "8235"; 826 } 827 828 if (pci_revision == 0x60) { 829 devc->chip_name = "VIA VT8237"; 830 version = "8237"; 831 } 832 833 if ((device == VIA_8233A_ID) || 834 (device == VIA_8233_ID && pci_revision == 0x40)) { 835 devc->chip_type = CHIP_8233A; 836 devc->chip_name = "VIA VT8233A"; 837 version = "8233A"; 838 } 839 audio_dev_set_description(devc->adev, devc->chip_name); 840 audio_dev_set_version(devc->adev, version); 841 842 pci_command = pci_config_get16(pcih, PCI_CONF_COMM); 843 pci_command |= PCI_COMM_ME | PCI_COMM_IO | PCI_COMM_MAE; 844 pci_config_put16(pcih, PCI_CONF_COMM, pci_command); 845 846 if ((ddi_regs_map_setup(dip, 1, &devc->base, 0, 0, &dev_attr, 847 &devc->regsh)) != DDI_SUCCESS) { 848 audio_dev_warn(devc->adev, "failed to map registers"); 849 goto error; 850 } 851 852 auvia_hwinit(devc); 853 854 if ((auvia_alloc_port(devc, AUVIA_PLAY_SGD_NUM) != DDI_SUCCESS) || 855 (auvia_alloc_port(devc, AUVIA_REC_SGD_NUM) != DDI_SUCCESS)) { 856 goto error; 857 } 858 859 if (auvia_setup_intrs(devc) != DDI_SUCCESS) { 860 goto error; 861 } 862 863 devc->ac97 = ac97_alloc(dip, auvia_read_ac97, auvia_write_ac97, devc); 864 if (devc->ac97 == NULL) { 865 audio_dev_warn(devc->adev, "failed to allocate ac97 handle"); 866 goto error; 867 } 868 869 if (ac97_init(devc->ac97, devc->adev) != DDI_SUCCESS) { 870 audio_dev_warn(devc->adev, "failed to init ac97"); 871 goto error; 872 } 873 874 /* set up kernel statistics */ 875 if ((devc->ksp = kstat_create(AUVIA_NAME, ddi_get_instance(dip), 876 AUVIA_NAME, "controller", KSTAT_TYPE_INTR, 1, 877 KSTAT_FLAG_PERSISTENT)) != NULL) { 878 kstat_install(devc->ksp); 879 } 880 881 if (audio_dev_register(devc->adev) != DDI_SUCCESS) { 882 audio_dev_warn(devc->adev, "unable to register with framework"); 883 goto error; 884 } 885 886 (void) ddi_intr_enable(devc->ih); 887 ddi_report_dev(dip); 888 889 return (DDI_SUCCESS); 890 891 error: 892 auvia_destroy(devc); 893 return (DDI_FAILURE); 894 } 895 896 int 897 auvia_resume(dev_info_t *dip) 898 { 899 auvia_devc_t *devc; 900 901 devc = ddi_get_driver_private(dip); 902 903 auvia_hwinit(devc); 904 905 /* allow ac97 operations again */ 906 ac97_resume(devc->ac97); 907 908 mutex_enter(&devc->mutex); 909 devc->suspended = B_TRUE; 910 for (int i = 0; i < AUVIA_NUM_PORTC; i++) { 911 912 auvia_portc_t *portc = devc->portc[i]; 913 914 if (portc->engine != NULL) 915 audio_engine_reset(portc->engine); 916 917 /* reset the port */ 918 portc->reset(portc); 919 920 if (portc->started) { 921 auvia_start_port(portc); 922 } else { 923 auvia_stop_port(portc); 924 } 925 } 926 mutex_exit(&devc->mutex); 927 return (DDI_SUCCESS); 928 } 929 930 931 int 932 auvia_detach(auvia_devc_t *devc) 933 { 934 if (audio_dev_unregister(devc->adev) != DDI_SUCCESS) 935 return (DDI_FAILURE); 936 937 auvia_destroy(devc); 938 return (DDI_SUCCESS); 939 } 940 941 int 942 auvia_suspend(auvia_devc_t *devc) 943 { 944 ac97_suspend(devc->ac97); 945 946 mutex_enter(&devc->mutex); 947 for (int i = 0; i < AUVIA_NUM_PORTC; i++) { 948 949 auvia_portc_t *portc = devc->portc[i]; 950 auvia_stop_port(portc); 951 } 952 devc->suspended = B_TRUE; 953 mutex_exit(&devc->mutex); 954 return (DDI_SUCCESS); 955 } 956 957 static int auvia_ddi_attach(dev_info_t *, ddi_attach_cmd_t); 958 static int auvia_ddi_detach(dev_info_t *, ddi_detach_cmd_t); 959 static int auvia_ddi_quiesce(dev_info_t *); 960 961 static struct dev_ops auvia_dev_ops = { 962 DEVO_REV, /* rev */ 963 0, /* refcnt */ 964 NULL, /* getinfo */ 965 nulldev, /* identify */ 966 nulldev, /* probe */ 967 auvia_ddi_attach, /* attach */ 968 auvia_ddi_detach, /* detach */ 969 nodev, /* reset */ 970 NULL, /* cb_ops */ 971 NULL, /* bus_ops */ 972 NULL, /* power */ 973 auvia_ddi_quiesce, /* quiesce */ 974 }; 975 976 static struct modldrv auvia_modldrv = { 977 &mod_driverops, /* drv_modops */ 978 "Via 823x Audio", /* linkinfo */ 979 &auvia_dev_ops, /* dev_ops */ 980 }; 981 982 static struct modlinkage modlinkage = { 983 MODREV_1, 984 { &auvia_modldrv, NULL } 985 }; 986 987 int 988 _init(void) 989 { 990 int rv; 991 992 audio_init_ops(&auvia_dev_ops, AUVIA_NAME); 993 if ((rv = mod_install(&modlinkage)) != 0) { 994 audio_fini_ops(&auvia_dev_ops); 995 } 996 return (rv); 997 } 998 999 int 1000 _fini(void) 1001 { 1002 int rv; 1003 1004 if ((rv = mod_remove(&modlinkage)) == 0) { 1005 audio_fini_ops(&auvia_dev_ops); 1006 } 1007 return (rv); 1008 } 1009 1010 int 1011 _info(struct modinfo *modinfop) 1012 { 1013 return (mod_info(&modlinkage, modinfop)); 1014 } 1015 1016 int 1017 auvia_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1018 { 1019 switch (cmd) { 1020 case DDI_ATTACH: 1021 return (auvia_attach(dip)); 1022 1023 case DDI_RESUME: 1024 return (auvia_resume(dip)); 1025 1026 default: 1027 return (DDI_FAILURE); 1028 } 1029 } 1030 1031 int 1032 auvia_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1033 { 1034 auvia_devc_t *devc; 1035 1036 devc = ddi_get_driver_private(dip); 1037 1038 switch (cmd) { 1039 case DDI_DETACH: 1040 return (auvia_detach(devc)); 1041 1042 case DDI_SUSPEND: 1043 return (auvia_suspend(devc)); 1044 1045 default: 1046 return (DDI_FAILURE); 1047 } 1048 } 1049 1050 int 1051 auvia_ddi_quiesce(dev_info_t *dip) 1052 { 1053 auvia_devc_t *devc; 1054 1055 devc = ddi_get_driver_private(dip); 1056 1057 for (int i = 0; i < AUVIA_NUM_PORTC; i++) { 1058 1059 auvia_portc_t *portc = devc->portc[i]; 1060 auvia_stop_port(portc); 1061 } 1062 return (DDI_SUCCESS); 1063 } 1064