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