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