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