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