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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/audio/audio_driver.h> 27 #include <sys/note.h> 28 #include <sys/beep.h> 29 #include <sys/pci.h> 30 #include "audiohd.h" 31 32 #define DEFINTS 175 33 #define DRVNAME "audiohd" 34 /* 35 * Module linkage routines for the kernel 36 */ 37 38 static int audiohd_attach(dev_info_t *, ddi_attach_cmd_t); 39 static int audiohd_detach(dev_info_t *, ddi_detach_cmd_t); 40 static int audiohd_quiesce(dev_info_t *); 41 static int audiohd_resume(audiohd_state_t *); 42 static int audiohd_suspend(audiohd_state_t *); 43 44 /* interrupt handler */ 45 static uint_t audiohd_intr(caddr_t, caddr_t); 46 47 /* 48 * Local routines 49 */ 50 static int audiohd_init_state(audiohd_state_t *, dev_info_t *); 51 static int audiohd_init_pci(audiohd_state_t *, ddi_device_acc_attr_t *); 52 static void audiohd_fini_pci(audiohd_state_t *); 53 static int audiohd_reset_controller(audiohd_state_t *); 54 static int audiohd_init_controller(audiohd_state_t *); 55 static void audiohd_fini_controller(audiohd_state_t *); 56 static void audiohd_stop_dma(audiohd_state_t *); 57 static void audiohd_disable_intr(audiohd_state_t *); 58 static int audiohd_create_codec(audiohd_state_t *); 59 static void audiohd_build_path(audiohd_state_t *); 60 static void audiohd_destroy_codec(audiohd_state_t *); 61 static int audiohd_alloc_dma_mem(audiohd_state_t *, audiohd_dma_t *, 62 size_t, ddi_dma_attr_t *, uint_t); 63 static void audiohd_finish_output_path(hda_codec_t *codec); 64 static uint32_t audioha_codec_verb_get(void *, uint8_t, 65 uint8_t, uint16_t, uint8_t); 66 static uint32_t audioha_codec_4bit_verb_get(void *, uint8_t, 67 uint8_t, uint16_t, uint16_t); 68 static int audiohd_reinit_hda(audiohd_state_t *); 69 static int audiohd_response_from_codec(audiohd_state_t *statep, 70 uint32_t *resp, uint32_t *respex); 71 static void audiohd_restore_codec_gpio(audiohd_state_t *statep); 72 static void audiohd_change_speaker_state(audiohd_state_t *statep, int on); 73 static int audiohd_allocate_port(audiohd_state_t *statep); 74 static void audiohd_free_port(audiohd_state_t *statep); 75 static void audiohd_restore_path(audiohd_state_t *statep); 76 static int audiohd_add_controls(audiohd_state_t *statep); 77 static void audiohd_get_channels(audiohd_state_t *statep); 78 static void audiohd_init_path(audiohd_state_t *statep); 79 static void audiohd_del_controls(audiohd_state_t *statep); 80 static void audiohd_destroy(audiohd_state_t *statep); 81 static void audiohd_beep_on(void *arg); 82 static void audiohd_beep_off(void *arg); 83 static void audiohd_beep_freq(void *arg, int freq); 84 static wid_t audiohd_find_beep(hda_codec_t *codec, wid_t wid, int depth); 85 static void audiohd_build_beep_path(hda_codec_t *codec); 86 static void audiohd_build_beep_amp(hda_codec_t *codec); 87 static void audiohd_finish_beep_path(hda_codec_t *codec); 88 static void audiohd_do_set_beep_volume(audiohd_state_t *statep, 89 audiohd_path_t *path, uint64_t val); 90 static void audiohd_set_beep_volume(audiohd_state_t *statep); 91 static int audiohd_set_beep(void *arg, uint64_t val); 92 93 static int audiohd_beep; 94 static int audiohd_beep_divider; 95 static int audiohd_beep_vol = 1; 96 97 static ddi_device_acc_attr_t hda_dev_accattr = { 98 DDI_DEVICE_ATTR_V0, 99 DDI_STRUCTURE_LE_ACC, 100 DDI_STRICTORDER_ACC 101 }; 102 103 static const char *audiohd_dtypes[] = { 104 AUDIO_PORT_LINEOUT, 105 AUDIO_PORT_SPEAKER, 106 AUDIO_PORT_HEADPHONES, 107 AUDIO_PORT_CD, 108 AUDIO_PORT_SPDIFOUT, 109 AUDIO_PORT_DIGOUT, 110 AUDIO_PORT_MODEM, 111 AUDIO_PORT_HANDSET, 112 AUDIO_PORT_LINEIN, 113 AUDIO_PORT_AUX1IN, 114 AUDIO_PORT_MIC, 115 AUDIO_PORT_PHONE, 116 AUDIO_PORT_SPDIFIN, 117 AUDIO_PORT_DIGIN, 118 AUDIO_PORT_NONE, /* reserved port, don't use */ 119 AUDIO_PORT_OTHER, 120 NULL, 121 }; 122 123 enum { 124 CTL_VOLUME = 0, 125 CTL_FRONT, 126 CTL_SPEAKER, 127 CTL_HEADPHONE, 128 CTL_REAR, 129 CTL_CENTER, 130 CTL_SURROUND, 131 CTL_LFE, 132 CTL_IGAIN, 133 CTL_LINEIN, 134 CTL_MIC, 135 CTL_CD, 136 CTL_MONGAIN, 137 CTL_MONSRC, 138 CTL_RECSRC, 139 CTL_BEEP 140 }; 141 142 static void 143 audiohd_set_chipset_info(audiohd_state_t *statep) 144 { 145 uint32_t devid; 146 const char *name; 147 const char *vers; 148 149 devid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID); 150 devid <<= 16; 151 devid |= pci_config_get16(statep->hda_pci_handle, PCI_CONF_DEVID); 152 153 name = AUDIOHD_DEV_CONFIG; 154 vers = AUDIOHD_DEV_VERSION; 155 156 switch (devid) { 157 case 0x80862668: 158 name = "Intel HD Audio"; 159 vers = "ICH6"; 160 break; 161 case 0x808627d8: 162 name = "Intel HD Audio"; 163 vers = "ICH7"; 164 break; 165 case 0x8086284b: 166 name = "Intel HD Audio"; 167 vers = "ICH8"; 168 break; 169 case 0x8086293e: 170 name = "Intel HD Audio"; 171 vers = "ICH9"; 172 break; 173 case 0x10de0371: 174 name = "NVIDIA HD Audio"; 175 vers = "MCP55"; 176 break; 177 case 0x10de03f0: 178 name = "NVIDIA HD Audio"; 179 vers = "MCP61A"; 180 break; 181 case 0x10de026c: 182 name = "NVIDIA HD Audio"; 183 vers = "6151"; 184 break; 185 case 0x10de03e4: 186 name = "NVIDIA HD Audio"; 187 vers = "MCP61"; 188 break; 189 case 0x10de044a: 190 name = "NVIDIA HD Audio"; 191 vers = "MCP65"; 192 break; 193 case 0x10de055c: 194 name = "NVIDIA HD Audio"; 195 vers = "MCP67"; 196 break; 197 case 0x1002437b: 198 name = "ATI HD Audio"; 199 vers = "SB450"; 200 break; 201 case 0x10024383: 202 name = "ATI HD Audio"; 203 vers = "SB600"; 204 break; 205 case 0x11063288: 206 name = "VIA HD Audio"; 207 vers = "HDA"; 208 break; 209 } 210 /* set device information */ 211 audio_dev_set_description(statep->adev, name); 212 audio_dev_set_version(statep->adev, vers); 213 } 214 215 216 /* 217 * audiohd_add_intrs: 218 * 219 * Register FIXED or MSI interrupts. 220 */ 221 static int 222 audiohd_add_intrs(audiohd_state_t *statep, int intr_type) 223 { 224 dev_info_t *dip = statep->hda_dip; 225 ddi_intr_handle_t ihandle; 226 int avail; 227 int actual; 228 int intr_size; 229 int count; 230 int i, j; 231 int ret; 232 233 /* Get number of interrupts */ 234 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 235 if ((ret != DDI_SUCCESS) || (count == 0)) { 236 audio_dev_warn(statep->adev, "ddi_intr_get_nintrs() failure," 237 "ret: %d, count: %d", ret, count); 238 return (DDI_FAILURE); 239 } 240 241 /* Get number of available interrupts */ 242 ret = ddi_intr_get_navail(dip, intr_type, &avail); 243 if ((ret != DDI_SUCCESS) || (avail == 0)) { 244 audio_dev_warn(statep->adev, "ddi_intr_get_navail() failure, " 245 "ret: %d, avail: %d", ret, avail); 246 return (DDI_FAILURE); 247 } 248 249 /* Allocate an array of interrupt handles */ 250 intr_size = count * sizeof (ddi_intr_handle_t); 251 statep->htable = kmem_alloc(intr_size, KM_SLEEP); 252 statep->intr_rqst = count; 253 254 /* Call ddi_intr_alloc() */ 255 ret = ddi_intr_alloc(dip, statep->htable, intr_type, 0, 256 count, &actual, DDI_INTR_ALLOC_NORMAL); 257 if (ret != DDI_SUCCESS || actual == 0) { 258 /* ddi_intr_alloc() failed */ 259 kmem_free(statep->htable, intr_size); 260 return (DDI_FAILURE); 261 } 262 if (actual < count) { 263 audio_dev_warn(statep->adev, "ddi_intr_alloc() Requested: %d," 264 "Received: %d", 265 count, actual); 266 } 267 statep->intr_cnt = actual; 268 269 /* 270 * Get priority for first msi, assume remaining are all the same 271 */ 272 if ((ret = ddi_intr_get_pri(statep->htable[0], &statep->intr_pri)) != 273 DDI_SUCCESS) { 274 audio_dev_warn(statep->adev, "ddi_intr_get_pri() failed %d", 275 ret); 276 /* Free already allocated intr */ 277 for (i = 0; i < actual; i++) { 278 (void) ddi_intr_free(statep->htable[i]); 279 } 280 kmem_free(statep->htable, intr_size); 281 return (DDI_FAILURE); 282 } 283 284 /* Test for high level mutex */ 285 if (statep->intr_pri >= ddi_intr_get_hilevel_pri()) { 286 audio_dev_warn(statep->adev, 287 "Hi level interrupt not supported"); 288 for (i = 0; i < actual; i++) 289 (void) ddi_intr_free(statep->htable[i]); 290 kmem_free(statep->htable, intr_size); 291 return (DDI_FAILURE); 292 } 293 294 /* Call ddi_intr_add_handler() */ 295 for (i = 0; i < actual; i++) { 296 if ((ret = ddi_intr_add_handler(statep->htable[i], audiohd_intr, 297 (caddr_t)statep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 298 audio_dev_warn(statep->adev, "ddi_intr_add_handler() " 299 "failed %d", ret); 300 /* Remove already added intr */ 301 for (j = 0; j < i; j++) { 302 ihandle = statep->htable[j]; 303 (void) ddi_intr_remove_handler(ihandle); 304 } 305 /* Free already allocated intr */ 306 for (i = 0; i < actual; i++) { 307 (void) ddi_intr_free(statep->htable[i]); 308 } 309 kmem_free(statep->htable, intr_size); 310 return (DDI_FAILURE); 311 } 312 } 313 314 if ((ret = ddi_intr_get_cap(statep->htable[0], &statep->intr_cap)) 315 != DDI_SUCCESS) { 316 audio_dev_warn(statep->adev, 317 "ddi_intr_get_cap() failed %d", ret); 318 for (i = 0; i < actual; i++) { 319 (void) ddi_intr_remove_handler(statep->htable[i]); 320 (void) ddi_intr_free(statep->htable[i]); 321 } 322 kmem_free(statep->htable, intr_size); 323 return (DDI_FAILURE); 324 } 325 326 return (DDI_SUCCESS); 327 } 328 329 /* 330 * audiohd_rem_intrs: 331 * 332 * Unregister FIXED or MSI interrupts 333 */ 334 static void 335 audiohd_rem_intrs(audiohd_state_t *statep) 336 { 337 338 int i; 339 340 /* Disable all interrupts */ 341 if (statep->intr_cap & DDI_INTR_FLAG_BLOCK) { 342 /* Call ddi_intr_block_disable() */ 343 (void) ddi_intr_block_disable(statep->htable, statep->intr_cnt); 344 } else { 345 for (i = 0; i < statep->intr_cnt; i++) { 346 (void) ddi_intr_disable(statep->htable[i]); 347 } 348 } 349 350 /* Call ddi_intr_remove_handler() */ 351 for (i = 0; i < statep->intr_cnt; i++) { 352 (void) ddi_intr_remove_handler(statep->htable[i]); 353 (void) ddi_intr_free(statep->htable[i]); 354 } 355 356 kmem_free(statep->htable, 357 statep->intr_rqst * sizeof (ddi_intr_handle_t)); 358 } 359 360 static int 361 audiohd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 362 { 363 audiohd_state_t *statep; 364 int instance; 365 int intr_types; 366 int i; 367 368 instance = ddi_get_instance(dip); 369 switch (cmd) { 370 case DDI_ATTACH: 371 break; 372 373 case DDI_RESUME: 374 statep = ddi_get_driver_private(dip); 375 ASSERT(statep != NULL); 376 return (audiohd_resume(statep)); 377 378 default: 379 return (DDI_FAILURE); 380 } 381 382 /* High-level interrupt isn't supported by this driver */ 383 if (ddi_intr_hilevel(dip, 0) != 0) { 384 cmn_err(CE_WARN, 385 "unsupported high level interrupt"); 386 return (DDI_FAILURE); 387 } 388 389 /* allocate the soft state structure */ 390 statep = kmem_zalloc(sizeof (*statep), KM_SLEEP); 391 ddi_set_driver_private(dip, statep); 392 393 /* interrupt cookie and initialize mutex */ 394 if (audiohd_init_state(statep, dip) != DDI_SUCCESS) { 395 cmn_err(CE_NOTE, 396 "audiohd_init_state failed"); 397 goto error; 398 } 399 400 /* Set PCI command register to enable bus master and memeory I/O */ 401 if (audiohd_init_pci(statep, &hda_dev_accattr) != DDI_SUCCESS) { 402 audio_dev_warn(statep->adev, 403 "couldn't init pci regs"); 404 goto error; 405 } 406 407 audiohd_set_chipset_info(statep); 408 409 if (audiohd_init_controller(statep) != DDI_SUCCESS) { 410 audio_dev_warn(statep->adev, 411 "couldn't init controller"); 412 goto error; 413 } 414 415 if (audiohd_create_codec(statep) != DDI_SUCCESS) { 416 audio_dev_warn(statep->adev, 417 "couldn't create codec"); 418 goto error; 419 } 420 421 audiohd_build_path(statep); 422 423 audiohd_get_channels(statep); 424 if (audiohd_allocate_port(statep) != DDI_SUCCESS) { 425 audio_dev_warn(statep->adev, "allocate port failure"); 426 goto error; 427 } 428 audiohd_init_path(statep); 429 /* set up kernel statistics */ 430 if ((statep->hda_ksp = kstat_create(DRVNAME, instance, 431 DRVNAME, "controller", KSTAT_TYPE_INTR, 1, 432 KSTAT_FLAG_PERSISTENT)) != NULL) { 433 kstat_install(statep->hda_ksp); 434 } 435 436 /* disable interrupts and clear interrupt status */ 437 audiohd_disable_intr(statep); 438 439 /* 440 * Get supported interrupt types 441 */ 442 if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) { 443 audio_dev_warn(statep->adev, 444 "ddi_intr_get_supported_types failed"); 445 goto error; 446 } 447 448 /* 449 * Add the h/w interrupt handler and initialise mutexes 450 */ 451 452 if ((intr_types & DDI_INTR_TYPE_MSI) && statep->msi_enable) { 453 if (audiohd_add_intrs(statep, DDI_INTR_TYPE_MSI) == 454 DDI_SUCCESS) { 455 statep->intr_type = DDI_INTR_TYPE_MSI; 456 statep->intr_added = B_TRUE; 457 } 458 } 459 if (!(statep->intr_added) && 460 (intr_types & DDI_INTR_TYPE_FIXED)) { 461 /* MSI registration failed, trying FIXED interrupt type */ 462 if (audiohd_add_intrs(statep, DDI_INTR_TYPE_FIXED) != 463 DDI_SUCCESS) { 464 audio_dev_warn(statep->adev, "FIXED interrupt " 465 "registration failed"); 466 goto error; 467 } 468 /* FIXED interrupt type is supported */ 469 statep->intr_type = DDI_INTR_TYPE_FIXED; 470 statep->intr_added = B_TRUE; 471 } 472 if (!(statep->intr_added)) { 473 audio_dev_warn(statep->adev, "No interrupts registered"); 474 goto error; 475 } 476 mutex_init(&statep->hda_mutex, NULL, MUTEX_DRIVER, 477 DDI_INTR_PRI(statep->intr_pri)); 478 479 /* 480 * Now that mutex lock is initialized, enable interrupts. 481 */ 482 if (statep->intr_cap & DDI_INTR_FLAG_BLOCK) { 483 /* Call ddi_intr_block_enable() for MSI interrupts */ 484 (void) ddi_intr_block_enable(statep->htable, statep->intr_cnt); 485 } else { 486 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 487 for (i = 0; i < statep->intr_cnt; i++) { 488 (void) ddi_intr_enable(statep->htable[i]); 489 } 490 } 491 492 /* 493 * Register audio controls. 494 */ 495 if (audiohd_add_controls(statep) == DDI_FAILURE) { 496 audio_dev_warn(statep->adev, 497 "unable to allocate controls"); 498 goto error; 499 } 500 if (audio_dev_register(statep->adev) != DDI_SUCCESS) { 501 audio_dev_warn(statep->adev, 502 "unable to register with framework"); 503 goto error; 504 } 505 ddi_report_dev(dip); 506 507 /* enable interrupt */ 508 AUDIOHD_REG_SET32(AUDIOHD_REG_INTCTL, 509 AUDIOHD_INTCTL_BIT_GIE | 510 AUDIOHD_INTCTL_BIT_SIE); 511 return (DDI_SUCCESS); 512 error: 513 audiohd_destroy(statep); 514 return (DDI_FAILURE); 515 } 516 517 static int 518 audiohd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 519 { 520 audiohd_state_t *statep; 521 522 statep = ddi_get_driver_private(dip); 523 ASSERT(statep != NULL); 524 525 switch (cmd) { 526 case DDI_DETACH: 527 break; 528 529 case DDI_SUSPEND: 530 return (audiohd_suspend(statep)); 531 532 default: 533 return (DDI_FAILURE); 534 } 535 if (audio_dev_unregister(statep->adev) != DDI_SUCCESS) 536 return (DDI_FAILURE); 537 538 if (audiohd_beep) 539 (void) beep_fini(); 540 audiohd_destroy(statep); 541 return (DDI_SUCCESS); 542 } 543 544 static struct dev_ops audiohd_dev_ops = { 545 DEVO_REV, /* rev */ 546 0, /* refcnt */ 547 NULL, /* getinfo */ 548 nulldev, /* identify */ 549 nulldev, /* probe */ 550 audiohd_attach, /* attach */ 551 audiohd_detach, /* detach */ 552 nodev, /* reset */ 553 NULL, /* cb_ops */ 554 NULL, /* bus_ops */ 555 NULL, /* power */ 556 audiohd_quiesce, /* quiesce */ 557 }; 558 559 static struct modldrv audiohd_modldrv = { 560 &mod_driverops, /* drv_modops */ 561 "AudioHD", /* linkinfo */ 562 &audiohd_dev_ops, /* dev_ops */ 563 }; 564 565 static struct modlinkage modlinkage = { 566 MODREV_1, 567 { &audiohd_modldrv, NULL } 568 }; 569 570 int 571 _init(void) 572 { 573 int rv; 574 575 audio_init_ops(&audiohd_dev_ops, DRVNAME); 576 if ((rv = mod_install(&modlinkage)) != 0) { 577 audio_fini_ops(&audiohd_dev_ops); 578 } 579 return (rv); 580 } 581 582 int 583 _fini(void) 584 { 585 int rv; 586 587 if ((rv = mod_remove(&modlinkage)) == 0) { 588 audio_fini_ops(&audiohd_dev_ops); 589 } 590 return (rv); 591 } 592 593 int 594 _info(struct modinfo *modinfop) 595 { 596 return (mod_info(&modlinkage, modinfop)); 597 } 598 599 /* 600 * Audio routines 601 */ 602 603 static int 604 audiohd_engine_format(void *arg) 605 { 606 _NOTE(ARGUNUSED(arg)); 607 608 return (AUDIO_FORMAT_S16_LE); 609 } 610 611 static int 612 audiohd_engine_channels(void *arg) 613 { 614 audiohd_port_t *port = arg; 615 616 return (port->nchan); 617 } 618 619 static int 620 audiohd_engine_rate(void *arg) 621 { 622 _NOTE(ARGUNUSED(arg)); 623 624 return (48000); 625 } 626 static void 627 audiohd_free_path(audiohd_state_t *statep) 628 { 629 audiohd_path_t *path; 630 int i; 631 632 for (i = 0; i < statep->pathnum; i++) { 633 if (statep->path[i]) { 634 path = statep->path[i]; 635 kmem_free(path, sizeof (audiohd_path_t)); 636 } 637 } 638 } 639 static void 640 audiohd_destroy(audiohd_state_t *statep) 641 { 642 mutex_enter(&statep->hda_mutex); 643 audiohd_stop_dma(statep); 644 audiohd_disable_intr(statep); 645 mutex_exit(&statep->hda_mutex); 646 if (statep->intr_added) { 647 audiohd_rem_intrs(statep); 648 } 649 if (statep->hda_ksp) 650 kstat_delete(statep->hda_ksp); 651 audiohd_free_port(statep); 652 audiohd_free_path(statep); 653 audiohd_destroy_codec(statep); 654 audiohd_del_controls(statep); 655 audiohd_fini_controller(statep); 656 audiohd_fini_pci(statep); 657 mutex_destroy(&statep->hda_mutex); 658 if (statep->adev) 659 audio_dev_free(statep->adev); 660 kmem_free(statep, sizeof (*statep)); 661 } 662 /* 663 * get the max channels the hardware supported 664 */ 665 static void 666 audiohd_get_channels(audiohd_state_t *statep) 667 { 668 int i; 669 uint8_t maxp, assoc; 670 671 maxp = 2; 672 for (i = 0; i < AUDIOHD_MAX_ASSOC; i++) { 673 if (maxp < statep->chann[i]) { 674 maxp = statep->chann[i]; 675 assoc = i; 676 } 677 } 678 statep->pchan = maxp; 679 statep->assoc = assoc; 680 /* for record, support stereo so far */ 681 statep->rchan = 2; 682 } 683 static void 684 audiohd_init_play_path(audiohd_path_t *path) 685 { 686 int i; 687 uint32_t ctrl; 688 uint8_t ctrl8; 689 uint8_t nchann; 690 audiohd_widget_t *widget; 691 audiohd_pin_t *pin; 692 wid_t wid; 693 audiohd_pin_color_t color; 694 695 audiohd_state_t *statep = path->statep; 696 hda_codec_t *codec = path->codec; 697 698 /* enable SPDIF output */ 699 for (i = 0; i < path->pin_nums; i++) { 700 wid = path->pin_wid[i]; 701 widget = codec->widget[wid]; 702 pin = (audiohd_pin_t *)widget->priv; 703 if (pin->device == DTYPE_SPDIF_OUT) { 704 ctrl = audioha_codec_verb_get( 705 statep, 706 codec->index, 707 path->adda_wid, 708 AUDIOHDC_VERB_GET_SPDIF_CTL, 709 0); 710 ctrl |= AUDIOHD_SPDIF_ON; 711 ctrl8 = ctrl & 712 AUDIOHD_SPDIF_MASK; 713 (void) audioha_codec_verb_get( 714 statep, 715 codec->index, 716 path->adda_wid, 717 AUDIOHDC_VERB_SET_SPDIF_LCL, 718 ctrl8); 719 /* 720 * We find that on intel ICH10 chipset with codec 721 * ALC888, audio is scratchy if we set the tag on the 722 * SPDIF path. So we just return here without setting 723 * the tag for the path as a workaround. 724 */ 725 if (codec->vid == AUDIOHD_CODECID_ALC888) { 726 return; 727 } 728 } 729 } 730 wid = path->pin_wid[0]; 731 widget = codec->widget[wid]; 732 pin = (audiohd_pin_t *)widget->priv; 733 734 /* two channels supported */ 735 if (pin->device == DTYPE_SPEAKER || 736 pin->device == DTYPE_HP_OUT || 737 pin->assoc != statep->assoc) { 738 (void) audioha_codec_verb_get( 739 statep, 740 codec->index, 741 path->adda_wid, 742 AUDIOHDC_VERB_SET_STREAM_CHANN, 743 statep->port[PORT_DAC]->index << 744 AUDIOHD_PLAY_TAG_OFF); 745 (void) audioha_codec_4bit_verb_get( 746 statep, 747 codec->index, 748 path->adda_wid, 749 AUDIOHDC_VERB_SET_CONV_FMT, 750 AUDIOHD_FMT_PCM << 4 | 751 statep->pchan - 1); 752 /* multichannel supported */ 753 } else { 754 color = (pin->config >> AUDIOHD_PIN_CLR_OFF) & 755 AUDIOHD_PIN_CLR_MASK; 756 switch (color) { 757 case AUDIOHD_PIN_BLACK: 758 nchann = statep->pchan - 2; 759 break; 760 case AUDIOHD_PIN_ORANGE: 761 nchann = 2; 762 break; 763 case AUDIOHD_PIN_GREY: 764 nchann = 4; 765 break; 766 case AUDIOHD_PIN_GREEN: 767 nchann = 0; 768 break; 769 default: 770 nchann = 0; 771 break; 772 } 773 (void) audioha_codec_verb_get(statep, 774 codec->index, 775 path->adda_wid, 776 AUDIOHDC_VERB_SET_STREAM_CHANN, 777 statep->port[PORT_DAC]->index << 778 AUDIOHD_PLAY_TAG_OFF | 779 nchann); 780 (void) audioha_codec_4bit_verb_get( 781 statep, 782 codec->index, 783 path->adda_wid, 784 AUDIOHDC_VERB_SET_CONV_FMT, 785 AUDIOHD_FMT_PCM << 4 | 786 statep->pchan - 1); 787 } 788 } 789 static void 790 audiohd_init_record_path(audiohd_path_t *path) 791 { 792 audiohd_state_t *statep = path->statep; 793 hda_codec_t *codec = path->codec; 794 int i; 795 wid_t wid; 796 audiohd_pin_t *pin; 797 audiohd_widget_t *widget; 798 799 for (i = 0; i < path->pin_nums; i++) { 800 wid = path->pin_wid[i]; 801 widget = codec->widget[wid]; 802 pin = (audiohd_pin_t *)widget->priv; 803 /* 804 * Since there is no SPDIF input device available for test, 805 * we will use this code in the future to support SPDIF input 806 */ 807 #if 0 808 if (pin->device == DTYPE_SPDIF_IN) { 809 ctrl = audioha_codec_verb_get( 810 statep, 811 codec->index, 812 path->adda_wid, 813 AUDIOHDC_VERB_GET_SPDIF_CTL, 814 0); 815 ctrl |= AUDIOHD_SPDIF_ON; 816 ctrl8 = ctrl & 817 AUDIOHD_SPDIF_MASK; 818 (void) audioha_codec_verb_get( 819 statep, 820 codec->index, 821 path->adda_wid, 822 AUDIOHDC_VERB_SET_SPDIF_LCL, 823 ctrl8); 824 statep->inmask |= (1U << DTYPE_SPDIF_IN); 825 } 826 #endif 827 if (pin->device == DTYPE_MIC_IN) { 828 if (((pin->config >> 829 AUDIOHD_PIN_CONTP_OFF) & 830 AUDIOHD_PIN_CONTP_MASK) == 831 AUDIOHD_PIN_CON_FIXED) 832 statep->port[PORT_ADC]->index = path->tag; 833 } 834 if ((pin->device == DTYPE_LINE_IN) || 835 (pin->device == DTYPE_CD) || 836 (pin->device == DTYPE_MIC_IN)) { 837 statep->inmask |= (1U << pin->device); 838 } 839 } 840 (void) audioha_codec_verb_get(statep, 841 codec->index, 842 path->adda_wid, 843 AUDIOHDC_VERB_SET_STREAM_CHANN, 844 path->tag << 845 AUDIOHD_REC_TAG_OFF); 846 (void) audioha_codec_4bit_verb_get(statep, 847 codec->index, 848 path->adda_wid, 849 AUDIOHDC_VERB_SET_CONV_FMT, 850 AUDIOHD_FMT_PCM << 4 | statep->rchan - 1); 851 852 } 853 static void 854 audiohd_init_path(audiohd_state_t *statep) 855 { 856 int i; 857 audiohd_path_t *path; 858 859 for (i = 0; i < statep->pathnum; i++) { 860 path = statep->path[i]; 861 if (!path) 862 continue; 863 switch (path->path_type) { 864 case PLAY: 865 audiohd_init_play_path(path); 866 break; 867 case RECORD: 868 audiohd_init_record_path(path); 869 break; 870 default: 871 break; 872 } 873 } 874 statep->in_port = 0; 875 } 876 877 static int 878 audiohd_reset_port(audiohd_port_t *port) 879 { 880 uint16_t regbase; 881 audiohd_state_t *statep; 882 uint8_t bTmp; 883 int i; 884 885 regbase = port->regoff; 886 statep = port->statep; 887 888 bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL); 889 /* stop stream */ 890 bTmp &= ~AUDIOHD_REG_RIRBSIZE; 891 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp); 892 893 /* wait 40us for stream to stop as HD spec */ 894 drv_usecwait(40); 895 896 /* reset stream */ 897 bTmp |= AUDIOHDR_SD_CTL_SRST; 898 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp); 899 900 for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) { 901 /* Empirical testing time, which works well */ 902 drv_usecwait(50); 903 bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL); 904 bTmp &= AUDIOHDR_SD_CTL_SRST; 905 if (bTmp) 906 break; 907 } 908 909 if (!bTmp) { 910 audio_dev_warn(statep->adev, "Failed to reset stream %d", 911 port->index); 912 return (DDI_FAILURE); 913 } 914 915 /* Empirical testing time, which works well */ 916 drv_usecwait(300); 917 918 /* exit reset stream */ 919 bTmp &= ~AUDIOHDR_SD_CTL_SRST; 920 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp); 921 922 for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) { 923 /* Empircal testing time */ 924 drv_usecwait(50); 925 bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL); 926 bTmp &= AUDIOHDR_SD_CTL_SRST; 927 if (!bTmp) 928 break; 929 } 930 931 if (bTmp) { 932 audio_dev_warn(statep->adev, 933 "Failed to exit reset state for" 934 " stream %d, bTmp=0x%02x", port->index, bTmp); 935 return (DDI_FAILURE); 936 } 937 938 AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPL, 939 (uint32_t)port->bdl_paddr); 940 AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPU, 941 (uint32_t)(port->bdl_paddr >> 32)); 942 AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_LVI, 943 AUDIOHD_BDLE_NUMS - 1); 944 AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_CBL, 945 port->samp_size * AUDIOHD_BDLE_NUMS); 946 947 AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_FORMAT, 948 port->format << 4 | port->nchan - 1); 949 950 /* clear status */ 951 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_STS, 952 AUDIOHDR_SD_STS_BCIS | AUDIOHDR_SD_STS_FIFOE | 953 AUDIOHDR_SD_STS_DESE); 954 955 /* set stream tag */ 956 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL + 957 AUDIOHD_PLAY_CTL_OFF, 958 (port->index) << AUDIOHD_PLAY_TAG_OFF); 959 960 return (DDI_SUCCESS); 961 } 962 static int 963 audiohd_engine_open(void *arg, int flag, 964 unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp) 965 { 966 audiohd_port_t *port = arg; 967 audiohd_state_t *statep = port->statep; 968 969 _NOTE(ARGUNUSED(flag)); 970 971 mutex_enter(&statep->hda_mutex); 972 (void) audiohd_reset_port(port); 973 mutex_exit(&statep->hda_mutex); 974 975 port->started = B_FALSE; 976 port->count = 0; 977 port->curpos = 0; 978 *fragfrp = port->fragfr; 979 *nfragsp = AUDIOHD_BDLE_NUMS; 980 *bufp = port->samp_kaddr; 981 982 return (0); 983 } 984 985 static void 986 audiohd_start_port(audiohd_port_t *port) 987 { 988 audiohd_state_t *statep = port->statep; 989 990 ASSERT(mutex_owned(&statep->hda_mutex)); 991 992 /* if suspended, then do nothing else */ 993 if (statep->suspended) { 994 return; 995 } 996 997 /* Enable interrupt and start DMA */ 998 AUDIOHD_REG_SET8(port->regoff + AUDIOHD_SDREG_OFFSET_CTL, 999 AUDIOHDR_SD_CTL_INTS | AUDIOHDR_SD_CTL_SRUN); 1000 } 1001 1002 static void 1003 audiohd_stop_port(audiohd_port_t *port) 1004 { 1005 audiohd_state_t *statep = port->statep; 1006 1007 ASSERT(mutex_owned(&statep->hda_mutex)); 1008 /* if suspended, then do nothing else */ 1009 if (statep->suspended) { 1010 return; 1011 } 1012 AUDIOHD_REG_SET8(port->regoff + AUDIOHD_SDREG_OFFSET_CTL, 0); 1013 } 1014 1015 static int 1016 audiohd_engine_start(void *arg) 1017 { 1018 audiohd_port_t *port = arg; 1019 audiohd_state_t *statep = port->statep; 1020 1021 mutex_enter(&statep->hda_mutex); 1022 if (!port->started) { 1023 audiohd_start_port(port); 1024 port->started = B_TRUE; 1025 port->triggered = B_TRUE; 1026 } 1027 mutex_exit(&statep->hda_mutex); 1028 return (0); 1029 } 1030 1031 static void 1032 audiohd_engine_stop(void *arg) 1033 { 1034 audiohd_port_t *port = arg; 1035 audiohd_state_t *statep = port->statep; 1036 1037 mutex_enter(&statep->hda_mutex); 1038 if (port->started) { 1039 audiohd_stop_port(port); 1040 } 1041 port->started = B_FALSE; 1042 mutex_exit(&statep->hda_mutex); 1043 } 1044 1045 static void 1046 audiohd_update_port(audiohd_port_t *port) 1047 { 1048 int pos; 1049 uint32_t len; 1050 audiohd_state_t *statep = port->statep; 1051 1052 pos = AUDIOHD_REG_GET32(port->regoff + AUDIOHD_SDREG_OFFSET_LPIB); 1053 pos &= AUDIOHD_POS_MASK; 1054 if (pos > port->curpos) 1055 len = (pos - port->curpos) & AUDIOHD_POS_MASK; 1056 else { 1057 len = pos + port->samp_size * AUDIOHD_BDLE_NUMS - port->curpos; 1058 len &= AUDIOHD_POS_MASK; 1059 } 1060 port->curpos += len; 1061 if (port->curpos >= port->samp_size * AUDIOHD_BDLE_NUMS) 1062 port->curpos -= port->samp_size * AUDIOHD_BDLE_NUMS; 1063 1064 port->count += len / (port->nchan * 2); 1065 1066 1067 } 1068 1069 static uint64_t 1070 audiohd_engine_count(void *arg) 1071 { 1072 audiohd_port_t *port = arg; 1073 audiohd_state_t *statep = port->statep; 1074 uint64_t val; 1075 1076 mutex_enter(&statep->hda_mutex); 1077 audiohd_update_port(port); 1078 val = port->count; 1079 mutex_exit(&statep->hda_mutex); 1080 return (val); 1081 } 1082 1083 static void 1084 audiohd_engine_close(void *arg) 1085 { 1086 audiohd_port_t *port = arg; 1087 audiohd_state_t *statep = port->statep; 1088 1089 mutex_enter(&statep->hda_mutex); 1090 audiohd_stop_port(port); 1091 port->started = B_FALSE; 1092 port->triggered = B_FALSE; 1093 mutex_exit(&statep->hda_mutex); 1094 } 1095 1096 static void 1097 audiohd_engine_sync(void *arg, unsigned nframes) 1098 { 1099 audiohd_port_t *port = arg; 1100 1101 _NOTE(ARGUNUSED(nframes)); 1102 1103 (void) ddi_dma_sync(port->samp_dmah, 0, 1104 0, port->sync_dir); 1105 1106 } 1107 1108 static size_t 1109 audiohd_engine_qlen(void *arg) 1110 { 1111 audiohd_port_t *port = arg; 1112 1113 return (port->fragfr); 1114 } 1115 1116 audio_engine_ops_t audiohd_engine_ops = { 1117 AUDIO_ENGINE_VERSION, /* version number */ 1118 audiohd_engine_open, 1119 audiohd_engine_close, 1120 audiohd_engine_start, 1121 audiohd_engine_stop, 1122 audiohd_engine_count, 1123 audiohd_engine_format, 1124 audiohd_engine_channels, 1125 audiohd_engine_rate, 1126 audiohd_engine_sync, 1127 audiohd_engine_qlen, 1128 }; 1129 1130 static int 1131 audiohd_get_value(void *arg, uint64_t *val) 1132 { 1133 audiohd_ctrl_t *pc = arg; 1134 audiohd_state_t *statep = pc->statep; 1135 1136 mutex_enter(&statep->hda_mutex); 1137 *val = pc->val; 1138 mutex_exit(&statep->hda_mutex); 1139 return (0); 1140 } 1141 1142 static void 1143 audiohd_set_output_gain(audiohd_state_t *statep) 1144 { 1145 int i; 1146 audiohd_path_t *path; 1147 uint_t tmp; 1148 wid_t wid; 1149 audiohd_widget_t *w; 1150 uint8_t gain; 1151 uint32_t maxgain; 1152 1153 if (statep->soft_volume) 1154 return; 1155 gain = (uint8_t)statep->controls[CTL_VOLUME]->val; 1156 for (i = 0; i < statep->pathnum; i++) { 1157 path = statep->path[i]; 1158 if (!path || path->path_type != PLAY) 1159 continue; 1160 /* use the DACs to adjust the volume */ 1161 wid = path->adda_wid; 1162 w = path->codec->widget[wid]; 1163 maxgain = w->outamp_cap & 1164 AUDIOHDC_AMP_CAP_STEP_NUMS; 1165 maxgain >>= AUDIOHD_GAIN_OFF; 1166 if (w->outamp_cap) { 1167 tmp = gain * maxgain / 100; 1168 (void) audioha_codec_4bit_verb_get(statep, 1169 path->codec->index, 1170 wid, 1171 AUDIOHDC_VERB_SET_AMP_MUTE, 1172 AUDIOHDC_AMP_SET_LEFT | 1173 AUDIOHDC_AMP_SET_OUTPUT | tmp); 1174 (void) audioha_codec_4bit_verb_get(statep, 1175 path->codec->index, 1176 wid, 1177 AUDIOHDC_VERB_SET_AMP_MUTE, 1178 AUDIOHDC_AMP_SET_RIGHT | 1179 AUDIOHDC_AMP_SET_OUTPUT | tmp); 1180 } 1181 } 1182 } 1183 1184 static void 1185 audiohd_do_set_pin_volume(audiohd_state_t *statep, audiohd_path_t *path, 1186 uint64_t val) 1187 { 1188 uint8_t l, r; 1189 uint_t tmp; 1190 int gain; 1191 1192 if (path->mute_wid && val == 0) { 1193 (void) audioha_codec_4bit_verb_get( 1194 statep, 1195 path->codec->index, 1196 path->mute_wid, 1197 AUDIOHDC_VERB_SET_AMP_MUTE, 1198 path->mute_dir | 1199 AUDIOHDC_AMP_SET_LNR | 1200 AUDIOHDC_AMP_SET_MUTE); 1201 return; 1202 } 1203 1204 l = (val & 0xff00) >> 8; 1205 r = (val & 0xff); 1206 1207 tmp = l * path->gain_bits / 100; 1208 (void) audioha_codec_4bit_verb_get(statep, 1209 path->codec->index, 1210 path->gain_wid, 1211 AUDIOHDC_VERB_SET_AMP_MUTE, 1212 AUDIOHDC_AMP_SET_LEFT | path->gain_dir | 1213 tmp); 1214 tmp = r * path->gain_bits / 100; 1215 (void) audioha_codec_4bit_verb_get(statep, 1216 path->codec->index, 1217 path->gain_wid, 1218 AUDIOHDC_VERB_SET_AMP_MUTE, 1219 AUDIOHDC_AMP_SET_RIGHT | path->gain_dir | 1220 tmp); 1221 if (path->mute_wid && path->mute_wid != path->gain_wid) { 1222 gain = AUDIOHDC_GAIN_MAX; 1223 (void) audioha_codec_4bit_verb_get( 1224 statep, 1225 path->codec->index, 1226 path->mute_wid, 1227 AUDIOHDC_VERB_SET_AMP_MUTE, 1228 path->mute_dir | 1229 AUDIOHDC_AMP_SET_LEFT | 1230 gain); 1231 (void) audioha_codec_4bit_verb_get( 1232 statep, 1233 path->codec->index, 1234 path->mute_wid, 1235 AUDIOHDC_VERB_SET_AMP_MUTE, 1236 path->mute_dir | 1237 AUDIOHDC_AMP_SET_RIGHT | 1238 gain); 1239 } 1240 } 1241 1242 static void 1243 audiohd_set_pin_volume(audiohd_state_t *statep, audiohda_device_type_t type) 1244 { 1245 int i, j; 1246 audiohd_path_t *path; 1247 audiohd_widget_t *widget; 1248 wid_t wid; 1249 audiohd_pin_t *pin; 1250 hda_codec_t *codec; 1251 uint64_t val; 1252 audiohd_ctrl_t *control; 1253 1254 switch (type) { 1255 case DTYPE_SPEAKER: 1256 control = statep->controls[CTL_SPEAKER]; 1257 if (control == NULL) 1258 return; 1259 val = control->val; 1260 break; 1261 case DTYPE_HP_OUT: 1262 control = statep->controls[CTL_HEADPHONE]; 1263 if (control == NULL) 1264 return; 1265 val = control->val; 1266 break; 1267 case DTYPE_LINEOUT: 1268 control = statep->controls[CTL_FRONT]; 1269 if (control == NULL) 1270 return; 1271 val = control->val; 1272 break; 1273 1274 case DTYPE_CD: 1275 control = statep->controls[CTL_CD]; 1276 if (control == NULL) 1277 return; 1278 val = control->val; 1279 break; 1280 case DTYPE_LINE_IN: 1281 control = statep->controls[CTL_LINEIN]; 1282 if (control == NULL) 1283 return; 1284 val = control->val; 1285 break; 1286 case DTYPE_MIC_IN: 1287 control = statep->controls[CTL_MIC]; 1288 if (control == NULL) 1289 return; 1290 val = control->val; 1291 break; 1292 } 1293 1294 for (i = 0; i < statep->pathnum; i++) { 1295 path = statep->path[i]; 1296 if (!path) 1297 continue; 1298 codec = path->codec; 1299 for (j = 0; j < path->pin_nums; j++) { 1300 wid = path->pin_wid[j]; 1301 widget = codec->widget[wid]; 1302 pin = (audiohd_pin_t *)widget->priv; 1303 if ((pin->device == type) && path->gain_wid) { 1304 audiohd_do_set_pin_volume(statep, path, val); 1305 } 1306 } 1307 } 1308 } 1309 1310 1311 static void 1312 audiohd_set_pin_volume_by_color(audiohd_state_t *statep, 1313 audiohd_pin_color_t color) 1314 { 1315 int i, j; 1316 audiohd_path_t *path; 1317 audiohd_widget_t *widget; 1318 wid_t wid; 1319 audiohd_pin_t *pin; 1320 hda_codec_t *codec; 1321 uint8_t l, r; 1322 uint64_t val; 1323 audiohd_pin_color_t clr; 1324 audiohd_ctrl_t *control; 1325 1326 switch (color) { 1327 case AUDIOHD_PIN_GREEN: 1328 control = statep->controls[CTL_FRONT]; 1329 if (control == NULL) 1330 return; 1331 val = control->val; 1332 break; 1333 case AUDIOHD_PIN_BLACK: 1334 control = statep->controls[CTL_REAR]; 1335 if (control == NULL) 1336 return; 1337 val = control->val; 1338 break; 1339 case AUDIOHD_PIN_ORANGE: 1340 control = statep->controls[CTL_CENTER]; 1341 if (control == NULL) 1342 return; 1343 l = control->val; 1344 control = statep->controls[CTL_LFE]; 1345 if (control == NULL) 1346 return; 1347 r = control->val; 1348 val = (l << 8) | r; 1349 break; 1350 case AUDIOHD_PIN_GREY: 1351 control = statep->controls[CTL_SURROUND]; 1352 if (control == NULL) 1353 return; 1354 val = control->val; 1355 break; 1356 } 1357 1358 for (i = 0; i < statep->pathnum; i++) { 1359 path = statep->path[i]; 1360 if (!path) 1361 continue; 1362 codec = path->codec; 1363 for (j = 0; j < path->pin_nums; j++) { 1364 wid = path->pin_wid[j]; 1365 widget = codec->widget[wid]; 1366 pin = (audiohd_pin_t *)widget->priv; 1367 clr = (pin->config >> AUDIOHD_PIN_CLR_OFF) & 1368 AUDIOHD_PIN_CLR_MASK; 1369 if ((clr == color) && path->gain_wid) { 1370 audiohd_do_set_pin_volume(statep, path, val); 1371 } 1372 } 1373 } 1374 } 1375 1376 static int 1377 audiohd_set_input_pin(audiohd_state_t *statep) 1378 { 1379 uint64_t val; 1380 hda_codec_t *codec; 1381 audiohd_pin_t *pin; 1382 audiohd_path_t *path; 1383 audiohd_widget_t *widget, *w; 1384 int i, j; 1385 wid_t wid, pin_wid = 0; 1386 1387 val = statep->controls[CTL_RECSRC]->val; 1388 for (i = 0; i < statep->pathnum; i++) { 1389 path = statep->path[i]; 1390 if (!path || path->path_type != RECORD) 1391 continue; 1392 switch ((ddi_ffs(val & 0xffff)) - 1) { 1393 case DTYPE_LINE_IN: 1394 case DTYPE_MIC_IN: 1395 case DTYPE_CD: 1396 for (j = 0; j < path->pin_nums; j++) { 1397 wid = path->pin_wid[j]; 1398 widget = path->codec->widget[wid]; 1399 pin = (audiohd_pin_t *)widget->priv; 1400 if ((1U << pin->device) == val) { 1401 AUDIOHD_ENABLE_PIN_IN(statep, 1402 path->codec->index, 1403 pin->wid); 1404 pin_wid = pin->wid; 1405 codec = path->codec; 1406 statep->in_port = pin->device; 1407 } else if (statep->in_port == pin->device) { 1408 AUDIOHD_DISABLE_PIN_IN(statep, 1409 path->codec->index, 1410 pin->wid); 1411 } 1412 } 1413 break; 1414 default: 1415 break; 1416 } 1417 break; 1418 } 1419 if (pin_wid == 0) 1420 return (DDI_SUCCESS); 1421 w = codec->widget[pin_wid]; 1422 pin = (audiohd_pin_t *)w->priv; 1423 w = codec->widget[pin->adc_dac_wid]; 1424 path = (audiohd_path_t *)w->priv; 1425 /* 1426 * If there is a real selector in this input path, 1427 * we select the right one input for the selector. 1428 */ 1429 if (path->sum_wid) { 1430 w = codec->widget[path->sum_wid]; 1431 if (w->type == WTYPE_AUDIO_SEL) { 1432 for (i = 0; i < path->pin_nums; i++) 1433 if (path->pin_wid[i] == pin_wid) 1434 break; 1435 (void) audioha_codec_verb_get( 1436 statep, codec->index, path->sum_wid, 1437 AUDIOHDC_VERB_SET_CONN_SEL, 1438 path->sum_selconn[i]); 1439 } 1440 } 1441 return (DDI_SUCCESS); 1442 } 1443 1444 static void 1445 audiohd_set_pin_monitor_gain(hda_codec_t *codec, audiohd_state_t *statep, 1446 uint_t caddr, audiohd_pin_t *pin, uint64_t gain) 1447 { 1448 int i, k; 1449 uint_t ltmp, rtmp; 1450 audiohd_widget_t *widget; 1451 uint8_t l, r; 1452 1453 l = (gain & 0xff00) >> 8; 1454 r = (gain & 0xff); 1455 1456 for (k = 0; k < pin->num; k++) { 1457 ltmp = l * pin->mg_gain[k] / 100; 1458 rtmp = r * pin->mg_gain[k] / 100; 1459 widget = codec->widget[pin->mg_wid[k]]; 1460 if (pin->mg_dir[k] == AUDIOHDC_AMP_SET_OUTPUT) { 1461 (void) audioha_codec_4bit_verb_get( 1462 statep, 1463 caddr, 1464 pin->mg_wid[k], 1465 AUDIOHDC_VERB_SET_AMP_MUTE, 1466 AUDIOHDC_AMP_SET_LEFT| 1467 pin->mg_dir[k] | ltmp); 1468 (void) audioha_codec_4bit_verb_get( 1469 statep, 1470 caddr, 1471 pin->mg_wid[k], 1472 AUDIOHDC_VERB_SET_AMP_MUTE, 1473 AUDIOHDC_AMP_SET_RIGHT| 1474 pin->mg_dir[k] | rtmp); 1475 } else if (pin->mg_dir[k] == AUDIOHDC_AMP_SET_INPUT) { 1476 for (i = 0; i < widget->used; i++) { 1477 (void) audioha_codec_4bit_verb_get( 1478 statep, 1479 caddr, 1480 pin->mg_wid[k], 1481 AUDIOHDC_VERB_SET_AMP_MUTE, 1482 AUDIOHDC_AMP_SET_RIGHT| 1483 widget->selmon[i]<< 1484 AUDIOHDC_AMP_SET_INDEX_OFFSET | 1485 pin->mg_dir[k] | rtmp); 1486 (void) audioha_codec_4bit_verb_get( 1487 statep, 1488 caddr, 1489 pin->mg_wid[k], 1490 AUDIOHDC_VERB_SET_AMP_MUTE, 1491 AUDIOHDC_AMP_SET_LEFT| 1492 widget->selmon[i]<< 1493 AUDIOHDC_AMP_SET_INDEX_OFFSET | 1494 pin->mg_dir[k] | ltmp); 1495 } 1496 } 1497 } 1498 } 1499 1500 static void 1501 audiohd_set_monitor_gain(audiohd_state_t *statep) 1502 { 1503 int i, j; 1504 audiohd_path_t *path; 1505 uint_t caddr; 1506 audiohd_widget_t *w; 1507 wid_t wid; 1508 audiohd_pin_t *pin; 1509 audiohd_ctrl_t *ctrl; 1510 uint64_t val; 1511 1512 ctrl = statep->controls[CTL_MONGAIN]; 1513 if (ctrl == NULL) 1514 return; 1515 val = ctrl->val; 1516 1517 for (i = 0; i < statep->pathnum; i++) { 1518 path = statep->path[i]; 1519 if (path == NULL || path->path_type != PLAY) 1520 continue; 1521 caddr = path->codec->index; 1522 for (j = 0; j < path->pin_nums; j++) { 1523 wid = path->pin_wid[j]; 1524 w = path->codec->widget[wid]; 1525 pin = (audiohd_pin_t *)w->priv; 1526 audiohd_set_pin_monitor_gain(path->codec, statep, 1527 caddr, pin, val); 1528 } 1529 } 1530 1531 } 1532 1533 static void 1534 audiohd_set_beep_volume(audiohd_state_t *statep) 1535 { 1536 int i; 1537 audiohd_path_t *path; 1538 hda_codec_t *codec; 1539 uint64_t val; 1540 uint_t tmp; 1541 audiohd_ctrl_t *control; 1542 uint32_t vid; 1543 1544 control = statep->controls[CTL_BEEP]; 1545 if (control == NULL) 1546 return; 1547 val = control->val; 1548 for (i = 0; i < statep->pathnum; i++) { 1549 path = statep->path[i]; 1550 if (!path || path->path_type != BEEP) 1551 continue; 1552 codec = path->codec; 1553 vid = codec->vid; 1554 vid = vid >> 16; 1555 1556 switch (vid) { 1557 case AUDIOHD_VID_SIGMATEL: 1558 /* 1559 * Sigmatel HD codec specific operation. 1560 * There is a workaround, 1561 * Due to Sigmatel HD codec hardware problem, 1562 * which it can't mute beep when volume is 0. 1563 * So add global value audiohd_beep_vol, 1564 * Set freq to 0 when volume is 0. 1565 */ 1566 tmp = val * path->gain_bits / 100; 1567 if (tmp == 0) { 1568 audiohd_beep_vol = 0; 1569 } else { 1570 audiohd_beep_vol = tmp; 1571 (void) audioha_codec_verb_get( 1572 statep, 1573 codec->index, 1574 path->beep_wid, 1575 AUDIOHDC_VERB_SET_BEEP_VOL, 1576 tmp); 1577 } 1578 break; 1579 1580 default: 1581 /* Common operation based on audiohd spec */ 1582 audiohd_do_set_beep_volume(statep, path, val); 1583 break; 1584 } 1585 } 1586 } 1587 1588 static void 1589 audiohd_do_set_beep_volume(audiohd_state_t *statep, audiohd_path_t *path, 1590 uint64_t val) 1591 { 1592 uint8_t l, r; 1593 uint_t tmp; 1594 int gain; 1595 1596 if (val == 0) { 1597 (void) audioha_codec_4bit_verb_get( 1598 statep, 1599 path->codec->index, 1600 path->mute_wid, 1601 AUDIOHDC_VERB_SET_AMP_MUTE, 1602 path->mute_dir | 1603 AUDIOHDC_AMP_SET_LNR | 1604 AUDIOHDC_AMP_SET_MUTE); 1605 return; 1606 } 1607 1608 r = (val & 0xff); 1609 l = r; 1610 1611 tmp = l * path->gain_bits / 100; 1612 (void) audioha_codec_4bit_verb_get(statep, 1613 path->codec->index, 1614 path->gain_wid, 1615 AUDIOHDC_VERB_SET_AMP_MUTE, 1616 AUDIOHDC_AMP_SET_LEFT | path->gain_dir | 1617 tmp); 1618 tmp = r * path->gain_bits / 100; 1619 (void) audioha_codec_4bit_verb_get(statep, 1620 path->codec->index, 1621 path->gain_wid, 1622 AUDIOHDC_VERB_SET_AMP_MUTE, 1623 AUDIOHDC_AMP_SET_RIGHT | path->gain_dir | 1624 tmp); 1625 if (path->mute_wid != path->gain_wid) { 1626 gain = AUDIOHDC_GAIN_MAX; 1627 (void) audioha_codec_4bit_verb_get( 1628 statep, 1629 path->codec->index, 1630 path->mute_wid, 1631 AUDIOHDC_VERB_SET_AMP_MUTE, 1632 path->mute_dir | 1633 AUDIOHDC_AMP_SET_LEFT | 1634 gain); 1635 (void) audioha_codec_4bit_verb_get( 1636 statep, 1637 path->codec->index, 1638 path->mute_wid, 1639 AUDIOHDC_VERB_SET_AMP_MUTE, 1640 path->mute_dir | 1641 AUDIOHDC_AMP_SET_RIGHT | 1642 gain); 1643 } 1644 } 1645 1646 static void 1647 audiohd_configure_output(audiohd_state_t *statep) 1648 { 1649 audiohd_set_pin_volume(statep, DTYPE_LINEOUT); 1650 audiohd_set_pin_volume(statep, DTYPE_SPEAKER); 1651 audiohd_set_pin_volume(statep, DTYPE_HP_OUT); 1652 1653 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREEN); 1654 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_BLACK); 1655 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREY); 1656 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE); 1657 1658 audiohd_set_output_gain(statep); 1659 } 1660 static void 1661 audiohd_configure_input(audiohd_state_t *statep) 1662 { 1663 (void) audiohd_set_input_pin(statep); 1664 audiohd_set_monitor_gain(statep); 1665 audiohd_set_pin_volume(statep, DTYPE_LINE_IN); 1666 audiohd_set_pin_volume(statep, DTYPE_CD); 1667 audiohd_set_pin_volume(statep, DTYPE_MIC_IN); 1668 } 1669 static int 1670 audiohd_set_volume(void *arg, uint64_t val) 1671 { 1672 audiohd_ctrl_t *pc = arg; 1673 audiohd_state_t *statep = pc->statep; 1674 1675 val &= 0xff; 1676 if (val > 100) 1677 return (EINVAL); 1678 1679 mutex_enter(&statep->hda_mutex); 1680 pc->val = val; 1681 audiohd_configure_output(statep); 1682 mutex_exit(&statep->hda_mutex); 1683 1684 return (0); 1685 } 1686 1687 static int 1688 audiohd_set_recsrc(void *arg, uint64_t val) 1689 { 1690 audiohd_ctrl_t *pc = arg; 1691 audiohd_state_t *statep = pc->statep; 1692 1693 if (val & ~(statep->inmask)) 1694 return (EINVAL); 1695 1696 mutex_enter(&statep->hda_mutex); 1697 pc->val = val; 1698 audiohd_configure_input(statep); 1699 mutex_exit(&statep->hda_mutex); 1700 return (0); 1701 } 1702 1703 static int 1704 audiohd_set_rear(void *arg, uint64_t val) 1705 { 1706 audiohd_ctrl_t *pc = arg; 1707 audiohd_state_t *statep = pc->statep; 1708 uint8_t l, r; 1709 1710 if (val & ~0xffff) 1711 return (EINVAL); 1712 1713 l = (val & 0xff00) >> 8; 1714 r = (val & 0xff); 1715 if ((l > 100) || (r > 100)) 1716 return (EINVAL); 1717 1718 mutex_enter(&statep->hda_mutex); 1719 pc->val = val; 1720 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_BLACK); 1721 mutex_exit(&statep->hda_mutex); 1722 1723 return (0); 1724 } 1725 1726 static int 1727 audiohd_set_center(void *arg, uint64_t val) 1728 { 1729 audiohd_ctrl_t *pc = arg; 1730 audiohd_state_t *statep = pc->statep; 1731 1732 val &= 0xff; 1733 1734 if (val > 100) 1735 return (EINVAL); 1736 1737 mutex_enter(&statep->hda_mutex); 1738 pc->val = val; 1739 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE); 1740 mutex_exit(&statep->hda_mutex); 1741 1742 return (0); 1743 } 1744 1745 static int 1746 audiohd_set_surround(void *arg, uint64_t val) 1747 { 1748 audiohd_ctrl_t *pc = arg; 1749 audiohd_state_t *statep = pc->statep; 1750 uint8_t l, r; 1751 1752 if (val & ~0xffff) 1753 return (EINVAL); 1754 1755 l = (val & 0xff00) >> 8; 1756 r = (val & 0xff); 1757 if ((l > 100) || (r > 100)) 1758 return (EINVAL); 1759 1760 mutex_enter(&statep->hda_mutex); 1761 pc->val = val; 1762 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREY); 1763 mutex_exit(&statep->hda_mutex); 1764 1765 return (0); 1766 } 1767 1768 static int 1769 audiohd_set_lfe(void *arg, uint64_t val) 1770 { 1771 audiohd_ctrl_t *pc = arg; 1772 audiohd_state_t *statep = pc->statep; 1773 1774 val &= 0xff; 1775 1776 if (val > 100) 1777 return (EINVAL); 1778 1779 mutex_enter(&statep->hda_mutex); 1780 pc->val = val; 1781 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE); 1782 mutex_exit(&statep->hda_mutex); 1783 1784 return (0); 1785 } 1786 static int 1787 audiohd_set_speaker(void *arg, uint64_t val) 1788 { 1789 audiohd_ctrl_t *pc = arg; 1790 audiohd_state_t *statep = pc->statep; 1791 uint8_t l, r; 1792 1793 if (val & ~0xffff) 1794 return (EINVAL); 1795 1796 l = (val & 0xff00) >> 8; 1797 r = (val & 0xff); 1798 if ((l > 100) || (r > 100)) 1799 return (EINVAL); 1800 1801 mutex_enter(&statep->hda_mutex); 1802 pc->val = val; 1803 audiohd_set_pin_volume(statep, DTYPE_SPEAKER); 1804 mutex_exit(&statep->hda_mutex); 1805 1806 return (0); 1807 } 1808 static int 1809 audiohd_set_front(void *arg, uint64_t val) 1810 { 1811 audiohd_ctrl_t *pc = arg; 1812 audiohd_state_t *statep = pc->statep; 1813 uint8_t l, r; 1814 1815 if (val & ~0xffff) 1816 return (EINVAL); 1817 1818 l = (val & 0xff00) >> 8; 1819 r = (val & 0xff); 1820 if ((l > 100) || (r > 100)) 1821 return (EINVAL); 1822 1823 mutex_enter(&statep->hda_mutex); 1824 pc->val = val; 1825 audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREEN); 1826 mutex_exit(&statep->hda_mutex); 1827 1828 return (0); 1829 } 1830 static int 1831 audiohd_set_headphone(void *arg, uint64_t val) 1832 { 1833 audiohd_ctrl_t *pc = arg; 1834 audiohd_state_t *statep = pc->statep; 1835 uint8_t l, r; 1836 1837 if (val & ~0xffff) 1838 return (EINVAL); 1839 1840 l = (val & 0xff00) >> 8; 1841 r = (val & 0xff); 1842 if ((l > 100) || (r > 100)) 1843 return (EINVAL); 1844 1845 mutex_enter(&statep->hda_mutex); 1846 pc->val = val; 1847 audiohd_set_pin_volume(statep, DTYPE_HP_OUT); 1848 mutex_exit(&statep->hda_mutex); 1849 1850 return (0); 1851 } 1852 static int 1853 audiohd_set_linein(void *arg, uint64_t val) 1854 { 1855 audiohd_ctrl_t *pc = arg; 1856 audiohd_state_t *statep = pc->statep; 1857 uint8_t l, r; 1858 1859 if (val & ~0xffff) 1860 return (EINVAL); 1861 1862 l = (val & 0xff00) >> 8; 1863 r = (val & 0xff); 1864 if ((l > 100) || (r > 100)) 1865 return (EINVAL); 1866 1867 mutex_enter(&statep->hda_mutex); 1868 pc->val = val; 1869 audiohd_set_pin_volume(statep, DTYPE_LINE_IN); 1870 mutex_exit(&statep->hda_mutex); 1871 1872 return (0); 1873 } 1874 1875 static int 1876 audiohd_set_mic(void *arg, uint64_t val) 1877 { 1878 audiohd_ctrl_t *pc = arg; 1879 audiohd_state_t *statep = pc->statep; 1880 uint8_t l, r; 1881 1882 if (val & ~0xffff) 1883 return (EINVAL); 1884 1885 l = (val & 0xff00) >> 8; 1886 r = (val & 0xff); 1887 if ((l > 100) || (r > 100)) 1888 return (EINVAL); 1889 1890 mutex_enter(&statep->hda_mutex); 1891 pc->val = val; 1892 audiohd_set_pin_volume(statep, DTYPE_MIC_IN); 1893 mutex_exit(&statep->hda_mutex); 1894 1895 return (0); 1896 } 1897 1898 static int 1899 audiohd_set_cd(void *arg, uint64_t val) 1900 { 1901 audiohd_ctrl_t *pc = arg; 1902 audiohd_state_t *statep = pc->statep; 1903 uint8_t l, r; 1904 1905 if (val & ~0xffff) 1906 return (EINVAL); 1907 1908 l = (val & 0xff00) >> 8; 1909 r = (val & 0xff); 1910 if ((l > 100) || (r > 100)) 1911 return (EINVAL); 1912 1913 mutex_enter(&statep->hda_mutex); 1914 pc->val = val; 1915 audiohd_set_pin_volume(statep, DTYPE_CD); 1916 mutex_exit(&statep->hda_mutex); 1917 1918 return (0); 1919 } 1920 1921 static int 1922 audiohd_set_mongain(void *arg, uint64_t val) 1923 { 1924 audiohd_ctrl_t *pc = arg; 1925 audiohd_state_t *statep = pc->statep; 1926 uint8_t l, r; 1927 1928 if (val & ~0xffff) 1929 return (EINVAL); 1930 1931 l = (val & 0xff00) >> 8; 1932 r = (val & 0xff); 1933 if ((l > 100) || (r > 100)) 1934 return (EINVAL); 1935 1936 mutex_enter(&statep->hda_mutex); 1937 pc->val = val; 1938 audiohd_configure_input(statep); 1939 mutex_exit(&statep->hda_mutex); 1940 1941 return (0); 1942 } 1943 1944 static int 1945 audiohd_set_beep(void *arg, uint64_t val) 1946 { 1947 audiohd_ctrl_t *pc = arg; 1948 audiohd_state_t *statep = pc->statep; 1949 1950 val &= 0xff; 1951 1952 if (val > 100) 1953 return (EINVAL); 1954 1955 mutex_enter(&statep->hda_mutex); 1956 pc->val = val; 1957 audiohd_set_beep_volume(statep); 1958 mutex_exit(&statep->hda_mutex); 1959 1960 return (0); 1961 } 1962 1963 #define PLAYCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY) 1964 #define RECCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC) 1965 #define MONCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR) 1966 #define PCMVOL (PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL) 1967 #define MONVOL (MONCTL | AUDIO_CTRL_FLAG_MONVOL) 1968 #define MAINVOL (PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL) 1969 #define RECVOL (RECCTL | AUDIO_CTRL_FLAG_RECVOL) 1970 #define RWCTL AUDIO_CTRL_FLAG_RW 1971 1972 static audiohd_ctrl_t * 1973 audiohd_alloc_ctrl(audiohd_state_t *statep, uint32_t num, uint64_t val) 1974 { 1975 audio_ctrl_desc_t desc; 1976 audio_ctrl_wr_t fn; 1977 audiohd_ctrl_t *pc; 1978 1979 pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); 1980 pc->statep = statep; 1981 pc->num = num; 1982 1983 bzero(&desc, sizeof (desc)); 1984 1985 switch (num) { 1986 case CTL_VOLUME: 1987 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 1988 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 1989 desc.acd_minvalue = 0; 1990 desc.acd_maxvalue = 100; 1991 desc.acd_flags = PCMVOL; 1992 fn = audiohd_set_volume; 1993 break; 1994 1995 case CTL_FRONT: 1996 desc.acd_name = AUDIO_CTRL_ID_FRONT; 1997 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 1998 desc.acd_minvalue = 0; 1999 desc.acd_maxvalue = 100; 2000 desc.acd_flags = MAINVOL; 2001 fn = audiohd_set_front; 2002 break; 2003 2004 case CTL_SPEAKER: 2005 desc.acd_name = AUDIO_CTRL_ID_SPEAKER; 2006 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2007 desc.acd_minvalue = 0; 2008 desc.acd_maxvalue = 100; 2009 desc.acd_flags = MAINVOL; 2010 fn = audiohd_set_speaker; 2011 break; 2012 2013 case CTL_HEADPHONE: 2014 desc.acd_name = AUDIO_CTRL_ID_HEADPHONE; 2015 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2016 desc.acd_minvalue = 0; 2017 desc.acd_maxvalue = 100; 2018 desc.acd_flags = MAINVOL; 2019 fn = audiohd_set_headphone; 2020 break; 2021 2022 case CTL_REAR: 2023 desc.acd_name = AUDIO_CTRL_ID_REAR; 2024 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2025 desc.acd_minvalue = 0; 2026 desc.acd_maxvalue = 100; 2027 desc.acd_flags = MAINVOL; 2028 fn = audiohd_set_rear; 2029 break; 2030 2031 case CTL_CENTER: 2032 desc.acd_name = AUDIO_CTRL_ID_CENTER; 2033 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 2034 desc.acd_minvalue = 0; 2035 desc.acd_maxvalue = 100; 2036 desc.acd_flags = MAINVOL; 2037 fn = audiohd_set_center; 2038 break; 2039 2040 case CTL_SURROUND: 2041 desc.acd_name = AUDIO_CTRL_ID_SURROUND; 2042 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2043 desc.acd_minvalue = 0; 2044 desc.acd_maxvalue = 100; 2045 desc.acd_flags = MAINVOL; 2046 fn = audiohd_set_surround; 2047 break; 2048 2049 case CTL_LFE: 2050 desc.acd_name = AUDIO_CTRL_ID_LFE; 2051 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 2052 desc.acd_minvalue = 0; 2053 desc.acd_maxvalue = 100; 2054 desc.acd_flags = MAINVOL; 2055 fn = audiohd_set_lfe; 2056 break; 2057 2058 case CTL_LINEIN: 2059 desc.acd_name = AUDIO_CTRL_ID_LINEIN; 2060 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2061 desc.acd_minvalue = 0; 2062 desc.acd_maxvalue = 100; 2063 desc.acd_flags = RECVOL; 2064 fn = audiohd_set_linein; 2065 break; 2066 2067 case CTL_MIC: 2068 desc.acd_name = AUDIO_CTRL_ID_MIC; 2069 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2070 desc.acd_minvalue = 0; 2071 desc.acd_maxvalue = 100; 2072 desc.acd_flags = RECVOL; 2073 fn = audiohd_set_mic; 2074 break; 2075 2076 case CTL_CD: 2077 desc.acd_name = AUDIO_CTRL_ID_CD; 2078 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2079 desc.acd_minvalue = 0; 2080 desc.acd_maxvalue = 100; 2081 desc.acd_flags = RECVOL; 2082 fn = audiohd_set_cd; 2083 break; 2084 2085 case CTL_MONGAIN: 2086 desc.acd_name = AUDIO_CTRL_ID_MONGAIN; 2087 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 2088 desc.acd_minvalue = 0; 2089 desc.acd_maxvalue = 100; 2090 desc.acd_flags = MONVOL; 2091 fn = audiohd_set_mongain; 2092 break; 2093 2094 case CTL_RECSRC: 2095 desc.acd_name = AUDIO_CTRL_ID_RECSRC; 2096 desc.acd_type = AUDIO_CTRL_TYPE_ENUM; 2097 desc.acd_minvalue = statep->inmask; 2098 desc.acd_maxvalue = statep->inmask; 2099 desc.acd_flags = RECCTL; 2100 for (int i = 0; audiohd_dtypes[i]; i++) { 2101 desc.acd_enum[i] = audiohd_dtypes[i]; 2102 } 2103 fn = audiohd_set_recsrc; 2104 break; 2105 2106 case CTL_BEEP: 2107 desc.acd_name = AUDIO_CTRL_ID_BEEP; 2108 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 2109 desc.acd_minvalue = 0; 2110 desc.acd_maxvalue = 100; 2111 desc.acd_flags = RWCTL; 2112 fn = audiohd_set_beep; 2113 break; 2114 } 2115 2116 pc->val = val; 2117 pc->ctrl = audio_dev_add_control(statep->adev, &desc, 2118 audiohd_get_value, fn, pc); 2119 2120 return (pc); 2121 } 2122 2123 static void 2124 audiohd_free_ctrl(audiohd_ctrl_t *pc) 2125 { 2126 if (pc == NULL) 2127 return; 2128 if (pc->ctrl) 2129 audio_dev_del_control(pc->ctrl); 2130 kmem_free(pc, sizeof (*pc)); 2131 } 2132 2133 static void 2134 audiohd_del_controls(audiohd_state_t *statep) 2135 { 2136 int i; 2137 for (i = 0; i < CTRL_NUM; i++) { 2138 if (statep->controls[i]) 2139 audiohd_free_ctrl(statep->controls[i]); 2140 } 2141 } 2142 2143 static int 2144 audiohd_add_controls(audiohd_state_t *statep) 2145 { 2146 int i, j; 2147 audiohd_path_t *path; 2148 wid_t wid; 2149 audiohd_pin_t *pin; 2150 audiohd_widget_t *widget, *w; 2151 hda_codec_t *codec; 2152 audiohd_pin_color_t clr; 2153 2154 #define ADD_CTRL(ID, VAL) \ 2155 if (statep->controls[ID] == NULL) \ 2156 statep->controls[ID] = audiohd_alloc_ctrl(statep, ID, VAL);\ 2157 if (statep->controls[ID] == NULL) { \ 2158 audio_dev_warn(statep->adev, \ 2159 "Unable to allocate %s control", #ID); \ 2160 return (DDI_FAILURE); \ 2161 } 2162 2163 for (i = 0; i < statep->pathnum; i++) { 2164 path = statep->path[i]; 2165 if (!path || path->path_type != PLAY) 2166 continue; 2167 /* 2168 * Firstly we check if all the DACs on the play paths 2169 * have amplifiers. If any of them doesn't have, we just use 2170 * the soft volume control to adjust the PCM volume. 2171 */ 2172 wid = path->adda_wid; 2173 w = path->codec->widget[wid]; 2174 if (!w->outamp_cap) { 2175 (void) audio_dev_add_soft_volume(statep->adev); 2176 statep->soft_volume = B_TRUE; 2177 break; 2178 } 2179 } 2180 /* 2181 * if all the DACs on the play paths have the amplifiers, we use DACs' 2182 * amplifiers to adjust volume. 2183 */ 2184 if (!statep->soft_volume) { 2185 ADD_CTRL(CTL_VOLUME, 0x4b); 2186 } 2187 /* allocate other controls */ 2188 for (i = 0; i < statep->pathnum; i++) { 2189 path = statep->path[i]; 2190 if (!path) 2191 continue; 2192 codec = path->codec; 2193 if (path->path_type == BEEP) { 2194 widget = codec->widget[path->beep_wid]; 2195 if (widget->type == WTYPE_BEEP && 2196 path->gain_wid != 0) { 2197 ADD_CTRL(CTL_BEEP, 0x4b4b); 2198 break; 2199 } 2200 } 2201 2202 for (j = 0; j < path->pin_nums; j++) { 2203 wid = path->pin_wid[j]; 2204 widget = codec->widget[wid]; 2205 pin = (audiohd_pin_t *)widget->priv; 2206 if (pin->device == DTYPE_SPEAKER) { 2207 ADD_CTRL(CTL_SPEAKER, 0x4b4b); 2208 } else if (pin->device == DTYPE_HP_OUT) { 2209 ADD_CTRL(CTL_HEADPHONE, 0x4b4b); 2210 } else if (pin->device == DTYPE_LINE_IN) { 2211 ADD_CTRL(CTL_LINEIN, 0x3232); 2212 } else if (pin->device == DTYPE_MIC_IN) { 2213 ADD_CTRL(CTL_MIC, 0x3232); 2214 } else if (pin->device == DTYPE_CD) { 2215 ADD_CTRL(CTL_CD, 0x3232); 2216 } 2217 clr = (pin->config >> AUDIOHD_PIN_CLR_OFF) & 2218 AUDIOHD_PIN_CLR_MASK; 2219 if (clr == AUDIOHD_PIN_GREEN) { 2220 ADD_CTRL(CTL_FRONT, 0x4b4b); 2221 } else if (clr == AUDIOHD_PIN_BLACK && 2222 pin->device != DTYPE_HP_OUT && 2223 pin->device != DTYPE_MIC_IN) { 2224 ADD_CTRL(CTL_REAR, 0x4b4b); 2225 } else if (clr == AUDIOHD_PIN_ORANGE) { 2226 ADD_CTRL(CTL_CENTER, 0x4b); 2227 ADD_CTRL(CTL_LFE, 0x4b); 2228 } else if (clr == AUDIOHD_PIN_GREY) { 2229 ADD_CTRL(CTL_SURROUND, 0x4b4b); 2230 } 2231 } 2232 } 2233 2234 if (!statep->monitor_unsupported) { 2235 ADD_CTRL(CTL_MONGAIN, 0); 2236 } 2237 2238 ADD_CTRL(CTL_RECSRC, (1U << DTYPE_MIC_IN)); 2239 2240 audiohd_configure_output(statep); 2241 audiohd_configure_input(statep); 2242 2243 return (DDI_SUCCESS); 2244 } 2245 2246 /* 2247 * quiesce(9E) entry point. 2248 * 2249 * This function is called when the system is single-threaded at high 2250 * PIL with preemption disabled. Therefore, this function must not be 2251 * blocked. 2252 * 2253 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 2254 * DDI_FAILURE indicates an error condition and should almost never happen. 2255 */ 2256 static int 2257 audiohd_quiesce(dev_info_t *dip) 2258 { 2259 audiohd_state_t *statep; 2260 2261 statep = ddi_get_driver_private(dip); 2262 2263 audiohd_stop_dma(statep); 2264 audiohd_disable_intr(statep); 2265 2266 return (DDI_SUCCESS); 2267 } 2268 2269 static void 2270 audiohd_beep_on(void *arg) 2271 { 2272 hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec; 2273 audiohd_state_t *statep = codec->soft_statep; 2274 int caddr = codec->index; 2275 wid_t wid = ((audiohd_widget_t *)arg)->wid_wid; 2276 2277 (void) audioha_codec_verb_get(statep, caddr, wid, 2278 AUDIOHDC_VERB_SET_BEEP_GEN, audiohd_beep_divider); 2279 } 2280 2281 static void 2282 audiohd_beep_off(void *arg) 2283 { 2284 hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec; 2285 audiohd_state_t *statep = codec->soft_statep; 2286 int caddr = codec->index; 2287 wid_t wid = ((audiohd_widget_t *)arg)->wid_wid; 2288 2289 (void) audioha_codec_verb_get(statep, caddr, wid, 2290 AUDIOHDC_VERB_SET_BEEP_GEN, AUDIOHDC_MUTE_BEEP_GEN); 2291 } 2292 2293 static void 2294 audiohd_beep_freq(void *arg, int freq) 2295 { 2296 _NOTE(ARGUNUSED(arg)); 2297 if (freq == 0) { 2298 audiohd_beep_divider = 0; 2299 } else { 2300 if (freq > AUDIOHDC_MAX_BEEP_GEN) 2301 freq = AUDIOHDC_MAX_BEEP_GEN; 2302 else if (freq < AUDIOHDC_MIX_BEEP_GEN) 2303 freq = AUDIOHDC_MIX_BEEP_GEN; 2304 audiohd_beep_divider = AUDIOHDC_SAMPR48000 / freq; 2305 } 2306 2307 if (audiohd_beep_vol == 0) 2308 audiohd_beep_divider = 0; 2309 } 2310 2311 /* 2312 * audiohd_init_state() 2313 * 2314 * Description 2315 * This routine initailizes soft state of driver instance, 2316 * also, it requests an interrupt cookie and initializes 2317 * mutex for soft state. 2318 */ 2319 /*ARGSUSED*/ 2320 static int 2321 audiohd_init_state(audiohd_state_t *statep, dev_info_t *dip) 2322 { 2323 audio_dev_t *adev; 2324 2325 statep->hda_dip = dip; 2326 2327 if ((adev = audio_dev_alloc(dip, 0)) == NULL) { 2328 cmn_err(CE_WARN, "unable to allocate audio dev"); 2329 return (DDI_FAILURE); 2330 } 2331 statep->adev = adev; 2332 statep->intr_added = B_FALSE; 2333 statep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 2334 DDI_PROP_DONTPASS, "msi_enable", B_TRUE); 2335 2336 /* set device information */ 2337 audio_dev_set_description(adev, AUDIOHD_DEV_CONFIG); 2338 audio_dev_set_version(adev, AUDIOHD_DEV_VERSION); 2339 2340 statep->hda_rirb_rp = 0; 2341 2342 return (DDI_SUCCESS); 2343 } /* audiohd_init_state() */ 2344 2345 /* 2346 * audiohd_init_pci() 2347 * 2348 * Description 2349 * enable driver to access PCI configure space and memory 2350 * I/O space. 2351 */ 2352 static int 2353 audiohd_init_pci(audiohd_state_t *statep, ddi_device_acc_attr_t *acc_attr) 2354 { 2355 uint16_t cmdreg; 2356 uint16_t vid; 2357 uint8_t cTmp; 2358 dev_info_t *dip = statep->hda_dip; 2359 audio_dev_t *ahandle = statep->adev; 2360 2361 if (pci_config_setup(dip, &statep->hda_pci_handle) == DDI_FAILURE) { 2362 audio_dev_warn(ahandle, 2363 "pci config mapping failed"); 2364 return (DDI_FAILURE); 2365 } 2366 2367 if (ddi_regs_map_setup(dip, 1, &statep->hda_reg_base, 0, 2368 0, acc_attr, &statep->hda_reg_handle) != DDI_SUCCESS) { 2369 audio_dev_warn(ahandle, 2370 "memory I/O mapping failed"); 2371 return (DDI_FAILURE); 2372 } 2373 2374 /* 2375 * HD audio control uses memory I/O only, enable it here. 2376 */ 2377 cmdreg = pci_config_get16(statep->hda_pci_handle, PCI_CONF_COMM); 2378 pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM, 2379 cmdreg | PCI_COMM_MAE | PCI_COMM_ME); 2380 2381 vid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID); 2382 switch (vid) { 2383 2384 case AUDIOHD_VID_INTEL: 2385 /* 2386 * Currently, Intel (G)MCH and ICHx chipsets support PCI 2387 * Express QoS. It implemenets two VCs(virtual channels) 2388 * and allows OS software to map 8 traffic classes to the 2389 * two VCs. Some BIOSes initialize HD audio hardware to 2390 * use TC7 (traffic class 7) and to map TC7 to VC1 as Intel 2391 * recommended. However, solaris doesn't support PCI express 2392 * QoS yet. As a result, this driver can not work for those 2393 * hardware without touching PCI express control registers. 2394 * Here, we set TCSEL to 0 so as to use TC0/VC0 (VC0 is 2395 * always enabled and TC0 is always mapped to VC0) for all 2396 * Intel HD audio controllers. 2397 */ 2398 cTmp = pci_config_get8(statep->hda_pci_handle, 2399 AUDIOHD_INTEL_PCI_TCSEL); 2400 pci_config_put8(statep->hda_pci_handle, 2401 AUDIOHD_INTEL_PCI_TCSEL, (cTmp & AUDIOHD_INTEL_TCS_MASK)); 2402 break; 2403 2404 case AUDIOHD_VID_ATI: 2405 /* 2406 * Refer to ATI SB450 datesheet. We set snoop for SB450 2407 * like hardware. 2408 */ 2409 cTmp = pci_config_get8(statep->hda_pci_handle, 2410 AUDIOHD_ATI_PCI_MISC2); 2411 pci_config_put8(statep->hda_pci_handle, AUDIOHD_ATI_PCI_MISC2, 2412 (cTmp & AUDIOHD_ATI_MISC2_MASK) | AUDIOHD_ATI_MISC2_SNOOP); 2413 break; 2414 /* 2415 * Refer to the datasheet, we set snoop for NVIDIA 2416 * like hardware 2417 */ 2418 case AUDIOHD_VID_NVIDIA: 2419 cTmp = pci_config_get8(statep->hda_pci_handle, 2420 AUDIOHD_CORB_SIZE_OFF); 2421 pci_config_put8(statep->hda_pci_handle, AUDIOHD_CORB_SIZE_OFF, 2422 cTmp | AUDIOHD_NVIDIA_SNOOP); 2423 break; 2424 2425 default: 2426 break; 2427 } 2428 2429 return (DDI_SUCCESS); 2430 } /* audiohd_init_pci() */ 2431 2432 2433 /* 2434 * audiohd_fini_pci() 2435 * 2436 * Description 2437 * Release mapping for PCI configure space. 2438 */ 2439 static void 2440 audiohd_fini_pci(audiohd_state_t *statep) 2441 { 2442 if (statep->hda_reg_handle != NULL) { 2443 ddi_regs_map_free(&statep->hda_reg_handle); 2444 statep->hda_reg_handle = NULL; 2445 } 2446 2447 if (statep->hda_pci_handle != NULL) { 2448 pci_config_teardown(&statep->hda_pci_handle); 2449 statep->hda_pci_handle = NULL; 2450 } 2451 2452 } /* audiohd_fini_pci() */ 2453 2454 /* 2455 * audiohd_stop_dma() 2456 * 2457 * Description 2458 * Stop all DMA behaviors of controllers, for command I/O 2459 * and each audio stream. 2460 */ 2461 static void 2462 audiohd_stop_dma(audiohd_state_t *statep) 2463 { 2464 int i; 2465 uint_t base; 2466 uint8_t bTmp; 2467 2468 AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, 0); 2469 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, 0); 2470 2471 base = AUDIOHD_REG_SD_BASE; 2472 for (i = 0; i < statep->hda_streams_nums; i++) { 2473 bTmp = AUDIOHD_REG_GET8(base + AUDIOHD_SDREG_OFFSET_CTL); 2474 2475 /* for input/output stream, it is the same */ 2476 bTmp &= ~AUDIOHDR_RIRBCTL_DMARUN; 2477 2478 AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_CTL, bTmp); 2479 base += AUDIOHD_REG_SD_LEN; 2480 } 2481 2482 /* wait 40us for stream DMA to stop */ 2483 drv_usecwait(40); 2484 2485 } /* audiohd_stop_dma() */ 2486 2487 /* 2488 * audiohd_reset_controller() 2489 * 2490 * Description: 2491 * This routine is just used to reset controller and 2492 * CODEC as well by HW reset bit in global control 2493 * register of HD controller. 2494 */ 2495 static int 2496 audiohd_reset_controller(audiohd_state_t *statep) 2497 { 2498 int i; 2499 uint16_t sTmp; 2500 uint32_t gctl; 2501 2502 /* Reset Status register but preserve the first bit */ 2503 sTmp = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS); 2504 AUDIOHD_REG_SET16(AUDIOHD_REG_STATESTS, sTmp & 0x8000); 2505 2506 /* reset controller */ 2507 gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL); 2508 gctl &= ~AUDIOHDR_GCTL_CRST; 2509 AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl); /* entering reset state */ 2510 for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) { 2511 /* Empirical testing time: 150 */ 2512 drv_usecwait(150); 2513 gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL); 2514 if ((gctl & AUDIOHDR_GCTL_CRST) == 0) 2515 break; 2516 } 2517 2518 if ((gctl & AUDIOHDR_GCTL_CRST) != 0) { 2519 audio_dev_warn(statep->adev, 2520 "failed to enter reset state"); 2521 return (DDI_FAILURE); 2522 } 2523 2524 /* Empirical testing time:300 */ 2525 drv_usecwait(300); 2526 2527 /* exit reset state */ 2528 AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl | AUDIOHDR_GCTL_CRST); 2529 2530 for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) { 2531 /* Empirical testing time: 150, which works well */ 2532 drv_usecwait(150); 2533 gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL); 2534 if (gctl & AUDIOHDR_GCTL_CRST) 2535 break; 2536 } 2537 2538 if ((gctl & AUDIOHDR_GCTL_CRST) == 0) { 2539 audio_dev_warn(statep->adev, 2540 "failed to exit reset state"); 2541 return (DDI_FAILURE); 2542 } 2543 2544 /* HD spec requires to wait 250us at least. we use 500us */ 2545 drv_usecwait(500); 2546 2547 /* enable unsolicited response */ 2548 AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, 2549 gctl | AUDIOHDR_GCTL_URESPE); 2550 2551 return (DDI_SUCCESS); 2552 2553 } /* audiohd_reset_controller() */ 2554 2555 /* 2556 * audiohd_alloc_dma_mem() 2557 * 2558 * Description: 2559 * This is an utility routine. It is used to allocate DMA 2560 * memory. 2561 */ 2562 static int 2563 audiohd_alloc_dma_mem(audiohd_state_t *statep, audiohd_dma_t *pdma, 2564 size_t memsize, ddi_dma_attr_t *dma_attr_p, uint_t dma_flags) 2565 { 2566 ddi_dma_cookie_t cookie; 2567 uint_t count; 2568 dev_info_t *dip = statep->hda_dip; 2569 audio_dev_t *ahandle = statep->adev; 2570 2571 if (ddi_dma_alloc_handle(dip, dma_attr_p, DDI_DMA_SLEEP, 2572 NULL, &pdma->ad_dmahdl) != DDI_SUCCESS) { 2573 audio_dev_warn(ahandle, 2574 "ddi_dma_alloc_handle failed"); 2575 return (DDI_FAILURE); 2576 } 2577 2578 if (ddi_dma_mem_alloc(pdma->ad_dmahdl, memsize, &hda_dev_accattr, 2579 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 2580 DDI_DMA_SLEEP, NULL, 2581 (caddr_t *)&pdma->ad_vaddr, &pdma->ad_real_sz, 2582 &pdma->ad_acchdl) != DDI_SUCCESS) { 2583 audio_dev_warn(ahandle, 2584 "ddi_dma_mem_alloc failed"); 2585 return (DDI_FAILURE); 2586 } 2587 2588 if (ddi_dma_addr_bind_handle(pdma->ad_dmahdl, NULL, 2589 (caddr_t)pdma->ad_vaddr, pdma->ad_real_sz, dma_flags, 2590 DDI_DMA_SLEEP, NULL, &cookie, &count) != DDI_DMA_MAPPED) { 2591 audio_dev_warn(ahandle, 2592 "ddi_dma_addr_bind_handle failed"); 2593 return (DDI_FAILURE); 2594 } 2595 2596 pdma->ad_paddr = (uint64_t)(cookie.dmac_laddress); 2597 pdma->ad_req_sz = memsize; 2598 2599 return (DDI_SUCCESS); 2600 } /* audiohd_alloc_dma_mem() */ 2601 2602 /* 2603 * audiohd_release_dma_mem() 2604 * 2605 * Description: 2606 * Release DMA memory. 2607 */ 2608 2609 static void 2610 audiohd_release_dma_mem(audiohd_dma_t *pdma) 2611 { 2612 if (pdma->ad_dmahdl != NULL) { 2613 (void) ddi_dma_unbind_handle(pdma->ad_dmahdl); 2614 } 2615 2616 if (pdma->ad_acchdl != NULL) { 2617 ddi_dma_mem_free(&pdma->ad_acchdl); 2618 pdma->ad_acchdl = NULL; 2619 } 2620 2621 if (pdma->ad_dmahdl != NULL) { 2622 ddi_dma_free_handle(&pdma->ad_dmahdl); 2623 pdma->ad_dmahdl = NULL; 2624 } 2625 2626 } /* audiohd_release_dma_mem() */ 2627 2628 /* 2629 * audiohd_reinit_hda() 2630 * 2631 * Description: 2632 * This routine is used to re-initialize HD controller and codec. 2633 */ 2634 static int 2635 audiohd_reinit_hda(audiohd_state_t *statep) 2636 { 2637 uint64_t addr; 2638 2639 /* set PCI configure space in case it's not restored OK */ 2640 (void) audiohd_init_pci(statep, &hda_dev_accattr); 2641 2642 /* reset controller */ 2643 if (audiohd_reset_controller(statep) != DDI_SUCCESS) 2644 return (DDI_FAILURE); 2645 AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */ 2646 2647 /* Initialize controller RIRB */ 2648 addr = statep->hda_dma_rirb.ad_paddr; 2649 AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr); 2650 AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE, 2651 (uint32_t)(addr >> 32)); 2652 AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET); 2653 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256); 2654 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN | 2655 AUDIOHDR_RIRBCTL_RINTCTL); 2656 2657 /* Initialize controller CORB */ 2658 addr = statep->hda_dma_corb.ad_paddr; 2659 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET); 2660 AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr); 2661 AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE, 2662 (uint32_t)(addr >> 32)); 2663 AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256); 2664 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0); 2665 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0); 2666 AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN); 2667 2668 audiohd_restore_codec_gpio(statep); 2669 audiohd_restore_path(statep); 2670 audiohd_init_path(statep); 2671 2672 return (DDI_SUCCESS); 2673 } /* audiohd_reinit_hda */ 2674 2675 /* 2676 * audiohd_init_controller() 2677 * 2678 * Description: 2679 * This routine is used to initialize HD controller. It 2680 * allocates DMA memory for CORB/RIRB, buffer descriptor 2681 * list and cylic data buffer for both play and record 2682 * stream. 2683 */ 2684 static int 2685 audiohd_init_controller(audiohd_state_t *statep) 2686 { 2687 uint64_t addr; 2688 uint16_t gcap; 2689 int retval; 2690 2691 ddi_dma_attr_t dma_attr = { 2692 DMA_ATTR_V0, /* version */ 2693 0, /* addr_lo */ 2694 0xffffffffffffffffULL, /* addr_hi */ 2695 0x00000000ffffffffULL, /* count_max */ 2696 128, /* 128-byte alignment as HD spec */ 2697 0xfff, /* burstsize */ 2698 1, /* minxfer */ 2699 0xffffffff, /* maxxfer */ 2700 0xffffffff, /* seg */ 2701 1, /* sgllen */ 2702 1, /* granular */ 2703 0 /* flags */ 2704 }; 2705 2706 gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP); 2707 2708 /* 2709 * If the device doesn't support 64-bit DMA, we should not 2710 * allocate DMA memory from 4G above 2711 */ 2712 if ((gcap & AUDIOHDR_GCAP_64OK) == 0) 2713 dma_attr.dma_attr_addr_hi = 0xffffffffUL; 2714 2715 statep->hda_input_streams = (gcap & AUDIOHDR_GCAP_INSTREAMS) >> 2716 AUDIOHD_INSTR_NUM_OFF; 2717 statep->hda_output_streams = (gcap & AUDIOHDR_GCAP_OUTSTREAMS) >> 2718 AUDIOHD_OUTSTR_NUM_OFF; 2719 statep->hda_streams_nums = statep->hda_input_streams + 2720 statep->hda_output_streams; 2721 2722 2723 statep->hda_record_regbase = AUDIOHD_REG_SD_BASE; 2724 statep->hda_play_regbase = AUDIOHD_REG_SD_BASE + AUDIOHD_REG_SD_LEN * 2725 statep->hda_input_streams; 2726 2727 2728 /* stop all dma before starting to reset controller */ 2729 audiohd_stop_dma(statep); 2730 2731 if (audiohd_reset_controller(statep) != DDI_SUCCESS) 2732 return (DDI_FAILURE); 2733 2734 /* check codec */ 2735 statep->hda_codec_mask = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS); 2736 if (!statep->hda_codec_mask) { 2737 audio_dev_warn(statep->adev, 2738 "no codec exists"); 2739 return (DDI_FAILURE); 2740 } 2741 2742 /* allocate DMA for CORB */ 2743 retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_corb, 2744 AUDIOHD_CDBIO_CORB_LEN, &dma_attr, 2745 DDI_DMA_WRITE | DDI_DMA_STREAMING); 2746 if (retval != DDI_SUCCESS) { 2747 audio_dev_warn(statep->adev, 2748 "failed to alloc DMA for CORB"); 2749 return (DDI_FAILURE); 2750 } 2751 2752 /* allocate DMA for RIRB */ 2753 retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_rirb, 2754 AUDIOHD_CDBIO_RIRB_LEN, &dma_attr, 2755 DDI_DMA_READ | DDI_DMA_STREAMING); 2756 if (retval != DDI_SUCCESS) { 2757 audio_dev_warn(statep->adev, 2758 "failed to alloc DMA for RIRB"); 2759 return (DDI_FAILURE); 2760 } 2761 2762 2763 AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */ 2764 2765 /* Initialize RIRB */ 2766 addr = statep->hda_dma_rirb.ad_paddr; 2767 AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr); 2768 AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE, 2769 (uint32_t)(addr >> 32)); 2770 AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET); 2771 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256); 2772 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN | 2773 AUDIOHDR_RIRBCTL_RINTCTL); 2774 2775 /* initialize CORB */ 2776 addr = statep->hda_dma_corb.ad_paddr; 2777 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET); 2778 AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr); 2779 AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE, 2780 (uint32_t)(addr >> 32)); 2781 AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256); 2782 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0); 2783 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0); 2784 AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN); 2785 2786 return (DDI_SUCCESS); 2787 } /* audiohd_init_controller() */ 2788 2789 /* 2790 * audiohd_fini_controller() 2791 * 2792 * Description: 2793 * Releases DMA memory allocated in audiohd_init_controller() 2794 */ 2795 static void 2796 audiohd_fini_controller(audiohd_state_t *statep) 2797 { 2798 audiohd_stop_dma(statep); 2799 audiohd_release_dma_mem(&statep->hda_dma_rirb); 2800 audiohd_release_dma_mem(&statep->hda_dma_corb); 2801 2802 } /* audiohd_fini_controller() */ 2803 2804 /* 2805 * audiohd_get_conns_from_entry() 2806 * 2807 * Description: 2808 * Get connection list from every entry for a widget 2809 */ 2810 static void 2811 audiohd_get_conns_from_entry(hda_codec_t *codec, audiohd_widget_t *widget, 2812 uint32_t entry, audiohd_entry_prop_t *prop) 2813 { 2814 int i, k, num; 2815 wid_t input_wid; 2816 2817 for (i = 0; i < prop->conns_per_entry && 2818 widget->nconns < prop->conn_len; 2819 i++, entry >>= prop->bits_per_conn) { 2820 ASSERT(widget->nconns < AUDIOHD_MAX_CONN); 2821 input_wid = entry & prop->mask_wid; 2822 if (entry & prop->mask_range) { 2823 if (widget->nconns == 0) { 2824 if (input_wid < codec->first_wid || 2825 (input_wid > codec->last_wid)) { 2826 break; 2827 } 2828 widget->avail_conn[widget->nconns++] = 2829 input_wid; 2830 } else { 2831 for (k = widget->avail_conn[widget->nconns-1] + 2832 1; k <= input_wid; k++) { 2833 ASSERT(widget->nconns < 2834 AUDIOHD_MAX_CONN); 2835 if (k < codec->first_wid || 2836 (k > codec->last_wid)) { 2837 break; 2838 } else { 2839 num = widget->nconns; 2840 widget->avail_conn[num] = k; 2841 widget->nconns++; 2842 } 2843 } 2844 } 2845 } else { 2846 if ((codec->first_wid <= input_wid) && (input_wid <= 2847 codec->last_wid)) 2848 widget->avail_conn[widget->nconns++] = 2849 input_wid; 2850 } 2851 } 2852 } 2853 2854 /* 2855 * audiohd_get_conns() 2856 * 2857 * Description: 2858 * Get all connection list for a widget. The connection list is used for 2859 * build output path, input path, and monitor path 2860 */ 2861 static void 2862 audiohd_get_conns(hda_codec_t *codec, wid_t wid) 2863 { 2864 audiohd_state_t *statep = codec->soft_statep; 2865 audiohd_widget_t *widget = codec->widget[wid]; 2866 uint8_t caddr = codec->index; 2867 uint32_t entry; 2868 audiohd_entry_prop_t prop; 2869 wid_t input_wid; 2870 int i; 2871 2872 prop.conn_len = audioha_codec_verb_get(statep, caddr, wid, 2873 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_CONNLIST_LEN); 2874 2875 if (prop.conn_len & AUDIOHD_FORM_MASK) { 2876 prop.conns_per_entry = 2; 2877 prop.bits_per_conn = 16; 2878 prop.mask_range = 0x00008000; 2879 prop.mask_wid = 0x00007fff; 2880 } else { 2881 prop.conns_per_entry = 4; 2882 prop.bits_per_conn = 8; 2883 prop.mask_range = 0x00000080; 2884 prop.mask_wid = 0x0000007f; 2885 } 2886 prop.conn_len &= AUDIOHD_LEN_MASK; 2887 2888 /* 2889 * This should not happen since the ConnectionList bit of 2890 * widget capabilities already told us that this widget 2891 * has a connection list 2892 */ 2893 if (prop.conn_len == 0) { 2894 widget->nconns = 0; 2895 cmn_err(CE_WARN, "node %d has 0 connections\n", wid); 2896 return; 2897 } 2898 2899 if (prop.conn_len == 1) { 2900 entry = audioha_codec_verb_get(statep, caddr, 2901 wid, AUDIOHDC_VERB_GET_CONN_LIST_ENT, 0); 2902 input_wid = entry & prop.mask_wid; 2903 if ((input_wid < codec->first_wid) || 2904 (input_wid > codec->last_wid)) { 2905 return; 2906 } 2907 widget->avail_conn[0] = input_wid; 2908 widget->nconns = 1; 2909 return; 2910 } 2911 widget->nconns = 0; 2912 for (i = 0; i < prop.conn_len; i += prop.conns_per_entry) { 2913 entry = audioha_codec_verb_get(statep, caddr, wid, 2914 AUDIOHDC_VERB_GET_CONN_LIST_ENT, i); 2915 audiohd_get_conns_from_entry(codec, widget, entry, &prop); 2916 } 2917 } 2918 2919 /* 2920 * Read PinCapabilities & default configuration 2921 */ 2922 static void 2923 audiohd_get_pin_config(audiohd_widget_t *widget) 2924 { 2925 hda_codec_t *codec = widget->codec; 2926 audiohd_state_t *statep = codec->soft_statep; 2927 audiohd_pin_t *pin, *prev, *p; 2928 2929 int caddr = codec->index; 2930 wid_t wid = widget->wid_wid; 2931 uint32_t cap, config, pinctrl; 2932 uint8_t urctrl, vrefbits; 2933 2934 cap = audioha_codec_verb_get(statep, caddr, wid, 2935 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PIN_CAP); 2936 config = audioha_codec_verb_get(statep, caddr, 2937 wid, AUDIOHDC_VERB_GET_DEFAULT_CONF, 0); 2938 pinctrl = audioha_codec_verb_get(statep, caddr, 2939 wid, AUDIOHDC_VERB_GET_PIN_CTRL, 0); 2940 2941 pin = (audiohd_pin_t *)kmem_zalloc(sizeof (audiohd_pin_t), KM_SLEEP); 2942 widget->priv = pin; 2943 2944 /* 2945 * If the pin has no physical connection for port, 2946 * we won't link it to pin linkage list ??? 2947 */ 2948 if (((config >> AUDIOHD_PIN_CON_STEP) & AUDIOHD_PIN_CON_MASK) == 0x1) { 2949 pin->no_phys_conn = 1; 2950 } 2951 2952 /* bit 4:3 are reserved, read-modify-write is needed */ 2953 pin->ctrl = pinctrl & AUDIOHD_PIN_IO_MASK; 2954 pin->wid = wid; 2955 pin->cap = cap; 2956 pin->config = config; 2957 pin->num = 0; 2958 pin->finish = 0; 2959 2960 vrefbits = (cap >> AUDIOHD_PIN_VREF_OFF) & AUDIOHD_PIN_VREF_MASK; 2961 if (vrefbits & AUDIOHD_PIN_VREF_L1) 2962 pin->vrefvalue = 0x5; 2963 else if (vrefbits & AUDIOHD_PIN_VREF_L2) 2964 pin->vrefvalue = 0x4; 2965 else if (vrefbits & AUDIOHD_PIN_VREF_L3) 2966 pin->vrefvalue = 0x2; 2967 else 2968 pin->vrefvalue = 0x1; 2969 2970 pin->seq = config & AUDIOHD_PIN_SEQ_MASK; 2971 pin->assoc = (config & AUDIOHD_PIN_ASO_MASK) >> AUDIOHD_PIN_ASO_OFF; 2972 pin->device = (config & AUDIOHD_PIN_DEV_MASK) >> AUDIOHD_PIN_DEV_OFF; 2973 2974 /* enable the unsolicited response of the pin */ 2975 if ((widget->widget_cap & AUDIOHD_URCAP_MASK) && 2976 (pin->cap & AUDIOHD_DTCCAP_MASK) && 2977 ((pin->device == DTYPE_LINEOUT) || 2978 (pin->device == DTYPE_SPDIF_OUT) || 2979 (pin->device == DTYPE_HP_OUT) || 2980 (pin->device == DTYPE_MIC_IN))) { 2981 urctrl = (uint8_t)(1 << (AUDIOHD_UR_ENABLE_OFF - 1)); 2982 urctrl |= (wid & AUDIOHD_UR_TAG_MASK); 2983 (void) audioha_codec_verb_get(statep, caddr, 2984 wid, AUDIOHDC_VERB_SET_URCTRL, urctrl); 2985 } 2986 /* accommodate all the pins in a link list sorted by assoc and seq */ 2987 if (codec->first_pin == NULL) { 2988 codec->first_pin = pin; 2989 } else { 2990 prev = NULL; 2991 p = codec->first_pin; 2992 while (p) { 2993 if (p->assoc > pin->assoc) 2994 break; 2995 if ((p->assoc == pin->assoc) && 2996 (p->seq > pin->seq)) 2997 break; 2998 prev = p; 2999 p = p->next; 3000 } 3001 if (prev) { 3002 pin->next = prev->next; 3003 prev->next = pin; 3004 } else { 3005 pin->next = codec->first_pin; 3006 codec->first_pin = pin; 3007 } 3008 } 3009 3010 } /* audiohd_get_pin_config() */ 3011 3012 /* 3013 * audiohd_create_widgets() 3014 * 3015 * Description: 3016 * All widgets are created and stored in an array of codec 3017 */ 3018 static int 3019 audiohd_create_widgets(hda_codec_t *codec) 3020 { 3021 audiohd_widget_t *widget; 3022 audiohd_state_t *statep = codec->soft_statep; 3023 wid_t wid; 3024 uint32_t type, widcap; 3025 int caddr = codec->index; 3026 3027 for (wid = codec->first_wid; 3028 wid <= codec->last_wid; wid++) { 3029 widget = (audiohd_widget_t *) 3030 kmem_zalloc(sizeof (audiohd_widget_t), KM_SLEEP); 3031 codec->widget[wid] = widget; 3032 widget->codec = codec; 3033 widget->selconn = AUDIOHD_NULL_CONN; 3034 3035 widcap = audioha_codec_verb_get(statep, caddr, wid, 3036 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AUDIO_WID_CAP); 3037 type = AUDIOHD_WIDCAP_TO_WIDTYPE(widcap); 3038 widget->wid_wid = wid; 3039 widget->type = type; 3040 widget->widget_cap = widcap; 3041 widget->finish = 0; 3042 widget->used = 0; 3043 3044 /* if there's connection list */ 3045 if (widcap & AUDIOHD_WIDCAP_CONNLIST) { 3046 audiohd_get_conns(codec, wid); 3047 } 3048 3049 /* if power control, power it up to D0 state */ 3050 if (widcap & AUDIOHD_WIDCAP_PWRCTRL) { 3051 (void) audioha_codec_verb_get(statep, caddr, wid, 3052 AUDIOHDC_VERB_SET_POWER_STATE, 0); 3053 } 3054 3055 /* 3056 * if this widget has format override, we read it. 3057 * Otherwise, it uses the format of audio function. 3058 */ 3059 if (widcap & AUDIOHD_WIDCAP_FMT_OVRIDE) { 3060 widget->pcm_format = 3061 audioha_codec_verb_get(statep, caddr, wid, 3062 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM); 3063 } else { 3064 widget->pcm_format = codec->pcm_format; 3065 } 3066 3067 /* 3068 * Input amplifier. Has the widget input amplifier ? 3069 */ 3070 if (widcap & AUDIOHD_WIDCAP_INAMP) { 3071 /* 3072 * if overrided bit is 0, use the default 3073 * amplifier of audio function as HD spec. 3074 * Otherwise, we read it. 3075 */ 3076 if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0) 3077 widget->inamp_cap = codec->inamp_cap; 3078 else 3079 widget->inamp_cap = 3080 audioha_codec_verb_get(statep, caddr, wid, 3081 AUDIOHDC_VERB_GET_PARAM, 3082 AUDIOHDC_PAR_INAMP_CAP); 3083 } else { 3084 widget->inamp_cap = 0; 3085 } 3086 3087 /* 3088 * output amplifier. Has this widget output amplifier ? 3089 */ 3090 if (widcap & AUDIOHD_WIDCAP_OUTAMP) { 3091 if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0) 3092 widget->outamp_cap = codec->outamp_cap; 3093 else 3094 widget->outamp_cap = 3095 audioha_codec_verb_get(statep, caddr, wid, 3096 AUDIOHDC_VERB_GET_PARAM, 3097 AUDIOHDC_PAR_OUTAMP_CAP); 3098 } else { 3099 widget->outamp_cap = 0; 3100 } 3101 3102 switch (type) { 3103 case WTYPE_AUDIO_OUT: 3104 case WTYPE_AUDIO_IN: 3105 case WTYPE_AUDIO_MIX: 3106 case WTYPE_AUDIO_SEL: 3107 case WTYPE_VENDOR: 3108 case WTYPE_POWER: 3109 case WTYPE_VOL_KNOB: 3110 break; 3111 case WTYPE_PIN: 3112 audiohd_get_pin_config(widget); 3113 break; 3114 case WTYPE_BEEP: 3115 /* 3116 * Get the audiohd_beep_switch value from audiohd.conf, 3117 * which is for turning on/off widget beep. 3118 */ 3119 audiohd_beep = ddi_prop_get_int(DDI_DEV_T_ANY, 3120 statep->hda_dip, 3121 DDI_PROP_DONTPASS, "audiohd_beep", 1); 3122 3123 if (audiohd_beep) { 3124 (void) beep_fini(); 3125 (void) beep_init((void *) widget, 3126 audiohd_beep_on, 3127 audiohd_beep_off, 3128 audiohd_beep_freq); 3129 } 3130 break; 3131 default: 3132 break; 3133 } 3134 } 3135 3136 return (DDI_SUCCESS); 3137 3138 } /* audiohd_create_widgets() */ 3139 3140 /* 3141 * audiohd_destroy_widgets() 3142 */ 3143 static void 3144 audiohd_destroy_widgets(hda_codec_t *codec) 3145 { 3146 for (int i = 0; i < AUDIOHD_MAX_WIDGET; i++) { 3147 if (codec->widget[i]) { 3148 kmem_free(codec->widget[i], sizeof (audiohd_widget_t)); 3149 codec->widget[i] = NULL; 3150 } 3151 } 3152 3153 } /* audiohd_destroy_widgets() */ 3154 3155 static void 3156 audiohd_set_codec_info(hda_codec_t *codec) 3157 { 3158 char buf[256]; 3159 3160 switch (codec->vid) { 3161 case 0x10ec0260: 3162 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC260"); 3163 break; 3164 case 0x10ec0262: 3165 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC262"); 3166 break; 3167 case 0x10ec0268: 3168 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC268"); 3169 break; 3170 case 0x10ec0662: 3171 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC662"); 3172 break; 3173 case 0x10ec861: 3174 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC861"); 3175 break; 3176 case 0x10ec0862: 3177 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC862"); 3178 break; 3179 case 0x10ec0880: 3180 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC880"); 3181 break; 3182 case 0x10ec0882: 3183 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC882"); 3184 break; 3185 case 0x10ec0883: 3186 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC883"); 3187 break; 3188 case 0x10ec0885: 3189 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC885"); 3190 break; 3191 case 0x10ec0888: 3192 (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC888"); 3193 break; 3194 case 0x13f69880: 3195 (void) snprintf(buf, sizeof (buf), "CMedia HD codec: CMI19880"); 3196 break; 3197 case 0x434d4980: 3198 (void) snprintf(buf, sizeof (buf), "CMedia HD codec: CMI19880"); 3199 break; 3200 case 0x11d41981: 3201 (void) snprintf(buf, sizeof (buf), 3202 "Analog Devices HD codec: AD1981"); 3203 break; 3204 case 0x11d41983: 3205 (void) snprintf(buf, sizeof (buf), 3206 "Analog Devices HD codec: AD1983"); 3207 break; 3208 case 0x11d41984: 3209 (void) snprintf(buf, sizeof (buf), 3210 "Analog Devices HD codec: AD1984"); 3211 break; 3212 case 0x11d41986: 3213 (void) snprintf(buf, sizeof (buf), 3214 "Analog Devices HD codec: AD1986A"); 3215 break; 3216 case 0x11d41988: 3217 (void) snprintf(buf, sizeof (buf), 3218 "Analog Devices HD codec: AD1988A"); 3219 break; 3220 case 0x11d4198b: 3221 (void) snprintf(buf, sizeof (buf), 3222 "Analog Devices HD codec: AD1988B"); 3223 break; 3224 case 0x83847690: 3225 (void) snprintf(buf, sizeof (buf), 3226 "Sigmatel HD codec: STAC9200"); 3227 break; 3228 case 0x838476a0: 3229 (void) snprintf(buf, sizeof (buf), 3230 "Sigmatel HD codec: STAC9205"); 3231 break; 3232 case 0x838476a1: 3233 (void) snprintf(buf, sizeof (buf), 3234 "Sigmatel HD codec: STAC9205D"); 3235 break; 3236 case 0x838476a2: 3237 (void) snprintf(buf, sizeof (buf), 3238 "Sigmatel HD codec: STAC9204"); 3239 break; 3240 case 0x838476a3: 3241 (void) snprintf(buf, sizeof (buf), 3242 "Sigmatel HD codec: STAC9204D"); 3243 break; 3244 case 0x83847880: 3245 (void) snprintf(buf, sizeof (buf), 3246 "Sigmatel HD codec: STAC9220 A1"); 3247 break; 3248 case 0x83847882: 3249 (void) snprintf(buf, sizeof (buf), 3250 "Sigmatel HD codec: STAC9220 A2"); 3251 break; 3252 case 0x83847680: 3253 (void) snprintf(buf, sizeof (buf), 3254 "Sigmatel HD codec: STAC9221 A1"); 3255 break; 3256 case 0x83847681: 3257 (void) snprintf(buf, sizeof (buf), 3258 "Sigmatel HD codec: STAC9220 D"); 3259 break; 3260 case 0x83847682: 3261 (void) snprintf(buf, sizeof (buf), 3262 "Sigmatel HD codec: STAC9221"); 3263 break; 3264 case 0x83847683: 3265 (void) snprintf(buf, sizeof (buf), 3266 "Sigmatel HD codec: STAC9221D"); 3267 break; 3268 case 0x83847610: 3269 (void) snprintf(buf, sizeof (buf), 3270 "Sigmatel HD codec: STAC9230XN"); 3271 break; 3272 case 0x83847611: 3273 (void) snprintf(buf, sizeof (buf), 3274 "Sigmatel HD codec: STAC9230DN"); 3275 break; 3276 case 0x83847612: 3277 (void) snprintf(buf, sizeof (buf), 3278 "Sigmatel HD codec: STAC9230XT"); 3279 break; 3280 case 0x83847613: 3281 (void) snprintf(buf, sizeof (buf), 3282 "Sigmatel HD codec: STAC9230DT"); 3283 break; 3284 case 0x83847614: 3285 (void) snprintf(buf, sizeof (buf), 3286 "Sigmatel HD codec: STAC9229X"); 3287 break; 3288 case 0x83847615: 3289 (void) snprintf(buf, sizeof (buf), 3290 "Sigmatel HD codec: STAC9229D"); 3291 break; 3292 case 0x83847616: 3293 (void) snprintf(buf, sizeof (buf), 3294 "Sigmatel HD codec: STAC9228X"); 3295 break; 3296 case 0x83847617: 3297 (void) snprintf(buf, sizeof (buf), 3298 "Sigmatel HD codec: STAC9228D"); 3299 break; 3300 case 0x83847618: 3301 (void) snprintf(buf, sizeof (buf), 3302 "Sigmatel HD codec: STAC9227X"); 3303 break; 3304 case 0x83847619: 3305 (void) snprintf(buf, sizeof (buf), 3306 "Sigmatel HD codec: STAC9227D"); 3307 break; 3308 case 0x838476a4: 3309 (void) snprintf(buf, sizeof (buf), 3310 "Sigmatel HD codec: STAC9255"); 3311 break; 3312 case 0x838476a5: 3313 (void) snprintf(buf, sizeof (buf), 3314 "Sigmatel HD codec: STAC9255D"); 3315 break; 3316 case 0x838476a6: 3317 (void) snprintf(buf, sizeof (buf), 3318 "Sigmatel HD codec: STAC9254"); 3319 break; 3320 case 0x838476a7: 3321 (void) snprintf(buf, sizeof (buf), 3322 "Sigmatel HD codec: STAC9254D"); 3323 break; 3324 case 0x83847620: 3325 (void) snprintf(buf, sizeof (buf), 3326 "Sigmatel HD codec: STAC9274"); 3327 break; 3328 case 0x83847621: 3329 (void) snprintf(buf, sizeof (buf), 3330 "Sigmatel HD codec: STAC9274D"); 3331 break; 3332 case 0x83847622: 3333 (void) snprintf(buf, sizeof (buf), 3334 "Sigmatel HD codec: STAC9273X"); 3335 break; 3336 case 0x83847623: 3337 (void) snprintf(buf, sizeof (buf), 3338 "Sigmatel HD codec: STAC9273D"); 3339 break; 3340 case 0x83847624: 3341 (void) snprintf(buf, sizeof (buf), 3342 "Sigmatel HD codec: STAC9272X"); 3343 break; 3344 case 0x83847625: 3345 (void) snprintf(buf, sizeof (buf), 3346 "Sigmatel HD codec: STAC9272D"); 3347 break; 3348 case 0x83847626: 3349 (void) snprintf(buf, sizeof (buf), 3350 "Sigmatel HD codec: STAC9271X"); 3351 break; 3352 case 0x83847627: 3353 (void) snprintf(buf, sizeof (buf), 3354 "Sigmatel HD codec: STAC9271D"); 3355 break; 3356 case 0x83847628: 3357 (void) snprintf(buf, sizeof (buf), 3358 "Sigmatel HD codec: STAC9274X5NH"); 3359 break; 3360 case 0x83847629: 3361 (void) snprintf(buf, sizeof (buf), 3362 "Sigmatel HD codec: STAC9274D5NH"); 3363 break; 3364 case 0x83847662: 3365 (void) snprintf(buf, sizeof (buf), 3366 "Sigmatel HD codec: STAC9872AK"); 3367 break; 3368 case 0x83847664: 3369 (void) snprintf(buf, sizeof (buf), 3370 "Sigmatel HD codec: STAC9872K"); 3371 break; 3372 default: 3373 (void) snprintf(buf, sizeof (buf), 3374 "Unknown HD codec: 0x%x", codec->vid); 3375 break; 3376 3377 } 3378 audio_dev_add_info(codec->soft_statep->adev, buf); 3379 } 3380 /* 3381 * audiohd_create_codec() 3382 * 3383 * Description: 3384 * Searching for supported CODEC. If find, allocate memory 3385 * to hold codec structure. 3386 */ 3387 static int 3388 audiohd_create_codec(audiohd_state_t *statep) 3389 { 3390 hda_codec_t *codec; 3391 uint32_t mask, type; 3392 uint32_t nums; 3393 uint32_t i, j; 3394 wid_t wid; 3395 3396 mask = statep->hda_codec_mask; 3397 ASSERT(mask != 0); 3398 3399 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 3400 if ((mask & (1 << i)) == 0) 3401 continue; 3402 codec = (hda_codec_t *)kmem_zalloc( 3403 sizeof (hda_codec_t), KM_SLEEP); 3404 codec->index = i; 3405 codec->vid = audioha_codec_verb_get(statep, i, 3406 AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM, 3407 AUDIOHDC_PAR_VENDOR_ID); 3408 codec->revid = 3409 audioha_codec_verb_get(statep, i, 3410 AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM, 3411 AUDIOHDC_PAR_REV_ID); 3412 3413 nums = audioha_codec_verb_get(statep, 3414 i, AUDIOHDC_NODE_ROOT, 3415 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_NODE_COUNT); 3416 if (nums == (uint32_t)(-1)) { 3417 kmem_free(codec, sizeof (hda_codec_t)); 3418 continue; 3419 } 3420 wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK; 3421 nums = nums & AUDIOHD_CODEC_NUM_MASK; 3422 3423 /* 3424 * Assume that each codec has just one audio function group 3425 */ 3426 for (j = 0; j < nums; j++, wid++) { 3427 type = audioha_codec_verb_get(statep, i, wid, 3428 AUDIOHDC_VERB_GET_PARAM, 3429 AUDIOHDC_PAR_FUNCTION_TYPE); 3430 if ((type & AUDIOHD_CODEC_TYPE_MASK) == 3431 AUDIOHDC_AUDIO_FUNC_GROUP) { 3432 codec->wid_afg = wid; 3433 break; 3434 } 3435 } 3436 3437 if (codec->wid_afg == 0) { 3438 kmem_free(codec, sizeof (hda_codec_t)); 3439 continue; 3440 } 3441 3442 ASSERT(codec->wid_afg == wid); 3443 3444 /* work around for Sony VAIO laptop with specific codec */ 3445 if ((codec->vid != AUDIOHD_CODECID_SONY1) && 3446 (codec->vid != AUDIOHD_CODECID_SONY2)) { 3447 /* 3448 * GPIO controls which are laptop specific workarounds 3449 * and might be changed. Some laptops use GPIO, 3450 * so we need to enable and set the GPIO correctly. 3451 */ 3452 (void) audioha_codec_verb_get(statep, i, wid, 3453 AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE); 3454 (void) audioha_codec_verb_get(statep, i, wid, 3455 AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT); 3456 (void) audioha_codec_verb_get(statep, i, wid, 3457 AUDIOHDC_VERB_SET_GPIO_STCK, 3458 AUDIOHDC_GPIO_DATA_CTRL); 3459 (void) audioha_codec_verb_get(statep, i, wid, 3460 AUDIOHDC_VERB_SET_GPIO_DATA, 3461 AUDIOHDC_GPIO_STCK_CTRL); 3462 } 3463 3464 /* power-up audio function group */ 3465 (void) audioha_codec_verb_get(statep, i, wid, 3466 AUDIOHDC_VERB_SET_POWER_STATE, 0); 3467 3468 /* subsystem id is attached to funtion group */ 3469 codec->outamp_cap = audioha_codec_verb_get(statep, i, wid, 3470 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_OUTAMP_CAP); 3471 codec->inamp_cap = audioha_codec_verb_get(statep, i, wid, 3472 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_INAMP_CAP); 3473 codec->stream_format = audioha_codec_verb_get(statep, i, wid, 3474 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_STREAM); 3475 codec->pcm_format = audioha_codec_verb_get(statep, i, wid, 3476 AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM); 3477 3478 nums = audioha_codec_verb_get(statep, i, wid, 3479 AUDIOHDC_VERB_GET_PARAM, 3480 AUDIOHDC_PAR_NODE_COUNT); 3481 wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK; 3482 nums = nums & AUDIOHD_CODEC_NUM_MASK; 3483 codec->first_wid = wid; 3484 codec->last_wid = wid + nums; 3485 codec->nnodes = nums; 3486 3487 /* 3488 * We output the codec information to syslog 3489 */ 3490 statep->codec[i] = codec; 3491 codec->soft_statep = statep; 3492 audiohd_set_codec_info(codec); 3493 (void) audiohd_create_widgets(codec); 3494 } 3495 3496 return (DDI_SUCCESS); 3497 3498 } /* audiohd_create_codec() */ 3499 3500 /* 3501 * audiohd_destroy_codec() 3502 * 3503 * Description: 3504 * destroy codec structure, and release its memory 3505 */ 3506 static void 3507 audiohd_destroy_codec(audiohd_state_t *statep) 3508 { 3509 int i; 3510 audiohd_pin_t *pin, *npin; 3511 3512 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 3513 if (statep->codec[i]) { 3514 audiohd_destroy_widgets(statep->codec[i]); 3515 /* 3516 * free pins 3517 */ 3518 pin = statep->codec[i]->first_pin; 3519 while (pin) { 3520 npin = pin; 3521 pin = pin->next; 3522 kmem_free(npin, sizeof (audiohd_pin_t)); 3523 } 3524 3525 kmem_free(statep->codec[i], sizeof (hda_codec_t)); 3526 statep->codec[i] = NULL; 3527 } 3528 } 3529 } /* audiohd_destroy_codec() */ 3530 3531 /* 3532 * audiohd_find_dac() 3533 * Description: 3534 * Find a dac for a output path. Then the play data can be sent to the out 3535 * put pin through the output path. 3536 * 3537 * Arguments: 3538 * hda_codec_t *codec where the dac widget exists 3539 * wid_t wid the no. of a widget 3540 * int mixer whether the path need mixer or not 3541 * int *mixernum the total of mixer in the output path 3542 * int exclusive an exclusive path or share path 3543 * int depth the depth of search 3544 * 3545 * Return: 3546 * 1) wid of the first shared widget in the path from 3547 * pin to DAC if exclusive is 0; 3548 * 2) wid of DAC widget; 3549 * 3) 0 if no path 3550 */ 3551 static wid_t 3552 audiohd_find_dac(hda_codec_t *codec, wid_t wid, 3553 int mixer, int *mixernum, 3554 int exclusive, int depth) 3555 { 3556 audiohd_widget_t *widget = codec->widget[wid]; 3557 wid_t wdac = (uint32_t)(DDI_FAILURE); 3558 wid_t retval; 3559 3560 if (depth > AUDIOHD_MAX_DEPTH) 3561 return (uint32_t)(DDI_FAILURE); 3562 3563 if (widget == NULL) 3564 return (uint32_t)(DDI_FAILURE); 3565 3566 /* 3567 * If exclusive is true, we try to find a path which doesn't 3568 * share any widget with other paths. 3569 */ 3570 if (exclusive) { 3571 if (widget->path_flags & AUDIOHD_PATH_DAC) 3572 return (uint32_t)(DDI_FAILURE); 3573 } else { 3574 if (widget->path_flags & AUDIOHD_PATH_DAC) 3575 return (wid); 3576 } 3577 3578 switch (widget->type) { 3579 case WTYPE_AUDIO_OUT: 3580 /* We need mixer widget, but the the mixer num is 0, failed */ 3581 if (mixer && !*mixernum) 3582 return (uint32_t)(DDI_FAILURE); 3583 widget->path_flags |= AUDIOHD_PATH_DAC; 3584 widget->out_weight++; 3585 wdac = widget->wid_wid; 3586 break; 3587 3588 case WTYPE_AUDIO_MIX: 3589 case WTYPE_AUDIO_SEL: 3590 if (widget->type == WTYPE_AUDIO_MIX) 3591 (*mixernum)++; 3592 for (int i = 0; i < widget->nconns; i++) { 3593 retval = audiohd_find_dac(codec, 3594 widget->avail_conn[i], 3595 mixer, mixernum, 3596 exclusive, depth + 1); 3597 if (retval != (uint32_t)DDI_FAILURE) { 3598 if (widget->selconn == AUDIOHD_NULL_CONN) { 3599 widget->selconn = i; 3600 wdac = retval; 3601 } 3602 widget->path_flags |= AUDIOHD_PATH_DAC; 3603 widget->out_weight++; 3604 3605 /* return when found a path */ 3606 return (wdac); 3607 } 3608 } 3609 default: 3610 break; 3611 } 3612 3613 return (wdac); 3614 } /* audiohd_find_dac() */ 3615 3616 /* 3617 * audiohd_do_build_output_path() 3618 * 3619 * Description: 3620 * Search an output path for each pin in the codec. 3621 * Arguments: 3622 * hda_codec_t *codec where the output path exists 3623 * int mixer wheter the path needs mixer widget 3624 * int *mnum total of mixer widget in the path 3625 * int exclusive an exclusive path or shared path 3626 * int depth search depth 3627 */ 3628 static void 3629 audiohd_do_build_output_path(hda_codec_t *codec, int mixer, int *mnum, 3630 int exclusive, int depth) 3631 { 3632 audiohd_pin_t *pin; 3633 audiohd_widget_t *widget, *wdac; 3634 audiohd_path_t *path; 3635 wid_t wid; 3636 audiohd_state_t *statep; 3637 int i; 3638 3639 statep = codec->soft_statep; 3640 3641 for (pin = codec->first_pin; pin; pin = pin->next) { 3642 if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0) 3643 continue; 3644 if ((pin->config & AUDIOHD_PIN_CONF_MASK) == 3645 AUDIOHD_PIN_NO_CONN) 3646 continue; 3647 if ((pin->device != DTYPE_LINEOUT) && 3648 (pin->device != DTYPE_SPEAKER) && 3649 (pin->device != DTYPE_SPDIF_OUT) && 3650 (pin->device != DTYPE_HP_OUT)) 3651 continue; 3652 if (pin->finish) 3653 continue; 3654 widget = codec->widget[pin->wid]; 3655 3656 widget->inamp_cap = 0; 3657 for (i = 0; i < widget->nconns; i++) { 3658 /* 3659 * If a dac found, the return value is the wid of the 3660 * widget on the path, or the return value is 3661 * DDI_FAILURE 3662 */ 3663 wid = audiohd_find_dac(codec, 3664 widget->avail_conn[i], mixer, mnum, exclusive, 3665 depth); 3666 /* 3667 * A dac was not found 3668 */ 3669 if (wid == (wid_t)DDI_FAILURE) 3670 continue; 3671 if (pin->device != DTYPE_SPEAKER && 3672 pin->device != DTYPE_HP_OUT) 3673 statep->chann[pin->assoc] += 2; 3674 path = (audiohd_path_t *) 3675 kmem_zalloc(sizeof (audiohd_path_t), 3676 KM_SLEEP); 3677 path->adda_wid = wid; 3678 path->pin_wid[0] = widget->wid_wid; 3679 path->pin_nums = 1; 3680 path->path_type = PLAY; 3681 path->codec = codec; 3682 path->statep = statep; 3683 wdac = codec->widget[wid]; 3684 wdac->priv = path; 3685 pin->adc_dac_wid = wid; 3686 pin->finish = 1; 3687 widget->path_flags |= AUDIOHD_PATH_DAC; 3688 widget->out_weight++; 3689 widget->selconn = i; 3690 statep->path[statep->pathnum++] = path; 3691 break; 3692 } 3693 } 3694 3695 } /* audiohd_do_build_output_path() */ 3696 3697 /* 3698 * audiohd_build_output_path() 3699 * 3700 * Description: 3701 * Build the output path in the codec for every pin. 3702 * First we try to search output path with mixer widget exclusively 3703 * Then we try to search shared output path with mixer widget. 3704 * Then we try to search output path without mixer widget exclusively. 3705 * At last we try to search shared ouput path for the remained pins 3706 */ 3707 static void 3708 audiohd_build_output_path(hda_codec_t *codec) 3709 { 3710 int mnum = 0; 3711 uint8_t mixer_allow = 1; 3712 3713 /* 3714 * Work around for laptops which have IDT or AD audio chipset, such as 3715 * HP mini 1000 laptop, Dell Lattitude 6400, Lenovo T60. We don't 3716 * allow mixer widget on such path, which leads to speaker 3717 * loud hiss noise. 3718 */ 3719 if (codec->vid == AUDIOHD_CODEC_IDT7608 || 3720 codec->vid == AUDIOHD_CODEC_IDT76B2 || 3721 codec->vid == AUDIOHD_CODEC_AD1981) 3722 mixer_allow = 0; 3723 /* search an exclusive mixer widget path. This is preferred */ 3724 audiohd_do_build_output_path(codec, mixer_allow, &mnum, 1, 0); 3725 3726 /* search a shared mixer widget path for the remained pins */ 3727 audiohd_do_build_output_path(codec, mixer_allow, &mnum, 0, 0); 3728 3729 /* search an exclusive widget path without mixer for the remained pin */ 3730 audiohd_do_build_output_path(codec, 0, &mnum, 1, 0); 3731 3732 /* search a shared widget path without mixer for the remained pin */ 3733 audiohd_do_build_output_path(codec, 0, &mnum, 0, 0); 3734 3735 } /* audiohd_build_output_path */ 3736 3737 /* 3738 * audiohd_build_output_amp 3739 * 3740 * Description: 3741 * Find the gain control and mute control widget 3742 */ 3743 static void 3744 audiohd_build_output_amp(hda_codec_t *codec) 3745 { 3746 audiohd_path_t *path; 3747 audiohd_widget_t *w, *widget, *wpin, *wdac; 3748 audiohd_pin_t *pin; 3749 wid_t wid; 3750 int weight; 3751 int i, j; 3752 uint32_t gain; 3753 3754 for (i = 0; i < codec->soft_statep->pathnum; i++) { 3755 path = codec->soft_statep->path[i]; 3756 if (path == NULL || path->path_type == RECORD || 3757 path->codec != codec) 3758 continue; 3759 for (j = 0; j < path->pin_nums; j++) { 3760 wid = path->pin_wid[j]; 3761 wpin = codec->widget[wid]; 3762 pin = (audiohd_pin_t *)wpin->priv; 3763 weight = wpin->out_weight; 3764 3765 /* 3766 * search a node which can mute this pin while 3767 * the mute functionality doesn't effect other 3768 * pins. 3769 */ 3770 widget = wpin; 3771 while (widget) { 3772 if (widget->outamp_cap & 3773 AUDIOHDC_AMP_CAP_MUTE_CAP) { 3774 pin->mute_wid = widget->wid_wid; 3775 pin->mute_dir = AUDIOHDC_AMP_SET_OUTPUT; 3776 break; 3777 } 3778 if (widget->inamp_cap & 3779 AUDIOHDC_AMP_CAP_MUTE_CAP) { 3780 pin->mute_wid = widget->wid_wid; 3781 pin->mute_dir = AUDIOHDC_AMP_SET_INPUT; 3782 break; 3783 } 3784 if (widget->selconn == AUDIOHD_NULL_CONN) 3785 break; 3786 wid = widget->avail_conn[widget->selconn]; 3787 widget = codec->widget[wid]; 3788 if (widget && widget->out_weight != weight) 3789 break; 3790 } 3791 3792 /* 3793 * We select the wid which has maxium gain range in 3794 * the output path. Meanwhile, the gain controlling 3795 * of this node doesn't effect other pins if this 3796 * output stream has multiple pins. 3797 */ 3798 gain = 0; 3799 widget = wpin; 3800 while (widget) { 3801 gain = (widget->outamp_cap & 3802 AUDIOHDC_AMP_CAP_STEP_NUMS); 3803 if (gain && gain > pin->gain_bits) { 3804 pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT; 3805 pin->gain_bits = gain; 3806 pin->gain_wid = widget->wid_wid; 3807 } 3808 gain = widget->inamp_cap & 3809 AUDIOHDC_AMP_CAP_STEP_NUMS; 3810 if (gain && gain > pin->gain_bits) { 3811 pin->gain_dir = AUDIOHDC_AMP_SET_INPUT; 3812 pin->gain_bits = gain; 3813 pin->gain_wid = widget->wid_wid; 3814 } 3815 if (widget->selconn == AUDIOHD_NULL_CONN) 3816 break; 3817 wid = widget->avail_conn[widget->selconn]; 3818 widget = codec->widget[wid]; 3819 if (widget && widget->out_weight != weight) 3820 break; 3821 } 3822 pin->gain_bits >>= AUDIOHD_GAIN_OFF; 3823 } 3824 3825 /* 3826 * if this stream has multiple pins, we try to find 3827 * a mute & gain-controlling nodes which can effect 3828 * all output pins of this stream to be used for the 3829 * whole stream 3830 */ 3831 if (path->pin_nums == 1) { 3832 path->mute_wid = pin->mute_wid; 3833 path->mute_dir = pin->mute_dir; 3834 path->gain_wid = pin->gain_wid; 3835 path->gain_dir = pin->gain_dir; 3836 path->gain_bits = pin->gain_bits; 3837 } else { 3838 wdac = codec->widget[path->adda_wid]; 3839 weight = wdac->out_weight; 3840 wid = path->pin_wid[0]; 3841 w = codec->widget[wid]; 3842 while (w && w->out_weight != weight) { 3843 wid = w->avail_conn[w->selconn]; 3844 w = codec->widget[wid]; 3845 } 3846 3847 /* find mute controlling node for this stream */ 3848 widget = w; 3849 while (widget) { 3850 if (widget->outamp_cap & 3851 AUDIOHDC_AMP_CAP_MUTE_CAP) { 3852 path->mute_wid = widget->wid_wid; 3853 path->mute_dir = 3854 AUDIOHDC_AMP_SET_OUTPUT; 3855 break; 3856 } 3857 if (widget->inamp_cap & 3858 AUDIOHDC_AMP_CAP_MUTE_CAP) { 3859 path->mute_wid = widget->wid_wid; 3860 path->mute_dir = 3861 AUDIOHDC_AMP_SET_INPUT; 3862 break; 3863 } 3864 if (widget->selconn == AUDIOHD_NULL_CONN) 3865 break; 3866 wid = widget->avail_conn[widget->selconn]; 3867 widget = codec->widget[wid]; 3868 } 3869 3870 /* find volume controlling node for this stream */ 3871 gain = 0; 3872 widget = w; 3873 while (widget) { 3874 gain = (widget->outamp_cap & 3875 AUDIOHDC_AMP_CAP_STEP_NUMS); 3876 if (gain && gain > pin->gain_bits) { 3877 path->gain_dir = 3878 AUDIOHDC_AMP_SET_OUTPUT; 3879 path->gain_bits = gain; 3880 path->gain_wid = widget->wid_wid; 3881 } 3882 gain = widget->inamp_cap & 3883 AUDIOHDC_AMP_CAP_STEP_NUMS; 3884 if (gain && (gain > pin->gain_bits) && 3885 (widget->type != WTYPE_AUDIO_MIX)) { 3886 path->gain_dir = 3887 AUDIOHDC_AMP_SET_INPUT; 3888 path->gain_bits = gain; 3889 path->gain_wid = widget->wid_wid; 3890 } 3891 if (widget->selconn == AUDIOHD_NULL_CONN) 3892 break; 3893 wid = widget->avail_conn[widget->selconn]; 3894 widget = codec->widget[wid]; 3895 } 3896 path->gain_bits >>= AUDIOHD_GAIN_OFF; 3897 } 3898 3899 } 3900 3901 } /* audiohd_build_output_amp */ 3902 3903 /* 3904 * audiohd_finish_output_path() 3905 * 3906 * Description: 3907 * Enable the widgets on the output path 3908 */ 3909 static void 3910 audiohd_finish_output_path(hda_codec_t *codec) 3911 { 3912 audiohd_state_t *statep = codec->soft_statep; 3913 audiohd_path_t *path; 3914 audiohd_widget_t *widget; 3915 audiohd_pin_t *pin; 3916 uint_t caddr = codec->index; 3917 wid_t wid; 3918 int i, j; 3919 3920 for (i = 0; i < codec->soft_statep->pathnum; i++) { 3921 path = codec->soft_statep->path[i]; 3922 if (!path || path->path_type != PLAY || path->codec != codec) 3923 continue; 3924 for (j = 0; j < path->pin_nums; j++) { 3925 wid = path->pin_wid[j]; 3926 widget = codec->widget[wid]; 3927 pin = (audiohd_pin_t *)widget->priv; 3928 { 3929 uint32_t lTmp; 3930 3931 lTmp = audioha_codec_verb_get(statep, caddr, wid, 3932 AUDIOHDC_VERB_GET_PIN_CTRL, 0); 3933 (void) audioha_codec_verb_get(statep, caddr, wid, 3934 AUDIOHDC_VERB_SET_PIN_CTRL, (lTmp | 3935 pin->vrefvalue | 3936 AUDIOHDC_PIN_CONTROL_OUT_ENABLE | 3937 AUDIOHDC_PIN_CONTROL_HP_ENABLE) & 3938 ~ AUDIOHDC_PIN_CONTROL_IN_ENABLE); 3939 } 3940 /* If this pin has external amplifier, enable it */ 3941 if (pin->cap & AUDIOHD_EXT_AMP_MASK) 3942 (void) audioha_codec_verb_get(statep, caddr, 3943 wid, AUDIOHDC_VERB_SET_EAPD, 3944 AUDIOHD_EXT_AMP_ENABLE); 3945 3946 if (widget->outamp_cap) { 3947 (void) audioha_codec_4bit_verb_get(statep, 3948 caddr, wid, AUDIOHDC_VERB_SET_AMP_MUTE, 3949 AUDIOHDC_AMP_SET_LR_OUTPUT | 3950 AUDIOHDC_GAIN_MAX); 3951 } 3952 3953 (void) audioha_codec_verb_get(statep, caddr, wid, 3954 AUDIOHDC_VERB_SET_CONN_SEL, widget->selconn); 3955 3956 wid = widget->avail_conn[widget->selconn]; 3957 widget = codec->widget[wid]; 3958 3959 while (widget) { 3960 /* 3961 * Set all amplifiers in this path to 3962 * the maximum 3963 * volume and unmute them. 3964 */ 3965 if (widget->outamp_cap) { 3966 (void) audioha_codec_4bit_verb_get( 3967 statep, 3968 caddr, 3969 wid, AUDIOHDC_VERB_SET_AMP_MUTE, 3970 AUDIOHDC_AMP_SET_LR_OUTPUT | 3971 AUDIOHDC_GAIN_MAX); 3972 } 3973 if (widget->inamp_cap) { 3974 (void) audioha_codec_4bit_verb_get( 3975 statep, 3976 caddr, 3977 wid, AUDIOHDC_VERB_SET_AMP_MUTE, 3978 AUDIOHDC_AMP_SET_LR_INPUT | 3979 AUDIOHDC_GAIN_MAX | 3980 (widget->selconn << 3981 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 3982 } 3983 3984 if (widget->selconn == AUDIOHD_NULL_CONN) 3985 break; 3986 /* 3987 * Accoding to HD spec, mixer doesn't support 3988 * "select connection" 3989 */ 3990 if ((widget->type != WTYPE_AUDIO_MIX) && 3991 (widget->nconns > 1)) 3992 (void) audioha_codec_verb_get(statep, 3993 caddr, 3994 wid, 3995 AUDIOHDC_VERB_SET_CONN_SEL, 3996 widget->selconn); 3997 3998 wid = widget->avail_conn[widget->selconn]; 3999 widget = codec->widget[wid]; 4000 } 4001 } 4002 } 4003 } /* audiohd_finish_output_path() */ 4004 4005 /* 4006 * audiohd_find_input_pins() 4007 * 4008 * Description: 4009 * Here we consider a mixer/selector with multi-input as a real sum 4010 * widget. Only the first real mixer/selector widget is permitted in 4011 * an input path(recording path). If there are more mixers/selectors 4012 * execept the first one, only the first input/connection of those 4013 * widgets will be used by our driver, that means, we ignore other 4014 * inputs of those mixers/selectors. 4015 */ 4016 static int 4017 audiohd_find_input_pins(hda_codec_t *codec, wid_t wid, int allowmixer, 4018 int depth, audiohd_path_t *path) 4019 { 4020 audiohd_widget_t *widget = codec->widget[wid]; 4021 audiohd_pin_t *pin; 4022 audiohd_state_t *statep = codec->soft_statep; 4023 uint_t caddr = codec->index; 4024 int retval = -1; 4025 int num, i; 4026 uint32_t pinctrl; 4027 4028 if (depth > AUDIOHD_MAX_DEPTH) 4029 return (uint32_t)(DDI_FAILURE); 4030 if (widget == NULL) 4031 return (uint32_t)(DDI_FAILURE); 4032 4033 /* we don't share widgets */ 4034 if (widget->path_flags & AUDIOHD_PATH_ADC || 4035 widget->path_flags & AUDIOHD_PATH_DAC) 4036 return (uint32_t)(DDI_FAILURE); 4037 4038 switch (widget->type) { 4039 case WTYPE_PIN: 4040 pin = (audiohd_pin_t *)widget->priv; 4041 if (pin->no_phys_conn) 4042 return (uint32_t)(DDI_FAILURE); 4043 /* enable the pins' input capability */ 4044 pinctrl = audioha_codec_verb_get(statep, caddr, wid, 4045 AUDIOHDC_VERB_GET_PIN_CTRL, 0); 4046 (void) audioha_codec_verb_get(statep, caddr, wid, 4047 AUDIOHDC_VERB_SET_PIN_CTRL, 4048 pinctrl | AUDIOHD_PIN_IN_ENABLE); 4049 if (pin->cap & AUDIOHD_EXT_AMP_MASK) { 4050 (void) audioha_codec_verb_get(statep, caddr, 4051 wid, AUDIOHDC_VERB_SET_EAPD, 4052 AUDIOHD_EXT_AMP_ENABLE); 4053 } 4054 switch (pin->device) { 4055 case DTYPE_CD: 4056 case DTYPE_LINE_IN: 4057 case DTYPE_MIC_IN: 4058 case DTYPE_AUX: 4059 widget->path_flags |= AUDIOHD_PATH_ADC; 4060 widget->in_weight++; 4061 path->pin_wid[path->pin_nums++] = wid; 4062 pin->adc_dac_wid = path->adda_wid; 4063 return (DDI_SUCCESS); 4064 } 4065 break; 4066 case WTYPE_AUDIO_MIX: 4067 case WTYPE_AUDIO_SEL: 4068 /* 4069 * If the sum widget has only one input, we don't 4070 * consider it as a real sum widget. 4071 */ 4072 if (widget->nconns == 1) { 4073 widget->selconn = 0; 4074 retval = audiohd_find_input_pins(codec, 4075 widget->avail_conn[0], 4076 allowmixer, depth + 1, path); 4077 if (retval != DDI_FAILURE) { 4078 widget->path_flags |= AUDIOHD_PATH_ADC; 4079 widget->in_weight++; 4080 } 4081 break; 4082 } 4083 4084 if (allowmixer) { 4085 /* 4086 * This is a real sum widget, we will reject 4087 * other real sum widget when we find more in 4088 * the following path-searching. 4089 */ 4090 for (int i = 0; i < widget->nconns; i++) { 4091 retval = audiohd_find_input_pins(codec, 4092 widget->avail_conn[i], 0, depth + 1, 4093 path); 4094 if (retval != DDI_FAILURE) { 4095 widget->in_weight++; 4096 num = path->pin_nums - 1; 4097 path->sum_selconn[num] = i; 4098 path->sum_wid = wid; 4099 widget->path_flags |= 4100 AUDIOHD_PATH_ADC; 4101 if (widget->selconn == 4102 AUDIOHD_NULL_CONN) { 4103 widget->selconn = i; 4104 } 4105 } 4106 } 4107 4108 /* return SUCCESS if we found at least one input path */ 4109 if (path->pin_nums > 0) 4110 retval = DDI_SUCCESS; 4111 } else { 4112 /* 4113 * We had already found a real sum before this one since 4114 * allowmixer is 0. 4115 */ 4116 for (i = 0; i < widget->nconns; i++) { 4117 retval = audiohd_find_input_pins(codec, 4118 widget->avail_conn[i], 0, depth + 1, 4119 path); 4120 if (retval != DDI_FAILURE) { 4121 widget->selconn = i; 4122 widget->path_flags |= AUDIOHD_PATH_ADC; 4123 widget->in_weight++; 4124 break; 4125 } 4126 } 4127 } 4128 break; 4129 default: 4130 break; 4131 } 4132 4133 return (retval); 4134 } /* audiohd_find_input_pins */ 4135 4136 /* 4137 * audiohd_build_input_path() 4138 * 4139 * Description: 4140 * Find input path for the codec 4141 */ 4142 static void 4143 audiohd_build_input_path(hda_codec_t *codec) 4144 { 4145 audiohd_widget_t *widget; 4146 audiohd_path_t *path = NULL; 4147 wid_t wid; 4148 int i; 4149 int retval; 4150 uint8_t rtag = 0; 4151 audiohd_state_t *statep = codec->soft_statep; 4152 4153 for (wid = codec->first_wid; wid <= codec->last_wid; wid++) { 4154 4155 widget = codec->widget[wid]; 4156 4157 /* check if it is an ADC widget */ 4158 if (!widget || widget->type != WTYPE_AUDIO_IN) 4159 continue; 4160 4161 if (path == NULL) 4162 path = kmem_zalloc(sizeof (audiohd_path_t), 4163 KM_SLEEP); 4164 else 4165 bzero(path, sizeof (audiohd_port_t)); 4166 4167 path->adda_wid = wid; 4168 4169 /* 4170 * Is there any ADC widget which has more than one input ?? 4171 * I don't believe. Anyway, we carefully deal with this. But 4172 * if hardware vendors embed a selector in a ADC, we just use 4173 * the first available input, which has connection to input pin 4174 * widget. Because selector cannot perform mixer functionality, 4175 * and we just permit one selector or mixer in a recording path, 4176 * if we use the selector embedded in ADC,we cannot use possible 4177 * mixer during path searching. 4178 */ 4179 for (i = 0; i < widget->nconns; i++) { 4180 retval = audiohd_find_input_pins(codec, 4181 widget->avail_conn[i], 1, 0, path); 4182 if (retval == DDI_SUCCESS) { 4183 path->codec = codec; 4184 path->statep = statep; 4185 path->path_type = RECORD; 4186 path->tag = ++rtag; 4187 codec->nistream++; 4188 statep->path[statep->pathnum++] = path; 4189 widget->selconn = i; 4190 widget->priv = path; 4191 path = NULL; 4192 break; 4193 } 4194 } 4195 } 4196 if (path) 4197 kmem_free(path, sizeof (audiohd_path_t)); 4198 } /* audiohd_build_input_path */ 4199 4200 /* 4201 * audiohd_build_input_amp() 4202 * 4203 * Description: 4204 * Find gain and mute control widgets on the input path 4205 */ 4206 static void 4207 audiohd_build_input_amp(hda_codec_t *codec) 4208 { 4209 audiohd_path_t *path; 4210 audiohd_widget_t *wsum, *wadc, *w; 4211 audiohd_pin_t *pin; 4212 uint_t gain; 4213 wid_t wid; 4214 int i, j; 4215 int weight; 4216 4217 for (i = 0; i < codec->soft_statep->pathnum; i++) { 4218 path = codec->soft_statep->path[i]; 4219 if (path == NULL || path->path_type != RECORD || 4220 path->codec != codec) 4221 continue; 4222 4223 wid = path->adda_wid; 4224 wadc = path->codec->widget[wid]; 4225 weight = wadc->in_weight; 4226 4227 /* 4228 * Search node which has mute functionality for 4229 * the whole input path 4230 */ 4231 w = wadc; 4232 while (w) { 4233 if (w->outamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) { 4234 path->mute_wid = w->wid_wid; 4235 path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT; 4236 break; 4237 } 4238 if ((w->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) && 4239 (w->wid_wid != path->sum_wid)) { 4240 path->mute_wid = w->wid_wid; 4241 path->mute_dir = AUDIOHDC_AMP_SET_INPUT; 4242 break; 4243 } 4244 4245 if (w->selconn == AUDIOHD_NULL_CONN) 4246 break; 4247 wid = w->avail_conn[w->selconn]; 4248 w = path->codec->widget[wid]; 4249 if (w && w->in_weight != weight) 4250 break; 4251 } 4252 4253 /* 4254 * Search a node for amplifier adjusting for the whole 4255 * input path 4256 */ 4257 w = wadc; 4258 gain = 0; 4259 while (w) { 4260 gain = (w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS); 4261 if (gain && gain > path->gain_bits) { 4262 path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT; 4263 path->gain_bits = gain; 4264 path->gain_wid = w->wid_wid; 4265 } 4266 gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS; 4267 if (gain && (gain > path->gain_bits) && 4268 (w->wid_wid != path->sum_wid)) { 4269 path->gain_dir = AUDIOHDC_AMP_SET_INPUT; 4270 path->gain_bits = gain; 4271 path->gain_wid = w->wid_wid; 4272 } 4273 if (w->selconn == AUDIOHD_NULL_CONN) 4274 break; 4275 wid = w->avail_conn[w->selconn]; 4276 w = path->codec->widget[wid]; 4277 } 4278 path->gain_bits >>= AUDIOHD_GAIN_OFF; 4279 4280 /* 4281 * If the input path has one pin only, the mute/amp 4282 * controlling is shared by the whole path and pin 4283 */ 4284 if (path->pin_nums == 1) { 4285 wid = path->pin_wid[0]; 4286 w = path->codec->widget[wid]; 4287 pin = (audiohd_pin_t *)w->priv; 4288 pin->gain_dir = path->gain_dir; 4289 pin->gain_bits = path->gain_bits; 4290 pin->gain_wid = path->gain_wid; 4291 pin->mute_wid = path->mute_wid; 4292 pin->mute_dir = path->mute_dir; 4293 continue; 4294 } 4295 4296 /* 4297 * For multi-pin device, there must be a selector 4298 * or mixer along the input path, and the sum_wid 4299 * is the widget's node id. 4300 */ 4301 wid = path->sum_wid; 4302 wsum = path->codec->widget[wid]; /* sum widget */ 4303 4304 for (j = 0; j < path->pin_nums; j++) { 4305 wid = path->pin_wid[j]; 4306 w = path->codec->widget[wid]; 4307 pin = (audiohd_pin_t *)w->priv; 4308 4309 /* find node for mute */ 4310 if (wsum->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) { 4311 pin->mute_wid = wsum->wid_wid; 4312 pin->mute_dir = AUDIOHDC_AMP_SET_INPUT; 4313 } else { 4314 wid = wsum->avail_conn[path->sum_selconn[i]]; 4315 w = path->codec->widget[wid]; 4316 while (w) { 4317 if (w->outamp_cap & 4318 AUDIOHDC_AMP_CAP_MUTE_CAP) { 4319 pin->mute_wid = w->wid_wid; 4320 pin->mute_dir = 4321 AUDIOHDC_AMP_SET_OUTPUT; 4322 break; 4323 } 4324 if (w->inamp_cap & 4325 AUDIOHDC_AMP_CAP_MUTE_CAP) { 4326 pin->mute_wid = w->wid_wid; 4327 pin->mute_dir = 4328 AUDIOHDC_AMP_SET_INPUT; 4329 break; 4330 } 4331 4332 if (w->selconn == AUDIOHD_NULL_CONN) 4333 break; 4334 wid = w->avail_conn[w->selconn]; 4335 w = path->codec->widget[wid]; 4336 } 4337 } 4338 4339 /* find node for amp controlling */ 4340 gain = (wsum->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS); 4341 wid = wsum->avail_conn[path->sum_selconn[i]]; 4342 w = path->codec->widget[wid]; 4343 while (w) { 4344 gain = (w->outamp_cap & 4345 AUDIOHDC_AMP_CAP_STEP_NUMS); 4346 if (gain && gain > pin->gain_bits) { 4347 pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT; 4348 pin->gain_bits = gain; 4349 pin->gain_wid = w->wid_wid; 4350 } 4351 gain = w->inamp_cap & 4352 AUDIOHDC_AMP_CAP_STEP_NUMS; 4353 if (gain && (gain > pin->gain_bits)) { 4354 pin->gain_dir = AUDIOHDC_AMP_SET_INPUT; 4355 pin->gain_bits = gain; 4356 pin->gain_wid = w->wid_wid; 4357 } 4358 if (w->selconn == AUDIOHD_NULL_CONN) 4359 break; 4360 wid = w->avail_conn[w->selconn]; 4361 w = path->codec->widget[wid]; 4362 } 4363 pin->gain_bits >>= AUDIOHD_GAIN_OFF; 4364 } 4365 } 4366 } /* audiohd_build_input_amp() */ 4367 4368 /* 4369 * audiohd_finish_input_path() 4370 * 4371 * Description: 4372 * Enable the widgets on the input path 4373 */ 4374 static void 4375 audiohd_finish_input_path(hda_codec_t *codec) 4376 { 4377 audiohd_state_t *statep = codec->soft_statep; 4378 audiohd_path_t *path; 4379 audiohd_widget_t *w, *wsum; 4380 uint_t caddr = codec->index; 4381 wid_t wid; 4382 int i, j; 4383 4384 for (i = 0; i < codec->soft_statep->pathnum; i++) { 4385 path = codec->soft_statep->path[i]; 4386 if (path == NULL || path->path_type != RECORD || 4387 path->codec != codec) 4388 continue; 4389 wid = path->adda_wid; 4390 w = path->codec->widget[wid]; 4391 while (w && (w->wid_wid != path->sum_wid) && 4392 (w->type != WTYPE_PIN)) { 4393 if ((w->type == WTYPE_AUDIO_SEL) && (w->nconns > 1)) 4394 (void) audioha_codec_verb_get(statep, caddr, 4395 w->wid_wid, 4396 AUDIOHDC_VERB_SET_CONN_SEL, w->selconn); 4397 4398 if (w->outamp_cap) { 4399 (void) audioha_codec_4bit_verb_get(statep, 4400 caddr, 4401 w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE, 4402 AUDIOHDC_AMP_SET_LR_OUTPUT | 4403 AUDIOHDC_GAIN_MAX); 4404 } 4405 4406 if (w->inamp_cap) { 4407 (void) audioha_codec_4bit_verb_get(statep, 4408 caddr, 4409 w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE, 4410 AUDIOHDC_AMP_SET_LR_INPUT | 4411 AUDIOHDC_GAIN_MAX | 4412 (w->selconn << 4413 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 4414 } 4415 4416 wid = w->avail_conn[w->selconn]; 4417 w = path->codec->widget[wid]; 4418 } 4419 4420 /* 4421 * After exiting from the above loop, the widget pointed 4422 * by w can be a pin widget or select/mixer widget. If it 4423 * is a pin widget, we already finish "select connection" 4424 * operation for the whole path. 4425 */ 4426 if (w && w->type == WTYPE_PIN) 4427 continue; 4428 4429 /* 4430 * deal with multi-pin input devices. 4431 */ 4432 wid = path->sum_wid; 4433 wsum = path->codec->widget[wid]; 4434 if (wsum == NULL) 4435 continue; 4436 if (wsum->outamp_cap) { 4437 (void) audioha_codec_4bit_verb_get(statep, 4438 caddr, 4439 wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE, 4440 AUDIOHDC_AMP_SET_LR_OUTPUT | 4441 AUDIOHDC_GAIN_MAX); 4442 } 4443 4444 for (j = 0; j < path->pin_nums; j++) { 4445 if (wsum->inamp_cap) { 4446 (void) audioha_codec_4bit_verb_get(statep, 4447 caddr, 4448 wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE, 4449 AUDIOHDC_AMP_SET_LR_INPUT | 4450 AUDIOHDC_GAIN_MAX | 4451 (path->sum_selconn[j] << 4452 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 4453 } 4454 if (wsum->type == WTYPE_AUDIO_SEL) { 4455 (void) audioha_codec_verb_get(statep, caddr, 4456 wsum->wid_wid, 4457 AUDIOHDC_VERB_SET_CONN_SEL, 4458 path->sum_selconn[j]); 4459 } 4460 4461 wid = wsum->avail_conn[path->sum_selconn[j]]; 4462 w = path->codec->widget[wid]; 4463 while (w && w->type != WTYPE_PIN) { 4464 if ((w->type != WTYPE_AUDIO_MIX) && 4465 (w->nconns > 1)) 4466 (void) audioha_codec_verb_get(statep, 4467 caddr, w->wid_wid, 4468 AUDIOHDC_VERB_SET_CONN_SEL, 4469 w->selconn); 4470 4471 if (w->outamp_cap) { 4472 (void) audioha_codec_4bit_verb_get( 4473 statep, 4474 caddr, 4475 w->wid_wid, 4476 AUDIOHDC_VERB_SET_AMP_MUTE, 4477 AUDIOHDC_AMP_SET_LR_OUTPUT | 4478 AUDIOHDC_GAIN_MAX); 4479 } 4480 4481 if (w->inamp_cap) { 4482 (void) audioha_codec_4bit_verb_get( 4483 statep, 4484 caddr, 4485 w->wid_wid, 4486 AUDIOHDC_VERB_SET_AMP_MUTE, 4487 AUDIOHDC_AMP_SET_LR_INPUT | 4488 AUDIOHDC_GAIN_MAX | 4489 (w->selconn << 4490 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 4491 } 4492 wid = w->avail_conn[w->selconn]; 4493 w = path->codec->widget[wid]; 4494 } 4495 } 4496 } /* end of istream loop */ 4497 } /* audiohd_finish_input_path */ 4498 4499 /* 4500 * audiohd_find_inpin_for_monitor() 4501 * 4502 * Description: 4503 * Find input pin for monitor path. 4504 * 4505 * Arguments: 4506 * hda_codec_t *codec where the monitor path exists 4507 * audiohd_ostream_t *ostream output ostream 4508 * wid_t id no. of widget being searched 4509 * int mixer share or not 4510 */ 4511 static int 4512 audiohd_find_inpin_for_monitor(hda_codec_t *codec, 4513 audiohd_path_t *path, wid_t id, int mixer) 4514 { 4515 wid_t wid; 4516 audiohd_widget_t *widget; 4517 audiohd_pin_t *pin; 4518 int i, find = 0; 4519 4520 wid = id; 4521 widget = codec->widget[wid]; 4522 if (widget == NULL) 4523 return (uint32_t)(DDI_FAILURE); 4524 4525 if (widget->type == WTYPE_PIN) { 4526 pin = (audiohd_pin_t *)widget->priv; 4527 if (pin->no_phys_conn) 4528 return (uint32_t)(DDI_FAILURE); 4529 switch (pin->device) { 4530 case DTYPE_SPDIF_IN: 4531 widget->path_flags |= AUDIOHD_PATH_MON; 4532 return (DDI_SUCCESS); 4533 case DTYPE_CD: 4534 widget->path_flags |= AUDIOHD_PATH_MON; 4535 return (DDI_SUCCESS); 4536 case DTYPE_LINE_IN: 4537 widget->path_flags |= AUDIOHD_PATH_MON; 4538 return (DDI_SUCCESS); 4539 case DTYPE_MIC_IN: 4540 widget->path_flags |= AUDIOHD_PATH_MON; 4541 return (DDI_SUCCESS); 4542 case DTYPE_AUX: 4543 widget->path_flags |= AUDIOHD_PATH_MON; 4544 return (DDI_SUCCESS); 4545 default: 4546 return (uint32_t)(DDI_FAILURE); 4547 } 4548 } 4549 /* the widget has been visited and can't be directed to input pin */ 4550 if (widget->path_flags & AUDIOHD_PATH_NOMON) { 4551 return (uint32_t)(DDI_FAILURE); 4552 } 4553 /* the widget has been used by the monitor path, and we can share it */ 4554 if (widget->path_flags & AUDIOHD_PATH_MON) { 4555 if (mixer) 4556 return (DDI_SUCCESS); 4557 else 4558 return (uint32_t)(DDI_FAILURE); 4559 } 4560 switch (widget->type) { 4561 case WTYPE_AUDIO_MIX: 4562 for (i = 0; i < widget->nconns; i++) { 4563 if (widget->selconn == i && widget->path_flags & 4564 AUDIOHD_PATH_DAC) 4565 continue; 4566 if (audiohd_find_inpin_for_monitor(codec, 4567 path, 4568 widget->avail_conn[i], mixer) == 4569 DDI_SUCCESS) { 4570 widget->selmon[widget->used++] = i; 4571 widget->path_flags |= AUDIOHD_PATH_MON; 4572 find = 1; 4573 } 4574 } 4575 break; 4576 case WTYPE_AUDIO_SEL: 4577 for (i = 0; i < widget->nconns; i++) { 4578 if (widget->selconn == i && widget->path_flags & 4579 AUDIOHD_PATH_DAC) 4580 continue; 4581 if (audiohd_find_inpin_for_monitor(codec, 4582 path, 4583 widget->avail_conn[i], 4584 mixer) == 4585 DDI_SUCCESS) { 4586 widget->selmon[0] = i; 4587 widget->path_flags |= AUDIOHD_PATH_MON; 4588 return (DDI_SUCCESS); 4589 } 4590 } 4591 default: 4592 break; 4593 } 4594 if (!find) { 4595 widget->path_flags |= AUDIOHD_PATH_NOMON; 4596 return (uint32_t)(DDI_FAILURE); 4597 } 4598 else 4599 return (DDI_SUCCESS); 4600 } /* audiohd_find_inpin_for_monitor */ 4601 4602 /* 4603 * audiohd_build_monitor_path() 4604 * 4605 * Description: 4606 * The functionality of mixer is to mix inputs, such as CD-IN, MIC, 4607 * Line-in, etc, with DAC outputs, so as to minitor what is being 4608 * recorded and implement "What you hear is what you get". However, 4609 * this functionality are really hardware-dependent: the inputs 4610 * must be directed to MIXER if they can be directed to ADC as 4611 * recording sources. 4612 */ 4613 static void 4614 audiohd_build_monitor_path(hda_codec_t *codec) 4615 { 4616 audiohd_path_t *path; 4617 audiohd_widget_t *widget; 4618 audiohd_state_t *statep = codec->soft_statep; 4619 wid_t wid; 4620 int i, j, k, l, find; 4621 int mixernum = 0; 4622 4623 for (i = 0; i < statep->pathnum; i++) { 4624 path = statep->path[i]; 4625 if (!path || path->codec != codec ||path->path_type != PLAY) 4626 continue; 4627 for (j = 0; j < path->pin_nums; j++) { 4628 wid = path->pin_wid[j]; 4629 widget = codec->widget[wid]; 4630 l = 0; 4631 while (widget) { 4632 while (widget && 4633 ((widget->type != WTYPE_AUDIO_MIX) || 4634 (widget->nconns < 2))) { 4635 if (widget->selconn == 4636 AUDIOHD_NULL_CONN) 4637 break; 4638 wid = 4639 widget->avail_conn[widget->selconn]; 4640 widget = codec->widget[wid]; 4641 } 4642 4643 /* 4644 * No mixer in this output path, we cannot build 4645 * mixer path for this path, skip it, 4646 * and continue 4647 * for next output path. 4648 */ 4649 if (widget == NULL || widget->selconn == 4650 AUDIOHD_NULL_CONN) { 4651 break; 4652 } 4653 mixernum++; 4654 for (k = 0; k < widget->nconns; k++) { 4655 4656 /* 4657 * this connection must be routined 4658 * to DAC instead of an input pin 4659 * widget, we needn't waste time for 4660 * it 4661 */ 4662 if (widget->selconn == k) 4663 continue; 4664 find = 0; 4665 if (audiohd_find_inpin_for_monitor( 4666 codec, 4667 path, 4668 widget->avail_conn[k], 0) == 4669 DDI_SUCCESS) { 4670 path->mon_wid[j][l] = wid; 4671 widget->selmon[widget->used++] = 4672 k; 4673 widget->path_flags |= 4674 AUDIOHD_PATH_MON; 4675 find = 1; 4676 } else if ( 4677 audiohd_find_inpin_for_monitor( 4678 codec, 4679 path, 4680 widget->avail_conn[k], 1) == 4681 DDI_SUCCESS) { 4682 path->mon_wid[j][l] = wid; 4683 widget->selmon[widget->used++] = 4684 k; 4685 widget->path_flags |= 4686 AUDIOHD_PATH_MON; 4687 find = 1; 4688 4689 } 4690 4691 } 4692 4693 /* 4694 * we needn't check widget->selconn here 4695 * since this 4696 * widget is a selector or mixer, it cannot 4697 * be NULL connection. 4698 */ 4699 if (!find) { 4700 path->mon_wid[i][l] = 0; 4701 widget->path_flags |= 4702 AUDIOHD_PATH_NOMON; 4703 } 4704 wid = widget->avail_conn[widget->selconn]; 4705 widget = codec->widget[wid]; 4706 l++; 4707 } 4708 path->maxmixer[j] = l; 4709 } 4710 4711 } 4712 if (mixernum == 0) 4713 statep->monitor_unsupported = B_TRUE; 4714 else 4715 statep->monitor_unsupported = B_FALSE; 4716 } /* audiohd_build_monitor_path */ 4717 4718 /* 4719 * audiohd_do_finish_monitor_path 4720 * 4721 * Description: 4722 * Enable the widgets on the monitor path 4723 */ 4724 static void 4725 audiohd_do_finish_monitor_path(hda_codec_t *codec, audiohd_widget_t *wgt) 4726 { 4727 uint_t caddr = codec->index; 4728 audiohd_widget_t *widget = wgt; 4729 audiohd_widget_t *w; 4730 audiohd_state_t *statep = codec->soft_statep; 4731 wid_t wid; 4732 int i; 4733 int share = 0; 4734 4735 if (!widget || widget->finish) 4736 return; 4737 if (widget->path_flags & AUDIOHD_PATH_ADC) 4738 share = 1; 4739 if ((widget->outamp_cap)&&!share) 4740 (void) audioha_codec_4bit_verb_get(statep, caddr, 4741 widget->wid_wid, 4742 AUDIOHDC_VERB_SET_AMP_MUTE, 4743 AUDIOHDC_AMP_SET_LR_OUTPUT 4744 | AUDIOHDC_GAIN_MAX); 4745 if ((widget->inamp_cap)&&!share) { 4746 for (i = 0; i < widget->used; i++) { 4747 (void) audioha_codec_4bit_verb_get(statep, caddr, 4748 widget->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE, 4749 AUDIOHDC_AMP_SET_LR_INPUT | 4750 AUDIOHDC_GAIN_MAX | 4751 (widget->selmon[i] << 4752 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 4753 } 4754 } 4755 if ((widget->type == WTYPE_AUDIO_SEL) && (widget->nconns > 1) && 4756 !share) { 4757 (void) audioha_codec_verb_get(statep, caddr, 4758 widget->wid_wid, 4759 AUDIOHDC_VERB_SET_CONN_SEL, widget->selmon[0]); 4760 } 4761 widget->finish = 1; 4762 if (widget->used == 0) 4763 return; 4764 if (widget->used > 0) { 4765 for (i = 0; i < widget->used; i++) { 4766 wid = widget->avail_conn[widget->selmon[i]]; 4767 w = codec->widget[wid]; 4768 audiohd_do_finish_monitor_path(codec, w); 4769 } 4770 } 4771 } /* audiohd_do_finish_monitor_path */ 4772 4773 /* 4774 * audiohd_finish_monitor_path 4775 * 4776 * Description: 4777 * Enable the monitor path for every ostream path 4778 */ 4779 static void 4780 audiohd_finish_monitor_path(hda_codec_t *codec) 4781 { 4782 audiohd_path_t *path; 4783 audiohd_widget_t *widget; 4784 audiohd_state_t *statep = codec->soft_statep; 4785 wid_t wid; 4786 int i, j, k; 4787 4788 for (i = 0; i < statep->pathnum; i++) { 4789 path = statep->path[i]; 4790 if (!path || path->codec != codec || path->path_type != PLAY) 4791 continue; 4792 for (j = 0; j < path->pin_nums; j++) { 4793 for (k = 0; k < path->maxmixer[j]; k++) { 4794 wid = path->mon_wid[j][k]; 4795 if (wid == 0) { 4796 continue; 4797 } 4798 widget = codec->widget[wid]; 4799 audiohd_do_finish_monitor_path(codec, widget); 4800 } 4801 } 4802 } 4803 } /* audiohd_finish_monitor_path */ 4804 4805 /* 4806 * audiohd_do_build_monit_amp() 4807 * 4808 * Description: 4809 * Search for the gain control widget for the monitor path 4810 */ 4811 static void 4812 audiohd_do_build_monitor_amp(hda_codec_t *codec, audiohd_pin_t *pin, 4813 audiohd_widget_t *widget) 4814 { 4815 audiohd_widget_t *w = widget; 4816 uint32_t gain; 4817 int i; 4818 wid_t wid; 4819 4820 if (!w || 4821 (w->type == WTYPE_PIN) || 4822 !w->used || 4823 (pin->num == AUDIOHD_MAX_CONN) || 4824 (w->path_flags & AUDIOHD_PATH_ADC)) 4825 return; 4826 if (!(w->path_flags & AUDIOHD_PATH_DAC)) { 4827 gain = w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS; 4828 if (gain) { 4829 pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_OUTPUT; 4830 pin->mg_gain[pin->num] = gain; 4831 pin->mg_wid[pin->num] = w->wid_wid; 4832 pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF; 4833 pin->num++; 4834 return; 4835 } 4836 gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS; 4837 if (gain) { 4838 pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_INPUT; 4839 pin->mg_gain[pin->num] = gain; 4840 pin->mg_wid[pin->num] = w->wid_wid; 4841 pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF; 4842 pin->num++; 4843 return; 4844 } 4845 } 4846 for (i = 0; i < w->used; i++) { 4847 wid = w->avail_conn[w->selmon[i]]; 4848 audiohd_do_build_monitor_amp(codec, pin, codec->widget[wid]); 4849 } 4850 4851 4852 } /* audiohd_do_build_monitor_amp() */ 4853 4854 /* 4855 * audiohd_build_monitor_amp() 4856 * 4857 * Description: 4858 * Search gain control widget for every ostream monitor 4859 */ 4860 static void 4861 audiohd_build_monitor_amp(hda_codec_t *codec) 4862 { 4863 audiohd_path_t *path; 4864 audiohd_widget_t *widget, *w; 4865 audiohd_state_t *statep = codec->soft_statep; 4866 audiohd_pin_t *pin; 4867 wid_t wid, id; 4868 int i, j, k; 4869 4870 for (i = 0; i < statep->pathnum; i++) { 4871 path = statep->path[i]; 4872 if (!path || path->codec != codec || path->path_type != PLAY) 4873 continue; 4874 for (j = 0; j < path->pin_nums; j++) { 4875 id = path->pin_wid[j]; 4876 w = codec->widget[id]; 4877 pin = (audiohd_pin_t *)(w->priv); 4878 for (k = 0; k < path->maxmixer[j]; k++) { 4879 wid = path->mon_wid[j][k]; 4880 if (!wid) 4881 continue; 4882 widget = codec->widget[wid]; 4883 audiohd_do_build_monitor_amp(codec, pin, 4884 widget); 4885 } 4886 } 4887 } 4888 } 4889 4890 /* 4891 * audiohd_find_beep() 4892 * Description: 4893 * Find a beep for a beep path. Then the play data can be sent to the out 4894 * put pin through the beep path. 4895 * 4896 * Arguments: 4897 * hda_codec_t *codec where the beep widget exists 4898 * wid_t wid the no. of a widget 4899 * int depth the depth of search 4900 * 4901 * Return: 4902 * 1) wid of Beep widget; 4903 * 2) 0 if no path 4904 */ 4905 static wid_t 4906 audiohd_find_beep(hda_codec_t *codec, wid_t wid, int depth) 4907 { 4908 audiohd_widget_t *widget = codec->widget[wid]; 4909 wid_t wbeep = (uint32_t)(DDI_FAILURE); 4910 wid_t retval; 4911 4912 if (depth > AUDIOHD_MAX_DEPTH) 4913 return (uint32_t)(DDI_FAILURE); 4914 4915 if (widget == NULL) 4916 return (uint32_t)(DDI_FAILURE); 4917 4918 switch (widget->type) { 4919 case WTYPE_BEEP: 4920 widget->path_flags |= AUDIOHD_PATH_BEEP; 4921 wbeep = widget->wid_wid; 4922 break; 4923 4924 case WTYPE_AUDIO_MIX: 4925 case WTYPE_AUDIO_SEL: 4926 for (int i = 0; i < widget->nconns; i++) { 4927 retval = audiohd_find_beep(codec, 4928 widget->avail_conn[i], depth + 1); 4929 if (retval != (uint32_t)DDI_FAILURE) { 4930 if (widget->selconn != AUDIOHD_NULL_CONN) 4931 continue; 4932 widget->selconn = i; 4933 wbeep = retval; 4934 widget->path_flags |= AUDIOHD_PATH_BEEP; 4935 return (wbeep); 4936 } 4937 } 4938 default: 4939 break; 4940 } 4941 4942 return (wbeep); 4943 } /* audiohd_find_beep() */ 4944 4945 /* 4946 * audiohd_build_beep_path() 4947 * 4948 * Description: 4949 * Search an beep path for each pin in the codec. 4950 * Arguments: 4951 * hda_codec_t *codec where the beep path exists 4952 */ 4953 static void 4954 audiohd_build_beep_path(hda_codec_t *codec) 4955 { 4956 audiohd_pin_t *pin; 4957 audiohd_widget_t *widget; 4958 audiohd_path_t *path; 4959 wid_t wid; 4960 audiohd_state_t *statep; 4961 int i; 4962 boolean_t beeppath = B_FALSE; 4963 4964 statep = codec->soft_statep; 4965 4966 for (pin = codec->first_pin; pin; pin = pin->next) { 4967 if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0) 4968 continue; 4969 if ((pin->config & AUDIOHD_PIN_CONF_MASK) == 4970 AUDIOHD_PIN_NO_CONN) 4971 continue; 4972 if ((pin->device != DTYPE_LINEOUT) && 4973 (pin->device != DTYPE_SPEAKER) && 4974 (pin->device != DTYPE_SPDIF_OUT) && 4975 (pin->device != DTYPE_HP_OUT)) 4976 continue; 4977 widget = codec->widget[pin->wid]; 4978 4979 widget->inamp_cap = 0; 4980 for (i = 0; i < widget->nconns; i++) { 4981 /* 4982 * If a beep found, the return value is the wid of the 4983 * widget on the path, or the return value is 4984 * DDI_FAILURE 4985 */ 4986 wid = audiohd_find_beep(codec, 4987 widget->avail_conn[i], 0); 4988 /* 4989 * A beep was not found 4990 */ 4991 if (wid == (wid_t)DDI_FAILURE) 4992 continue; 4993 if (widget->selconn != AUDIOHD_NULL_CONN) 4994 continue; 4995 path = (audiohd_path_t *) 4996 kmem_zalloc(sizeof (audiohd_path_t), 4997 KM_SLEEP); 4998 path->beep_wid = wid; 4999 path->pin_wid[0] = widget->wid_wid; 5000 path->pin_nums = 1; 5001 path->path_type = BEEP; 5002 beeppath = 1; 5003 path->codec = codec; 5004 path->statep = statep; 5005 widget->path_flags |= AUDIOHD_PATH_BEEP; 5006 widget->selconn = i; 5007 statep->path[statep->pathnum++] = path; 5008 5009 break; 5010 } 5011 } 5012 5013 if (!beeppath) { 5014 for (int i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5015 codec = statep->codec[i]; 5016 if (!codec) 5017 continue; 5018 for (wid = codec->first_wid; wid <= codec->last_wid; 5019 wid++) { 5020 widget = codec->widget[wid]; 5021 if (widget->type == WTYPE_BEEP) { 5022 path = (audiohd_path_t *) 5023 kmem_zalloc(sizeof (audiohd_path_t), 5024 KM_SLEEP); 5025 path->beep_wid = wid; 5026 path->pin_nums = 0; 5027 path->path_type = BEEP; 5028 beeppath = 1; 5029 path->codec = codec; 5030 path->statep = statep; 5031 widget->path_flags |= AUDIOHD_PATH_BEEP; 5032 statep->path[statep->pathnum++] = path; 5033 break; 5034 } 5035 } 5036 } 5037 } 5038 } /* audiohd_build_beep_path() */ 5039 5040 /* 5041 * audiohd_build_beep_amp 5042 * 5043 * Description: 5044 * Find the gain control and mute control widget 5045 */ 5046 static void 5047 audiohd_build_beep_amp(hda_codec_t *codec) 5048 { 5049 audiohd_path_t *path; 5050 audiohd_widget_t *widget, *wpin, *wbeep; 5051 wid_t wid; 5052 int i, j; 5053 uint32_t gain; 5054 5055 for (i = 0; i < codec->soft_statep->pathnum; i++) { 5056 path = codec->soft_statep->path[i]; 5057 if (path == NULL || path->path_type != BEEP || 5058 path->codec != codec) 5059 continue; 5060 if (path->pin_nums == 0) { 5061 path->mute_wid = path->beep_wid; 5062 path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT; 5063 wbeep = codec->widget[path->beep_wid]; 5064 gain = (wbeep->outamp_cap & 5065 AUDIOHDC_AMP_CAP_STEP_NUMS); 5066 if (gain) { 5067 path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT; 5068 path->gain_bits = gain; 5069 path->gain_wid = path->beep_wid; 5070 } 5071 path->gain_bits >>= AUDIOHD_GAIN_OFF; 5072 break; 5073 } 5074 for (j = 0; j < path->pin_nums; j++) { 5075 wid = path->pin_wid[j]; 5076 wpin = codec->widget[wid]; 5077 wbeep = codec->widget[path->beep_wid]; 5078 5079 widget = wpin; 5080 while (widget) { 5081 if (widget->out_weight == 0 && 5082 widget->outamp_cap & 5083 AUDIOHDC_AMP_CAP_MUTE_CAP) { 5084 path->mute_wid = widget->wid_wid; 5085 path->mute_dir = 5086 AUDIOHDC_AMP_SET_OUTPUT; 5087 break; 5088 } 5089 if (widget->selconn == AUDIOHD_NULL_CONN) 5090 break; 5091 wid = widget->avail_conn[widget->selconn]; 5092 widget = codec->widget[wid]; 5093 } 5094 5095 gain = 0; 5096 widget = wpin; 5097 while (widget) { 5098 if (widget->out_weight == 0 && 5099 widget->outamp_cap & 5100 AUDIOHDC_AMP_CAP_STEP_NUMS) { 5101 gain = (widget->outamp_cap & 5102 AUDIOHDC_AMP_CAP_STEP_NUMS); 5103 if (gain && gain > path->gain_bits) { 5104 path->gain_dir = 5105 AUDIOHDC_AMP_SET_OUTPUT; 5106 path->gain_bits = gain; 5107 path->gain_wid = 5108 widget->wid_wid; 5109 } 5110 } 5111 if (widget->selconn == AUDIOHD_NULL_CONN) 5112 break; 5113 wid = widget->avail_conn[widget->selconn]; 5114 widget = codec->widget[wid]; 5115 } 5116 path->gain_bits >>= AUDIOHD_GAIN_OFF; 5117 } 5118 } 5119 } /* audiohd_build_beep_amp */ 5120 5121 /* 5122 * audiohd_finish_beep_path() 5123 * 5124 * Description: 5125 * Enable the widgets on the beep path 5126 */ 5127 static void 5128 audiohd_finish_beep_path(hda_codec_t *codec) 5129 { 5130 audiohd_state_t *statep = codec->soft_statep; 5131 audiohd_path_t *path; 5132 audiohd_widget_t *widget; 5133 uint_t caddr = codec->index; 5134 wid_t wid; 5135 int i, j; 5136 5137 for (i = 0; i < codec->soft_statep->pathnum; i++) { 5138 path = codec->soft_statep->path[i]; 5139 if (!path || path->path_type != BEEP || path->codec != codec) 5140 continue; 5141 for (j = 0; j < path->pin_nums; j++) { 5142 wid = path->pin_wid[j]; 5143 widget = codec->widget[wid]; 5144 5145 (void) audioha_codec_verb_get(statep, caddr, wid, 5146 AUDIOHDC_VERB_SET_CONN_SEL, widget->selconn); 5147 5148 wid = widget->avail_conn[widget->selconn]; 5149 widget = codec->widget[wid]; 5150 5151 while (widget) { 5152 /* 5153 * Set all amplifiers in this path to 5154 * the maximum 5155 * volume and unmute them. 5156 */ 5157 if (widget->out_weight != 0) 5158 continue; 5159 if (widget->outamp_cap) { 5160 (void) audioha_codec_4bit_verb_get( 5161 statep, 5162 caddr, 5163 wid, AUDIOHDC_VERB_SET_AMP_MUTE, 5164 AUDIOHDC_AMP_SET_LR_OUTPUT | 5165 AUDIOHDC_GAIN_MAX); 5166 } 5167 if (widget->inamp_cap) { 5168 (void) audioha_codec_4bit_verb_get( 5169 statep, 5170 caddr, 5171 wid, AUDIOHDC_VERB_SET_AMP_MUTE, 5172 AUDIOHDC_AMP_SET_LR_INPUT | 5173 AUDIOHDC_GAIN_MAX | 5174 (widget->selconn << 5175 AUDIOHDC_AMP_SET_INDEX_OFFSET)); 5176 } 5177 5178 if (widget->selconn == AUDIOHD_NULL_CONN) 5179 break; 5180 /* 5181 * Accoding to HD spec, mixer doesn't support 5182 * "select connection" 5183 */ 5184 if ((widget->type != WTYPE_AUDIO_MIX) && 5185 (widget->nconns > 1)) 5186 (void) audioha_codec_verb_get(statep, 5187 caddr, 5188 wid, 5189 AUDIOHDC_VERB_SET_CONN_SEL, 5190 widget->selconn); 5191 5192 wid = widget->avail_conn[widget->selconn]; 5193 widget = codec->widget[wid]; 5194 } 5195 } 5196 } 5197 } /* audiohd_finish_beep_path */ 5198 5199 /* 5200 * audiohd_build_path() 5201 * 5202 * Description: 5203 * Here we build the output, input, monitor path. 5204 * And also enable the path in default. 5205 * Search for the gain and mute control for the path 5206 */ 5207 static void 5208 audiohd_build_path(audiohd_state_t *statep) 5209 { 5210 int i; 5211 5212 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5213 if (statep->codec[i]) { 5214 audiohd_build_output_path(statep->codec[i]); 5215 audiohd_build_output_amp(statep->codec[i]); 5216 audiohd_finish_output_path(statep->codec[i]); 5217 5218 audiohd_build_input_path(statep->codec[i]); 5219 audiohd_build_input_amp(statep->codec[i]); 5220 audiohd_finish_input_path(statep->codec[i]); 5221 5222 audiohd_build_monitor_path(statep->codec[i]); 5223 audiohd_build_monitor_amp(statep->codec[i]); 5224 audiohd_finish_monitor_path(statep->codec[i]); 5225 5226 audiohd_build_beep_path(statep->codec[i]); 5227 audiohd_build_beep_amp(statep->codec[i]); 5228 audiohd_finish_beep_path(statep->codec[i]); 5229 } 5230 } 5231 } /* audiohd_build_path */ 5232 5233 /* 5234 * audiohd_allocate_port() 5235 */ 5236 static int 5237 audiohd_allocate_port(audiohd_state_t *statep) 5238 { 5239 int i, j; 5240 audiohd_port_t *port; 5241 int dir; 5242 unsigned caps; 5243 char *prop; 5244 int rc; 5245 audio_dev_t *adev; 5246 dev_info_t *dip; 5247 ddi_dma_cookie_t cookie; 5248 uint_t count; 5249 uint64_t buf_phys_addr; 5250 sd_bdle_t *entry; 5251 uint16_t gcap; 5252 size_t real_size; 5253 5254 adev = statep->adev; 5255 dip = statep->hda_dip; 5256 5257 ddi_dma_attr_t dma_attr = { 5258 DMA_ATTR_V0, /* version */ 5259 0, /* addr_lo */ 5260 0xffffffffffffffffULL, /* addr_hi */ 5261 0x00000000ffffffffULL, /* count_max */ 5262 128, /* 128-byte alignment as HD spec */ 5263 0xfff, /* burstsize */ 5264 1, /* minxfer */ 5265 0xffffffff, /* maxxfer */ 5266 0xffffffff, /* seg */ 5267 1, /* sgllen */ 5268 1, /* granular */ 5269 0 /* flags */ 5270 }; 5271 5272 gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP); 5273 if ((gcap & AUDIOHDR_GCAP_64OK) == 0) 5274 dma_attr.dma_attr_addr_hi = 0xffffffffUL; 5275 5276 for (i = 0; i < PORT_MAX; i++) { 5277 port = kmem_zalloc(sizeof (*port), KM_SLEEP); 5278 port->started = B_FALSE; 5279 port->triggered = B_FALSE; 5280 statep->port[i] = port; 5281 port->statep = statep; 5282 switch (i) { 5283 case PORT_ADC: 5284 prop = "record-interrupts"; 5285 dir = DDI_DMA_READ | DDI_DMA_CONSISTENT; 5286 caps = ENGINE_INPUT_CAP; 5287 port->sync_dir = DDI_DMA_SYNC_FORKERNEL; 5288 port->nchan = statep->rchan; 5289 port->index = 1; 5290 port->regoff = AUDIOHD_REG_SD_BASE; 5291 break; 5292 case PORT_DAC: 5293 prop = "play-interrupts"; 5294 dir = DDI_DMA_WRITE | DDI_DMA_CONSISTENT; 5295 caps = ENGINE_OUTPUT_CAP; 5296 port->sync_dir = DDI_DMA_SYNC_FORDEV; 5297 port->nchan = statep->pchan; 5298 port->index = statep->hda_input_streams + 1; 5299 port->regoff = AUDIOHD_REG_SD_BASE + 5300 AUDIOHD_REG_SD_LEN * 5301 statep->hda_input_streams; 5302 break; 5303 default: 5304 return (DDI_FAILURE); 5305 } 5306 5307 port->intrs = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 5308 DDI_PROP_DONTPASS, prop, AUDIOHD_INTS); 5309 5310 /* make sure the values are good */ 5311 if (port->intrs < AUDIOHD_MIN_INTS) { 5312 audio_dev_warn(adev, "%s too low, %d, resetting to %d", 5313 prop, port->intrs, AUDIOHD_INTS); 5314 port->intrs = AUDIOHD_INTS; 5315 } else if (port->intrs > AUDIOHD_MAX_INTS) { 5316 audio_dev_warn(adev, "%s too high, %d, resetting to %d", 5317 prop, port->intrs, AUDIOHD_INTS); 5318 port->intrs = AUDIOHD_INTS; 5319 } 5320 5321 port->format = AUDIOHD_FMT_PCM; 5322 port->fragfr = 48000 / port->intrs; 5323 port->fragfr = (port->fragfr + AUDIOHD_FRAGFR_ALIGN - 1) & ~ 5324 (AUDIOHD_FRAGFR_ALIGN - 1); 5325 port->samp_size = port->fragfr * port->nchan * 2; 5326 port->samp_size = (port->samp_size + 5327 AUDIOHD_BDLE_BUF_ALIGN - 1) & ~ 5328 (AUDIOHD_BDLE_BUF_ALIGN - 1); 5329 5330 /* allocate dma handle */ 5331 rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP, 5332 NULL, &port->samp_dmah); 5333 if (rc != DDI_SUCCESS) { 5334 audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d", 5335 rc); 5336 return (DDI_FAILURE); 5337 } 5338 /* 5339 * Warning: please be noted that allocating the dma memory 5340 * with the flag IOMEM_DATA_UNCACHED is a hack due 5341 * to an incorrect cache synchronization on NVidia MCP79 5342 * chipset which causes the audio distortion problem, 5343 * and that it should be fixed later. There should be 5344 * no reason you have to allocate UNCACHED memory. In 5345 * complex architectures with nested IO caches, 5346 * reliance on this flag might lead to failure. 5347 */ 5348 rc = ddi_dma_mem_alloc(port->samp_dmah, port->samp_size * 5349 AUDIOHD_BDLE_NUMS, 5350 &hda_dev_accattr, 5351 DDI_DMA_CONSISTENT | IOMEM_DATA_UNCACHED, 5352 DDI_DMA_SLEEP, NULL, &port->samp_kaddr, 5353 &real_size, &port->samp_acch); 5354 if (rc == DDI_FAILURE) { 5355 if (ddi_dma_mem_alloc(port->samp_dmah, 5356 port->samp_size * AUDIOHD_BDLE_NUMS, 5357 &hda_dev_accattr, 5358 DDI_DMA_CONSISTENT, 5359 DDI_DMA_SLEEP, NULL, 5360 &port->samp_kaddr, &real_size, 5361 &port->samp_acch) != DDI_SUCCESS) { 5362 audio_dev_warn(adev, 5363 "ddi_dma_mem_alloc failed"); 5364 return (DDI_FAILURE); 5365 } 5366 } 5367 5368 /* bind DMA buffer */ 5369 rc = ddi_dma_addr_bind_handle(port->samp_dmah, NULL, 5370 port->samp_kaddr, real_size, dir, 5371 DDI_DMA_SLEEP, NULL, &cookie, &count); 5372 if ((rc != DDI_DMA_MAPPED) || (count != 1)) { 5373 audio_dev_warn(adev, 5374 "ddi_dma_addr_bind_handle failed: %d", rc); 5375 return (DDI_FAILURE); 5376 } 5377 port->samp_paddr = (uint64_t)cookie.dmac_laddress; 5378 5379 /* 5380 * now, from here we allocate DMA 5381 * memory for buffer descriptor list. 5382 * we allocate adjacent DMA memory for all DMA engines. 5383 */ 5384 rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP, 5385 NULL, &port->bdl_dmah); 5386 if (rc != DDI_SUCCESS) { 5387 audio_dev_warn(adev, 5388 "ddi_dma_alloc_handle(bdlist) failed"); 5389 return (DDI_FAILURE); 5390 } 5391 5392 /* 5393 * we allocate all buffer descriptors lists in continuous 5394 * dma memory. 5395 */ 5396 port->bdl_size = sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS; 5397 rc = ddi_dma_mem_alloc(port->bdl_dmah, port->bdl_size, 5398 &hda_dev_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 5399 &port->bdl_kaddr, &real_size, &port->bdl_acch); 5400 if (rc != DDI_SUCCESS) { 5401 audio_dev_warn(adev, 5402 "ddi_dma_mem_alloc(bdlist) failed"); 5403 return (DDI_FAILURE); 5404 } 5405 5406 rc = ddi_dma_addr_bind_handle(port->bdl_dmah, NULL, 5407 port->bdl_kaddr, 5408 real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 5409 DDI_DMA_SLEEP, 5410 NULL, &cookie, &count); 5411 if ((rc != DDI_DMA_MAPPED) || (count != 1)) { 5412 audio_dev_warn(adev, "addr_bind_handle failed"); 5413 return (DDI_FAILURE); 5414 } 5415 port->bdl_paddr = (uint64_t)cookie.dmac_laddress; 5416 5417 entry = (sd_bdle_t *)port->bdl_kaddr; 5418 buf_phys_addr = port->samp_paddr; 5419 5420 for (j = 0; j < AUDIOHD_BDLE_NUMS; j++) { 5421 entry->sbde_addr = buf_phys_addr; 5422 entry->sbde_len = port->samp_size; 5423 entry->sbde_ioc = 1; 5424 buf_phys_addr += port->samp_size; 5425 entry++; 5426 } 5427 (void) ddi_dma_sync(port->bdl_dmah, 0, sizeof (sd_bdle_t) * 5428 AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV); 5429 port->curpos = 0; 5430 5431 port->engine = audio_engine_alloc(&audiohd_engine_ops, caps); 5432 if (port->engine == NULL) { 5433 return (DDI_FAILURE); 5434 } 5435 5436 audio_engine_set_private(port->engine, port); 5437 audio_dev_add_engine(adev, port->engine); 5438 } 5439 5440 return (DDI_SUCCESS); 5441 } 5442 5443 static void 5444 audiohd_free_port(audiohd_state_t *statep) 5445 { 5446 int i; 5447 audiohd_port_t *port; 5448 5449 if (statep == NULL) { 5450 return; 5451 } 5452 for (i = 0; i < PORT_MAX; i++) { 5453 port = statep->port[i]; 5454 if (port == NULL) 5455 continue; 5456 if (port->engine) { 5457 audio_dev_remove_engine(statep->adev, 5458 port->engine); 5459 audio_engine_free(port->engine); 5460 } 5461 if (port->samp_dmah) { 5462 (void) ddi_dma_unbind_handle(port->samp_dmah); 5463 } 5464 if (port->samp_acch) { 5465 ddi_dma_mem_free(&port->samp_acch); 5466 } 5467 if (port->samp_dmah) { 5468 ddi_dma_free_handle(&port->samp_dmah); 5469 } 5470 if (port->bdl_dmah) { 5471 (void) ddi_dma_unbind_handle(port->bdl_dmah); 5472 } 5473 if (port->bdl_acch) { 5474 ddi_dma_mem_free(&port->bdl_acch); 5475 } 5476 if (port->bdl_dmah) { 5477 ddi_dma_free_handle(&port->bdl_dmah); 5478 } 5479 5480 kmem_free(port, sizeof (audiohd_port_t)); 5481 } 5482 } 5483 5484 /* 5485 * audiohd_change_widget_power_state(audiohd_state_t *statep, int off) 5486 * Description: 5487 * This routine is used to change the widget power betwen D0 and D2. 5488 * D0 is fully on; D2 allows the lowest possible power consuming state 5489 * from which it can return to the fully on state: D0. 5490 */ 5491 static void 5492 audiohd_change_widget_power_state(audiohd_state_t *statep, int off) 5493 { 5494 int i; 5495 wid_t wid; 5496 hda_codec_t *codec; 5497 audiohd_widget_t *widget; 5498 5499 /* Change power to D2 */ 5500 if (off) { 5501 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5502 codec = statep->codec[i]; 5503 if (!codec) 5504 continue; 5505 for (wid = codec->first_wid; wid <= codec->last_wid; 5506 wid++) { 5507 widget = codec->widget[wid]; 5508 if (widget->widget_cap & 5509 AUDIOHD_WIDCAP_PWRCTRL) { 5510 (void) audioha_codec_verb_get(statep, 5511 codec->index, wid, 5512 AUDIOHDC_VERB_SET_POWER_STATE, 5513 AUDIOHD_PW_D2); 5514 } 5515 } 5516 } 5517 /* Change power to D0 */ 5518 } else { 5519 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5520 codec = statep->codec[i]; 5521 if (!codec) 5522 continue; 5523 for (wid = codec->first_wid; wid <= codec->last_wid; 5524 wid++) { 5525 widget = codec->widget[wid]; 5526 if (widget->widget_cap & 5527 AUDIOHD_WIDCAP_PWRCTRL) { 5528 (void) audioha_codec_verb_get(statep, 5529 codec->index, wid, 5530 AUDIOHDC_VERB_SET_POWER_STATE, 5531 AUDIOHD_PW_D0); 5532 } 5533 } 5534 } 5535 } 5536 } 5537 /* 5538 * audiohd_restore_path() 5539 * Description: 5540 * This routine is used to restore the path on the codec. 5541 */ 5542 static void 5543 audiohd_restore_path(audiohd_state_t *statep) 5544 { 5545 int i; 5546 hda_codec_t *codec; 5547 5548 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5549 codec = statep->codec[i]; 5550 if (!codec) 5551 continue; 5552 audiohd_finish_output_path(statep->codec[i]); 5553 audiohd_finish_input_path(statep->codec[i]); 5554 audiohd_finish_monitor_path(statep->codec[i]); 5555 } 5556 } 5557 5558 /* 5559 * restore_play_and_record() 5560 */ 5561 static void 5562 audiohd_restore_play_and_record(audiohd_state_t *statep) 5563 { 5564 int i; 5565 audiohd_port_t *port; 5566 5567 mutex_enter(&statep->hda_mutex); 5568 for (i = 0; i < PORT_MAX; i++) { 5569 port = statep->port[i]; 5570 if (port == NULL) 5571 continue; 5572 if (port != NULL) 5573 audio_engine_reset(port->engine); 5574 if (port->triggered) { 5575 (void) audiohd_reset_port(port); 5576 audiohd_start_port(port); 5577 } else { 5578 audiohd_stop_port(port); 5579 5580 } 5581 } 5582 mutex_exit(&statep->hda_mutex); 5583 } 5584 /* 5585 * audiohd_reset_pins_ur_cap() 5586 * Description: 5587 * Enable the unsolicited response of the pins which have the unsolicited 5588 * response capability 5589 */ 5590 static void 5591 audiohd_reset_pins_ur_cap(audiohd_state_t *statep) 5592 { 5593 hda_codec_t *codec; 5594 audiohd_pin_t *pin; 5595 audiohd_widget_t *widget; 5596 uint32_t urctrl; 5597 int i; 5598 5599 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5600 codec = statep->codec[i]; 5601 if (!codec) 5602 continue; 5603 pin = codec->first_pin; 5604 while (pin) { 5605 /* enable the unsolicited response of the pin */ 5606 widget = codec->widget[pin->wid]; 5607 if ((widget->widget_cap & 5608 (AUDIOHD_URCAP_MASK) && 5609 (pin->cap & AUDIOHD_DTCCAP_MASK)) && 5610 ((pin->device == DTYPE_LINEOUT) || 5611 (pin->device == DTYPE_SPDIF_OUT) || 5612 (pin->device == DTYPE_HP_OUT) || 5613 (pin->device == DTYPE_MIC_IN))) { 5614 urctrl = (uint8_t)(1 << 5615 (AUDIOHD_UR_ENABLE_OFF - 1)); 5616 urctrl |= (pin->wid & AUDIOHD_UR_TAG_MASK); 5617 (void) audioha_codec_verb_get(statep, 5618 codec->index, 5619 pin->wid, 5620 AUDIOHDC_VERB_SET_URCTRL, urctrl); 5621 } 5622 pin = pin->next; 5623 } 5624 } 5625 } 5626 static void 5627 audiohd_restore_codec_gpio(audiohd_state_t *statep) 5628 { 5629 int i; 5630 wid_t wid; 5631 hda_codec_t *codec; 5632 5633 for (i = 0; i < AUDIOHD_CODEC_MAX; i++) { 5634 codec = statep->codec[i]; 5635 if (codec == NULL) 5636 continue; 5637 wid = codec->wid_afg; 5638 5639 /* power-up audio function group */ 5640 (void) audioha_codec_verb_get(statep, i, wid, 5641 AUDIOHDC_VERB_SET_POWER_STATE, 0); 5642 /* work around for Sony VAIO laptop with specific codec */ 5643 if ((codec->vid != AUDIOHD_CODECID_SONY1) && 5644 (codec->vid != AUDIOHD_CODECID_SONY2)) { 5645 /* 5646 * GPIO controls which are laptop specific workarounds 5647 * and might be changed. Some laptops use GPIO, 5648 * so we need to enable and set the GPIO correctly. 5649 */ 5650 (void) audioha_codec_verb_get(statep, i, wid, 5651 AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE); 5652 (void) audioha_codec_verb_get(statep, i, wid, 5653 AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT); 5654 (void) audioha_codec_verb_get(statep, i, wid, 5655 AUDIOHDC_VERB_SET_GPIO_STCK, 5656 AUDIOHDC_GPIO_DATA_CTRL); 5657 (void) audioha_codec_verb_get(statep, i, wid, 5658 AUDIOHDC_VERB_SET_GPIO_DATA, 5659 AUDIOHDC_GPIO_STCK_CTRL); 5660 } 5661 } 5662 } 5663 /* 5664 * audiohd_resume() 5665 */ 5666 static int 5667 audiohd_resume(audiohd_state_t *statep) 5668 { 5669 uint8_t rirbsts; 5670 5671 mutex_enter(&statep->hda_mutex); 5672 statep->suspended = B_FALSE; 5673 /* Restore the hda state */ 5674 if (audiohd_reinit_hda(statep) == DDI_FAILURE) { 5675 audio_dev_warn(statep->adev, 5676 "hda reinit failed"); 5677 mutex_exit(&statep->hda_mutex); 5678 return (DDI_SUCCESS); 5679 } 5680 /* reset to enable the capability of unsolicited response for pin */ 5681 audiohd_reset_pins_ur_cap(statep); 5682 /* Enable interrupt */ 5683 AUDIOHD_REG_SET32(AUDIOHD_REG_INTCTL, 5684 AUDIOHD_INTCTL_BIT_GIE | 5685 AUDIOHD_INTCTL_BIT_SIE); 5686 /* clear the unsolicited response interrupt */ 5687 rirbsts = AUDIOHD_REG_GET8(AUDIOHD_REG_RIRBSTS); 5688 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSTS, rirbsts); 5689 mutex_exit(&statep->hda_mutex); 5690 5691 audiohd_restore_play_and_record(statep); 5692 audiohd_configure_output(statep); 5693 audiohd_configure_input(statep); 5694 5695 /* set widget power to D0 */ 5696 audiohd_change_widget_power_state(statep, AUDIOHD_PW_ON); 5697 5698 return (DDI_SUCCESS); 5699 } /* audiohd_resume */ 5700 5701 /* 5702 * audiohd_suspend() 5703 */ 5704 static int 5705 audiohd_suspend(audiohd_state_t *statep) 5706 { 5707 mutex_enter(&statep->hda_mutex); 5708 statep->suspended = B_TRUE; 5709 5710 /* set widget power to D2 */ 5711 audiohd_change_widget_power_state(statep, AUDIOHD_PW_OFF); 5712 /* Disable h/w */ 5713 audiohd_disable_intr(statep); 5714 audiohd_stop_dma(statep); 5715 mutex_exit(&statep->hda_mutex); 5716 5717 return (DDI_SUCCESS); 5718 } /* audiohd_suspend */ 5719 5720 /* 5721 * audiohd_disable_pin() 5722 */ 5723 static int 5724 audiohd_disable_pin(audiohd_state_t *statep, int caddr, wid_t wid) 5725 { 5726 AUDIOHD_DISABLE_PIN_OUT(statep, caddr, wid); 5727 return (DDI_SUCCESS); 5728 } 5729 5730 /* 5731 * audiohd_enable_pin() 5732 */ 5733 static int 5734 audiohd_enable_pin(audiohd_state_t *statep, int caddr, wid_t wid) 5735 { 5736 AUDIOHD_ENABLE_PIN_OUT(statep, caddr, wid); 5737 return (DDI_SUCCESS); 5738 } 5739 /* 5740 * audiohd_change_speaker_state() 5741 */ 5742 static void 5743 audiohd_change_speaker_state(audiohd_state_t *statep, int on) 5744 { 5745 audiohd_path_t *path; 5746 audiohd_widget_t *widget; 5747 audiohd_pin_t *pin; 5748 int i, j; 5749 wid_t wid; 5750 5751 for (i = 0; i < statep->pathnum; i++) { 5752 path = statep->path[i]; 5753 if (!path || path->path_type != PLAY) 5754 continue; 5755 if (on) { 5756 for (j = 0; j < path->pin_nums; j++) { 5757 wid = path->pin_wid[j]; 5758 widget = path->codec->widget[wid]; 5759 pin = (audiohd_pin_t *)widget->priv; 5760 if (pin->device == DTYPE_SPEAKER) { 5761 (void) audiohd_enable_pin( 5762 statep, 5763 path->codec->index, 5764 pin->wid); 5765 } 5766 } 5767 5768 } else { 5769 for (j = 0; j < path->pin_nums; j++) { 5770 wid = path->pin_wid[j]; 5771 widget = path->codec->widget[wid]; 5772 pin = (audiohd_pin_t *)widget->priv; 5773 if (pin->device == DTYPE_SPEAKER) { 5774 (void) audiohd_disable_pin( 5775 statep, 5776 path->codec->index, 5777 pin->wid); 5778 } 5779 } 5780 } 5781 } 5782 } 5783 /* 5784 * audiohd_select_mic() 5785 * 5786 * Description: 5787 * This function is used for the recording path which has a selector 5788 * as the sumwidget. We select the external MIC if it is plugged into the 5789 * MIC jack, otherwise the internal integrated MIC is selected. 5790 */ 5791 static void 5792 audiohd_select_mic(audiohd_state_t *statep, uint8_t index, 5793 uint8_t id, int select) 5794 { 5795 hda_codec_t *codec; 5796 audiohd_path_t *path; 5797 audiohd_widget_t *widget, *sumwgt; 5798 audiohd_pin_t *pin; 5799 int i, j; 5800 wid_t wid; 5801 5802 codec = statep->codec[index]; 5803 if (codec == NULL) 5804 return; 5805 for (i = 0; i < statep->pathnum; i++) { 5806 path = statep->path[i]; 5807 if (path->codec != codec || path->path_type != RECORD) 5808 continue; 5809 sumwgt = codec->widget[path->sum_wid]; 5810 if (path && sumwgt && 5811 (sumwgt->type == WTYPE_AUDIO_SEL)) { 5812 for (j = 0; j < path->pin_nums; j++) { 5813 wid = path->pin_wid[j]; 5814 widget = codec->widget[wid]; 5815 if (widget == NULL) 5816 return; 5817 pin = (audiohd_pin_t *)widget->priv; 5818 if (select && 5819 pin->device == DTYPE_MIC_IN && 5820 pin->wid == id && 5821 (((pin->config >> 5822 AUDIOHD_PIN_CONTP_OFF) & 5823 AUDIOHD_PIN_CONTP_MASK) == 5824 AUDIOHD_PIN_CON_JACK)) { 5825 (void) audioha_codec_verb_get( 5826 statep, 5827 index, 5828 path->sum_wid, 5829 AUDIOHDC_VERB_SET_CONN_SEL, 5830 path->sum_selconn[j]); 5831 statep->port[PORT_ADC]->index = 5832 path->tag; 5833 return; 5834 } else if (!select && 5835 pin->device == DTYPE_MIC_IN && 5836 pin->wid == id && 5837 (((pin->config >> 5838 AUDIOHD_PIN_CONTP_OFF) & 5839 AUDIOHD_PIN_CONTP_MASK) == 5840 AUDIOHD_PIN_CON_JACK)) { 5841 (void) audioha_codec_verb_get( 5842 statep, 5843 index, 5844 path->sum_wid, 5845 AUDIOHDC_VERB_SET_CONN_SEL, 5846 path->sum_selconn[j]); 5847 statep->port[PORT_ADC]->index = 5848 path->tag; 5849 return; 5850 } 5851 } 5852 if (path == NULL) 5853 break; 5854 sumwgt = codec->widget[path->sum_wid]; 5855 } 5856 } 5857 /* 5858 * If the input istream > 1, we should set the record stream tag 5859 * respectively. All the input streams sharing one tag may make the 5860 * record sound distorted. 5861 */ 5862 if (codec->nistream > 1) { 5863 for (i = 0; i < statep->pathnum; i++) { 5864 path = statep->path[i]; 5865 if (!path || path->path_type != RECORD) 5866 continue; 5867 for (j = 0; j < path->pin_nums; j++) { 5868 wid = path->pin_wid[j]; 5869 widget = codec->widget[wid]; 5870 if (widget == NULL) 5871 return; 5872 pin = (audiohd_pin_t *)widget->priv; 5873 if (select && 5874 pin->device == DTYPE_MIC_IN && 5875 pin->wid == id && 5876 (((pin->config >> 5877 AUDIOHD_PIN_CONTP_OFF) & 5878 AUDIOHD_PIN_CONTP_MASK) == 5879 AUDIOHD_PIN_CON_JACK)) { 5880 statep->port[PORT_ADC]->index = 5881 path->tag; 5882 return; 5883 } else if (!select && 5884 pin->device == DTYPE_MIC_IN && 5885 (((pin->config >> 5886 AUDIOHD_PIN_CONTP_OFF) & 5887 AUDIOHD_PIN_CONTP_MASK) == 5888 AUDIOHD_PIN_CON_FIXED)) { 5889 statep->port[PORT_ADC]->index = 5890 path->tag; 5891 return; 5892 } 5893 } 5894 } 5895 } 5896 } 5897 /* 5898 * audiohd_pin_sense() 5899 * 5900 * Description 5901 * 5902 * When the earphone is plugged into the jack associtated with the pin 5903 * complex, we disable the built in speaker. When the earphone is plugged 5904 * out of the jack, we enable the built in speaker. 5905 */ 5906 static void 5907 audiohd_pin_sense(audiohd_state_t *statep, uint32_t resp, uint32_t respex) 5908 { 5909 uint8_t index; 5910 uint8_t id; 5911 uint32_t rs; 5912 audiohd_widget_t *widget; 5913 audiohd_pin_t *pin; 5914 hda_codec_t *codec; 5915 5916 index = respex & AUDIOHD_RIRB_CODEC_MASK; 5917 id = resp >> (AUDIOHD_RIRB_WID_OFF - 1); 5918 5919 codec = statep->codec[index]; 5920 if (codec == NULL) 5921 return; 5922 widget = codec->widget[id]; 5923 if (widget == NULL) 5924 return; 5925 5926 rs = audioha_codec_verb_get(statep, index, id, 5927 AUDIOHDC_VERB_GET_PIN_SENSE, 0); 5928 if (rs >> (AUDIOHD_PIN_PRES_OFF - 1) & 1) { 5929 /* A MIC is plugged in, we select the MIC as input */ 5930 if ((widget->type == WTYPE_PIN) && 5931 (pin = (audiohd_pin_t *)widget->priv) && 5932 (pin->device == DTYPE_MIC_IN)) { 5933 audiohd_select_mic(statep, index, id, 1); 5934 return; 5935 } 5936 /* output pin is plugged */ 5937 audiohd_change_speaker_state(statep, AUDIOHD_SP_OFF); 5938 } else { 5939 /* 5940 * A MIC is unplugged, we select the built in MIC 5941 * as input. 5942 */ 5943 if ((widget->type == WTYPE_PIN) && 5944 (pin = (audiohd_pin_t *)widget->priv) && 5945 (pin->device == DTYPE_MIC_IN)) { 5946 audiohd_select_mic(statep, index, id, 0); 5947 return; 5948 } 5949 /* output pin is unplugged */ 5950 audiohd_change_speaker_state(statep, AUDIOHD_SP_ON); 5951 } 5952 5953 } 5954 /* 5955 * audiohd_intr() 5956 * 5957 * Description 5958 * 5959 * 5960 * Arguments: 5961 * caddr_t arg Pointer to the interrupting device's state 5962 * structure 5963 * 5964 * Returns: 5965 * DDI_INTR_CLAIMED Interrupt claimed and processed 5966 * DDI_INTR_UNCLAIMED Interrupt not claimed, and thus ignored 5967 */ 5968 static uint_t 5969 audiohd_intr(caddr_t arg1, caddr_t arg2) 5970 { 5971 audiohd_state_t *statep = (void *)arg1; 5972 uint32_t status; 5973 uint32_t regbase; 5974 uint32_t resp, respex; 5975 uint8_t sdstatus, rirbsts; 5976 int i, ret; 5977 5978 _NOTE(ARGUNUSED(arg2)) 5979 audio_engine_t *do_adc = NULL; 5980 audio_engine_t *do_dac = NULL; 5981 5982 5983 mutex_enter(&statep->hda_mutex); 5984 if (statep->suspended) { 5985 mutex_exit(&statep->hda_mutex); 5986 return (DDI_INTR_UNCLAIMED); 5987 } 5988 5989 status = AUDIOHD_REG_GET32(AUDIOHD_REG_INTSTS); 5990 if (status == 0) { 5991 mutex_exit(&statep->hda_mutex); 5992 return (DDI_INTR_UNCLAIMED); 5993 } 5994 AUDIOHD_REG_SET32(AUDIOHD_REG_INTSTS, status); 5995 5996 /* 5997 * unsolicited response from pins, maybe something plugged in or out 5998 * of the jack. 5999 */ 6000 if (status & AUDIOHD_CIS_MASK) { 6001 /* clear the unsolicited response interrupt */ 6002 rirbsts = AUDIOHD_REG_GET8(AUDIOHD_REG_RIRBSTS); 6003 AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSTS, rirbsts); 6004 /* 6005 * We have to wait and try several times to make sure the 6006 * unsolicited response is generated by our pins. 6007 * we need to make it work for audiohd spec 0.9, which is 6008 * just a draft version and requires more time to wait. 6009 */ 6010 for (i = 0; i < AUDIOHD_TEST_TIMES; i++) { 6011 ret = audiohd_response_from_codec(statep, &resp, 6012 &respex); 6013 if ((ret == DDI_SUCCESS) && 6014 (respex & AUDIOHD_RIRB_UR_MASK)) { 6015 /* 6016 * A pin may generate more than one ur rirb, 6017 * we only need handle one of them, and clear 6018 * the other ones 6019 */ 6020 statep->hda_rirb_rp = 6021 AUDIOHD_REG_GET16(AUDIOHD_REG_RIRBWP) & 6022 AUDIOHD_RIRB_WPMASK; 6023 break; 6024 } 6025 } 6026 if ((ret == DDI_SUCCESS) && 6027 (respex & AUDIOHD_RIRB_UR_MASK)) { 6028 audiohd_pin_sense(statep, resp, respex); 6029 } 6030 } 6031 6032 /* stream intr */ 6033 for (i = 0; i < statep->hda_streams_nums; i++) { 6034 if ((status & (1<<i)) == 0) 6035 continue; 6036 6037 regbase = AUDIOHD_REG_SD_BASE + AUDIOHD_REG_SD_LEN * i; 6038 sdstatus = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_STS); 6039 6040 /* clear intrs */ 6041 AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_STS, sdstatus); 6042 if (i < statep->hda_input_streams) 6043 do_adc = statep->port[PORT_ADC]->engine; 6044 else 6045 do_dac = statep->port[PORT_DAC]->engine; 6046 } 6047 6048 /* update the kernel interrupt statistics */ 6049 if (statep->hda_ksp) { 6050 ((kstat_intr_t *) 6051 (statep->hda_ksp->ks_data))->intrs[KSTAT_INTR_HARD]++; 6052 } 6053 6054 mutex_exit(&statep->hda_mutex); 6055 6056 if (do_adc) 6057 audio_engine_produce(do_adc); 6058 if (do_dac) 6059 audio_engine_consume(do_dac); 6060 return (DDI_INTR_CLAIMED); 6061 } /* audiohd_intr() */ 6062 6063 /* 6064 * audiohd_disable_intr() 6065 * 6066 * Description: 6067 * Disable all possible interrupts. 6068 */ 6069 static void 6070 audiohd_disable_intr(audiohd_state_t *statep) 6071 { 6072 int i; 6073 uint32_t base; 6074 6075 AUDIOHD_REG_SET32(AUDIOHD_REG_INTCTL, 0); 6076 base = AUDIOHD_REG_SD_BASE; 6077 for (i = 0; i < statep->hda_streams_nums; i++) { 6078 AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_STS, 6079 AUDIOHDR_SD_STS_INTRS); 6080 base += AUDIOHD_REG_SD_LEN; 6081 } 6082 AUDIOHD_REG_SET32(AUDIOHD_REG_INTSTS, (uint32_t)(-1)); 6083 6084 } /* audiohd_disable_intr() */ 6085 6086 6087 /* 6088 * audiohd_12bit_verb_to_codec() 6089 * 6090 * Description: 6091 * 6092 */ 6093 static int 6094 audiohd_12bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr, 6095 uint8_t wid, 6096 uint16_t cmd, uint8_t param) 6097 { 6098 uint32_t verb; 6099 uint16_t wptr; 6100 uint16_t rptr; 6101 6102 ASSERT((cmd & AUDIOHDC_12BIT_VERB_MASK) == 0); 6103 6104 wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK; 6105 rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK; 6106 6107 wptr++; 6108 wptr &= AUDIOHD_CMDIO_ENT_MASK; 6109 6110 /* overflow */ 6111 if (wptr == rptr) { 6112 return (DDI_FAILURE); 6113 } 6114 6115 verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF; 6116 verb |= wid << AUDIOHD_VERB_NID_OFF; 6117 verb |= cmd << AUDIOHD_VERB_CMD_OFF; 6118 verb |= param; 6119 6120 *((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb; 6121 (void) ddi_dma_sync(statep->hda_dma_corb.ad_dmahdl, 0, 6122 sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV); 6123 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr); 6124 6125 return (DDI_SUCCESS); 6126 6127 } /* audiohd_12bit_verb_to_codec() */ 6128 6129 /* 6130 * audiohd_4bit_verb_to_codec() 6131 * 6132 * Description: 6133 * 6134 */ 6135 static int 6136 audiohd_4bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr, 6137 uint8_t wid, 6138 uint32_t cmd, uint16_t param) 6139 { 6140 uint32_t verb; 6141 uint16_t wptr; 6142 uint16_t rptr; 6143 6144 ASSERT((cmd & AUDIOHDC_4BIT_VERB_MASK) == 0); 6145 6146 wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK; 6147 rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK; 6148 6149 wptr++; 6150 wptr &= AUDIOHD_CMDIO_ENT_MASK; 6151 6152 /* overflow */ 6153 if (wptr == rptr) { 6154 return (DDI_FAILURE); 6155 } 6156 6157 verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF; 6158 verb |= wid << AUDIOHD_VERB_NID_OFF; 6159 verb |= cmd << AUDIOHD_VERB_CMD16_OFF; 6160 verb |= param; 6161 6162 *((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb; 6163 AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr); 6164 6165 return (DDI_SUCCESS); 6166 6167 } /* audiohd_4bit_verb_to_codec() */ 6168 6169 /* 6170 * audiohd_response_from_codec() 6171 * 6172 * Description: 6173 * 6174 */ 6175 static int 6176 audiohd_response_from_codec(audiohd_state_t *statep, uint32_t *resp, 6177 uint32_t *respex) 6178 { 6179 uint16_t wptr; 6180 uint16_t rptr; 6181 uint32_t *lp; 6182 6183 wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_RIRBWP) & 0x00ff; 6184 rptr = statep->hda_rirb_rp; 6185 6186 if (rptr == wptr) { 6187 return (DDI_FAILURE); 6188 } 6189 6190 rptr++; 6191 rptr &= AUDIOHD_RING_MAX_SIZE; 6192 6193 lp = (uint32_t *)(statep->hda_dma_rirb.ad_vaddr) + (rptr << 1); 6194 *resp = *(lp); 6195 *respex = *(lp + 1); 6196 6197 statep->hda_rirb_rp = rptr; 6198 6199 return (DDI_SUCCESS); 6200 6201 } /* audiohd_response_from_codec() */ 6202 6203 6204 /* 6205 * audioha_codec_verb_get() 6206 */ 6207 static uint32_t 6208 audioha_codec_verb_get(void *arg, uint8_t caddr, uint8_t wid, 6209 uint16_t verb, 6210 uint8_t param) 6211 { 6212 audiohd_state_t *statep = (audiohd_state_t *)arg; 6213 uint32_t resp; 6214 uint32_t respex; 6215 int ret; 6216 int i; 6217 6218 ret = audiohd_12bit_verb_to_codec(statep, caddr, wid, verb, param); 6219 if (ret != DDI_SUCCESS) { 6220 return (uint32_t)(-1); 6221 } 6222 6223 /* 6224 * Empirical testing times. 50 times is enough for audiohd spec 1.0. 6225 * But we need to make it work for audiohd spec 0.9, which is just a 6226 * draft version and requires more time to wait. 6227 */ 6228 for (i = 0; i < 500; i++) { 6229 ret = audiohd_response_from_codec(statep, &resp, &respex); 6230 if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) && 6231 ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) && 6232 (ret == DDI_SUCCESS)) 6233 break; 6234 /* Empirical testing time, which works well */ 6235 drv_usecwait(30); 6236 } 6237 6238 if (ret == DDI_SUCCESS) { 6239 return (resp); 6240 } 6241 6242 audio_dev_warn(statep->adev, "timeout when get " 6243 "response from codec: wid=%d, verb=0x%04x, param=0x%04x", 6244 wid, verb, param); 6245 6246 return ((uint32_t)(-1)); 6247 6248 } /* audioha_codec_verb_get() */ 6249 6250 6251 /* 6252 * audioha_codec_4bit_verb_get() 6253 */ 6254 static uint32_t 6255 audioha_codec_4bit_verb_get(void *arg, uint8_t caddr, uint8_t wid, 6256 uint16_t verb, uint16_t param) 6257 { 6258 audiohd_state_t *statep = (audiohd_state_t *)arg; 6259 uint32_t resp; 6260 uint32_t respex; 6261 int ret; 6262 int i; 6263 6264 ret = audiohd_4bit_verb_to_codec(statep, caddr, wid, verb, param); 6265 if (ret != DDI_SUCCESS) { 6266 return (uint32_t)(-1); 6267 } 6268 6269 for (i = 0; i < 500; i++) { 6270 ret = audiohd_response_from_codec(statep, &resp, &respex); 6271 if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) && 6272 ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) && 6273 (ret == DDI_SUCCESS)) 6274 break; 6275 /* Empirical testing time, which works well */ 6276 drv_usecwait(30); 6277 } 6278 6279 if (ret == DDI_SUCCESS) { 6280 return (resp); 6281 } 6282 6283 audio_dev_warn(statep->adev, "timeout when get " 6284 " response from codec: wid=%d, verb=0x%04x, param=0x%04x", 6285 wid, verb, param); 6286 6287 return ((uint32_t)(-1)); 6288 6289 } /* audioha_codec_4bit_verb_get() */ 6290