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