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