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