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