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