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