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