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