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