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