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