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