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