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