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