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