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