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