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