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