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