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