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