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