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         if (statep->inmask != 0)
1978                 audiohd_create_recsrc(statep);
1979         audiohd_configure_output(statep);
1980         audiohd_configure_input(statep);
1981 }
1982 
1983 /*
1984  * quiesce(9E) entry point.
1985  *
1986  * This function is called when the system is single-threaded at high
1987  * PIL with preemption disabled. Therefore, this function must not be
1988  * blocked.
1989  *
1990  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1991  * DDI_FAILURE indicates an error condition and should almost never happen.
1992  */
1993 static int
1994 audiohd_quiesce(dev_info_t *dip)
1995 {
1996         audiohd_state_t         *statep;
1997 
1998         statep = ddi_get_driver_private(dip);
1999 
2000         mutex_enter(&statep->hda_mutex);
2001         audiohd_stop_dma(statep);
2002         mutex_exit(&statep->hda_mutex);
2003 
2004         return (DDI_SUCCESS);
2005 }
2006 
2007 static void
2008 audiohd_beep_on(void *arg)
2009 {
2010         hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec;
2011         audiohd_state_t *statep = codec->statep;
2012         int caddr = codec->index;
2013         wid_t wid = ((audiohd_widget_t *)arg)->wid_wid;
2014 
2015         mutex_enter(&statep->hda_mutex);
2016         (void) audioha_codec_verb_get(statep, caddr, wid,
2017             AUDIOHDC_VERB_SET_BEEP_GEN, audiohd_beep_divider);
2018         mutex_exit(&statep->hda_mutex);
2019 }
2020 
2021 static void
2022 audiohd_beep_off(void *arg)
2023 {
2024         hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec;
2025         audiohd_state_t *statep = codec->statep;
2026         int caddr = codec->index;
2027         wid_t wid = ((audiohd_widget_t *)arg)->wid_wid;
2028 
2029         mutex_enter(&statep->hda_mutex);
2030         (void) audioha_codec_verb_get(statep, caddr, wid,
2031             AUDIOHDC_VERB_SET_BEEP_GEN, AUDIOHDC_MUTE_BEEP_GEN);
2032         mutex_exit(&statep->hda_mutex);
2033 }
2034 
2035 static void
2036 audiohd_beep_freq(void *arg, int freq)
2037 {
2038         hda_codec_t     *codec = ((audiohd_widget_t *)arg)->codec;
2039         audiohd_state_t *statep = codec->statep;
2040         uint32_t        vid = codec->vid >> 16;
2041         int             divider;
2042 
2043         _NOTE(ARGUNUSED(arg));
2044         if (freq == 0) {
2045                 divider = 0;
2046         } else {
2047                 if (freq > AUDIOHDC_MAX_BEEP_GEN)
2048                         freq = AUDIOHDC_MAX_BEEP_GEN;
2049                 else if (freq < AUDIOHDC_MIX_BEEP_GEN)
2050                         freq = AUDIOHDC_MIX_BEEP_GEN;
2051 
2052                 switch (vid) {
2053                 case AUDIOHD_VID_SIGMATEL:
2054                         /*
2055                          * Sigmatel HD codec specification:
2056                          * frequency = 48000 * (257 - Divider) / 1024
2057                          */
2058                         divider = 257 - freq * 1024 / AUDIOHDC_SAMPR48000;
2059                         break;
2060                 default:
2061                         divider = AUDIOHDC_SAMPR48000 / freq;
2062                         break;
2063                 }
2064         }
2065 
2066         if (audiohd_beep_vol == 0)
2067                 divider = 0;
2068 
2069         mutex_enter(&statep->hda_mutex);
2070         audiohd_beep_divider = divider;
2071         mutex_exit(&statep->hda_mutex);
2072 }
2073 
2074 /*
2075  * audiohd_init_state()
2076  *
2077  * Description
2078  *      This routine initailizes soft state of driver instance,
2079  *      also, it requests an interrupt cookie and initializes
2080  *      mutex for soft state.
2081  */
2082 /*ARGSUSED*/
2083 static int
2084 audiohd_init_state(audiohd_state_t *statep, dev_info_t *dip)
2085 {
2086         audio_dev_t     *adev;
2087 
2088         statep->hda_dip = dip;
2089         statep->hda_rirb_rp = 0;
2090 
2091         if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
2092                 audio_dev_warn(NULL, "unable to allocate audio dev");
2093                 return (DDI_FAILURE);
2094         }
2095         statep->adev = adev;
2096 
2097         /* set device information */
2098         audio_dev_set_description(adev, AUDIOHD_DEV_CONFIG);
2099         audio_dev_set_version(adev, AUDIOHD_DEV_VERSION);
2100 
2101         return (DDI_SUCCESS);
2102 }       /* audiohd_init_state() */
2103 
2104 /*
2105  * audiohd_init_pci()
2106  *
2107  * Description
2108  *      enable driver to access PCI configure space and memory
2109  *      I/O space.
2110  */
2111 static int
2112 audiohd_init_pci(audiohd_state_t *statep, ddi_device_acc_attr_t *acc_attr)
2113 {
2114         uint16_t        cmdreg;
2115         uint16_t        vid;
2116         uint8_t         cTmp;
2117         dev_info_t      *dip = statep->hda_dip;
2118         audio_dev_t     *adev = statep->adev;
2119 
2120         if (pci_config_setup(dip, &statep->hda_pci_handle) == DDI_FAILURE) {
2121                 audio_dev_warn(adev,
2122                     "pci config mapping failed");
2123                 return (DDI_FAILURE);
2124         }
2125 
2126         if (ddi_regs_map_setup(dip, 1, &statep->hda_reg_base, 0,
2127             0, acc_attr, &statep->hda_reg_handle) != DDI_SUCCESS) {
2128                 audio_dev_warn(adev,
2129                     "memory I/O mapping failed");
2130                 return (DDI_FAILURE);
2131         }
2132 
2133         /*
2134          * HD audio control uses memory I/O only, enable it here.
2135          */
2136         cmdreg = pci_config_get16(statep->hda_pci_handle, PCI_CONF_COMM);
2137         pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM,
2138             cmdreg | PCI_COMM_MAE | PCI_COMM_ME);
2139 
2140         vid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID);
2141         switch (vid) {
2142         case AUDIOHD_VID_INTEL:
2143                 /*
2144                  * Currently, Intel (G)MCH and ICHx chipsets support PCI
2145                  * Express QoS. It implemenets two VCs(virtual channels)
2146                  * and allows OS software to map 8 traffic classes to the
2147                  * two VCs. Some BIOSes initialize HD audio hardware to
2148                  * use TC7 (traffic class 7) and to map TC7 to VC1 as Intel
2149                  * recommended. However, solaris doesn't support PCI express
2150                  * QoS yet. As a result, this driver can not work for those
2151                  * hardware without touching PCI express control registers.
2152                  * Here, we set TCSEL to 0 so as to use TC0/VC0 (VC0 is
2153                  * always enabled and TC0 is always mapped to VC0) for all
2154                  * Intel HD audio controllers.
2155                  */
2156                 cTmp = pci_config_get8(statep->hda_pci_handle,
2157                     AUDIOHD_INTEL_PCI_TCSEL);
2158                 pci_config_put8(statep->hda_pci_handle,
2159                     AUDIOHD_INTEL_PCI_TCSEL, (cTmp & AUDIOHD_INTEL_TCS_MASK));
2160                 break;
2161         case AUDIOHD_VID_ATI:
2162                 /*
2163                  * Refer to ATI SB450 datesheet. We set snoop for SB450
2164                  * like hardware.
2165                  */
2166                 cTmp = pci_config_get8(statep->hda_pci_handle,
2167                     AUDIOHD_ATI_PCI_MISC2);
2168                 pci_config_put8(statep->hda_pci_handle, AUDIOHD_ATI_PCI_MISC2,
2169                     (cTmp & AUDIOHD_ATI_MISC2_MASK) | AUDIOHD_ATI_MISC2_SNOOP);
2170                 break;
2171         case AUDIOHD_VID_NVIDIA:
2172                 /*
2173                  * Refer to the datasheet, we set snoop for NVIDIA
2174                  * like hardware
2175                  */
2176                 cTmp = pci_config_get8(statep->hda_pci_handle,
2177                     AUDIOHD_CORB_SIZE_OFF);
2178                 pci_config_put8(statep->hda_pci_handle, AUDIOHD_CORB_SIZE_OFF,
2179                     cTmp | AUDIOHD_NVIDIA_SNOOP);
2180                 break;
2181         default:
2182                 break;
2183         }
2184 
2185         return (DDI_SUCCESS);
2186 }       /* audiohd_init_pci() */
2187 
2188 
2189 /*
2190  * audiohd_fini_pci()
2191  *
2192  * Description
2193  *      Release mapping for PCI configure space.
2194  */
2195 static void
2196 audiohd_fini_pci(audiohd_state_t *statep)
2197 {
2198         if (statep->hda_reg_handle != NULL) {
2199                 ddi_regs_map_free(&statep->hda_reg_handle);
2200         }
2201 
2202         if (statep->hda_pci_handle != NULL) {
2203                 pci_config_teardown(&statep->hda_pci_handle);
2204         }
2205 
2206 }       /* audiohd_fini_pci() */
2207 
2208 /*
2209  * audiohd_stop_dma()
2210  *
2211  * Description
2212  *      Stop all DMA behaviors of controllers, for command I/O
2213  *      and each audio stream.
2214  */
2215 static void
2216 audiohd_stop_dma(audiohd_state_t *statep)
2217 {
2218         int     i;
2219         uint_t  base;
2220         uint8_t bTmp;
2221 
2222         AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, 0);
2223         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, 0);
2224 
2225         base = AUDIOHD_REG_SD_BASE;
2226         for (i = 0; i < statep->hda_streams_nums; i++) {
2227                 bTmp = AUDIOHD_REG_GET8(base + AUDIOHD_SDREG_OFFSET_CTL);
2228 
2229                 /* for input/output stream, it is the same */
2230                 bTmp &= ~AUDIOHDR_RIRBCTL_DMARUN;
2231 
2232                 AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_CTL, bTmp);
2233                 base += AUDIOHD_REG_SD_LEN;
2234         }
2235 
2236         /* wait 40us for stream DMA to stop */
2237         drv_usecwait(40);
2238 
2239 }       /* audiohd_stop_dma() */
2240 
2241 /*
2242  * audiohd_reset_controller()
2243  *
2244  * Description:
2245  *      This routine is just used to reset controller and
2246  *      CODEC as well by HW reset bit in global control
2247  *      register of HD controller.
2248  */
2249 static int
2250 audiohd_reset_controller(audiohd_state_t *statep)
2251 {
2252         int             i;
2253         uint16_t        sTmp;
2254         uint32_t        gctl;
2255 
2256         /* Reset Status register but preserve the first bit */
2257         sTmp = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS);
2258         AUDIOHD_REG_SET16(AUDIOHD_REG_STATESTS, sTmp & 0x8000);
2259 
2260         /* reset controller */
2261         gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2262         gctl &= ~AUDIOHDR_GCTL_CRST;
2263         AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl);  /* entering reset state */
2264         for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
2265                 /* Empirical testing time: 150 */
2266                 drv_usecwait(150);
2267                 gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2268                 if ((gctl & AUDIOHDR_GCTL_CRST) == 0)
2269                         break;
2270         }
2271 
2272         if ((gctl & AUDIOHDR_GCTL_CRST) != 0) {
2273                 audio_dev_warn(statep->adev,
2274                     "failed to enter reset state");
2275                 return (DDI_FAILURE);
2276         }
2277 
2278         /* Empirical testing time:300 */
2279         drv_usecwait(300);
2280 
2281         /* exit reset state */
2282         AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl | AUDIOHDR_GCTL_CRST);
2283 
2284         for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
2285                 /* Empirical testing time: 150, which works well */
2286                 drv_usecwait(150);
2287                 gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2288                 if (gctl & AUDIOHDR_GCTL_CRST)
2289                         break;
2290         }
2291 
2292         if ((gctl & AUDIOHDR_GCTL_CRST) == 0) {
2293                 audio_dev_warn(statep->adev,
2294                     "failed to exit reset state");
2295                 return (DDI_FAILURE);
2296         }
2297 
2298         /* HD spec requires to wait 250us at least. we use 500us */
2299         drv_usecwait(500);
2300 
2301         /* enable unsolicited response */
2302         AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL,
2303             gctl |  AUDIOHDR_GCTL_URESPE);
2304 
2305         return (DDI_SUCCESS);
2306 
2307 }       /* audiohd_reset_controller() */
2308 
2309 /*
2310  * audiohd_alloc_dma_mem()
2311  *
2312  * Description:
2313  *      This is an utility routine. It is used to allocate DMA
2314  *      memory.
2315  */
2316 static int
2317 audiohd_alloc_dma_mem(audiohd_state_t *statep, audiohd_dma_t *pdma,
2318     size_t memsize, ddi_dma_attr_t *dma_attr_p, uint_t dma_flags)
2319 {
2320         ddi_dma_cookie_t        cookie;
2321         uint_t                  count;
2322         dev_info_t              *dip = statep->hda_dip;
2323         audio_dev_t             *ahandle = statep->adev;
2324 
2325         if (ddi_dma_alloc_handle(dip, dma_attr_p, DDI_DMA_SLEEP,
2326             NULL, &pdma->ad_dmahdl) != DDI_SUCCESS) {
2327                 audio_dev_warn(ahandle,
2328                     "ddi_dma_alloc_handle failed");
2329                 return (DDI_FAILURE);
2330         }
2331 
2332         if (ddi_dma_mem_alloc(pdma->ad_dmahdl, memsize, &hda_dev_accattr,
2333             dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
2334             DDI_DMA_SLEEP, NULL,
2335             (caddr_t *)&pdma->ad_vaddr, &pdma->ad_real_sz,
2336             &pdma->ad_acchdl) != DDI_SUCCESS) {
2337                 audio_dev_warn(ahandle,
2338                     "ddi_dma_mem_alloc failed");
2339                 return (DDI_FAILURE);
2340         }
2341 
2342         if (ddi_dma_addr_bind_handle(pdma->ad_dmahdl, NULL,
2343             (caddr_t)pdma->ad_vaddr, pdma->ad_real_sz, dma_flags,
2344             DDI_DMA_SLEEP, NULL, &cookie, &count) != DDI_DMA_MAPPED) {
2345                 audio_dev_warn(ahandle,
2346                     "ddi_dma_addr_bind_handle failed");
2347                 return (DDI_FAILURE);
2348         }
2349 
2350         pdma->ad_paddr = (uint64_t)(cookie.dmac_laddress);
2351         pdma->ad_req_sz = memsize;
2352 
2353         return (DDI_SUCCESS);
2354 }       /* audiohd_alloc_dma_mem() */
2355 
2356 /*
2357  * audiohd_release_dma_mem()
2358  *
2359  * Description:
2360  *      Release DMA memory.
2361  */
2362 
2363 static void
2364 audiohd_release_dma_mem(audiohd_dma_t *pdma)
2365 {
2366         if (pdma->ad_dmahdl != NULL) {
2367                 (void) ddi_dma_unbind_handle(pdma->ad_dmahdl);
2368         }
2369 
2370         if (pdma->ad_acchdl != NULL) {
2371                 ddi_dma_mem_free(&pdma->ad_acchdl);
2372                 pdma->ad_acchdl = NULL;
2373         }
2374 
2375         if (pdma->ad_dmahdl != NULL) {
2376                 ddi_dma_free_handle(&pdma->ad_dmahdl);
2377                 pdma->ad_dmahdl = NULL;
2378         }
2379 
2380 }       /* audiohd_release_dma_mem() */
2381 
2382 /*
2383  * audiohd_reinit_hda()
2384  *
2385  * Description:
2386  *      This routine is used to re-initialize HD controller and codec.
2387  */
2388 static int
2389 audiohd_reinit_hda(audiohd_state_t *statep)
2390 {
2391         uint64_t        addr;
2392 
2393         /* set PCI configure space in case it's not restored OK */
2394         (void) audiohd_init_pci(statep, &hda_dev_accattr);
2395 
2396         /* reset controller */
2397         if (audiohd_reset_controller(statep) != DDI_SUCCESS)
2398                 return (DDI_FAILURE);
2399         AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */
2400 
2401         /* Initialize controller RIRB */
2402         addr = statep->hda_dma_rirb.ad_paddr;
2403         AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr);
2404         AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE,
2405             (uint32_t)(addr >> 32));
2406         AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET);
2407         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256);
2408         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN |
2409             AUDIOHDR_RIRBCTL_RINTCTL);
2410 
2411         /* Initialize controller CORB */
2412         addr = statep->hda_dma_corb.ad_paddr;
2413         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET);
2414         AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr);
2415         AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE,
2416             (uint32_t)(addr >> 32));
2417         AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256);
2418         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0);
2419         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0);
2420         AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN);
2421 
2422         audiohd_restore_codec_gpio(statep);
2423         audiohd_restore_path(statep);
2424         audiohd_init_path(statep);
2425 
2426         return (DDI_SUCCESS);
2427 }       /* audiohd_reinit_hda */
2428 
2429 /*
2430  * audiohd_init_controller()
2431  *
2432  * Description:
2433  *      This routine is used to initialize HD controller. It
2434  *      allocates DMA memory for CORB/RIRB, buffer descriptor
2435  *      list and cylic data buffer for both play and record
2436  *      stream.
2437  */
2438 static int
2439 audiohd_init_controller(audiohd_state_t *statep)
2440 {
2441         uint64_t        addr;
2442         uint16_t        gcap;
2443         int             retval;
2444 
2445         ddi_dma_attr_t  dma_attr = {
2446                 DMA_ATTR_V0,            /* version */
2447                 0,                      /* addr_lo */
2448                 0xffffffffffffffffULL,  /* addr_hi */
2449                 0x00000000ffffffffULL,  /* count_max */
2450                 128,                    /* 128-byte alignment as HD spec */
2451                 0xfff,                  /* burstsize */
2452                 1,                      /* minxfer */
2453                 0xffffffff,             /* maxxfer */
2454                 0xffffffff,             /* seg */
2455                 1,                      /* sgllen */
2456                 1,                      /* granular */
2457                 0                       /* flags */
2458         };
2459 
2460         gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP);
2461 
2462         /*
2463          * If the device doesn't support 64-bit DMA, we should not
2464          * allocate DMA memory from 4G above
2465          */
2466         if ((gcap & AUDIOHDR_GCAP_64OK) == 0)
2467                 dma_attr.dma_attr_addr_hi = 0xffffffffUL;
2468 
2469         statep->hda_input_streams = (gcap & AUDIOHDR_GCAP_INSTREAMS) >>
2470             AUDIOHD_INSTR_NUM_OFF;
2471         statep->hda_output_streams = (gcap & AUDIOHDR_GCAP_OUTSTREAMS) >>
2472             AUDIOHD_OUTSTR_NUM_OFF;
2473         statep->hda_streams_nums = statep->hda_input_streams +
2474             statep->hda_output_streams;
2475 
2476         statep->hda_record_regbase = AUDIOHD_REG_SD_BASE;
2477         statep->hda_play_regbase = AUDIOHD_REG_SD_BASE + AUDIOHD_REG_SD_LEN *
2478             statep->hda_input_streams;
2479 
2480         /* stop all dma before starting to reset controller */
2481         audiohd_stop_dma(statep);
2482 
2483         if (audiohd_reset_controller(statep) != DDI_SUCCESS)
2484                 return (DDI_FAILURE);
2485 
2486         /* check codec */
2487         statep->hda_codec_mask = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS);
2488         if (!statep->hda_codec_mask) {
2489                 audio_dev_warn(statep->adev,
2490                     "no codec exists");
2491                 return (DDI_FAILURE);
2492         }
2493 
2494         /* allocate DMA for CORB */
2495         retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_corb,
2496             AUDIOHD_CDBIO_CORB_LEN, &dma_attr,
2497             DDI_DMA_WRITE | DDI_DMA_STREAMING);
2498         if (retval != DDI_SUCCESS) {
2499                 audio_dev_warn(statep->adev,
2500                     "failed to alloc DMA for CORB");
2501                 return (DDI_FAILURE);
2502         }
2503 
2504         /* allocate DMA for RIRB */
2505         retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_rirb,
2506             AUDIOHD_CDBIO_RIRB_LEN, &dma_attr,
2507             DDI_DMA_READ | DDI_DMA_STREAMING);
2508         if (retval != DDI_SUCCESS) {
2509                 audio_dev_warn(statep->adev,
2510                     "failed to alloc DMA for RIRB");
2511                 return (DDI_FAILURE);
2512         }
2513 
2514         AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */
2515 
2516         /* Initialize RIRB */
2517         addr = statep->hda_dma_rirb.ad_paddr;
2518         AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr);
2519         AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE, (uint32_t)(addr >> 32));
2520         AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET);
2521         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256);
2522         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN |
2523             AUDIOHDR_RIRBCTL_RINTCTL);
2524 
2525         /* initialize CORB */
2526         addr = statep->hda_dma_corb.ad_paddr;
2527         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET);
2528         AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr);
2529         AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE, (uint32_t)(addr >> 32));
2530         AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256);
2531         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0);
2532         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0);
2533         AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN);
2534 
2535         return (DDI_SUCCESS);
2536 }       /* audiohd_init_controller() */
2537 
2538 /*
2539  * audiohd_fini_controller()
2540  *
2541  * Description:
2542  *      Releases DMA memory allocated in audiohd_init_controller()
2543  */
2544 static void
2545 audiohd_fini_controller(audiohd_state_t *statep)
2546 {
2547         audiohd_release_dma_mem(&statep->hda_dma_rirb);
2548         audiohd_release_dma_mem(&statep->hda_dma_corb);
2549 
2550 }       /* audiohd_fini_controller() */
2551 
2552 /*
2553  * audiohd_get_conns_from_entry()
2554  *
2555  * Description:
2556  *      Get connection list from every entry for a widget
2557  */
2558 static void
2559 audiohd_get_conns_from_entry(hda_codec_t *codec, audiohd_widget_t *widget,
2560     uint32_t entry, audiohd_entry_prop_t *prop)
2561 {
2562         int     i, k, num;
2563         wid_t   input_wid;
2564 
2565         for (i = 0; i < prop->conns_per_entry &&
2566             widget->nconns < prop->conn_len;
2567             i++, entry >>= prop->bits_per_conn) {
2568                 ASSERT(widget->nconns < AUDIOHD_MAX_CONN);
2569                 input_wid = entry & prop->mask_wid;
2570                 if (entry & prop->mask_range) {
2571                         if (widget->nconns == 0) {
2572                                 if (input_wid < codec->first_wid ||
2573                                     (input_wid > codec->last_wid)) {
2574                                         break;
2575                                 }
2576                                 widget->avail_conn[widget->nconns++] =
2577                                     input_wid;
2578                         } else {
2579                                 for (k = widget->avail_conn[widget->nconns-1] +
2580                                     1; k <= input_wid; k++) {
2581                                         ASSERT(widget->nconns <
2582                                             AUDIOHD_MAX_CONN);
2583                                         if (k < codec->first_wid ||
2584                                             (k > codec->last_wid)) {
2585                                                 break;
2586                                         } else {
2587                                                 num = widget->nconns;
2588                                                 widget->avail_conn[num] = k;
2589                                                 widget->nconns++;
2590                                         }
2591                                 }
2592                         }
2593                 } else {
2594                         if ((codec->first_wid <= input_wid) && (input_wid <=
2595                             codec->last_wid))
2596                                 widget->avail_conn[widget->nconns++] =
2597                                     input_wid;
2598                 }
2599         }
2600 }
2601 
2602 /*
2603  * audiohd_get_conns()
2604  *
2605  * Description:
2606  *      Get all connection list for a widget. The connection list is used for
2607  *      build output path, input path, and monitor path
2608  */
2609 static void
2610 audiohd_get_conns(hda_codec_t *codec, wid_t wid)
2611 {
2612         audiohd_state_t         *statep = codec->statep;
2613         audiohd_widget_t        *widget = codec->widget[wid];
2614         uint8_t caddr = codec->index;
2615         uint32_t        entry;
2616         audiohd_entry_prop_t    prop;
2617         wid_t   input_wid;
2618         int     i;
2619 
2620         prop.conn_len = audioha_codec_verb_get(statep, caddr, wid,
2621             AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_CONNLIST_LEN);
2622 
2623         if (prop.conn_len & AUDIOHD_FORM_MASK) {
2624                 prop.conns_per_entry = 2;
2625                 prop.bits_per_conn = 16;
2626                 prop.mask_range = 0x00008000;
2627                 prop.mask_wid = 0x00007fff;
2628         } else {
2629                 prop.conns_per_entry = 4;
2630                 prop.bits_per_conn = 8;
2631                 prop.mask_range = 0x00000080;
2632                 prop.mask_wid = 0x0000007f;
2633         }
2634         prop.conn_len &= AUDIOHD_LEN_MASK;
2635 
2636         /*
2637          * This should not happen since the ConnectionList bit of
2638          * widget capabilities already told us that this widget
2639          * has a connection list
2640          */
2641         if (prop.conn_len == 0) {
2642                 widget->nconns = 0;
2643                 audio_dev_warn(statep->adev,
2644                     "node %d has 0 connections", wid);
2645                 return;
2646         }
2647 
2648         if (prop.conn_len == 1) {
2649                 entry = audioha_codec_verb_get(statep, caddr,
2650                     wid, AUDIOHDC_VERB_GET_CONN_LIST_ENT, 0);
2651                 input_wid = entry & prop.mask_wid;
2652                 if ((input_wid < codec->first_wid) ||
2653                     (input_wid > codec->last_wid)) {
2654                         return;
2655                 }
2656                 widget->avail_conn[0] = input_wid;
2657                 widget->nconns = 1;
2658                 return;
2659         }
2660         widget->nconns = 0;
2661         for (i = 0; i < prop.conn_len; i += prop.conns_per_entry) {
2662                 entry = audioha_codec_verb_get(statep, caddr, wid,
2663                     AUDIOHDC_VERB_GET_CONN_LIST_ENT, i);
2664                 audiohd_get_conns_from_entry(codec, widget, entry, &prop);
2665         }
2666 }
2667 
2668 /*
2669  * Read PinCapabilities & default configuration
2670  */
2671 static void
2672 audiohd_get_pin_config(audiohd_widget_t *widget)
2673 {
2674         hda_codec_t             *codec = widget->codec;
2675         audiohd_state_t         *statep = codec->statep;
2676         audiohd_pin_t           *pin, *prev, *p;
2677 
2678         int             caddr = codec->index;
2679         wid_t           wid = widget->wid_wid;
2680         uint32_t        cap, config, pinctrl;
2681         uint8_t         urctrl, vrefbits;
2682 
2683         cap = audioha_codec_verb_get(statep, caddr, wid,
2684             AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PIN_CAP);
2685         config = audioha_codec_verb_get(statep, caddr,
2686             wid, AUDIOHDC_VERB_GET_DEFAULT_CONF, 0);
2687         pinctrl = audioha_codec_verb_get(statep, caddr,
2688             wid, AUDIOHDC_VERB_GET_PIN_CTRL, 0);
2689 
2690         pin = (audiohd_pin_t *)kmem_zalloc(sizeof (audiohd_pin_t), KM_SLEEP);
2691         widget->priv = pin;
2692 
2693         /*
2694          * If the pin has no physical connection for port,
2695          * we won't link it to pin linkage list ???
2696          */
2697         if (((config >> AUDIOHD_PIN_CON_STEP) & AUDIOHD_PIN_CON_MASK) == 0x1) {
2698                 pin->no_phys_conn = 1;
2699         }
2700 
2701         /* bit 4:3 are reserved, read-modify-write is needed */
2702         pin->ctrl = pinctrl & AUDIOHD_PIN_IO_MASK;
2703         pin->wid = wid;
2704         pin->cap = cap;
2705         pin->config = config;
2706         pin->num = 0;
2707         pin->finish = 0;
2708 
2709         vrefbits = (cap >> AUDIOHD_PIN_VREF_OFF) & AUDIOHD_PIN_VREF_MASK;
2710         if (vrefbits & AUDIOHD_PIN_VREF_L1)
2711                 pin->vrefvalue = 0x5;
2712         else if (vrefbits & AUDIOHD_PIN_VREF_L2)
2713                 pin->vrefvalue = 0x4;
2714         else if (vrefbits & AUDIOHD_PIN_VREF_L3)
2715                 pin->vrefvalue = 0x2;
2716         else
2717                 pin->vrefvalue = 0x1;
2718 
2719         pin->seq = config & AUDIOHD_PIN_SEQ_MASK;
2720         pin->assoc = (config & AUDIOHD_PIN_ASO_MASK) >> AUDIOHD_PIN_ASO_OFF;
2721         pin->device = (config & AUDIOHD_PIN_DEV_MASK) >> AUDIOHD_PIN_DEV_OFF;
2722 
2723         /* enable the unsolicited response of the pin */
2724         if ((widget->widget_cap & AUDIOHD_URCAP_MASK) &&
2725             (pin->cap & AUDIOHD_DTCCAP_MASK) &&
2726             ((pin->device == DTYPE_LINEOUT) ||
2727             (pin->device == DTYPE_SPDIF_OUT) ||
2728             (pin->device == DTYPE_HP_OUT) ||
2729             (pin->device == DTYPE_MIC_IN))) {
2730                         urctrl = (uint8_t)(1 << (AUDIOHD_UR_ENABLE_OFF - 1));
2731                         urctrl |= (wid & AUDIOHD_UR_TAG_MASK);
2732                         (void) audioha_codec_verb_get(statep, caddr,
2733                             wid, AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
2734         }
2735         /* accommodate all the pins in a link list sorted by assoc and seq */
2736         if (codec->first_pin == NULL) {
2737                 codec->first_pin = pin;
2738         } else {
2739                 prev = NULL;
2740                 p = codec->first_pin;
2741                 while (p) {
2742                         if (p->assoc > pin->assoc)
2743                                 break;
2744                         if ((p->assoc == pin->assoc) &&
2745                             (p->seq > pin->seq))
2746                                 break;
2747                         prev = p;
2748                         p = p->next;
2749                 }
2750                 if (prev) {
2751                         pin->next = prev->next;
2752                         prev->next = pin;
2753                 } else {
2754                         pin->next = codec->first_pin;
2755                         codec->first_pin = pin;
2756                 }
2757         }
2758 
2759 }       /* audiohd_get_pin_config() */
2760 
2761 /*
2762  * audiohd_create_widgets()
2763  *
2764  * Description:
2765  *      All widgets are created and stored in an array of codec
2766  */
2767 static int
2768 audiohd_create_widgets(hda_codec_t *codec)
2769 {
2770         audiohd_widget_t        *widget;
2771         audiohd_state_t         *statep = codec->statep;
2772         wid_t   wid;
2773         uint32_t        type, widcap;
2774         int             caddr = codec->index;
2775 
2776         for (wid = codec->first_wid;
2777             wid <= codec->last_wid; wid++) {
2778                 widget = (audiohd_widget_t *)
2779                     kmem_zalloc(sizeof (audiohd_widget_t), KM_SLEEP);
2780                 codec->widget[wid] = widget;
2781                 widget->codec = codec;
2782                 widget->output_path_next = AUDIOHD_NULL_CONN;
2783                 widget->input_path_next = AUDIOHD_NULL_CONN;
2784                 widget->beep_path_next = AUDIOHD_NULL_CONN;
2785                 widget->loopback_path_next = AUDIOHD_NULL_CONN;
2786 
2787                 widcap = audioha_codec_verb_get(statep, caddr, wid,
2788                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AUDIO_WID_CAP);
2789                 type = AUDIOHD_WIDCAP_TO_WIDTYPE(widcap);
2790                 widget->wid_wid = wid;
2791                 widget->type = type;
2792                 widget->widget_cap = widcap;
2793                 widget->finish = 0;
2794                 widget->used = 0;
2795 
2796                 /* if there's connection list */
2797                 if (widcap & AUDIOHD_WIDCAP_CONNLIST) {
2798                         audiohd_get_conns(codec, wid);
2799                 }
2800 
2801                 /* if power control, power it up to D0 state */
2802                 if (widcap & AUDIOHD_WIDCAP_PWRCTRL) {
2803                         (void) audioha_codec_verb_get(statep, caddr, wid,
2804                             AUDIOHDC_VERB_SET_POWER_STATE, 0);
2805                 }
2806 
2807                 /*
2808                  * if this widget has format override, we read it.
2809                  * Otherwise, it uses the format of audio function.
2810                  */
2811                 if (widcap & AUDIOHD_WIDCAP_FMT_OVRIDE) {
2812                         widget->pcm_format =
2813                             audioha_codec_verb_get(statep, caddr, wid,
2814                             AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM);
2815                 } else {
2816                         widget->pcm_format = codec->pcm_format;
2817                 }
2818 
2819                 /*
2820                  * Input amplifier. Has the widget input amplifier ?
2821                  */
2822                 if (widcap & AUDIOHD_WIDCAP_INAMP) {
2823                         /*
2824                          * if overrided bit is 0, use the default
2825                          * amplifier of audio function as HD spec.
2826                          * Otherwise, we read it.
2827                          */
2828                         if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0)
2829                                 widget->inamp_cap = codec->inamp_cap;
2830                         else
2831                                 widget->inamp_cap =
2832                                     audioha_codec_verb_get(statep, caddr, wid,
2833                                     AUDIOHDC_VERB_GET_PARAM,
2834                                     AUDIOHDC_PAR_INAMP_CAP);
2835                 } else {
2836                         widget->inamp_cap = 0;
2837                 }
2838 
2839                 /*
2840                  * output amplifier. Has this widget output amplifier ?
2841                  */
2842                 if (widcap & AUDIOHD_WIDCAP_OUTAMP) {
2843                         if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0)
2844                                 widget->outamp_cap = codec->outamp_cap;
2845                         else
2846                                 widget->outamp_cap =
2847                                     audioha_codec_verb_get(statep, caddr, wid,
2848                                     AUDIOHDC_VERB_GET_PARAM,
2849                                     AUDIOHDC_PAR_OUTAMP_CAP);
2850                 } else {
2851                         widget->outamp_cap = 0;
2852                 }
2853 
2854                 switch (type) {
2855                 case WTYPE_AUDIO_OUT:
2856                 case WTYPE_AUDIO_IN:
2857                 case WTYPE_AUDIO_MIX:
2858                 case WTYPE_AUDIO_SEL:
2859                 case WTYPE_VENDOR:
2860                 case WTYPE_POWER:
2861                 case WTYPE_VOL_KNOB:
2862                         break;
2863                 case WTYPE_PIN:
2864                         /*
2865                          * Some codec(like ALC262) don't provide beep widget,
2866                          * it only has input Pin to connect an external beep
2867                          * (maybe in motherboard or elsewhere). So we open
2868                          * all PINs here in order to enable external beep
2869                          * source.
2870                          */
2871                         if ((codec->codec_info->flags & EN_PIN_BEEP) == 0) {
2872                                 (void) audioha_codec_4bit_verb_get(statep,
2873                                     caddr, widget->wid_wid,
2874                                     AUDIOHDC_VERB_SET_AMP_MUTE,
2875                                     AUDIOHDC_AMP_SET_LR_OUTPUT |
2876                                     AUDIOHDC_GAIN_MAX);
2877                         }
2878 
2879                         audiohd_get_pin_config(widget);
2880                         break;
2881                 case WTYPE_BEEP:
2882                         /*
2883                          * Get the audiohd_beep_switch value from audiohd.conf,
2884                          * which is for turning on/off widget beep.
2885                          */
2886                         audiohd_beep = ddi_prop_get_int(DDI_DEV_T_ANY,
2887                             statep->hda_dip,
2888                             DDI_PROP_DONTPASS, "audiohd_beep", 1);
2889 
2890                         if (audiohd_beep) {
2891                                 (void) beep_fini();
2892                                 (void) beep_init((void *) widget,
2893                                     audiohd_beep_on,
2894                                     audiohd_beep_off,
2895                                     audiohd_beep_freq);
2896                         }
2897                         break;
2898                 default:
2899                         break;
2900                 }
2901         }
2902 
2903         return (DDI_SUCCESS);
2904 
2905 }       /* audiohd_create_widgets() */
2906 
2907 /*
2908  * audiohd_destroy_widgets()
2909  */
2910 static void
2911 audiohd_destroy_widgets(hda_codec_t *codec)
2912 {
2913         for (int i = 0; i < AUDIOHD_MAX_WIDGET; i++) {
2914                 if (codec->widget[i]) {
2915                         kmem_free(codec->widget[i], sizeof (audiohd_widget_t));
2916                         codec->widget[i] = NULL;
2917                 }
2918         }
2919 
2920 }       /* audiohd_destroy_widgets() */
2921 
2922 /*
2923  * audiohd_create_codec()
2924  *
2925  * Description:
2926  *      Searching for supported CODEC. If find, allocate memory
2927  *      to hold codec structure.
2928  */
2929 static int
2930 audiohd_create_codec(audiohd_state_t *statep)
2931 {
2932         hda_codec_t     *codec;
2933         uint32_t        mask, type;
2934         uint32_t        nums;
2935         uint32_t        i, j, len;
2936         wid_t           wid;
2937         char            buf[128];
2938         int             rate, bits;
2939         dev_info_t      *dip = statep->hda_dip;
2940 
2941 
2942         mask = statep->hda_codec_mask;
2943         ASSERT(mask != 0);
2944 
2945         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
2946                 if ((mask & (1 << i)) == 0)
2947                         continue;
2948                 codec = (hda_codec_t *)kmem_zalloc(
2949                     sizeof (hda_codec_t), KM_SLEEP);
2950                 codec->index = i;
2951                 codec->vid = audioha_codec_verb_get(statep, i,
2952                     AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM,
2953                     AUDIOHDC_PAR_VENDOR_ID);
2954                 if (codec->vid == (uint32_t)(-1)) {
2955                         kmem_free(codec, sizeof (hda_codec_t));
2956                         continue;
2957                 }
2958 
2959                 codec->revid =
2960                     audioha_codec_verb_get(statep, i,
2961                     AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM,
2962                     AUDIOHDC_PAR_REV_ID);
2963 
2964                 nums = audioha_codec_verb_get(statep,
2965                     i, AUDIOHDC_NODE_ROOT,
2966                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_NODE_COUNT);
2967                 if (nums == (uint32_t)(-1)) {
2968                         kmem_free(codec, sizeof (hda_codec_t));
2969                         continue;
2970                 }
2971                 wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK;
2972                 nums = nums & AUDIOHD_CODEC_NUM_MASK;
2973 
2974                 /*
2975                  * Assume that each codec has just one audio function group
2976                  */
2977                 for (j = 0; j < nums; j++, wid++) {
2978                         type = audioha_codec_verb_get(statep, i, wid,
2979                             AUDIOHDC_VERB_GET_PARAM,
2980                             AUDIOHDC_PAR_FUNCTION_TYPE);
2981                         if ((type & AUDIOHD_CODEC_TYPE_MASK) ==
2982                             AUDIOHDC_AUDIO_FUNC_GROUP) {
2983                                 codec->wid_afg = wid;
2984                                 break;
2985                         }
2986                 }
2987 
2988                 if (codec->wid_afg == 0) {
2989                         kmem_free(codec, sizeof (hda_codec_t));
2990                         continue;
2991                 }
2992 
2993                 ASSERT(codec->wid_afg == wid);
2994 
2995                 len = sizeof (audiohd_codecs) / sizeof (audiohd_codec_info_t);
2996                 for (j = 0; j < len-1; j++) {
2997                         if (audiohd_codecs[j].devid == codec->vid) {
2998                                 codec->codec_info = &(audiohd_codecs[j]);
2999                                 break;
3000                         }
3001                 }
3002 
3003                 if (codec->codec_info == NULL) {
3004                         codec->codec_info = &(audiohd_codecs[len-1]);
3005                         (void) snprintf(buf, sizeof (buf),
3006                             "Unknown HD codec: 0x%x", codec->vid);
3007                 } else {
3008                         (void) snprintf(buf, sizeof (buf), "HD codec: %s",
3009                             codec->codec_info->buf);
3010                 }
3011                 audio_dev_add_info(statep->adev, buf);
3012 
3013                 /* work around for Sony VAIO laptop with specific codec */
3014                 if ((codec->codec_info->flags & NO_GPIO) == 0) {
3015                         /*
3016                          * GPIO controls which are laptop specific workarounds
3017                          * and might be changed. Some laptops use GPIO,
3018                          * so we need to enable and set the GPIO correctly.
3019                          */
3020                         (void) audioha_codec_verb_get(statep, i, wid,
3021                             AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE);
3022                         (void) audioha_codec_verb_get(statep, i, wid,
3023                             AUDIOHDC_VERB_SET_UNSOL_ENABLE_MASK,
3024                             AUDIOHDC_GPIO_ENABLE);
3025                         (void) audioha_codec_verb_get(statep, i, wid,
3026                             AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT);
3027                         (void) audioha_codec_verb_get(statep, i, wid,
3028                             AUDIOHDC_VERB_SET_GPIO_STCK,
3029                             AUDIOHDC_GPIO_DATA_CTRL);
3030                         (void) audioha_codec_verb_get(statep, i, wid,
3031                             AUDIOHDC_VERB_SET_GPIO_DATA,
3032                             AUDIOHDC_GPIO_STCK_CTRL);
3033                 }
3034 
3035                 /* power-up audio function group */
3036                 (void) audioha_codec_verb_get(statep, i, wid,
3037                     AUDIOHDC_VERB_SET_POWER_STATE, AUDIOHD_PW_D0);
3038 
3039                 /* subsystem id is attached to funtion group */
3040                 codec->outamp_cap = audioha_codec_verb_get(statep, i, wid,
3041                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_OUTAMP_CAP);
3042                 codec->inamp_cap = audioha_codec_verb_get(statep, i, wid,
3043                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_INAMP_CAP);
3044                 codec->stream_format = audioha_codec_verb_get(statep, i, wid,
3045                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_STREAM);
3046                 codec->pcm_format = audioha_codec_verb_get(statep, i, wid,
3047                     AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM);
3048 
3049                 statep->sample_rate = 48000;
3050                 rate = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3051                     DDI_PROP_DONTPASS, "sample-rate", 48000);
3052                 if (rate == 192000 &&
3053                     (codec->pcm_format & AUDIOHD_SAMP_RATE192)) {
3054                         statep->sample_rate = 192000;
3055                 } else if (rate == 96000 &&
3056                     (codec->pcm_format & AUDIOHD_SAMP_RATE96)) {
3057                         statep->sample_rate = 96000;
3058                 } else {
3059                         statep->sample_rate = 48000;
3060                 }
3061 
3062                 statep->sample_bit_depth = AUDIOHD_BIT_DEPTH16;
3063                 bits = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3064                     DDI_PROP_DONTPASS, "sample-bits", 16);
3065                 if (bits == 24 &&
3066                     (codec->pcm_format & AUDIOHD_BIT_DEPTH24)) {
3067                         statep->sample_bit_depth = AUDIOHD_BIT_DEPTH24;
3068                 } else {
3069                         statep->sample_bit_depth = AUDIOHD_BIT_DEPTH16;
3070                 }
3071 
3072                 nums = audioha_codec_verb_get(statep, i, wid,
3073                     AUDIOHDC_VERB_GET_PARAM,
3074                     AUDIOHDC_PAR_NODE_COUNT);
3075                 wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK;
3076                 nums = nums & AUDIOHD_CODEC_NUM_MASK;
3077                 codec->first_wid = wid;
3078                 codec->last_wid = wid + nums;
3079                 codec->nnodes = nums;
3080 
3081                 /*
3082                  * We output the codec information to syslog
3083                  */
3084                 statep->codec[i] = codec;
3085                 codec->statep = statep;
3086                 (void) audiohd_create_widgets(codec);
3087         }
3088 
3089         return (DDI_SUCCESS);
3090 
3091 }       /* audiohd_create_codec() */
3092 
3093 /*
3094  * audiohd_destroy_codec()
3095  *
3096  * Description:
3097  *      destroy codec structure, and release its memory
3098  */
3099 static void
3100 audiohd_destroy_codec(audiohd_state_t *statep)
3101 {
3102         int                     i;
3103         audiohd_pin_t           *pin, *npin;
3104 
3105         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
3106                 if (statep->codec[i]) {
3107                         audiohd_destroy_widgets(statep->codec[i]);
3108                         /*
3109                          * free pins
3110                          */
3111                         pin = statep->codec[i]->first_pin;
3112                         while (pin) {
3113                                 npin = pin;
3114                                 pin = pin->next;
3115                                 kmem_free(npin, sizeof (audiohd_pin_t));
3116                         }
3117 
3118                         kmem_free(statep->codec[i], sizeof (hda_codec_t));
3119                         statep->codec[i] = NULL;
3120                 }
3121         }
3122 }       /* audiohd_destroy_codec() */
3123 
3124 /*
3125  * audiohd_find_dac()
3126  * Description:
3127  *      Find a dac for a output path. Then the play data can be sent to the out
3128  *      put pin through the output path.
3129  *
3130  * Arguments:
3131  *      hda_codec_t     *codec          where the dac widget exists
3132  *      wid_t           wid             the no. of a widget
3133  *      int             mixer           whether the path need mixer or not
3134  *      int             *mixernum       the total of mixer in the output path
3135  *      int             exclusive       an exclusive path or share path
3136  *      int             depth           the depth of search
3137  *
3138  * Return:
3139  *      1) wid of the first shared widget in the path from
3140  *         pin to DAC if exclusive is 0;
3141  *      2) wid of DAC widget;
3142  *      3) 0 if no path
3143  */
3144 static wid_t
3145 audiohd_find_dac(hda_codec_t *codec, wid_t wid,
3146     int mixer, int *mixernum,
3147     int exclusive, int depth)
3148 {
3149         audiohd_widget_t        *widget = codec->widget[wid];
3150         wid_t   wdac = (uint32_t)(DDI_FAILURE);
3151         wid_t   retval;
3152 
3153         if (depth > AUDIOHD_MAX_DEPTH)
3154                 return (uint32_t)(DDI_FAILURE);
3155 
3156         if (widget == NULL)
3157                 return (uint32_t)(DDI_FAILURE);
3158 
3159         /*
3160          * If exclusive is true, we try to find a path which doesn't
3161          * share any widget with other paths.
3162          */
3163         if (exclusive) {
3164                 if (widget->path_flags & AUDIOHD_PATH_DAC)
3165                         return (uint32_t)(DDI_FAILURE);
3166         } else {
3167                 if (widget->path_flags & AUDIOHD_PATH_DAC)
3168                         return (wid);
3169         }
3170 
3171         switch (widget->type) {
3172         case WTYPE_AUDIO_OUT:
3173                 /* We need mixer widget, but the the mixer num is 0, failed  */
3174                 if (mixer && !*mixernum)
3175                         return (uint32_t)(DDI_FAILURE);
3176                 widget->path_flags |= AUDIOHD_PATH_DAC;
3177                 widget->out_weight++;
3178                 wdac = widget->wid_wid;
3179                 break;
3180 
3181         case WTYPE_AUDIO_MIX:
3182                 (*mixernum)++;
3183                 /* FALLTHRU */
3184         case WTYPE_AUDIO_SEL:
3185                 for (int i = 0; i < widget->nconns; i++) {
3186                         retval = audiohd_find_dac(codec,
3187                             widget->avail_conn[i],
3188                             mixer, mixernum,
3189                             exclusive, depth + 1);
3190                         if (retval != (uint32_t)DDI_FAILURE) {
3191                                 if (widget->output_path_next ==
3192                                     AUDIOHD_NULL_CONN) {
3193                                         widget->output_path_next = i;
3194                                         wdac = retval;
3195                                 }
3196                                 widget->path_flags |= AUDIOHD_PATH_DAC;
3197                                 widget->out_weight++;
3198 
3199                                 /* return when found a path */
3200                                 return (wdac);
3201                         }
3202                 }
3203         default:
3204                 break;
3205         }
3206 
3207         return (wdac);
3208 }       /* audiohd_find_dac() */
3209 
3210 /*
3211  * audiohd_do_build_output_path()
3212  *
3213  * Description:
3214  *      Search an output path for each pin in the codec.
3215  * Arguments:
3216  *      hda_codec_t     *codec          where the output path exists
3217  *      int             mixer           whether the path needs mixer widget
3218  *      int             *mnum           total of mixer widget in the path
3219  *      int             exclusive       an exclusive path or shared path
3220  *      int             depth           search depth
3221  */
3222 static void
3223 audiohd_do_build_output_path(hda_codec_t *codec, int mixer, int *mnum,
3224     int exclusive, int depth)
3225 {
3226         audiohd_pin_t           *pin;
3227         audiohd_widget_t        *widget, *wdac;
3228         audiohd_path_t          *path;
3229         wid_t                   wid;
3230         audiohd_state_t         *statep;
3231         int                     i;
3232 
3233         statep = codec->statep;
3234 
3235         for (pin = codec->first_pin; pin; pin = pin->next) {
3236                 if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
3237                         continue;
3238                 if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
3239                     AUDIOHD_PIN_NO_CONN)
3240                         continue;
3241                 if ((pin->device != DTYPE_LINEOUT) &&
3242                     (pin->device != DTYPE_SPEAKER) &&
3243                     (pin->device != DTYPE_SPDIF_OUT) &&
3244                     (pin->device != DTYPE_HP_OUT))
3245                         continue;
3246                 if (pin->finish)
3247                         continue;
3248                 widget = codec->widget[pin->wid];
3249 
3250                 widget->inamp_cap = 0;
3251                 for (i = 0; i < widget->nconns; i++) {
3252                         /*
3253                          * If a dac found, the return value is the wid of the
3254                          * widget on the path, or the return value is
3255                          * DDI_FAILURE
3256                          */
3257                         wid = audiohd_find_dac(codec,
3258                             widget->avail_conn[i], mixer, mnum, exclusive,
3259                             depth);
3260                         /*
3261                          * A dac was not found
3262                          */
3263                         if (wid == (wid_t)DDI_FAILURE)
3264                                 continue;
3265                         if (pin->device != DTYPE_SPEAKER &&
3266                             pin->device != DTYPE_HP_OUT)
3267                                 statep->chann[pin->assoc] += 2;
3268                         path = (audiohd_path_t *)
3269                             kmem_zalloc(sizeof (audiohd_path_t),
3270                             KM_SLEEP);
3271                         path->adda_wid = wid;
3272                         path->pin_wid[0] = widget->wid_wid;
3273                         path->pin_nums = 1;
3274                         path->path_type = PLAY;
3275                         path->codec = codec;
3276                         path->statep = statep;
3277                         wdac = codec->widget[wid];
3278                         wdac->priv = path;
3279                         pin->dac_wid = wid;
3280                         pin->finish = 1;
3281                         widget->path_flags |= AUDIOHD_PATH_DAC;
3282                         widget->out_weight++;
3283                         widget->output_path_next = i;
3284                         statep->path[statep->pathnum++] = path;
3285                         break;
3286                 }
3287         }
3288 
3289 }       /* audiohd_do_build_output_path() */
3290 
3291 /*
3292  * audiohd_build_output_path()
3293  *
3294  * Description:
3295  *      Build the output path in the codec for every pin.
3296  *      First we try to search output path with mixer widget exclusively
3297  *      Then we try to search shared output path with mixer widget.
3298  *      Then we try to search output path without mixer widget exclusively.
3299  *      At last we try to search shared ouput path for the remained pins
3300  */
3301 static void
3302 audiohd_build_output_path(hda_codec_t *codec)
3303 {
3304         int                     mnum = 0;
3305         uint8_t                 mixer_allow = 1;
3306 
3307         /*
3308          * Work around for laptops which have IDT or AD audio chipset, such as
3309          * HP mini 1000 laptop, Dell Lattitude 6400, Lenovo T60, Lenove R61e.
3310          * We don't allow mixer widget on such path, which leads to speaker
3311          * loud hiss noise.
3312          */
3313         if (codec->codec_info->flags & NO_MIXER)
3314                 mixer_allow = 0;
3315 
3316         /* search an exclusive mixer widget path. This is preferred */
3317         audiohd_do_build_output_path(codec, mixer_allow, &mnum, 1, 0);
3318 
3319         /* search a shared mixer widget path for the remained pins */
3320         audiohd_do_build_output_path(codec, mixer_allow, &mnum, 0, 0);
3321 
3322         /* search an exclusive widget path without mixer for the remained pin */
3323         audiohd_do_build_output_path(codec, 0, &mnum, 1, 0);
3324 
3325         /* search a shared widget path without mixer for the remained pin */
3326         audiohd_do_build_output_path(codec, 0, &mnum, 0, 0);
3327 
3328 }       /* audiohd_build_output_path */
3329 
3330 /*
3331  * audiohd_build_output_amp
3332  *
3333  * Description:
3334  *      Find the gain control and mute control widget
3335  */
3336 static void
3337 audiohd_build_output_amp(hda_codec_t *codec)
3338 {
3339         audiohd_path_t          *path;
3340         audiohd_widget_t        *w, *widget, *wpin, *wdac;
3341         audiohd_pin_t           *pin;
3342         wid_t           wid, next;
3343         int             weight;
3344         int             i, j;
3345         uint32_t        gain;
3346 
3347         for (i = 0; i < codec->statep->pathnum; i++) {
3348                 path = codec->statep->path[i];
3349                 if (path == NULL || path->path_type != PLAY ||
3350                     path->codec != codec)
3351                         continue;
3352                 for (j = 0; j < path->pin_nums; j++) {
3353                         wid = path->pin_wid[j];
3354                         wpin = codec->widget[wid];
3355                         pin = (audiohd_pin_t *)wpin->priv;
3356                         weight = wpin->out_weight;
3357 
3358                         /*
3359                          * search a node which can mute this pin while
3360                          * the mute functionality doesn't effect other
3361                          * pins.
3362                          */
3363                         widget = wpin;
3364                         while (widget) {
3365                                 if (widget->outamp_cap &
3366                                     AUDIOHDC_AMP_CAP_MUTE_CAP) {
3367                                         pin->mute_wid = widget->wid_wid;
3368                                         pin->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
3369                                         break;
3370                                 }
3371                                 if (widget->inamp_cap &
3372                                     AUDIOHDC_AMP_CAP_MUTE_CAP) {
3373                                         pin->mute_wid = widget->wid_wid;
3374                                         pin->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3375                                         break;
3376                                 }
3377                                 next = widget->output_path_next;
3378                                 if (next == AUDIOHD_NULL_CONN)
3379                                         break;
3380                                 wid = widget->avail_conn[next];
3381                                 widget = codec->widget[wid];
3382                                 if (widget && widget->out_weight != weight)
3383                                         break;
3384                         }
3385 
3386                         /*
3387                          * We select the wid which has maxium gain range in
3388                          * the output path. Meanwhile, the gain controlling
3389                          * of this node doesn't effect other pins if this
3390                          * output stream has multiple pins.
3391                          */
3392                         gain = 0;
3393                         widget = wpin;
3394                         while (widget) {
3395                                 gain = (widget->outamp_cap &
3396                                     AUDIOHDC_AMP_CAP_STEP_NUMS);
3397                                 if (gain && gain > pin->gain_bits) {
3398                                         pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3399                                         pin->gain_bits = gain;
3400                                         pin->gain_wid = widget->wid_wid;
3401                                 }
3402                                 gain = widget->inamp_cap &
3403                                     AUDIOHDC_AMP_CAP_STEP_NUMS;
3404                                 if (gain && gain > pin->gain_bits) {
3405                                         pin->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3406                                         pin->gain_bits = gain;
3407                                         pin->gain_wid = widget->wid_wid;
3408                                 }
3409                                 next = widget->output_path_next;
3410                                 if (next == AUDIOHD_NULL_CONN)
3411                                         break;
3412                                 wid = widget->avail_conn[next];
3413                                 widget = codec->widget[wid];
3414                                 if (widget && widget->out_weight != weight)
3415                                         break;
3416                         }
3417                         pin->gain_bits >>= AUDIOHD_GAIN_OFF;
3418                 }
3419 
3420                 /*
3421                  * if this stream has multiple pins, we try to find
3422                  * a mute & gain-controlling nodes which can effect
3423                  * all output pins of this stream to be used for the
3424                  * whole stream
3425                  */
3426                 if (path->pin_nums == 1) {
3427                         path->mute_wid = pin->mute_wid;
3428                         path->mute_dir = pin->mute_dir;
3429                         path->gain_wid = pin->gain_wid;
3430                         path->gain_dir = pin->gain_dir;
3431                         path->gain_bits = pin->gain_bits;
3432                 } else {
3433                         wdac = codec->widget[path->adda_wid];
3434                         weight = wdac->out_weight;
3435                         wid = path->pin_wid[0];
3436                         w = codec->widget[wid];
3437                         while (w && w->out_weight != weight) {
3438                                 wid = w->avail_conn[w->output_path_next];
3439                                 w = codec->widget[wid];
3440                         }
3441 
3442                         /* find mute controlling node for this stream */
3443                         widget = w;
3444                         while (widget) {
3445                                 if (widget->outamp_cap &
3446                                     AUDIOHDC_AMP_CAP_MUTE_CAP) {
3447                                         path->mute_wid = widget->wid_wid;
3448                                         path->mute_dir =
3449                                             AUDIOHDC_AMP_SET_OUTPUT;
3450                                         break;
3451                                 }
3452                                 if (widget->inamp_cap &
3453                                     AUDIOHDC_AMP_CAP_MUTE_CAP) {
3454                                         path->mute_wid = widget->wid_wid;
3455                                         path->mute_dir =
3456                                             AUDIOHDC_AMP_SET_INPUT;
3457                                         break;
3458                                 }
3459                                 next = widget->output_path_next;
3460                                 if (next == AUDIOHD_NULL_CONN)
3461                                         break;
3462                                 wid = widget->avail_conn[next];
3463                                 widget = codec->widget[wid];
3464                         }
3465 
3466                         /* find volume controlling node for this stream */
3467                         gain = 0;
3468                         widget = w;
3469                         while (widget) {
3470                                 gain = (widget->outamp_cap &
3471                                     AUDIOHDC_AMP_CAP_STEP_NUMS);
3472                                 if (gain && gain > pin->gain_bits) {
3473                                         path->gain_dir =
3474                                             AUDIOHDC_AMP_SET_OUTPUT;
3475                                         path->gain_bits = gain;
3476                                         path->gain_wid = widget->wid_wid;
3477                                 }
3478                                 gain = widget->inamp_cap &
3479                                     AUDIOHDC_AMP_CAP_STEP_NUMS;
3480                                 if (gain && (gain > pin->gain_bits) &&
3481                                     (widget->type != WTYPE_AUDIO_MIX)) {
3482                                         path->gain_dir =
3483                                             AUDIOHDC_AMP_SET_INPUT;
3484                                         path->gain_bits = gain;
3485                                         path->gain_wid = widget->wid_wid;
3486                                 }
3487                                 next = widget->output_path_next;
3488                                 if (next == AUDIOHD_NULL_CONN)
3489                                         break;
3490                                 wid = widget->avail_conn[next];
3491                                 widget = codec->widget[wid];
3492                         }
3493                         path->gain_bits >>= AUDIOHD_GAIN_OFF;
3494                 }
3495 
3496         }
3497 
3498 }       /* audiohd_build_output_amp */
3499 
3500 /*
3501  * audiohd_finish_output_path()
3502  *
3503  * Description:
3504  *      Enable the widgets on the output path
3505  */
3506 static void
3507 audiohd_finish_output_path(hda_codec_t *codec)
3508 {
3509         audiohd_state_t         *statep = codec->statep;
3510         audiohd_path_t          *path;
3511         audiohd_widget_t        *widget;
3512         audiohd_pin_t           *pin;
3513         uint_t                  caddr = codec->index;
3514         wid_t                   wid, next;
3515         int                     i, j;
3516 
3517         for (i = 0; i < codec->statep->pathnum; i++) {
3518                 path = codec->statep->path[i];
3519                 if (!path || path->path_type != PLAY || path->codec != codec)
3520                         continue;
3521                 for (j = 0; j < path->pin_nums; j++) {
3522                         wid = path->pin_wid[j];
3523                         widget = codec->widget[wid];
3524                         pin = (audiohd_pin_t *)widget->priv;
3525                         {
3526                         uint32_t    lTmp;
3527 
3528                         lTmp = audioha_codec_verb_get(statep, caddr, wid,
3529                             AUDIOHDC_VERB_GET_PIN_CTRL, 0);
3530                         (void) audioha_codec_verb_get(statep, caddr, wid,
3531                             AUDIOHDC_VERB_SET_PIN_CTRL, (lTmp |
3532                             pin->vrefvalue |
3533                             AUDIOHDC_PIN_CONTROL_OUT_ENABLE |
3534                             AUDIOHDC_PIN_CONTROL_HP_ENABLE) &
3535                             ~ AUDIOHDC_PIN_CONTROL_IN_ENABLE);
3536                         }
3537                         /* If this pin has external amplifier, enable it */
3538                         if (pin->cap & AUDIOHD_EXT_AMP_MASK)
3539                                 (void) audioha_codec_verb_get(statep, caddr,
3540                                     wid, AUDIOHDC_VERB_SET_EAPD,
3541                                     AUDIOHD_EXT_AMP_ENABLE);
3542 
3543                         if (widget->outamp_cap) {
3544                                 (void) audioha_codec_4bit_verb_get(statep,
3545                                     caddr, wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3546                                     AUDIOHDC_AMP_SET_LR_OUTPUT |
3547                                     AUDIOHDC_GAIN_MAX);
3548                         }
3549 
3550                         (void) audioha_codec_verb_get(statep, caddr, wid,
3551                             AUDIOHDC_VERB_SET_CONN_SEL,
3552                             widget->output_path_next);
3553 
3554                         wid = widget->avail_conn[widget->output_path_next];
3555                         widget = codec->widget[wid];
3556 
3557                         while (widget) {
3558                                 /*
3559                                  * Set all amplifiers in this path to
3560                                  * the maximum volume and unmute them.
3561                                  */
3562                                 if (widget->outamp_cap) {
3563                                         (void) audioha_codec_4bit_verb_get(
3564                                             statep, caddr,
3565                                             wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3566                                             AUDIOHDC_AMP_SET_LR_OUTPUT |
3567                                             AUDIOHDC_GAIN_MAX);
3568                                 }
3569                                 if (widget->inamp_cap) {
3570                                         (void) audioha_codec_4bit_verb_get(
3571                                             statep, caddr,
3572                                             wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3573                                             AUDIOHDC_AMP_SET_LR_INPUT |
3574                                             AUDIOHDC_GAIN_MAX |
3575                                             (widget->output_path_next <<
3576                                             AUDIOHDC_AMP_SET_INDEX_OFFSET));
3577                                 }
3578 
3579                                 next = widget->output_path_next;
3580                                 if (next == AUDIOHD_NULL_CONN)
3581                                         break;
3582                                 /*
3583                                  * Accoding to HD spec, mixer doesn't support
3584                                  * "select connection"
3585                                  */
3586                                 if ((widget->type == WTYPE_AUDIO_SEL) &&
3587                                     (widget->nconns > 1))
3588                                         (void) audioha_codec_verb_get(statep,
3589                                             caddr, wid,
3590                                             AUDIOHDC_VERB_SET_CONN_SEL,
3591                                             widget->output_path_next);
3592 
3593                                 wid = widget->avail_conn[next];
3594                                 widget = codec->widget[wid];
3595                         }
3596                 }
3597         }
3598 }       /* audiohd_finish_output_path() */
3599 
3600 /*
3601  * audiohd_find_input_pins()
3602  *
3603  * Description:
3604  *      Here we consider a mixer/selector with multi-input as a real sum
3605  *      widget. Only the first real mixer/selector widget is permitted in
3606  *      an input path(recording path). If there are more mixers/selectors
3607  *      execept the first one, only the first input/connection of those
3608  *      widgets will be used by our driver, that means, we ignore other
3609  *      inputs of those mixers/selectors.
3610  */
3611 static int
3612 audiohd_find_input_pins(hda_codec_t *codec, wid_t wid, int allowmixer,
3613     int depth, audiohd_path_t *path)
3614 {
3615         audiohd_widget_t        *widget = codec->widget[wid];
3616         audiohd_pin_t           *pin;
3617         audiohd_state_t         *statep = codec->statep;
3618         uint_t                  caddr = codec->index;
3619         int                     retval = -1;
3620         int                     num, i;
3621         uint32_t                pinctrl;
3622 
3623         if (depth > AUDIOHD_MAX_DEPTH)
3624                 return (uint32_t)(DDI_FAILURE);
3625         if (widget == NULL)
3626                 return (uint32_t)(DDI_FAILURE);
3627 
3628         /* we don't share widgets */
3629         if (widget->path_flags & AUDIOHD_PATH_ADC ||
3630             widget->path_flags & AUDIOHD_PATH_DAC)
3631                 return (uint32_t)(DDI_FAILURE);
3632 
3633         switch (widget->type) {
3634         case WTYPE_PIN:
3635                 pin = (audiohd_pin_t *)widget->priv;
3636                 if (pin->no_phys_conn)
3637                         return (uint32_t)(DDI_FAILURE);
3638                 /* enable the pins' input capability */
3639                 pinctrl = audioha_codec_verb_get(statep, caddr, wid,
3640                     AUDIOHDC_VERB_GET_PIN_CTRL, 0);
3641                 (void) audioha_codec_verb_get(statep, caddr, wid,
3642                     AUDIOHDC_VERB_SET_PIN_CTRL,
3643                     pinctrl | AUDIOHD_PIN_IN_ENABLE);
3644                 if (pin->cap & AUDIOHD_EXT_AMP_MASK) {
3645                         (void) audioha_codec_verb_get(statep, caddr,
3646                             wid, AUDIOHDC_VERB_SET_EAPD,
3647                             AUDIOHD_EXT_AMP_ENABLE);
3648                 }
3649                 switch (pin->device) {
3650                 case DTYPE_CD:
3651                 case DTYPE_LINE_IN:
3652                 case DTYPE_MIC_IN:
3653                 case DTYPE_AUX:
3654                         widget->path_flags |= AUDIOHD_PATH_ADC;
3655                         widget->in_weight++;
3656                         path->pin_wid[path->pin_nums++] = wid;
3657                         pin->adc_wid = path->adda_wid;
3658                         return (DDI_SUCCESS);
3659                 }
3660                 break;
3661         case WTYPE_AUDIO_MIX:
3662         case WTYPE_AUDIO_SEL:
3663                 /*
3664                  * If the sum widget has only one input, we don't
3665                  * consider it as a real sum widget.
3666                  */
3667                 if (widget->nconns == 1) {
3668                         widget->input_path_next = 0;
3669                         retval = audiohd_find_input_pins(codec,
3670                             widget->avail_conn[0],
3671                             allowmixer, depth + 1, path);
3672                         if (retval == DDI_SUCCESS) {
3673                                 widget->path_flags |= AUDIOHD_PATH_ADC;
3674                                 widget->in_weight++;
3675                         }
3676                         break;
3677                 }
3678 
3679                 if (allowmixer) {
3680                         /*
3681                          * This is a real sum widget, we will reject
3682                          * other real sum widget when we find more in
3683                          * the following path-searching.
3684                          */
3685                         for (int i = 0; i < widget->nconns; i++) {
3686                                 retval = audiohd_find_input_pins(codec,
3687                                     widget->avail_conn[i], 0, depth + 1,
3688                                     path);
3689                                 if (retval == DDI_SUCCESS) {
3690                                         widget->input_path_next = i;
3691                                         widget->in_weight++;
3692                                         num = path->pin_nums - 1;
3693                                         path->sum_selconn[num] = i;
3694                                         path->sum_wid = wid;
3695                                         widget->path_flags |=
3696                                             AUDIOHD_PATH_ADC;
3697                                 }
3698                         }
3699 
3700                         /* return SUCCESS if we found at least one input path */
3701                         if (path->pin_nums > 0)
3702                                 retval = DDI_SUCCESS;
3703                 } else {
3704                         /*
3705                          * We had already found a real sum before this one since
3706                          * allowmixer is 0.
3707                          */
3708                         for (i = 0; i < widget->nconns; i++) {
3709                                 retval = audiohd_find_input_pins(codec,
3710                                     widget->avail_conn[i], 0, depth + 1,
3711                                     path);
3712                                 if (retval == DDI_SUCCESS) {
3713                                         widget->input_path_next = i;
3714                                         widget->path_flags |= AUDIOHD_PATH_ADC;
3715                                         widget->in_weight++;
3716                                         break;
3717                                 }
3718                         }
3719                 }
3720                 break;
3721         default:
3722                 break;
3723         }
3724 
3725         return (retval);
3726 }       /* audiohd_find_input_pins */
3727 
3728 /*
3729  * audiohd_build_input_path()
3730  *
3731  * Description:
3732  *      Find input path for the codec
3733  */
3734 static void
3735 audiohd_build_input_path(hda_codec_t *codec)
3736 {
3737         audiohd_widget_t        *widget;
3738         audiohd_path_t          *path = NULL;
3739         wid_t                   wid;
3740         int                     i;
3741         int                     retval;
3742         uint8_t                 rtag = 0;
3743         audiohd_state_t         *statep = codec->statep;
3744 
3745         for (wid = codec->first_wid; wid <= codec->last_wid; wid++) {
3746 
3747                 widget = codec->widget[wid];
3748 
3749                 /* check if it is an ADC widget */
3750                 if (widget == NULL || widget->type != WTYPE_AUDIO_IN)
3751                         continue;
3752 
3753                 if (path == NULL)
3754                         path = kmem_zalloc(sizeof (audiohd_path_t),
3755                             KM_SLEEP);
3756                 else
3757                         bzero(path, sizeof (audiohd_port_t));
3758 
3759                 path->adda_wid = wid;
3760 
3761                 /*
3762                  * Is there any ADC widget which has more than one input ??
3763                  * I don't believe. Anyway, we carefully deal with this. But
3764                  * if hardware vendors embed a selector in a ADC, we just use
3765                  * the first available input, which has connection to input pin
3766                  * widget. Because selector cannot perform mixer functionality,
3767                  * and we just permit one selector or mixer in a recording path,
3768                  * if we use the selector embedded in ADC,we cannot use possible
3769                  * mixer during path searching.
3770                  */
3771                 for (i = 0; i < widget->nconns; i++) {
3772                         retval = audiohd_find_input_pins(codec,
3773                             widget->avail_conn[i], 1, 0, path);
3774                         if (retval == DDI_SUCCESS) {
3775                                 path->codec = codec;
3776                                 path->statep = statep;
3777                                 path->path_type = RECORD;
3778                                 path->tag = ++rtag;
3779                                 codec->nistream++;
3780                                 statep->path[statep->pathnum++] = path;
3781                                 widget->input_path_next = i;
3782                                 widget->priv = path;
3783                                 path = NULL;
3784                                 break;
3785                         }
3786                 }
3787         }
3788         if (path)
3789                 kmem_free(path, sizeof (audiohd_path_t));
3790 }       /* audiohd_build_input_path */
3791 
3792 /*
3793  * audiohd_build_input_amp()
3794  *
3795  * Description:
3796  *      Find gain and mute control widgets on the input path
3797  */
3798 static void
3799 audiohd_build_input_amp(hda_codec_t *codec)
3800 {
3801         audiohd_path_t          *path;
3802         audiohd_widget_t        *wsum, *wadc, *w;
3803         audiohd_pin_t           *pin;
3804         uint_t                  gain;
3805         wid_t                   wid, next;
3806         int                     i, j;
3807         int                     weight;
3808 
3809         for (i = 0; i < codec->statep->pathnum; i++) {
3810                 path = codec->statep->path[i];
3811                 if (path == NULL || path->path_type != RECORD ||
3812                     path->codec != codec)
3813                         continue;
3814 
3815                 wid = path->adda_wid;
3816                 wadc = path->codec->widget[wid];
3817                 weight = wadc->in_weight;
3818 
3819                 /*
3820                  * Search node which has mute functionality for
3821                  * the whole input path
3822                  */
3823                 w = wadc;
3824                 while (w) {
3825                         if (w->outamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) {
3826                                 path->mute_wid = w->wid_wid;
3827                                 path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
3828                                 break;
3829                         }
3830                         if ((w->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) &&
3831                             (w->wid_wid != path->sum_wid)) {
3832                                 path->mute_wid = w->wid_wid;
3833                                 path->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3834                                 break;
3835                         }
3836 
3837                         next = w->input_path_next;
3838                         if (next == AUDIOHD_NULL_CONN)
3839                                 break;
3840                         wid = w->avail_conn[next];
3841                         w = path->codec->widget[wid];
3842                         if (w && w->in_weight != weight)
3843                                 break;
3844                 }
3845 
3846                 /*
3847                  * Search a node for amplifier adjusting for the whole
3848                  * input path
3849                  */
3850                 w = wadc;
3851                 gain = 0;
3852                 while (w) {
3853                         gain = (w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS);
3854                         if (gain && gain > path->gain_bits) {
3855                                 path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3856                                 path->gain_bits = gain;
3857                                 path->gain_wid = w->wid_wid;
3858                         }
3859                         gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
3860                         if (gain && (gain > path->gain_bits) &&
3861                             (w->wid_wid != path->sum_wid)) {
3862                                 path->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3863                                 path->gain_bits = gain;
3864                                 path->gain_wid = w->wid_wid;
3865                         }
3866 
3867                         next = w->input_path_next;
3868                         if (next == AUDIOHD_NULL_CONN)
3869                                 break;
3870                         wid = w->avail_conn[next];
3871                         w = path->codec->widget[wid];
3872                 }
3873                 path->gain_bits >>= AUDIOHD_GAIN_OFF;
3874 
3875                 /*
3876                  * If the input path has one pin only, the mute/amp
3877                  * controlling is shared by the whole path and pin
3878                  */
3879                 if (path->pin_nums == 1) {
3880                         wid = path->pin_wid[0];
3881                         w = path->codec->widget[wid];
3882                         pin = (audiohd_pin_t *)w->priv;
3883                         pin->gain_dir = path->gain_dir;
3884                         pin->gain_bits = path->gain_bits;
3885                         pin->gain_wid = path->gain_wid;
3886                         pin->mute_wid = path->mute_wid;
3887                         pin->mute_dir = path->mute_dir;
3888                         continue;
3889                 }
3890 
3891                 /*
3892                  * For multi-pin device, there must be a selector
3893                  * or mixer along the input path, and the sum_wid
3894                  * is the widget's node id.
3895                  */
3896                 wid = path->sum_wid;
3897                 wsum = path->codec->widget[wid]; /* sum widget */
3898 
3899                 for (j = 0; j < path->pin_nums; j++) {
3900                         wid = path->pin_wid[j];
3901                         w = path->codec->widget[wid];
3902                         pin = (audiohd_pin_t *)w->priv;
3903 
3904                         /* find node for mute */
3905                         if (wsum->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) {
3906                                 pin->mute_wid = wsum->wid_wid;
3907                                 pin->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3908                         } else {
3909                                 wid = wsum->avail_conn[path->sum_selconn[i]];
3910                                 w = path->codec->widget[wid];
3911                                 while (w) {
3912                                         if (w->outamp_cap &
3913                                             AUDIOHDC_AMP_CAP_MUTE_CAP) {
3914                                                 pin->mute_wid = w->wid_wid;
3915                                                 pin->mute_dir =
3916                                                     AUDIOHDC_AMP_SET_OUTPUT;
3917                                                 break;
3918                                         }
3919                                         if (w->inamp_cap &
3920                                             AUDIOHDC_AMP_CAP_MUTE_CAP) {
3921                                                 pin->mute_wid = w->wid_wid;
3922                                                 pin->mute_dir =
3923                                                     AUDIOHDC_AMP_SET_INPUT;
3924                                                 break;
3925                                         }
3926 
3927                                         next = w->input_path_next;
3928                                         if (next == AUDIOHD_NULL_CONN)
3929                                                 break;
3930                                         wid = w->avail_conn[next];
3931                                         w = path->codec->widget[wid];
3932                                 }
3933                         }
3934 
3935                         /* find node for amp controlling */
3936                         gain = (wsum->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS);
3937                         wid = wsum->avail_conn[path->sum_selconn[i]];
3938                         w = path->codec->widget[wid];
3939                         while (w) {
3940                                 gain = (w->outamp_cap &
3941                                     AUDIOHDC_AMP_CAP_STEP_NUMS);
3942                                 if (gain && gain > pin->gain_bits) {
3943                                         pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3944                                         pin->gain_bits = gain;
3945                                         pin->gain_wid = w->wid_wid;
3946                                 }
3947                                 gain = w->inamp_cap &
3948                                     AUDIOHDC_AMP_CAP_STEP_NUMS;
3949                                 if (gain && (gain > pin->gain_bits)) {
3950                                         pin->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3951                                         pin->gain_bits = gain;
3952                                         pin->gain_wid = w->wid_wid;
3953                                 }
3954 
3955                                 next = w->input_path_next;
3956                                 if (next == AUDIOHD_NULL_CONN)
3957                                         break;
3958                                 wid = w->avail_conn[next];
3959                                 w = path->codec->widget[wid];
3960                         }
3961                         pin->gain_bits >>= AUDIOHD_GAIN_OFF;
3962                 }
3963         }
3964 }       /* audiohd_build_input_amp() */
3965 
3966 /*
3967  * audiohd_finish_input_path()
3968  *
3969  * Description:
3970  *      Enable the widgets on the input path
3971  */
3972 static void
3973 audiohd_finish_input_path(hda_codec_t *codec)
3974 {
3975         audiohd_state_t         *statep = codec->statep;
3976         audiohd_path_t          *path;
3977         audiohd_widget_t        *w, *wsum;
3978         uint_t                  caddr = codec->index;
3979         wid_t                   wid;
3980         int                     i, j;
3981 
3982         for (i = 0; i < codec->statep->pathnum; i++) {
3983                 path = codec->statep->path[i];
3984                 if (path == NULL || path->path_type != RECORD ||
3985                     path->codec != codec)
3986                         continue;
3987                 wid = path->adda_wid;
3988                 w = path->codec->widget[wid];
3989                 while (w && (w->wid_wid != path->sum_wid) &&
3990                     (w->type != WTYPE_PIN)) {
3991                         if ((w->type == WTYPE_AUDIO_SEL) && (w->nconns > 1))
3992                                 (void) audioha_codec_verb_get(statep, caddr,
3993                                     w->wid_wid, AUDIOHDC_VERB_SET_CONN_SEL,
3994                                     w->input_path_next);
3995 
3996                         if (w->outamp_cap) {
3997                                 (void) audioha_codec_4bit_verb_get(statep,
3998                                     caddr,
3999                                     w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4000                                     AUDIOHDC_AMP_SET_LR_OUTPUT |
4001                                     AUDIOHDC_GAIN_MAX);
4002                         }
4003 
4004                         if (w->inamp_cap) {
4005                                 (void) audioha_codec_4bit_verb_get(statep,
4006                                     caddr,
4007                                     w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4008                                     AUDIOHDC_AMP_SET_LR_INPUT |
4009                                     AUDIOHDC_GAIN_MAX |
4010                                     (w->input_path_next <<
4011                                     AUDIOHDC_AMP_SET_INDEX_OFFSET));
4012                         }
4013 
4014                         wid = w->avail_conn[w->input_path_next];
4015                         w = path->codec->widget[wid];
4016                 }
4017 
4018                 /*
4019                  * After exiting from the above loop, the widget pointed
4020                  * by w can be a pin widget or select/mixer widget. If it
4021                  * is a pin widget, we already finish "select connection"
4022                  * operation for the whole path.
4023                  */
4024                 if (w && w->type == WTYPE_PIN)
4025                         continue;
4026 
4027                 /*
4028                  * deal with multi-pin input devices.
4029                  */
4030                 wid = path->sum_wid;
4031                 wsum = path->codec->widget[wid];
4032                 if (wsum == NULL)
4033                         continue;
4034                 if (wsum->outamp_cap) {
4035                         (void) audioha_codec_4bit_verb_get(statep,
4036                             caddr,
4037                             wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4038                             AUDIOHDC_AMP_SET_LR_OUTPUT |
4039                             AUDIOHDC_GAIN_MAX);
4040                 }
4041 
4042                 for (j = 0; j < path->pin_nums; j++) {
4043                         if (wsum->inamp_cap) {
4044                                 (void) audioha_codec_4bit_verb_get(statep,
4045                                     caddr,
4046                                     wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4047                                     AUDIOHDC_AMP_SET_LR_INPUT |
4048                                     AUDIOHDC_GAIN_MAX |
4049                                     (path->sum_selconn[j] <<
4050                                     AUDIOHDC_AMP_SET_INDEX_OFFSET));
4051                         }
4052                         if (wsum->type == WTYPE_AUDIO_SEL) {
4053                                 (void) audioha_codec_verb_get(statep, caddr,
4054                                     wsum->wid_wid,
4055                                     AUDIOHDC_VERB_SET_CONN_SEL,
4056                                     path->sum_selconn[j]);
4057                         }
4058 
4059                         wid = wsum->avail_conn[path->sum_selconn[j]];
4060                         w = path->codec->widget[wid];
4061                         while (w && w->type != WTYPE_PIN) {
4062                                 if ((w->type != WTYPE_AUDIO_MIX) &&
4063                                     (w->nconns > 1))
4064                                         (void) audioha_codec_verb_get(statep,
4065                                             caddr, w->wid_wid,
4066                                             AUDIOHDC_VERB_SET_CONN_SEL,
4067                                             w->input_path_next);
4068 
4069                                 if (w->outamp_cap) {
4070                                         (void) audioha_codec_4bit_verb_get(
4071                                             statep,
4072                                             caddr,
4073                                             w->wid_wid,
4074                                             AUDIOHDC_VERB_SET_AMP_MUTE,
4075                                             AUDIOHDC_AMP_SET_LR_OUTPUT |
4076                                             AUDIOHDC_GAIN_MAX);
4077                                 }
4078 
4079                                 if (w->inamp_cap) {
4080                                         (void) audioha_codec_4bit_verb_get(
4081                                             statep,
4082                                             caddr,
4083                                             w->wid_wid,
4084                                             AUDIOHDC_VERB_SET_AMP_MUTE,
4085                                             AUDIOHDC_AMP_SET_LR_INPUT |
4086                                             AUDIOHDC_GAIN_MAX |
4087                                             (w->input_path_next <<
4088                                             AUDIOHDC_AMP_SET_INDEX_OFFSET));
4089                                 }
4090                                 wid = w->avail_conn[w->input_path_next];
4091                                 w = path->codec->widget[wid];
4092                         }
4093                 }
4094         }       /* end of istream loop */
4095 }       /* audiohd_finish_input_path */
4096 
4097 /*
4098  * audiohd_find_inpin_for_monitor()
4099  *
4100  * Description:
4101  *      Find input pin for monitor path.
4102  *
4103  * Arguments:
4104  *      hda_codec_t             *codec          where the monitor path exists
4105  *      wid_t                   id              no. of widget being searched
4106  *      int                     mixer           share or not
4107  */
4108 static int
4109 audiohd_find_inpin_for_monitor(hda_codec_t *codec, wid_t id, int mixer)
4110 {
4111         wid_t                   wid;
4112         audiohd_widget_t        *widget, *w;
4113         audiohd_pin_t           *pin;
4114         int                     i, find = 0;
4115 
4116         wid = id;
4117         widget = codec->widget[wid];
4118         if (widget == NULL)
4119                 return (uint32_t)(DDI_FAILURE);
4120 
4121         if (widget->type == WTYPE_PIN) {
4122                 pin = (audiohd_pin_t *)widget->priv;
4123                 if (pin->no_phys_conn)
4124                         return (uint32_t)(DDI_FAILURE);
4125                 switch (pin->device) {
4126                         case DTYPE_SPDIF_IN:
4127                         case DTYPE_CD:
4128                         case DTYPE_LINE_IN:
4129                         case DTYPE_MIC_IN:
4130                         case DTYPE_AUX:
4131                                 widget->path_flags |= AUDIOHD_PATH_MON;
4132                                 return (DDI_SUCCESS);
4133                         default:
4134                                 return (uint32_t)(DDI_FAILURE);
4135                 }
4136         }
4137         /* the widget has been visited and can't be directed to input pin */
4138         if (widget->path_flags & AUDIOHD_PATH_NOMON) {
4139                 return (uint32_t)(DDI_FAILURE);
4140         }
4141         /* the widget has been used by the monitor path, and we can share it */
4142         if (widget->path_flags & AUDIOHD_PATH_MON) {
4143                 if (mixer)
4144                         return (DDI_SUCCESS);
4145                 else
4146                         return (uint32_t)(DDI_FAILURE);
4147         }
4148         switch (widget->type) {
4149                 case WTYPE_AUDIO_MIX:
4150                         for (i = 0; i < widget->nconns; i++) {
4151                                 if (widget->output_path_next == i)
4152                                         continue;
4153                                 if (audiohd_find_inpin_for_monitor(codec,
4154                                     widget->avail_conn[i], mixer) ==
4155                                     DDI_SUCCESS) {
4156                                         w = widget;
4157                                         w->monitor_path_next[w->used++] = i;
4158                                         w->path_flags |= AUDIOHD_PATH_MON;
4159                                         find = 1;
4160                                 }
4161                         }
4162                         break;
4163                 case WTYPE_AUDIO_SEL:
4164                         for (i = 0; i < widget->nconns; i++) {
4165                                 if (widget->output_path_next == i)
4166                                         continue;
4167                                 if (audiohd_find_inpin_for_monitor(codec,
4168                                     widget->avail_conn[i], mixer) ==
4169                                     DDI_SUCCESS) {
4170                                         widget->monitor_path_next[0] = i;
4171                                         widget->path_flags |= AUDIOHD_PATH_MON;
4172                                         find = 1;
4173                                         break;
4174                                 }
4175                         }
4176                         break;
4177                 default:
4178                         break;
4179         }
4180         if (!find) {
4181                 widget->path_flags |= AUDIOHD_PATH_NOMON;
4182                 return (uint32_t)(DDI_FAILURE);
4183         }
4184         else
4185                 return (DDI_SUCCESS);
4186 }       /* audiohd_find_inpin_for_monitor */
4187 
4188 /*
4189  * audiohd_build_monitor_path()
4190  *
4191  * Description:
4192  *      The functionality of mixer is to mix inputs, such as CD-IN, MIC,
4193  *      Line-in, etc, with DAC outputs, so as to minitor what is being
4194  *      recorded and implement "What you hear is what you get". However,
4195  *      this functionality are really hardware-dependent: the inputs
4196  *      must be directed to MIXER if they can be directed to ADC as
4197  *      recording sources.
4198  */
4199 static void
4200 audiohd_build_monitor_path(hda_codec_t *codec)
4201 {
4202         audiohd_path_t          *path;
4203         audiohd_widget_t        *widget, *w;
4204         audiohd_state_t         *statep = codec->statep;
4205         wid_t                   wid, next;
4206         int                     i, j, k, l, find;
4207         int                     mixernum = 0;
4208 
4209         for (i = 0; i < statep->pathnum; i++) {
4210                 path = statep->path[i];
4211                 if (path == NULL || path->codec != codec ||
4212                     path->path_type != PLAY)
4213                         continue;
4214                 for (j = 0; j < path->pin_nums; j++) {
4215                         wid = path->pin_wid[j];
4216                         widget = codec->widget[wid];
4217                         l = 0;
4218                         while (widget) {
4219                                 while (widget &&
4220                                     ((widget->type != WTYPE_AUDIO_MIX) ||
4221                                     (widget->nconns < 2))) {
4222                                         next = widget->output_path_next;
4223                                         if (next == AUDIOHD_NULL_CONN)
4224                                                 break;
4225                                         wid = widget->avail_conn[next];
4226                                         widget = codec->widget[wid];
4227                                 }
4228 
4229                                 /*
4230                                  * No mixer in this output path, we cannot build
4231                                  * mixer path for this path, skip it,
4232                                  * and continue for next output path.
4233                                  */
4234                                 if (widget == NULL ||
4235                                     widget->output_path_next ==
4236                                     AUDIOHD_NULL_CONN) {
4237                                         break;
4238                                 }
4239                                 mixernum++;
4240                                 for (k = 0; k < widget->nconns; k++) {
4241 
4242                                         /*
4243                                          * this connection must be routined
4244                                          * to DAC instead of an input pin
4245                                          * widget, we needn't waste time for
4246                                          * it
4247                                          */
4248                                         if (widget->output_path_next == k)
4249                                                 continue;
4250                                         find = 0;
4251                                         if (audiohd_find_inpin_for_monitor(
4252                                             codec,
4253                                             widget->avail_conn[k], 0) ==
4254                                             DDI_SUCCESS) {
4255                                                 path->mon_wid[j][l] = wid;
4256                                                 w = widget;
4257                                                 w->monitor_path_next[w->used++]
4258                                                     = k;
4259                                                 w->path_flags |=
4260                                                     AUDIOHD_PATH_MON;
4261                                                 find = 1;
4262                                         } else if (
4263                                             audiohd_find_inpin_for_monitor(
4264                                             codec,
4265                                             widget->avail_conn[k], 1) ==
4266                                             DDI_SUCCESS) {
4267                                                 path->mon_wid[j][l] = wid;
4268                                                 w = widget;
4269                                                 w->monitor_path_next[w->used++]
4270                                                     = k;
4271                                                 w->path_flags |=
4272                                                     AUDIOHD_PATH_MON;
4273                                                 find = 1;
4274                                         }
4275 
4276                                 }
4277 
4278                                 /*
4279                                  * we needn't check widget->output_path_next
4280                                  * here since this widget is a selector or
4281                                  * mixer, it cannot be NULL connection.
4282                                  */
4283                                 if (!find) {
4284                                         path->mon_wid[j][l] = 0;
4285                                         widget->path_flags |=
4286                                             AUDIOHD_PATH_NOMON;
4287                                 }
4288                                 next = widget->output_path_next;
4289                                 wid = widget->avail_conn[next];
4290                                 widget = codec->widget[wid];
4291                                 l++;
4292                         }
4293                         path->maxmixer[j] = l;
4294                 }
4295 
4296         }
4297         if (mixernum == 0)
4298                 statep->monitor_supported = B_FALSE;
4299         else
4300                 statep->monitor_supported = B_TRUE;
4301 }       /* audiohd_build_monitor_path */
4302 
4303 /*
4304  * audiohd_do_finish_monitor_path
4305  *
4306  * Description:
4307  *      Enable the widgets on the monitor path
4308  */
4309 static void
4310 audiohd_do_finish_monitor_path(hda_codec_t *codec, audiohd_widget_t *wgt)
4311 {
4312         uint_t                  caddr = codec->index;
4313         audiohd_widget_t        *widget = wgt;
4314         audiohd_widget_t        *w;
4315         audiohd_state_t         *statep = codec->statep;
4316         wid_t                   wid;
4317         int                     i;
4318         int                     share = 0;
4319 
4320         if (!widget || widget->finish)
4321                 return;
4322         if (widget->path_flags & AUDIOHD_PATH_ADC)
4323                 share = 1;
4324         if ((widget->outamp_cap) && !share)
4325                 (void) audioha_codec_4bit_verb_get(statep, caddr,
4326                     widget->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4327                     AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX);
4328         if ((widget->inamp_cap) && !share) {
4329                 for (i = 0; i < widget->used; i++) {
4330                 (void) audioha_codec_4bit_verb_get(statep, caddr,
4331                     widget->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4332                     AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX |
4333                     (widget->monitor_path_next[i]
4334                     << AUDIOHDC_AMP_SET_INDEX_OFFSET));
4335                 }
4336         }
4337         if ((widget->type == WTYPE_AUDIO_SEL) && (widget->nconns > 1) &&
4338             !share) {
4339                 (void) audioha_codec_verb_get(statep, caddr, widget->wid_wid,
4340                     AUDIOHDC_VERB_SET_CONN_SEL, widget->monitor_path_next[0]);
4341         }
4342         widget->finish = 1;
4343         if (widget->used == 0)
4344                 return;
4345         if (widget->used > 0) {
4346                 for (i = 0; i < widget->used; i++) {
4347                         wid = widget->avail_conn[widget->monitor_path_next[i]];
4348                         w = codec->widget[wid];
4349                         audiohd_do_finish_monitor_path(codec, w);
4350                 }
4351         }
4352 }       /* audiohd_do_finish_monitor_path */
4353 
4354 /*
4355  * audiohd_finish_monitor_path
4356  *
4357  * Description:
4358  *      Enable the monitor path for every ostream path
4359  */
4360 static void
4361 audiohd_finish_monitor_path(hda_codec_t *codec)
4362 {
4363         audiohd_path_t          *path;
4364         audiohd_widget_t        *widget;
4365         audiohd_state_t         *statep = codec->statep;
4366         wid_t                   wid;
4367         int                     i, j, k;
4368 
4369         for (i = 0; i < statep->pathnum; i++) {
4370                 path = statep->path[i];
4371                 if (!path || path->codec != codec || path->path_type != PLAY)
4372                         continue;
4373                 for (j = 0; j < path->pin_nums; j++) {
4374                         for (k = 0; k < path->maxmixer[j]; k++) {
4375                                 wid = path->mon_wid[j][k];
4376                                 if (wid == 0) {
4377                                         continue;
4378                                 }
4379                                 widget = codec->widget[wid];
4380                                 audiohd_do_finish_monitor_path(codec, widget);
4381                         }
4382                 }
4383         }
4384 }       /* audiohd_finish_monitor_path */
4385 
4386 /*
4387  * audiohd_do_build_monit_amp()
4388  *
4389  * Description:
4390  *      Search for the gain control widget for the monitor path
4391  */
4392 static void
4393 audiohd_do_build_monitor_amp(hda_codec_t *codec, audiohd_pin_t *pin,
4394     audiohd_widget_t *widget)
4395 {
4396         audiohd_widget_t        *w = widget;
4397         uint32_t                gain;
4398         int                     i;
4399         wid_t                   wid;
4400 
4401         if (!w ||
4402             (w->type == WTYPE_PIN) ||
4403             !w->used ||
4404             (pin->num == AUDIOHD_MAX_CONN) ||
4405             (w->path_flags & AUDIOHD_PATH_ADC))
4406                 return;
4407         if (!(w->path_flags & AUDIOHD_PATH_DAC)) {
4408                 gain = w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
4409                 if (gain) {
4410                         pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_OUTPUT;
4411                         pin->mg_gain[pin->num] = gain;
4412                         pin->mg_wid[pin->num] = w->wid_wid;
4413                         pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF;
4414                         pin->num++;
4415                         return;
4416                 }
4417                 gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
4418                 if (gain) {
4419                         pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_INPUT;
4420                         pin->mg_gain[pin->num] = gain;
4421                         pin->mg_wid[pin->num] = w->wid_wid;
4422                         pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF;
4423                         pin->num++;
4424                         return;
4425                 }
4426         }
4427         for (i = 0; i < w->used; i++) {
4428                 wid = w->avail_conn[w->monitor_path_next[i]];
4429                 audiohd_do_build_monitor_amp(codec, pin, codec->widget[wid]);
4430         }
4431 
4432 
4433 }       /* audiohd_do_build_monitor_amp() */
4434 
4435 /*
4436  * audiohd_build_monitor_amp()
4437  *
4438  * Description:
4439  *      Search gain control widget for every ostream monitor
4440  */
4441 static void
4442 audiohd_build_monitor_amp(hda_codec_t *codec)
4443 {
4444         audiohd_path_t          *path;
4445         audiohd_widget_t        *widget, *w;
4446         audiohd_state_t         *statep = codec->statep;
4447         audiohd_pin_t           *pin;
4448         wid_t                   wid, id;
4449         int                     i, j, k;
4450 
4451         for (i = 0; i < statep->pathnum; i++) {
4452                 path = statep->path[i];
4453                 if (!path || path->codec != codec || path->path_type != PLAY)
4454                         continue;
4455                 for (j = 0; j < path->pin_nums; j++) {
4456                         id = path->pin_wid[j];
4457                         w = codec->widget[id];
4458                         pin = (audiohd_pin_t *)(w->priv);
4459                         for (k = 0; k < path->maxmixer[j]; k++) {
4460                                 wid = path->mon_wid[j][k];
4461                                 if (!wid)
4462                                         continue;
4463                                 widget = codec->widget[wid];
4464                                 audiohd_do_build_monitor_amp(codec, pin,
4465                                     widget);
4466                         }
4467                 }
4468         }
4469 }
4470 
4471 /*
4472  * audiohd_find_beep()
4473  * Description:
4474  *      Find a beep for a beep path. Then the play data can be sent to the out
4475  *      put pin through the beep path.
4476  *
4477  * Arguments:
4478  *      hda_codec_t     *codec          where the beep widget exists
4479  *      wid_t           wid             the no. of a widget
4480  *      int             depth           the depth of search
4481  *
4482  * Return:
4483  *      1) wid of Beep widget;
4484  *      2) 0 if no path
4485  */
4486 static wid_t
4487 audiohd_find_beep(hda_codec_t *codec, wid_t wid, int depth)
4488 {
4489         audiohd_widget_t        *widget = codec->widget[wid];
4490         wid_t                   wbeep = (uint32_t)(DDI_FAILURE);
4491         wid_t                   retval;
4492 
4493         if (depth > AUDIOHD_MAX_DEPTH)
4494                 return (uint32_t)(DDI_FAILURE);
4495 
4496         if (widget == NULL)
4497                 return (uint32_t)(DDI_FAILURE);
4498 
4499         switch (widget->type) {
4500         case WTYPE_BEEP:
4501                 widget->path_flags |= AUDIOHD_PATH_BEEP;
4502                 wbeep = widget->wid_wid;
4503                 break;
4504         case WTYPE_AUDIO_MIX:
4505         case WTYPE_AUDIO_SEL:
4506                 for (int i = 0; i < widget->nconns; i++) {
4507                         retval = audiohd_find_beep(codec,
4508                             widget->avail_conn[i], depth + 1);
4509                         if (retval == DDI_SUCCESS) {
4510                                 if (widget->output_path_next !=
4511                                     AUDIOHD_NULL_CONN)
4512                                         continue;
4513                                 widget->beep_path_next = i;
4514                                 wbeep = retval;
4515                                 widget->path_flags |= AUDIOHD_PATH_BEEP;
4516                                 return (wbeep);
4517                         }
4518                 }
4519                 break;
4520         default:
4521                 break;
4522         }
4523 
4524         return (wbeep);
4525 }       /* audiohd_find_beep() */
4526 
4527 /*
4528  * audiohd_build_beep_path()
4529  *
4530  * Description:
4531  *      Search an beep path for each pin in the codec.
4532  * Arguments:
4533  *      hda_codec_t     *codec          where the beep path exists
4534  */
4535 static void
4536 audiohd_build_beep_path(hda_codec_t *codec)
4537 {
4538         audiohd_pin_t           *pin;
4539         audiohd_widget_t        *widget;
4540         audiohd_path_t          *path;
4541         wid_t                   wid;
4542         audiohd_state_t         *statep;
4543         int                     i;
4544         boolean_t               beeppath = B_FALSE;
4545 
4546         statep = codec->statep;
4547 
4548         for (pin = codec->first_pin; pin; pin = pin->next) {
4549                 if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
4550                         continue;
4551                 if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
4552                     AUDIOHD_PIN_NO_CONN)
4553                         continue;
4554                 if ((pin->device != DTYPE_LINEOUT) &&
4555                     (pin->device != DTYPE_SPEAKER) &&
4556                     (pin->device != DTYPE_SPDIF_OUT) &&
4557                     (pin->device != DTYPE_HP_OUT))
4558                         continue;
4559                 widget = codec->widget[pin->wid];
4560 
4561                 widget->inamp_cap = 0;
4562                 for (i = 0; i < widget->nconns; i++) {
4563                         /*
4564                          * If a beep found, the return value is the wid of the
4565                          * widget on the path, or the return value is
4566                          * DDI_FAILURE
4567                          */
4568                         wid = audiohd_find_beep(codec,
4569                             widget->avail_conn[i], 0);
4570                         /*
4571                          * A beep was not found
4572                          */
4573                         if (wid == (wid_t)DDI_FAILURE)
4574                                 continue;
4575                         if (widget->output_path_next != AUDIOHD_NULL_CONN)
4576                                 continue;
4577                         path = (audiohd_path_t *)
4578                             kmem_zalloc(sizeof (audiohd_path_t),
4579                             KM_SLEEP);
4580                         path->beep_wid = wid;
4581                         path->pin_wid[0] = widget->wid_wid;
4582                         path->pin_nums = 1;
4583                         path->path_type = BEEP;
4584                         beeppath = 1;
4585                         path->codec = codec;
4586                         path->statep = statep;
4587                         widget->path_flags |= AUDIOHD_PATH_BEEP;
4588                         widget->beep_path_next = i;
4589                         statep->path[statep->pathnum++] = path;
4590                         break;
4591                 }
4592         }
4593 
4594         if (!beeppath) {
4595                 for (int i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4596                         codec = statep->codec[i];
4597                         if (codec == NULL)
4598                                 continue;
4599                         for (wid = codec->first_wid; wid <= codec->last_wid;
4600                             wid++) {
4601                                 widget = codec->widget[wid];
4602 
4603                                 if (widget->type == WTYPE_BEEP) {
4604                                         path = (audiohd_path_t *)
4605                                             kmem_zalloc(sizeof (audiohd_path_t),
4606                                             KM_SLEEP);
4607                                         path->beep_wid = wid;
4608                                         path->pin_nums = 0;
4609                                         path->path_type = BEEP;
4610                                         beeppath = 1;
4611                                         path->codec = codec;
4612                                         path->statep = statep;
4613                                         widget->path_flags |= AUDIOHD_PATH_BEEP;
4614                                         statep->path[statep->pathnum++] = path;
4615                                         break;
4616                                 }
4617                         }
4618                 }
4619         }
4620 }       /* audiohd_build_beep_path() */
4621 
4622 /*
4623  * audiohd_build_beep_amp
4624  *
4625  * Description:
4626  *      Find the gain control and mute control widget
4627  */
4628 static void
4629 audiohd_build_beep_amp(hda_codec_t *codec)
4630 {
4631         audiohd_path_t          *path;
4632         audiohd_widget_t        *widget, *wpin, *wbeep;
4633         wid_t                   wid, next;
4634         int                     i, j;
4635         uint32_t                gain;
4636 
4637         for (i = 0; i < codec->statep->pathnum; i++) {
4638                 path = codec->statep->path[i];
4639                 if (path == NULL || path->path_type != BEEP ||
4640                     path->codec != codec)
4641                         continue;
4642                 if (path->pin_nums == 0) {
4643                         path->mute_wid = path->beep_wid;
4644                         path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
4645                         wbeep = codec->widget[path->beep_wid];
4646                         gain = (wbeep->outamp_cap &
4647                             AUDIOHDC_AMP_CAP_STEP_NUMS);
4648                         if (gain) {
4649                                 path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
4650                                 path->gain_bits = gain;
4651                                 path->gain_wid = path->beep_wid;
4652                         }
4653                         path->gain_bits >>= AUDIOHD_GAIN_OFF;
4654                         break;
4655                 }
4656                 for (j = 0; j < path->pin_nums; j++) {
4657                         wid = path->pin_wid[j];
4658                         wpin = codec->widget[wid];
4659                         wbeep = codec->widget[path->beep_wid];
4660 
4661                         widget = wpin;
4662                         while (widget) {
4663                                 if (widget->out_weight == 0 &&
4664                                     widget->outamp_cap &
4665                                     AUDIOHDC_AMP_CAP_MUTE_CAP) {
4666                                         path->mute_wid = widget->wid_wid;
4667                                         path->mute_dir =
4668                                             AUDIOHDC_AMP_SET_OUTPUT;
4669                                         break;
4670                                 }
4671                                 next = widget->beep_path_next;
4672                                 if (next == AUDIOHD_NULL_CONN)
4673                                         break;
4674                                 wid = widget->avail_conn[next];
4675                                 widget = codec->widget[wid];
4676                         }
4677 
4678                         gain = 0;
4679                         widget = wpin;
4680                         while (widget) {
4681                                 if (widget->out_weight == 0 &&
4682                                     widget->outamp_cap &
4683                                     AUDIOHDC_AMP_CAP_STEP_NUMS) {
4684                                         gain = (widget->outamp_cap &
4685                                             AUDIOHDC_AMP_CAP_STEP_NUMS);
4686                                         if (gain && gain > path->gain_bits) {
4687                                                 path->gain_dir =
4688                                                     AUDIOHDC_AMP_SET_OUTPUT;
4689                                                 path->gain_bits = gain;
4690                                                 path->gain_wid =
4691                                                     widget->wid_wid;
4692                                         }
4693                                 }
4694                                 next = widget->beep_path_next;
4695                                 if (next == AUDIOHD_NULL_CONN)
4696                                         break;
4697                                 wid = widget->avail_conn[next];
4698                                 widget = codec->widget[wid];
4699                         }
4700                         path->gain_bits >>= AUDIOHD_GAIN_OFF;
4701                 }
4702         }
4703 }       /* audiohd_build_beep_amp */
4704 
4705 /*
4706  * audiohd_finish_beep_path()
4707  *
4708  * Description:
4709  *      Enable the widgets on the beep path
4710  */
4711 static void
4712 audiohd_finish_beep_path(hda_codec_t *codec)
4713 {
4714         audiohd_state_t         *statep = codec->statep;
4715         audiohd_path_t          *path;
4716         audiohd_widget_t        *widget;
4717         uint_t                  caddr = codec->index;
4718         wid_t                   wid, next;
4719         int                     i, j;
4720 
4721         for (i = 0; i < codec->statep->pathnum; i++) {
4722                 path = codec->statep->path[i];
4723                 if (!path || path->path_type != BEEP || path->codec != codec)
4724                         continue;
4725                 if (path->pin_nums == 0) {
4726                         widget = codec->widget[path->beep_wid];
4727                         if (widget->outamp_cap) {
4728                                 (void) audioha_codec_4bit_verb_get(
4729                                     statep, caddr,
4730                                     path->beep_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4731                                     AUDIOHDC_AMP_SET_LR_OUTPUT |
4732                                     AUDIOHDC_GAIN_MAX);
4733                         }
4734                         if (widget->inamp_cap) {
4735                                 (void) audioha_codec_4bit_verb_get(
4736                                     statep, caddr,
4737                                     path->beep_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4738                                     AUDIOHDC_AMP_SET_LR_INPUT |
4739                                     AUDIOHDC_GAIN_MAX |
4740                                     (widget->beep_path_next <<
4741                                     AUDIOHDC_AMP_SET_INDEX_OFFSET));
4742                         }
4743                         continue;
4744                 }
4745 
4746                 for (j = 0; j < path->pin_nums; j++) {
4747                         wid = path->pin_wid[j];
4748                         widget = codec->widget[wid];
4749 
4750                         (void) audioha_codec_verb_get(statep, caddr, wid,
4751                             AUDIOHDC_VERB_SET_CONN_SEL, widget->beep_path_next);
4752 
4753                         wid = widget->avail_conn[widget->beep_path_next];
4754                         widget = codec->widget[wid];
4755 
4756                         while (widget) {
4757                                 /*
4758                                  * Set all amplifiers in this path to
4759                                  * the maximum volume and unmute them.
4760                                  */
4761                                 if (widget->out_weight != 0)
4762                                         continue;
4763                                 if (widget->outamp_cap) {
4764                                         (void) audioha_codec_4bit_verb_get(
4765                                             statep, caddr,
4766                                             wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4767                                             AUDIOHDC_AMP_SET_LR_OUTPUT |
4768                                             AUDIOHDC_GAIN_MAX);
4769                                 }
4770                                 if (widget->inamp_cap) {
4771                                         (void) audioha_codec_4bit_verb_get(
4772                                             statep, caddr,
4773                                             wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4774                                             AUDIOHDC_AMP_SET_LR_INPUT |
4775                                             AUDIOHDC_GAIN_MAX |
4776                                             (widget->beep_path_next <<
4777                                             AUDIOHDC_AMP_SET_INDEX_OFFSET));
4778                                 }
4779 
4780                                 next = widget->beep_path_next;
4781                                 if (next == AUDIOHD_NULL_CONN)
4782                                         break;
4783                                 /*
4784                                  * Accoding to HD spec, mixer doesn't support
4785                                  * "select connection"
4786                                  */
4787                                 if ((widget->type != WTYPE_AUDIO_MIX) &&
4788                                     (widget->nconns > 1))
4789                                         (void) audioha_codec_verb_get(statep,
4790                                             caddr, wid,
4791                                             AUDIOHDC_VERB_SET_CONN_SEL,
4792                                             widget->beep_path_next);
4793 
4794                                 wid = widget->avail_conn[next];
4795                                 widget = codec->widget[wid];
4796                         }
4797                 }
4798         }
4799 }       /* audiohd_finish_beep_path */
4800 
4801 static int
4802 audiohd_find_output_pins(hda_codec_t *codec, wid_t wid, int depth,
4803     audiohd_path_t *path)
4804 {
4805         audiohd_widget_t        *widget = codec->widget[wid];
4806         audiohd_pin_t           *pin = NULL;
4807         int                     num, retval = (DDI_FAILURE);
4808 
4809         if (depth > AUDIOHD_MAX_DEPTH)
4810                 return (retval);
4811         if (widget == NULL)
4812                 return (retval);
4813 
4814         switch (widget->type) {
4815         case WTYPE_PIN:
4816                 pin = (audiohd_pin_t *)widget->priv;
4817                 if (pin->no_phys_conn)
4818                         return (DDI_FAILURE);
4819 
4820                 switch (pin->device) {
4821                 case DTYPE_LINE_IN:
4822                         /* Connection between line-in and output pins */
4823                         path->pin_wid[path->pin_nums++] = wid;
4824                         break;
4825                 case DTYPE_LINEOUT:
4826                 case DTYPE_HP_OUT:
4827                 case DTYPE_SPDIF_OUT:
4828                         widget->path_flags |= AUDIOHD_PATH_LOOPBACK;
4829                         widget->in_weight++;
4830                         pin->adc_wid = path->adda_wid;
4831                         path->pin_wid[path->pin_nums++] = wid;
4832                         retval = (DDI_SUCCESS);
4833                         break;
4834                 default:
4835                         break;
4836                 }
4837                 break;
4838         case WTYPE_AUDIO_MIX:
4839         case WTYPE_AUDIO_SEL:
4840                 /*
4841                  * If the sum widget has only one input, we don't
4842                  * consider it as a real sum widget.
4843                  */
4844                 if (widget->nconns == 1) {
4845                         widget->loopback_path_next = 0;
4846                         retval = audiohd_find_output_pins(codec,
4847                             widget->avail_conn[0], depth + 1, path);
4848                         if (retval == (DDI_SUCCESS)) {
4849                                 widget->path_flags |= AUDIOHD_PATH_LOOPBACK;
4850                                 widget->in_weight++;
4851                         }
4852                         break;
4853                 }
4854 
4855                 for (int i = 0; i < widget->nconns; i++) {
4856                         retval = audiohd_find_output_pins(codec,
4857                             widget->avail_conn[i], depth + 1, path);
4858                         if (retval == (DDI_SUCCESS)) {
4859                                 widget->loopback_path_next = i;
4860                                 widget->in_weight++;
4861                                 num = path->pin_nums - 1;
4862                                 path->sum_selconn[num] = i;
4863                                 path->sum_wid = wid;
4864                                 widget->path_flags |= AUDIOHD_PATH_LOOPBACK;
4865                                 break;
4866                         }
4867                 }
4868                 break;
4869         default:
4870                 break;
4871         }
4872 
4873         return (retval);
4874 }
4875 
4876 static void
4877 audiohd_build_loopback_path(hda_codec_t *codec)
4878 {
4879         audiohd_state_t         *statep = codec->statep;
4880         audiohd_widget_t        *widget;
4881         audiohd_path_t          *path = NULL;
4882         wid_t                   wid;
4883         int                     i, retval;
4884         uint8_t                 rtag = 0;
4885 
4886         for (wid = codec->first_wid; wid <= codec->last_wid; wid++) {
4887                 widget = codec->widget[wid];
4888 
4889                 /* check if it is an ADC widget */
4890                 if (widget == NULL || widget->type != WTYPE_AUDIO_IN)
4891                         continue;
4892 
4893                 if (path == NULL)
4894                         path = kmem_zalloc(sizeof (audiohd_path_t), KM_SLEEP);
4895                 else
4896                         bzero(path, sizeof (audiohd_port_t));
4897                 path->adda_wid = wid;
4898 
4899                 for (i = 0; i < widget->nconns; i++) {
4900                         retval = audiohd_find_output_pins(codec,
4901                             widget->avail_conn[i], 0, path);
4902                         if (retval == (DDI_SUCCESS)) {
4903                                 path->codec = codec;
4904                                 path->statep = statep;
4905                                 path->path_type = LOOPBACK;
4906                                 path->tag = ++rtag;
4907                                 codec->nistream++;
4908                                 statep->path[statep->pathnum++] = path;
4909                                 widget->loopback_path_next = i;
4910                                 widget->priv = path;
4911                                 path = NULL;
4912                                 statep->loopback_supported = B_TRUE;
4913                                 break;
4914                         }
4915                 }
4916         }
4917 
4918 
4919         if (path)
4920                 kmem_free(path, sizeof (audiohd_path_t));
4921 }       /* audiohd_build_loopback_path() */
4922 
4923 /*
4924  * audiohd_build_path()
4925  *
4926  * Description:
4927  *      Here we build the output, input, monitor path.
4928  *      And also enable the path in default.
4929  *      Search for the gain and mute control for the path
4930  */
4931 static void
4932 audiohd_build_path(audiohd_state_t *statep)
4933 {
4934         int             i;
4935 
4936         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4937                 if (statep->codec[i]) {
4938                         audiohd_build_output_path(statep->codec[i]);
4939                         audiohd_build_output_amp(statep->codec[i]);
4940                         audiohd_finish_output_path(statep->codec[i]);
4941 
4942                         audiohd_build_input_path(statep->codec[i]);
4943                         audiohd_build_input_amp(statep->codec[i]);
4944                         audiohd_finish_input_path(statep->codec[i]);
4945 
4946                         audiohd_build_monitor_path(statep->codec[i]);
4947                         audiohd_build_monitor_amp(statep->codec[i]);
4948                         audiohd_finish_monitor_path(statep->codec[i]);
4949 
4950                         audiohd_build_beep_path(statep->codec[i]);
4951                         audiohd_build_beep_amp(statep->codec[i]);
4952                         audiohd_finish_beep_path(statep->codec[i]);
4953 
4954                         audiohd_build_loopback_path(statep->codec[i]);
4955                 }
4956         }
4957 }       /* audiohd_build_path */
4958 
4959 /*
4960  * audiohd_allocate_port()
4961  */
4962 static int
4963 audiohd_allocate_port(audiohd_state_t *statep)
4964 {
4965         int                     i, j;
4966         audiohd_port_t          *port;
4967         int                     dir;
4968         unsigned                caps;
4969         int                     rc;
4970         audio_dev_t             *adev;
4971         dev_info_t              *dip;
4972         ddi_dma_cookie_t        cookie;
4973         uint_t                  count;
4974         uint64_t                buf_phys_addr;
4975         sd_bdle_t               *entry;
4976         uint16_t                gcap;
4977         size_t                  real_size;
4978 
4979         adev = statep->adev;
4980         dip = statep->hda_dip;
4981 
4982         ddi_dma_attr_t  dma_attr = {
4983                 DMA_ATTR_V0,            /* version */
4984                 0,                      /* addr_lo */
4985                 0xffffffffffffffffULL,  /* addr_hi */
4986                 0x00000000ffffffffULL,  /* count_max */
4987                 128,                    /* 128-byte alignment as HD spec */
4988                 0xfff,                  /* burstsize */
4989                 1,                      /* minxfer */
4990                 0xffffffff,             /* maxxfer */
4991                 0xffffffff,             /* seg */
4992                 1,                      /* sgllen */
4993                 1,                      /* granular */
4994                 0                       /* flags */
4995         };
4996 
4997         gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP);
4998         if ((gcap & AUDIOHDR_GCAP_64OK) == 0)
4999                 dma_attr.dma_attr_addr_hi = 0xffffffffUL;
5000 
5001         for (i = 0; i < PORT_MAX; i++) {
5002                 port = kmem_zalloc(sizeof (*port), KM_SLEEP);
5003                 statep->port[i] = port;
5004                 port->statep = statep;
5005                 switch (i) {
5006                 case PORT_ADC:
5007                         dir = DDI_DMA_READ | DDI_DMA_CONSISTENT;
5008                         caps = ENGINE_INPUT_CAP;
5009                         port->sync_dir = DDI_DMA_SYNC_FORKERNEL;
5010                         port->nchan = statep->rchan;
5011                         port->index = 1;
5012                         port->regoff = AUDIOHD_REG_SD_BASE;
5013                         break;
5014                 case PORT_DAC:
5015                         dir = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
5016                         caps = ENGINE_OUTPUT_CAP;
5017                         port->sync_dir = DDI_DMA_SYNC_FORDEV;
5018                         port->nchan = statep->pchan;
5019                         port->index = statep->hda_input_streams + 1;
5020                         port->regoff = AUDIOHD_REG_SD_BASE +
5021                             AUDIOHD_REG_SD_LEN *
5022                             statep->hda_input_streams;
5023                         break;
5024                 default:
5025                         return (DDI_FAILURE);
5026                 }
5027 
5028                 switch (statep->sample_rate) {
5029                 case 192000:
5030                         port->format = 0x18 << 4;
5031                         break;
5032                 case 96000:
5033                         port->format = 0x08 << 4;
5034                         break;
5035                 case 48000:
5036                 default: /* 48kHz is default */
5037                         port->format = 0x00;
5038                         break;
5039                 }
5040 
5041                 switch (statep->sample_bit_depth) {
5042                 case AUDIOHD_BIT_DEPTH24:
5043                         port->format |= 0x3;
5044                         statep->sample_packed_bytes = 4;
5045                         break;
5046                 case AUDIOHD_BIT_DEPTH16:
5047                 default: /* 16 bits is default */
5048                         port->format |= 0x1;
5049                         statep->sample_packed_bytes = 2;
5050                         break;
5051                 }
5052 
5053                 port->nframes = 1024 * AUDIOHD_BDLE_NUMS *
5054                     statep->sample_rate / 48000;
5055                 port->fragsize = 1024 * port->nchan *
5056                     statep->sample_packed_bytes *
5057                     statep->sample_rate / 48000;
5058                 port->bufsize = port->nframes * port->nchan *
5059                     statep->sample_packed_bytes;
5060 
5061                 /* allocate dma handle */
5062                 rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP,
5063                     NULL, &port->samp_dmah);
5064                 if (rc != DDI_SUCCESS) {
5065                         audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d",
5066                             rc);
5067                         return (DDI_FAILURE);
5068                 }
5069 
5070                 /*
5071                  * Warning: please be noted that allocating the dma memory
5072                  * with the flag IOMEM_DATA_UNCACHED is a hack due
5073                  * to an incorrect cache synchronization on NVidia MCP79
5074                  * chipset which causes the audio distortion problem,
5075                  * and that it should be fixed later. There should be
5076                  * no reason you have to allocate UNCACHED memory. In
5077                  * complex architectures with nested IO caches,
5078                  * reliance on this flag might lead to failure.
5079                  */
5080                 rc = ddi_dma_mem_alloc(port->samp_dmah, port->bufsize,
5081                     &hda_dev_accattr, DDI_DMA_CONSISTENT | IOMEM_DATA_UNCACHED,
5082                     DDI_DMA_SLEEP, NULL, &port->samp_kaddr,
5083                     &real_size, &port->samp_acch);
5084                 if (rc == DDI_FAILURE) {
5085                         if (ddi_dma_mem_alloc(port->samp_dmah, port->bufsize,
5086                             &hda_dev_accattr, DDI_DMA_CONSISTENT,
5087                             DDI_DMA_SLEEP, NULL,
5088                             &port->samp_kaddr, &real_size,
5089                             &port->samp_acch) != DDI_SUCCESS) {
5090                                 audio_dev_warn(adev,
5091                                     "ddi_dma_mem_alloc failed");
5092                                 return (DDI_FAILURE);
5093                         }
5094                 }
5095 
5096                 /* bind DMA buffer */
5097                 rc = ddi_dma_addr_bind_handle(port->samp_dmah, NULL,
5098                     port->samp_kaddr, real_size, dir,
5099                     DDI_DMA_SLEEP, NULL, &cookie, &count);
5100                 if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
5101                         audio_dev_warn(adev,
5102                             "ddi_dma_addr_bind_handle failed: %d", rc);
5103                         return (DDI_FAILURE);
5104                 }
5105                 port->samp_paddr = (uint64_t)cookie.dmac_laddress;
5106 
5107                 /*
5108                  * now, from here we allocate DMA
5109                  * memory for buffer descriptor list.
5110                  * we allocate adjacent DMA memory for all DMA engines.
5111                  */
5112                 rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP,
5113                     NULL, &port->bdl_dmah);
5114                 if (rc != DDI_SUCCESS) {
5115                         audio_dev_warn(adev,
5116                             "ddi_dma_alloc_handle(bdlist) failed");
5117                         return (DDI_FAILURE);
5118                 }
5119 
5120                 /*
5121                  * we allocate all buffer descriptors lists in continuous
5122                  * dma memory.
5123                  */
5124                 port->bdl_size = sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS;
5125                 rc = ddi_dma_mem_alloc(port->bdl_dmah, port->bdl_size,
5126                     &hda_dev_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
5127                     &port->bdl_kaddr, &real_size, &port->bdl_acch);
5128                 if (rc != DDI_SUCCESS) {
5129                         audio_dev_warn(adev,
5130                             "ddi_dma_mem_alloc(bdlist) failed");
5131                         return (DDI_FAILURE);
5132                 }
5133 
5134                 rc = ddi_dma_addr_bind_handle(port->bdl_dmah, NULL,
5135                     port->bdl_kaddr,
5136                     real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
5137                     DDI_DMA_SLEEP,
5138                     NULL, &cookie, &count);
5139                 if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
5140                         audio_dev_warn(adev, "addr_bind_handle failed");
5141                         return (DDI_FAILURE);
5142                 }
5143                 port->bdl_paddr = (uint64_t)cookie.dmac_laddress;
5144 
5145                 entry = (sd_bdle_t *)port->bdl_kaddr;
5146                 buf_phys_addr = port->samp_paddr;
5147 
5148                 for (j = 0; j < AUDIOHD_BDLE_NUMS; j++) {
5149                         entry->sbde_addr = buf_phys_addr;
5150                         entry->sbde_len = port->fragsize;
5151                         entry->sbde_ioc = 1;
5152                         buf_phys_addr += port->fragsize;
5153                         entry++;
5154                 }
5155                 (void) ddi_dma_sync(port->bdl_dmah, 0, sizeof (sd_bdle_t) *
5156                     AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV);
5157                 port->curpos = 0;
5158 
5159                 port->engine = audio_engine_alloc(&audiohd_engine_ops, caps);
5160                 if (port->engine == NULL) {
5161                         return (DDI_FAILURE);
5162                 }
5163 
5164                 audio_engine_set_private(port->engine, port);
5165                 audio_dev_add_engine(adev, port->engine);
5166         }
5167 
5168         return (DDI_SUCCESS);
5169 }
5170 
5171 static void
5172 audiohd_free_port(audiohd_state_t *statep)
5173 {
5174         int                     i;
5175         audiohd_port_t          *port;
5176 
5177         for (i = 0; i < PORT_MAX; i++) {
5178                 port = statep->port[i];
5179                 if (port == NULL)
5180                         continue;
5181                 if (port->engine) {
5182                         audio_dev_remove_engine(statep->adev,
5183                             port->engine);
5184                         audio_engine_free(port->engine);
5185                 }
5186                 if (port->samp_dmah) {
5187                         (void) ddi_dma_unbind_handle(port->samp_dmah);
5188                 }
5189                 if (port->samp_acch) {
5190                         ddi_dma_mem_free(&port->samp_acch);
5191                 }
5192                 if (port->samp_dmah) {
5193                         ddi_dma_free_handle(&port->samp_dmah);
5194                 }
5195                 if (port->bdl_dmah) {
5196                         (void) ddi_dma_unbind_handle(port->bdl_dmah);
5197                 }
5198                 if (port->bdl_acch) {
5199                         ddi_dma_mem_free(&port->bdl_acch);
5200                 }
5201                 if (port->bdl_dmah) {
5202                         ddi_dma_free_handle(&port->bdl_dmah);
5203                 }
5204 
5205                 kmem_free(port, sizeof (audiohd_port_t));
5206         }
5207 }
5208 
5209 /*
5210  * audiohd_change_widget_power_state(audiohd_state_t *statep, int state)
5211  * Description:
5212  *      This routine is used to change the widget power betwen D0 and D2.
5213  *      D0 is fully on; D2 allows the lowest possible power consuming state
5214  *      from which it can return to the fully on state: D0.
5215  */
5216 static void
5217 audiohd_change_widget_power_state(audiohd_state_t *statep, int state)
5218 {
5219         int                     i;
5220         wid_t                   wid;
5221         hda_codec_t             *codec;
5222         audiohd_widget_t        *widget;
5223 
5224         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
5225                 codec = statep->codec[i];
5226                 if (codec == NULL)
5227                         continue;
5228                 for (wid = codec->first_wid; wid <= codec->last_wid;
5229                     wid++) {
5230                         widget = codec->widget[wid];
5231                         if (widget->widget_cap &
5232                             AUDIOHD_WIDCAP_PWRCTRL) {
5233                                 (void) audioha_codec_verb_get(statep,
5234                                     codec->index, wid,
5235                                     AUDIOHDC_VERB_SET_POWER_STATE,
5236                                     state);
5237                         }
5238                 }
5239         }
5240 }
5241 /*
5242  * audiohd_restore_path()
5243  * Description:
5244  *      This routine is used to restore the path on the codec.
5245  */
5246 static void
5247 audiohd_restore_path(audiohd_state_t *statep)
5248 {
5249         int                     i;
5250         hda_codec_t             *codec;
5251 
5252         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
5253                 codec = statep->codec[i];
5254                 if (codec == NULL)
5255                         continue;
5256                 audiohd_finish_output_path(statep->codec[i]);
5257                 audiohd_finish_input_path(statep->codec[i]);
5258                 audiohd_finish_monitor_path(statep->codec[i]);
5259                 audiohd_finish_beep_path(statep->codec[i]);
5260         }
5261 }
5262 
5263 /*
5264  * audiohd_reset_pins_ur_cap()
5265  * Description:
5266  *      Enable the unsolicited response of the pins which have the unsolicited
5267  *      response capability
5268  */
5269 static void
5270 audiohd_reset_pins_ur_cap(audiohd_state_t *statep)
5271 {
5272         hda_codec_t             *codec;
5273         audiohd_pin_t           *pin;
5274         audiohd_widget_t        *widget;
5275         uint32_t                urctrl;
5276         int                     i;
5277 
5278         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
5279                 codec = statep->codec[i];
5280                 if (codec == NULL)
5281                         continue;
5282                 pin = codec->first_pin;
5283                 while (pin) {
5284                         /* enable the unsolicited response of the pin */
5285                         widget = codec->widget[pin->wid];
5286                         if ((widget->widget_cap &
5287                             (AUDIOHD_URCAP_MASK) &&
5288                             (pin->cap & AUDIOHD_DTCCAP_MASK)) &&
5289                             ((pin->device == DTYPE_LINEOUT) ||
5290                             (pin->device == DTYPE_SPDIF_OUT) ||
5291                             (pin->device == DTYPE_HP_OUT) ||
5292                             (pin->device == DTYPE_MIC_IN))) {
5293                                 urctrl = (uint8_t)(1 <<
5294                                     (AUDIOHD_UR_ENABLE_OFF - 1));
5295                                 urctrl |= (pin->wid & AUDIOHD_UR_TAG_MASK);
5296                                 (void) audioha_codec_verb_get(statep,
5297                                     codec->index,
5298                                     pin->wid,
5299                                     AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
5300                         }
5301                         pin = pin->next;
5302                 }
5303         }
5304 }
5305 static void
5306 audiohd_restore_codec_gpio(audiohd_state_t *statep)
5307 {
5308         int             i;
5309         wid_t           wid;
5310         hda_codec_t     *codec;
5311 
5312         for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
5313                 codec = statep->codec[i];
5314                 if (codec == NULL)
5315                         continue;
5316                 wid = codec->wid_afg;
5317 
5318                 /* power-up audio function group */
5319                 (void) audioha_codec_verb_get(statep, i, wid,
5320                     AUDIOHDC_VERB_SET_POWER_STATE, AUDIOHD_PW_D0);
5321 
5322                 /* work around for Sony VAIO laptop with specific codec */
5323                 if ((codec->codec_info->flags & NO_GPIO) == 0) {
5324                         /*
5325                          * GPIO controls which are laptop specific workarounds
5326                          * and might be changed. Some laptops use GPIO,
5327                          * so we need to enable and set the GPIO correctly.
5328                          */
5329                         (void) audioha_codec_verb_get(statep, i, wid,
5330                             AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE);
5331                         (void) audioha_codec_verb_get(statep, i, wid,
5332                             AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT);
5333                         (void) audioha_codec_verb_get(statep, i, wid,
5334                             AUDIOHDC_VERB_SET_GPIO_STCK,
5335                             AUDIOHDC_GPIO_DATA_CTRL);
5336                         (void) audioha_codec_verb_get(statep, i, wid,
5337                             AUDIOHDC_VERB_SET_GPIO_DATA,
5338                             AUDIOHDC_GPIO_STCK_CTRL);
5339                 }
5340         }
5341 }
5342 /*
5343  * audiohd_resume()
5344  */
5345 static int
5346 audiohd_resume(audiohd_state_t *statep)
5347 {
5348         uint8_t         rirbsts;
5349 
5350         mutex_enter(&statep->hda_mutex);
5351         statep->suspended = B_FALSE;
5352         /* Restore the hda state */
5353         if (audiohd_reinit_hda(statep) == DDI_FAILURE) {
5354                 audio_dev_warn(statep->adev,
5355                     "hda reinit failed");
5356                 mutex_exit(&statep->hda_mutex);
5357                 return (DDI_FAILURE);
5358         }
5359         /* reset to enable the capability of unsolicited response for pin */
5360         audiohd_reset_pins_ur_cap(statep);
5361         /* clear the unsolicited response interrupt */
5362         rirbsts = AUDIOHD_REG_GET8(AUDIOHD_REG_RIRBSTS);
5363         AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSTS, rirbsts);
5364         /* set widget power to D0 */
5365         audiohd_change_widget_power_state(statep, AUDIOHD_PW_D0);
5366 
5367         audiohd_configure_output(statep);
5368         audiohd_configure_input(statep);
5369         mutex_exit(&statep->hda_mutex);
5370 
5371         audio_dev_resume(statep->adev);
5372 
5373         return (DDI_SUCCESS);
5374 }       /* audiohd_resume */
5375 
5376 /*
5377  * audiohd_suspend()
5378  */
5379 static int
5380 audiohd_suspend(audiohd_state_t *statep)
5381 {
5382         audio_dev_suspend(statep->adev);
5383 
5384         mutex_enter(&statep->hda_mutex);
5385         statep->suspended = B_TRUE;
5386 
5387         /* set widget power to D2 */
5388         audiohd_change_widget_power_state(statep, AUDIOHD_PW_D2);
5389         /* Disable h/w */
5390         audiohd_stop_dma(statep);
5391         audiohd_fini_pci(statep);
5392         mutex_exit(&statep->hda_mutex);
5393 
5394         return (DDI_SUCCESS);
5395 }       /* audiohd_suspend */
5396 
5397 /*
5398  * audiohd_disable_pin()
5399  */
5400 static void
5401 audiohd_disable_pin(audiohd_state_t *statep, int caddr, wid_t wid)
5402 {
5403         uint32_t        tmp;
5404 
5405         tmp = audioha_codec_verb_get(statep, caddr, wid,
5406             AUDIOHDC_VERB_GET_PIN_CTRL, 0);
5407         if (tmp == AUDIOHD_CODEC_FAILURE)
5408                 return;
5409         tmp = audioha_codec_verb_get(statep, caddr, wid,
5410             AUDIOHDC_VERB_SET_PIN_CTRL,
5411             (tmp & ~AUDIOHDC_PIN_CONTROL_OUT_ENABLE));
5412 }
5413 
5414 /*
5415  * audiohd_enable_pin()
5416  */
5417 static void
5418 audiohd_enable_pin(audiohd_state_t *statep, int caddr, wid_t wid)
5419 {
5420         uint32_t        tmp;
5421 
5422         tmp = audioha_codec_verb_get(statep, caddr, wid,
5423             AUDIOHDC_VERB_GET_PIN_CTRL, 0);
5424         if (tmp == AUDIOHD_CODEC_FAILURE)
5425                 return;
5426         tmp = audioha_codec_verb_get(statep, caddr, wid,
5427             AUDIOHDC_VERB_SET_PIN_CTRL,
5428             tmp | AUDIOHDC_PIN_CONTROL_OUT_ENABLE |
5429             AUDIOHDC_PIN_CONTROL_HP_ENABLE);
5430 }
5431 
5432 /*
5433  * audiohd_change_speaker_state()
5434  */
5435 static void
5436 audiohd_change_speaker_state(audiohd_state_t *statep, int on)
5437 {
5438         audiohd_path_t          *path;
5439         audiohd_widget_t        *widget;
5440         audiohd_pin_t           *pin;
5441         int                     i, j;
5442         wid_t                   wid;
5443 
5444         for (i = 0; i < statep->pathnum; i++) {
5445                 path = statep->path[i];
5446                 if (!path || path->path_type != PLAY)
5447                         continue;
5448                 if (on) {
5449                         for (j = 0; j < path->pin_nums; j++) {
5450                                 wid = path->pin_wid[j];
5451                                 widget = path->codec->widget[wid];
5452                                 pin = (audiohd_pin_t *)widget->priv;
5453                                 if (pin->device == DTYPE_SPEAKER) {
5454                                         audiohd_enable_pin(statep,
5455                                             path->codec->index,
5456                                             pin->wid);
5457                                 }
5458                         }
5459 
5460                 } else {
5461                         for (j = 0; j < path->pin_nums; j++) {
5462                                 wid = path->pin_wid[j];
5463                                 widget = path->codec->widget[wid];
5464                                 pin = (audiohd_pin_t *)widget->priv;
5465                                 if (pin->device == DTYPE_SPEAKER) {
5466                                         audiohd_disable_pin(statep,
5467                                             path->codec->index,
5468                                             pin->wid);
5469                                 }
5470                         }
5471                 }
5472         }
5473 }
5474 /*
5475  * audiohd_select_mic()
5476  *
5477  * Description:
5478  *      This function is used for the recording path which has a selector
5479  *      as the sumwidget. We select the external MIC if it is plugged into the
5480  *      MIC jack, otherwise the internal integrated MIC is selected.
5481  */
5482 static void
5483 audiohd_select_mic(audiohd_state_t *statep, uint8_t index,
5484     uint8_t id, int select)
5485 {
5486         hda_codec_t             *codec;
5487         audiohd_path_t          *path;
5488         audiohd_widget_t        *widget, *sumwgt = NULL;
5489         audiohd_pin_t           *pin;
5490         int                     i, j;
5491         wid_t                   wid;
5492 
5493         codec = statep->codec[index];
5494         if (codec == NULL)
5495                 return;
5496 
5497         for (i = 0; i < statep->pathnum; i++) {
5498                 path = statep->path[i];
5499                 if (path->codec != codec || path->path_type != RECORD)
5500                         continue;
5501                 sumwgt = codec->widget[path->sum_wid];
5502 
5503                 for (j = 0; j < path->pin_nums; j++) {
5504                         wid = path->pin_wid[j];
5505                         widget = codec->widget[wid];
5506                         pin = (audiohd_pin_t *)widget->priv;
5507 
5508                         if (pin->device != DTYPE_MIC_IN)
5509                                 continue;
5510 
5511                         if (sumwgt != NULL &&
5512                             sumwgt->type == WTYPE_AUDIO_SEL) {
5513                                 /* Have a selector to choose input pin */
5514 
5515                                 if (select && pin->wid == id &&
5516                                     (((pin->config >>
5517                                     AUDIOHD_PIN_CONTP_OFF) &
5518                                     AUDIOHD_PIN_CONTP_MASK) ==
5519                                     AUDIOHD_PIN_CON_JACK)) {
5520                                         (void) audioha_codec_verb_get(
5521                                             statep,
5522                                             index,
5523                                             path->sum_wid,
5524                                             AUDIOHDC_VERB_SET_CONN_SEL,
5525                                             path->sum_selconn[j]);
5526                                         statep->port[PORT_ADC]->index =
5527                                             path->tag;
5528                                         return;
5529                                 } else if (!select && pin->wid != id &&
5530                                     (((pin->config >>
5531                                     AUDIOHD_PIN_CONTP_OFF) &
5532                                     AUDIOHD_PIN_CONTP_MASK) ==
5533                                     AUDIOHD_PIN_CON_FIXED)) {
5534                                         (void) audioha_codec_verb_get(
5535                                             statep,
5536                                             index,
5537                                             path->sum_wid,
5538                                             AUDIOHDC_VERB_SET_CONN_SEL,
5539                                             path->sum_selconn[j]);
5540                                         statep->port[PORT_ADC]->index =
5541                                             path->tag;
5542                                         return;
5543                                 }
5544                         } else {
5545                                 /*
5546                                  * No selector widget in the path,
5547                                  * mute unselected input pin
5548                                  */
5549 
5550                                 /* Open all input pin, and then mute others */
5551                                 audiohd_set_pin_volume(statep, DTYPE_MIC_IN);
5552 
5553                                 if (select == 1) {
5554                                         /* Select external mic, mute internal */
5555                                         if (wid != id) {
5556                                                 (void)
5557                                                     audioha_codec_4bit_verb_get(
5558                                                     statep, path->codec->index,
5559                                                     wid,
5560                                                     AUDIOHDC_VERB_SET_AMP_MUTE,
5561                                                     path->mute_dir |
5562                                                     AUDIOHDC_AMP_SET_LNR |
5563                                                     AUDIOHDC_AMP_SET_MUTE);
5564                                         }
5565                                 } else {
5566                                         /* Select internal mic, mute external */
5567                                         if (wid == id) {
5568                                                 (void)
5569                                                     audioha_codec_4bit_verb_get(
5570                                                     statep, path->codec->index,
5571                                                     wid,
5572                                                     AUDIOHDC_VERB_SET_AMP_MUTE,
5573                                                     path->mute_dir |
5574                                                     AUDIOHDC_AMP_SET_LNR |
5575                                                     AUDIOHDC_AMP_SET_MUTE);
5576                                         }
5577                                 }
5578                         }
5579                 }
5580         }
5581 
5582         /*
5583          * If the input istream > 1, we should set the record stream tag
5584          * respectively. All the input streams sharing one tag may make the
5585          * record sound distorted.
5586          */
5587         if (codec->nistream > 1) {
5588                 for (i = 0; i < statep->pathnum; i++) {
5589                         path = statep->path[i];
5590                         if (!path || path->path_type != RECORD)
5591                                 continue;
5592                         for (j = 0; j < path->pin_nums; j++) {
5593                                 wid = path->pin_wid[j];
5594                                 widget = codec->widget[wid];
5595                                 if (widget == NULL)
5596                                         return;
5597                                 pin = (audiohd_pin_t *)widget->priv;
5598                                 if (select &&
5599                                     pin->device == DTYPE_MIC_IN &&
5600                                     pin->wid == id &&
5601                                     (((pin->config >>
5602                                     AUDIOHD_PIN_CONTP_OFF) &
5603                                     AUDIOHD_PIN_CONTP_MASK) ==
5604                                     AUDIOHD_PIN_CON_JACK)) {
5605                                         statep->port[PORT_ADC]->index =
5606                                             path->tag;
5607                                         return;
5608                                 } else if (!select &&
5609                                     pin->device == DTYPE_MIC_IN &&
5610                                     (((pin->config >>
5611                                     AUDIOHD_PIN_CONTP_OFF) &
5612                                     AUDIOHD_PIN_CONTP_MASK) ==
5613                                     AUDIOHD_PIN_CON_FIXED)) {
5614                                         statep->port[PORT_ADC]->index =
5615                                             path->tag;
5616                                         return;
5617                                 }
5618                         }
5619                 }
5620         }
5621 }
5622 /*
5623  * audiohd_pin_sense()
5624  *
5625  * Description
5626  *
5627  *      When the earphone is plugged into the jack associtated with the pin
5628  *      complex, we disable the built in speaker. When the earphone is plugged
5629  *      out of the jack, we enable the built in speaker.
5630  */
5631 static void
5632 audiohd_pin_sense(audiohd_state_t *statep, uint32_t resp, uint32_t respex)
5633 {
5634         uint8_t                 index;
5635         uint8_t                 id;
5636         uint32_t                rs;
5637         audiohd_widget_t        *widget;
5638         audiohd_pin_t           *pin;
5639         hda_codec_t             *codec;
5640 
5641         index = respex & AUDIOHD_RIRB_CODEC_MASK;
5642         id = resp >> (AUDIOHD_RIRB_WID_OFF - 1);
5643 
5644         codec = statep->codec[index];
5645         if (codec == NULL)
5646                 return;
5647         widget = codec->widget[id];
5648         if (widget == NULL)
5649                 return;
5650 
5651         rs = audioha_codec_verb_get(statep, index, id,
5652             AUDIOHDC_VERB_GET_PIN_SENSE, 0);
5653         if (rs & AUDIOHD_PIN_PRES_MASK) {
5654                 /* A MIC is plugged in, we select the MIC as input */
5655                 if ((widget->type == WTYPE_PIN) &&
5656                     (pin = (audiohd_pin_t *)widget->priv) &&
5657                     (pin->device == DTYPE_MIC_IN)) {
5658                         audiohd_select_mic(statep, index, id, 1);
5659                         return;
5660                 }
5661                 /* output pin is plugged */
5662                 audiohd_change_speaker_state(statep, AUDIOHD_SP_OFF);
5663         } else {
5664                 /*
5665                  * A MIC is unplugged, we select the built in MIC
5666                  * as input.
5667                  */
5668                 if ((widget->type == WTYPE_PIN) &&
5669                     (pin = (audiohd_pin_t *)widget->priv) &&
5670                     (pin->device == DTYPE_MIC_IN)) {
5671                         audiohd_select_mic(statep, index, id, 0);
5672                         return;
5673                 }
5674                 /* output pin is unplugged */
5675                 audiohd_change_speaker_state(statep, AUDIOHD_SP_ON);
5676         }
5677 
5678 }
5679 
5680 /*
5681  * audiohd_disable_intr()
5682  *
5683  * Description:
5684  *      Disable all possible interrupts.
5685  */
5686 static void
5687 audiohd_disable_intr(audiohd_state_t *statep)
5688 {
5689         int             i;
5690         uint32_t        base;
5691 
5692         AUDIOHD_REG_SET32(AUDIOHD_REG_INTCTL, 0);
5693         base = AUDIOHD_REG_SD_BASE;
5694         for (i = 0; i < statep->hda_streams_nums; i++) {
5695                 AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_STS,
5696                     AUDIOHDR_SD_STS_INTRS);
5697                 base += AUDIOHD_REG_SD_LEN;
5698         }
5699         AUDIOHD_REG_SET32(AUDIOHD_REG_INTSTS, (uint32_t)(-1));
5700 
5701 }       /* audiohd_disable_intr() */
5702 
5703 
5704 /*
5705  * audiohd_12bit_verb_to_codec()
5706  *
5707  * Description:
5708  *
5709  */
5710 static int
5711 audiohd_12bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr,
5712     uint8_t wid,
5713     uint16_t cmd, uint8_t param)
5714 {
5715         uint32_t        verb;
5716         uint16_t        wptr;
5717         uint16_t        rptr;
5718 
5719         ASSERT((cmd & AUDIOHDC_12BIT_VERB_MASK) == 0);
5720 
5721         wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK;
5722         rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK;
5723 
5724         wptr++;
5725         wptr &= AUDIOHD_CMDIO_ENT_MASK;
5726 
5727         /* overflow */
5728         if (wptr == rptr) {
5729                 return (DDI_FAILURE);
5730         }
5731 
5732         verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF;
5733         verb |= wid << AUDIOHD_VERB_NID_OFF;
5734         verb |= cmd << AUDIOHD_VERB_CMD_OFF;
5735         verb |= param;
5736 
5737         *((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb;
5738         (void) ddi_dma_sync(statep->hda_dma_corb.ad_dmahdl, 0,
5739             sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV);
5740         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr);
5741 
5742         return (DDI_SUCCESS);
5743 
5744 }       /* audiohd_12bit_verb_to_codec() */
5745 
5746 /*
5747  * audiohd_4bit_verb_to_codec()
5748  *
5749  * Description:
5750  *
5751  */
5752 static int
5753 audiohd_4bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr,
5754     uint8_t wid,
5755     uint32_t cmd, uint16_t param)
5756 {
5757         uint32_t        verb;
5758         uint16_t        wptr;
5759         uint16_t        rptr;
5760 
5761         ASSERT((cmd & AUDIOHDC_4BIT_VERB_MASK) == 0);
5762 
5763         wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK;
5764         rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK;
5765 
5766         wptr++;
5767         wptr &= AUDIOHD_CMDIO_ENT_MASK;
5768 
5769         /* overflow */
5770         if (wptr == rptr) {
5771                 return (DDI_FAILURE);
5772         }
5773 
5774         verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF;
5775         verb |= wid << AUDIOHD_VERB_NID_OFF;
5776         verb |= cmd << AUDIOHD_VERB_CMD16_OFF;
5777         verb |= param;
5778 
5779         *((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb;
5780         AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr);
5781 
5782         return (DDI_SUCCESS);
5783 
5784 }       /* audiohd_4bit_verb_to_codec() */
5785 
5786 /*
5787  * audiohd_response_from_codec()
5788  *
5789  * Description:
5790  *
5791  */
5792 static int
5793 audiohd_response_from_codec(audiohd_state_t *statep, uint32_t *resp,
5794     uint32_t *respex)
5795 {
5796         uint16_t        wptr;
5797         uint16_t        rptr;
5798         uint32_t        *lp;
5799 
5800         wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_RIRBWP) & 0x00ff;
5801         rptr = statep->hda_rirb_rp;
5802 
5803         if (rptr == wptr) {
5804                 return (DDI_FAILURE);
5805         }
5806 
5807         rptr++;
5808         rptr &= AUDIOHD_RING_MAX_SIZE;
5809 
5810         lp = (uint32_t *)(statep->hda_dma_rirb.ad_vaddr) + (rptr << 1);
5811         *resp = *(lp);
5812         *respex = *(lp + 1);
5813 
5814         statep->hda_rirb_rp = rptr;
5815 
5816         return (DDI_SUCCESS);
5817 
5818 }       /* audiohd_response_from_codec() */
5819 
5820 
5821 /*
5822  * audioha_codec_verb_get()
5823  */
5824 static uint32_t
5825 audioha_codec_verb_get(void *arg, uint8_t caddr, uint8_t wid,
5826     uint16_t verb,
5827     uint8_t param)
5828 {
5829         audiohd_state_t *statep = (audiohd_state_t *)arg;
5830         uint32_t        resp;
5831         uint32_t        respex;
5832         int             ret;
5833         int             i;
5834 
5835         ret = audiohd_12bit_verb_to_codec(statep, caddr, wid, verb, param);
5836         if (ret != DDI_SUCCESS) {
5837                 return (uint32_t)(-1);
5838         }
5839 
5840         /*
5841          * Empirical testing times. 50 times is enough for audiohd spec 1.0.
5842          * But we need to make it work for audiohd spec 0.9, which is just a
5843          * draft version and requires more time to wait.
5844          */
5845         for (i = 0; i < 500; i++) {
5846                 ret = audiohd_response_from_codec(statep, &resp, &respex);
5847                 if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) &&
5848                     ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) &&
5849                     (ret == DDI_SUCCESS))
5850                         break;
5851                 /* Empirical testing time, which works well */
5852                 drv_usecwait(30);
5853         }
5854 
5855         if (ret == DDI_SUCCESS) {
5856                 return (resp);
5857         }
5858 
5859         if (wid != AUDIOHDC_NODE_ROOT && param != AUDIOHDC_PAR_VENDOR_ID) {
5860                 audio_dev_warn(statep->adev,  "timeout when get "
5861                     "response from codec: wid=%d, verb=0x%04x, param=0x%04x",
5862                     wid, verb, param);
5863         }
5864 
5865         return ((uint32_t)(-1));
5866 
5867 }       /* audioha_codec_verb_get() */
5868 
5869 
5870 /*
5871  * audioha_codec_4bit_verb_get()
5872  */
5873 static uint32_t
5874 audioha_codec_4bit_verb_get(void *arg, uint8_t caddr, uint8_t wid,
5875     uint16_t verb, uint16_t param)
5876 {
5877         audiohd_state_t *statep = (audiohd_state_t *)arg;
5878         uint32_t        resp;
5879         uint32_t        respex;
5880         int             ret;
5881         int             i;
5882 
5883         ret = audiohd_4bit_verb_to_codec(statep, caddr, wid, verb, param);
5884         if (ret != DDI_SUCCESS) {
5885                 return (uint32_t)(-1);
5886         }
5887 
5888         for (i = 0; i < 500; i++) {
5889                 ret = audiohd_response_from_codec(statep, &resp, &respex);
5890                 if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) &&
5891                     ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) &&
5892                     (ret == DDI_SUCCESS))
5893                         break;
5894                 /* Empirical testing time, which works well */
5895                 drv_usecwait(30);
5896         }
5897 
5898         if (ret == DDI_SUCCESS) {
5899                 return (resp);
5900         }
5901 
5902         audio_dev_warn(statep->adev,  "timeout when get "
5903             "response from codec: wid=%d, verb=0x%04x, param=0x%04x",
5904             wid, verb, param);
5905 
5906         return ((uint32_t)(-1));
5907 
5908 }       /* audioha_codec_4bit_verb_get() */