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