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