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