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