1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (C) 4Front Technologies 1996-2008. 23 * 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/list.h> 30 #include <sys/sysmacros.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/callb.h> 34 #include <sys/kstat.h> 35 #include <sys/note.h> 36 37 #include "audio_impl.h" 38 39 /* 40 * Audio Engine functions. 41 */ 42 43 audio_dev_t * 44 audio_dev_alloc(dev_info_t *dip, int instance) 45 { 46 audio_dev_t *d; 47 48 /* 49 * For a card with multiple independent audio ports on it, we 50 * allow the driver to provide a different instance numbering 51 * scheme than the standard DDI instance number. (This is 52 * sort of like the PPA numbering scheme used by NIC drivers 53 * -- by default PPA == instance, but sometimes we need more 54 * flexibility.) 55 */ 56 if (instance == 0) { 57 instance = ddi_get_instance(dip); 58 } 59 /* generally this shouldn't occur */ 60 if (instance > AUDIO_MN_INST_MASK) { 61 audio_dev_warn(NULL, "bad instance number for %s (%d)", 62 ddi_driver_name(dip), instance); 63 return (NULL); 64 } 65 66 if ((d = kmem_zalloc(sizeof (*d), KM_NOSLEEP)) == NULL) { 67 audio_dev_warn(NULL, "unable to allocate audio device struct"); 68 return (NULL); 69 } 70 d->d_dip = dip; 71 d->d_number = -1; 72 d->d_major = ddi_driver_major(dip); 73 d->d_instance = instance; 74 d->d_pcmvol = 100; 75 mutex_init(&d->d_lock, NULL, MUTEX_DRIVER, NULL); 76 cv_init(&d->d_cv, NULL, CV_DRIVER, NULL); 77 rw_init(&d->d_ctrl_lock, NULL, RW_DRIVER, NULL); 78 list_create(&d->d_clients, sizeof (struct audio_client), 79 offsetof(struct audio_client, c_dev_linkage)); 80 list_create(&d->d_engines, sizeof (struct audio_engine), 81 offsetof(struct audio_engine, e_dev_linkage)); 82 list_create(&d->d_controls, sizeof (struct audio_ctrl), 83 offsetof(struct audio_ctrl, ctrl_linkage)); 84 list_create(&d->d_hwinfo, sizeof (struct audio_infostr), 85 offsetof(struct audio_infostr, i_linkage)); 86 (void) snprintf(d->d_name, sizeof (d->d_name), "%s#%d", 87 ddi_driver_name(dip), instance); 88 89 return (d); 90 } 91 92 void 93 audio_dev_free(audio_dev_t *d) 94 { 95 struct audio_infostr *isp; 96 while ((isp = list_remove_head(&d->d_hwinfo)) != NULL) { 97 kmem_free(isp, sizeof (*isp)); 98 } 99 if (d->d_pcmvol_ctrl != NULL) { 100 audio_dev_del_control(d->d_pcmvol_ctrl); 101 } 102 list_destroy(&d->d_hwinfo); 103 list_destroy(&d->d_engines); 104 list_destroy(&d->d_controls); 105 list_destroy(&d->d_clients); 106 rw_destroy(&d->d_ctrl_lock); 107 mutex_destroy(&d->d_lock); 108 cv_destroy(&d->d_cv); 109 kmem_free(d, sizeof (*d)); 110 } 111 112 void 113 audio_dev_set_description(audio_dev_t *d, const char *desc) 114 { 115 (void) strlcpy(d->d_desc, desc, sizeof (d->d_desc)); 116 } 117 118 void 119 audio_dev_set_version(audio_dev_t *d, const char *vers) 120 { 121 (void) strlcpy(d->d_vers, vers, sizeof (d->d_vers)); 122 } 123 124 void 125 audio_dev_add_info(audio_dev_t *d, const char *info) 126 { 127 struct audio_infostr *isp; 128 129 /* failure to add information structure is not critical */ 130 isp = kmem_zalloc(sizeof (*isp), KM_NOSLEEP); 131 if (isp == NULL) { 132 audio_dev_warn(d, "unable to allocate information structure"); 133 } else { 134 (void) snprintf(isp->i_line, sizeof (isp->i_line), info); 135 list_insert_tail(&d->d_hwinfo, isp); 136 } 137 } 138 139 void 140 audio_engine_consume(audio_engine_t *e) 141 { 142 mutex_enter(&e->e_lock); 143 e->e_tail = ENG_COUNT(e); 144 if (e->e_tail > e->e_head) { 145 /* want more data than we have, not much we can do */ 146 e->e_errors++; 147 e->e_underruns++; 148 } 149 auimpl_output_callback(e); 150 mutex_exit(&e->e_lock); 151 } 152 153 void 154 audio_engine_produce(audio_engine_t *e) 155 { 156 mutex_enter(&e->e_lock); 157 e->e_head = ENG_COUNT(e); 158 if ((e->e_head - e->e_tail) > e->e_nframes) { 159 /* no room for engine data, not much we can do */ 160 e->e_errors++; 161 e->e_overruns++; 162 } 163 auimpl_input_callback(e); 164 mutex_exit(&e->e_lock); 165 } 166 167 void 168 audio_engine_reset(audio_engine_t *e) 169 { 170 char *buf; 171 char *ptr; 172 int nfr; 173 int tail; 174 175 176 if ((e->e_flags & (ENGINE_INPUT | ENGINE_OUTPUT)) == 0) { 177 /* engine not open, nothing to do */ 178 return; 179 } 180 181 buf = kmem_alloc(e->e_nbytes, KM_SLEEP); 182 ptr = buf; 183 184 mutex_enter(&e->e_lock); 185 186 tail = e->e_tidx; 187 nfr = min(e->e_head - e->e_tail, e->e_nframes); 188 while (nfr) { 189 int cnt; 190 int nbytes; 191 192 cnt = min((e->e_nframes - tail), nfr); 193 nbytes = cnt * e->e_framesz; 194 195 bcopy(e->e_data + (tail * e->e_framesz), ptr, nbytes); 196 ptr += nbytes; 197 tail += cnt; 198 if (tail >= e->e_framesz) { 199 tail -= e->e_framesz; 200 } 201 nfr -= cnt; 202 } 203 204 nfr = min(e->e_head - e->e_tail, e->e_nframes); 205 if (e->e_flags & ENGINE_INPUT) { 206 /* record */ 207 e->e_hidx = 0; 208 e->e_tidx = (e->e_nframes - nfr) % e->e_nframes; 209 } else { 210 /* play */ 211 e->e_hidx = nfr % e->e_nframes; 212 e->e_tidx = 0; 213 } 214 215 /* relocate from scratch area to destination */ 216 bcopy(buf, e->e_data + (e->e_tidx * e->e_framesz), nfr * e->e_framesz); 217 mutex_exit(&e->e_lock); 218 219 kmem_free(buf, e->e_nbytes); 220 } 221 222 audio_engine_t * 223 audio_engine_alloc(audio_engine_ops_t *ops, unsigned flags) 224 { 225 int i; 226 audio_engine_t *e; 227 228 if (ops->audio_engine_version != AUDIO_ENGINE_VERSION) { 229 audio_dev_warn(NULL, "audio engine version mismatch: %d != %d", 230 ops->audio_engine_version, AUDIO_ENGINE_VERSION); 231 return (NULL); 232 } 233 234 /* NB: The ops vector must be held in persistent storage! */ 235 e = kmem_zalloc(sizeof (audio_engine_t), KM_NOSLEEP); 236 if (e == NULL) { 237 audio_dev_warn(NULL, "unable to allocate engine struct"); 238 return (NULL); 239 } 240 e->e_ops = *ops; 241 mutex_init(&e->e_lock, NULL, MUTEX_DRIVER, NULL); 242 list_create(&e->e_streams, sizeof (struct audio_stream), 243 offsetof(struct audio_stream, s_eng_linkage)); 244 245 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) { 246 e->e_chbufs[i] = kmem_zalloc(sizeof (int32_t) * AUDIO_CHBUFS, 247 KM_NOSLEEP); 248 if (e->e_chbufs[i] == NULL) { 249 audio_dev_warn(NULL, "unable to allocate channel buf"); 250 audio_engine_free(e); 251 return (NULL); 252 } 253 } 254 255 e->e_flags = flags & ENGINE_DRIVER_FLAGS; 256 return (e); 257 } 258 259 void 260 audio_engine_free(audio_engine_t *e) 261 { 262 int i; 263 264 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) { 265 if (e->e_chbufs[i] != NULL) { 266 kmem_free(e->e_chbufs[i], 267 sizeof (int32_t) * AUDIO_CHBUFS); 268 } 269 } 270 list_destroy(&e->e_streams); 271 mutex_destroy(&e->e_lock); 272 kmem_free(e, sizeof (*e)); 273 } 274 275 static list_t auimpl_devs_by_index; 276 static list_t auimpl_devs_by_number; 277 static krwlock_t auimpl_dev_lock; 278 279 /* 280 * Not for public consumption: Private interfaces. 281 */ 282 void 283 auimpl_dev_hold(audio_dev_t *d) 284 { 285 /* bump the reference count */ 286 mutex_enter(&d->d_lock); 287 d->d_refcnt++; 288 mutex_exit(&d->d_lock); 289 } 290 291 audio_dev_t * 292 auimpl_dev_hold_by_devt(dev_t dev) 293 { 294 audio_dev_t *d; 295 major_t major; 296 int instance; 297 list_t *l = &auimpl_devs_by_index; 298 299 major = getmajor(dev); 300 instance = (getminor(dev) >> AUDIO_MN_INST_SHIFT) & AUDIO_MN_INST_MASK; 301 302 rw_enter(&auimpl_dev_lock, RW_READER); 303 304 for (d = list_head(l); d; d = list_next(l, d)) { 305 if ((d->d_major == major) && (d->d_instance == instance)) { 306 auimpl_dev_hold(d); 307 break; 308 } 309 } 310 311 rw_exit(&auimpl_dev_lock); 312 return (d); 313 } 314 315 audio_dev_t * 316 auimpl_dev_hold_by_index(int index) 317 { 318 audio_dev_t *d; 319 list_t *l = &auimpl_devs_by_index; 320 321 rw_enter(&auimpl_dev_lock, RW_READER); 322 323 for (d = list_head(l); d; d = list_next(l, d)) { 324 if (d->d_index == index) { 325 auimpl_dev_hold(d); 326 break; 327 } 328 } 329 330 rw_exit(&auimpl_dev_lock); 331 return (d); 332 } 333 334 void 335 auimpl_dev_release(audio_dev_t *d) 336 { 337 mutex_enter(&d->d_lock); 338 d->d_refcnt--; 339 mutex_exit(&d->d_lock); 340 } 341 342 int 343 auimpl_choose_format(int fmts) 344 { 345 /* 346 * Choose the very best format we can. We choose 24 bit in 347 * preference to 32 bit because we mix in 24 bit. We do that 348 * to allow overflows to fit within 32-bits. (Very few humans 349 * can tell a difference between 24 and 32 bit audio anyway.) 350 */ 351 if (fmts & AUDIO_FORMAT_S24_NE) 352 return (AUDIO_FORMAT_S24_NE); 353 354 if (fmts & AUDIO_FORMAT_S32_NE) 355 return (AUDIO_FORMAT_S32_NE); 356 357 if (fmts & AUDIO_FORMAT_S24_OE) 358 return (AUDIO_FORMAT_S24_OE); 359 360 if (fmts & AUDIO_FORMAT_S32_OE) 361 return (AUDIO_FORMAT_S32_OE); 362 363 if (fmts & AUDIO_FORMAT_S16_NE) 364 return (AUDIO_FORMAT_S16_NE); 365 366 if (fmts & AUDIO_FORMAT_S16_OE) 367 return (AUDIO_FORMAT_S16_OE); 368 369 if (fmts & AUDIO_FORMAT_AC3) 370 return (AUDIO_FORMAT_AC3); 371 372 return (AUDIO_FORMAT_NONE); 373 } 374 375 int 376 auimpl_engine_open(audio_dev_t *d, int fmts, int flags, audio_stream_t *sp) 377 { 378 audio_engine_t *e = NULL; 379 list_t *list; 380 unsigned caps; 381 int priority = 0; 382 int rv = ENODEV; 383 int sampsz; 384 int i; 385 386 /* 387 * Engine selection: 388 * 389 * We try hard to avoid consuming an engine that can be used 390 * for another purpose. 391 * 392 */ 393 394 /* 395 * Which direction are we opening. (We must open exactly 396 * one direction, otherwise the open is meaningless.) 397 */ 398 if (flags & ENGINE_OUTPUT) 399 caps = ENGINE_OUTPUT_CAP; 400 else if (flags & ENGINE_INPUT) 401 caps = ENGINE_INPUT_CAP; 402 else 403 return (EINVAL); 404 405 list = &d->d_engines; 406 407 mutex_enter(&d->d_lock); 408 409 /* 410 * First we want to know if we already have "default" input 411 * and output engines. 412 */ 413 414 again: 415 416 for (audio_engine_t *t = list_head(list); t; t = list_next(list, t)) { 417 int mypri; 418 419 /* make sure the engine can do what we want it to */ 420 mutex_enter(&t->e_lock); 421 if ((((t->e_flags & caps) & caps) == 0) || 422 ((ENG_FORMAT(t) & fmts) == 0)) { 423 mutex_exit(&t->e_lock); 424 continue; 425 } 426 427 /* if engine is in exclusive use, can't do it */ 428 if (t->e_flags & ENGINE_EXCLUSIVE) { 429 mutex_exit(&t->e_lock); 430 rv = EBUSY; 431 continue; 432 } 433 434 /* if engine is in incompatible use, can't do it */ 435 if (((flags & ENGINE_INPUT) && (t->e_flags & ENGINE_OUTPUT)) || 436 ((flags & ENGINE_OUTPUT) && (t->e_flags & ENGINE_INPUT))) { 437 mutex_exit(&t->e_lock); 438 rv = EBUSY; 439 continue; 440 } 441 442 /* 443 * In order to support as many different possible 444 * output streams (e.g. AC3 passthru or AC3 decode), 445 * or multiple exclusive outputs, we treat audio 446 * engines as *precious*. 447 * 448 * This means that we will try hard to reuse an 449 * existing allocated engine. This may not be the 450 * optimal performance configuration (especially if we 451 * wanted to avoid rate conversion, for example), but 452 * it should have fewer cases where the configuration 453 * results in denying service to any client. 454 */ 455 456 rv = 0; 457 mypri = 2000; 458 459 /* try not to pick on idle engines */ 460 if (list_is_empty(&t->e_streams)) { 461 mypri -= 1000; 462 } 463 464 /* try not to pick on duplex engines first */ 465 if ((t->e_flags & ENGINE_CAPS) != caps) { 466 mypri -= 100; 467 } 468 469 /* try not to pick on engines that can do other formats */ 470 if (t->e_format & ~fmts) { 471 mypri -= 10; 472 } 473 474 if (mypri > priority) { 475 if (e != NULL) { 476 mutex_exit(&e->e_lock); 477 } 478 e = t; 479 priority = mypri; 480 } else { 481 mutex_exit(&t->e_lock); 482 } 483 } 484 485 if ((rv == EBUSY) && ((flags & ENGINE_NDELAY) == 0)) { 486 ASSERT(e == NULL); 487 if (cv_wait_sig(&d->d_cv, &d->d_lock) == 0) { 488 mutex_exit(&d->d_lock); 489 return (EINTR); 490 } 491 goto again; 492 } 493 494 if (rv != 0) { 495 ASSERT(e == NULL); 496 mutex_exit(&d->d_lock); 497 return (rv); 498 } 499 500 ASSERT(e != NULL); 501 ASSERT(mutex_owned(&e->e_lock)); 502 503 /* 504 * If the engine is already open, there is no need for further 505 * work. The first open will be relatively expensive, but 506 * subsequent opens should be as cheap as possible. 507 */ 508 if (!list_is_empty(&e->e_streams)) { 509 rv = 0; 510 goto ok; 511 } 512 513 e->e_format = ENG_FORMAT(e); 514 e->e_nchan = ENG_CHANNELS(e); 515 e->e_rate = ENG_RATE(e); 516 517 /* Find out the "best" sample format supported by the device */ 518 switch (e->e_format) { 519 case AUDIO_FORMAT_S24_NE: 520 e->e_export = auimpl_export_24ne; 521 e->e_import = auimpl_import_24ne; 522 sampsz = 4; 523 break; 524 case AUDIO_FORMAT_S32_NE: 525 e->e_export = auimpl_export_32ne; 526 e->e_import = auimpl_import_32ne; 527 sampsz = 4; 528 break; 529 case AUDIO_FORMAT_S24_OE: 530 e->e_export = auimpl_export_24oe; 531 e->e_import = auimpl_import_24oe; 532 sampsz = 4; 533 break; 534 case AUDIO_FORMAT_S32_OE: 535 e->e_export = auimpl_export_32oe; 536 e->e_import = auimpl_import_32oe; 537 sampsz = 4; 538 break; 539 case AUDIO_FORMAT_S16_NE: 540 e->e_export = auimpl_export_16ne; 541 e->e_import = auimpl_import_16ne; 542 sampsz = 2; 543 break; 544 case AUDIO_FORMAT_S16_OE: 545 e->e_export = auimpl_export_16oe; 546 e->e_import = auimpl_import_16oe; 547 sampsz = 2; 548 break; 549 case AUDIO_FORMAT_AC3: 550 e->e_export = auimpl_export_24ne; 551 e->e_import = auimpl_import_24ne; 552 flags |= ENGINE_EXCLUSIVE; 553 sampsz = 2; 554 break; 555 default: 556 audio_dev_warn(d, "bad format"); 557 rv = ENOTSUP; 558 goto done; 559 } 560 561 /* sanity test a few values */ 562 if ((e->e_nchan < 0) || (e->e_nchan > AUDIO_MAX_CHANNELS) || 563 (e->e_rate < 5000) || (e->e_rate > 192000)) { 564 audio_dev_warn(d, "bad engine channels or rate"); 565 rv = EINVAL; 566 goto done; 567 } 568 569 rv = ENG_OPEN(e, &e->e_fragfr, &e->e_nfrags, &e->e_data); 570 if (rv != 0) { 571 audio_dev_warn(d, "unable to open engine"); 572 goto done; 573 } 574 if ((e->e_fragfr < 1) || (e->e_data == NULL)) { 575 audio_dev_warn(d, "improper engine configuration"); 576 rv = EINVAL; 577 goto done; 578 } 579 580 if ((e->e_fragfr > AUDIO_CHBUFS) || (e->e_nfrags < 2)) { 581 rv = EINVAL; 582 audio_dev_warn(d, "invalid fragment configuration"); 583 goto done; 584 } 585 586 e->e_framesz = e->e_nchan * sampsz; 587 e->e_fragbytes = e->e_fragfr * e->e_framesz; 588 e->e_nframes = e->e_nfrags * e->e_fragfr; 589 e->e_intrs = e->e_rate / e->e_fragfr; 590 e->e_nbytes = e->e_nframes * e->e_framesz; 591 e->e_head = 0; 592 e->e_tail = 0; 593 e->e_hidx = 0; 594 e->e_tidx = 0; 595 e->e_limiter_state = 0x10000; 596 bzero(e->e_data, e->e_nbytes); 597 598 for (i = 0; i < e->e_nchan; i++) { 599 if (e->e_ops.audio_engine_chinfo == NULL) { 600 e->e_choffs[i] = i; 601 e->e_chincr[i] = e->e_nchan; 602 } else { 603 ENG_CHINFO(e, i, &e->e_choffs[i], &e->e_chincr[i]); 604 } 605 } 606 607 e->e_flags |= (ENGINE_OPEN | (flags & (ENGINE_OUTPUT | ENGINE_INPUT))); 608 609 /* 610 * Start the output callback to populate the engine on 611 * startup. This avoids a false underrun when we're first 612 * starting up. 613 */ 614 if (flags & ENGINE_OUTPUT) { 615 auimpl_output_callback(e); 616 } 617 618 /* 619 * Start the engine up now. 620 * 621 * AC3: Note that this will need to be modified for AC3, since 622 * for AC3 we can't start the device until we actually have 623 * some data for it from the application. Probably the best 624 * way to do this would be to add a flag, ENGINE_DEFERRED or 625 * somesuch. 626 */ 627 if (e->e_ops.audio_engine_start != NULL) { 628 rv = ENG_START(e); 629 if (rv != 0) { 630 ENG_CLOSE(e); 631 goto done; 632 } 633 } 634 635 ok: 636 sp->s_phys_parms->p_rate = e->e_rate; 637 sp->s_phys_parms->p_nchan = e->e_nchan; 638 639 list_insert_tail(&e->e_streams, sp); 640 sp->s_engine = e; 641 642 done: 643 mutex_exit(&e->e_lock); 644 mutex_exit(&d->d_lock); 645 return (rv); 646 } 647 648 void 649 auimpl_engine_close(audio_stream_t *sp) 650 { 651 audio_engine_t *e = sp->s_engine; 652 audio_dev_t *d; 653 654 if (e == NULL) 655 return; 656 657 d = e->e_dev; 658 659 mutex_enter(&d->d_lock); 660 mutex_enter(&e->e_lock); 661 sp->s_engine = NULL; 662 list_remove(&e->e_streams, sp); 663 if (list_is_empty(&e->e_streams)) { 664 /* if last client holding engine open, close it all down */ 665 if (e->e_ops.audio_engine_stop != NULL) 666 ENG_STOP(e); 667 e->e_flags &= ENGINE_DRIVER_FLAGS; 668 ENG_CLOSE(e); 669 } 670 mutex_exit(&e->e_lock); 671 672 cv_broadcast(&d->d_cv); 673 mutex_exit(&d->d_lock); 674 } 675 676 int 677 audio_dev_register(audio_dev_t *d) 678 { 679 list_t *l; 680 audio_dev_t *srch; 681 int start; 682 683 /* 684 * Make sure we don't automatically unload. This prevents 685 * loss of hardware settings when no audio clients are 686 * running. 687 */ 688 (void) ddi_prop_update_int(DDI_DEV_T_NONE, d->d_dip, 689 DDI_NO_AUTODETACH, 1); 690 691 /* 692 * This does an in-order insertion, finding the first available 693 * free index. "Special" devices (ones without any actual engines) 694 * are all numbered 0. There should only be one of them anyway. 695 * All others start at one. 696 */ 697 if (d->d_flags & DEV_SNDSTAT_CAP) { 698 start = 0; 699 } else { 700 start = 1; 701 } 702 d->d_index = start; 703 rw_enter(&auimpl_dev_lock, RW_WRITER); 704 l = &auimpl_devs_by_index; 705 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 706 /* skip over special nodes */ 707 if (srch->d_index < start) 708 continue; 709 if (srch->d_index > d->d_index) { 710 /* found a free spot! */ 711 break; 712 } 713 d->d_index++; 714 } 715 /* 716 * NB: If srch is NULL, then list_insert_before puts 717 * it on the tail of the list. So if we didn't find a 718 * hole, then that's where we want it. 719 */ 720 list_insert_before(l, srch, d); 721 722 /* insert in order by number */ 723 l = &auimpl_devs_by_number; 724 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 725 if (srch->d_number >= d->d_number) { 726 break; 727 } 728 } 729 list_insert_before(l, srch, d); 730 731 rw_exit(&auimpl_dev_lock); 732 733 if (auimpl_create_minors(d) != 0) { 734 rw_enter(&auimpl_dev_lock, RW_WRITER); 735 auimpl_remove_minors(d); 736 list_remove(&auimpl_devs_by_index, d); 737 list_remove(&auimpl_devs_by_number, d); 738 rw_exit(&auimpl_dev_lock); 739 return (DDI_FAILURE); 740 } 741 742 return (DDI_SUCCESS); 743 } 744 745 int 746 audio_dev_unregister(audio_dev_t *d) 747 { 748 rw_enter(&auimpl_dev_lock, RW_WRITER); 749 750 mutex_enter(&d->d_lock); 751 /* if we are still in use, we can't unregister */ 752 if (d->d_refcnt) { 753 mutex_exit(&d->d_lock); 754 rw_exit(&auimpl_dev_lock); 755 return (DDI_FAILURE); 756 } 757 auimpl_remove_minors(d); 758 list_remove(&auimpl_devs_by_index, d); 759 list_remove(&auimpl_devs_by_number, d); 760 mutex_exit(&d->d_lock); 761 762 rw_exit(&auimpl_dev_lock); 763 764 return (DDI_SUCCESS); 765 } 766 767 static int 768 auimpl_engine_ksupdate(kstat_t *ksp, int rw) 769 { 770 audio_engine_t *e = ksp->ks_private; 771 struct audio_stats *st = &e->e_stats; 772 773 if (rw == KSTAT_WRITE) { 774 return (EACCES); 775 } 776 777 mutex_enter(&e->e_lock); 778 st->st_head.value.ui64 = e->e_head; 779 st->st_tail.value.ui64 = e->e_tail; 780 st->st_flags.value.ui32 = e->e_flags; 781 st->st_fragfr.value.ui32 = e->e_fragfr; 782 st->st_nfrags.value.ui32 = e->e_nfrags; 783 st->st_framesz.value.ui32 = e->e_framesz; 784 st->st_nbytes.value.ui32 = e->e_nbytes; 785 st->st_hidx.value.ui32 = e->e_hidx; 786 st->st_tidx.value.ui32 = e->e_tidx; 787 st->st_format.value.ui32 = e->e_format; 788 st->st_nchan.value.ui32 = e->e_nchan; 789 st->st_rate.value.ui32 = e->e_rate; 790 st->st_intrs.value.ui32 = e->e_intrs; 791 st->st_errors.value.ui32 = e->e_errors; 792 st->st_engine_underruns.value.ui32 = e->e_underruns; 793 st->st_engine_overruns.value.ui32 = e->e_overruns; 794 st->st_stream_underruns.value.ui32 = e->e_stream_underruns; 795 st->st_stream_overruns.value.ui32 = e->e_stream_overruns; 796 st->st_suspended.value.ui32 = e->e_suspended; 797 mutex_exit(&e->e_lock); 798 799 return (0); 800 } 801 802 static void 803 auimpl_engine_ksinit(audio_dev_t *d, audio_engine_t *e) 804 { 805 char name[32]; 806 struct audio_stats *st; 807 808 (void) snprintf(name, sizeof (name), "engine_%d", e->e_num); 809 810 e->e_ksp = kstat_create(ddi_driver_name(d->d_dip), d->d_instance, 811 name, "misc", KSTAT_TYPE_NAMED, 812 sizeof (struct audio_stats) / sizeof (kstat_named_t), 0); 813 814 if (e->e_ksp == NULL) { 815 audio_dev_warn(d, "unable to initialize kstats"); 816 return; 817 } 818 819 st = &e->e_stats; 820 e->e_ksp->ks_data = st; 821 e->e_ksp->ks_private = e; 822 e->e_ksp->ks_lock = NULL; 823 e->e_ksp->ks_update = auimpl_engine_ksupdate; 824 kstat_named_init(&st->st_head, "head", KSTAT_DATA_UINT64); 825 kstat_named_init(&st->st_tail, "tail", KSTAT_DATA_UINT64); 826 kstat_named_init(&st->st_flags, "flags", KSTAT_DATA_UINT32); 827 kstat_named_init(&st->st_fragfr, "fragfr", KSTAT_DATA_UINT32); 828 kstat_named_init(&st->st_nfrags, "nfrags", KSTAT_DATA_UINT32); 829 kstat_named_init(&st->st_framesz, "framesz", KSTAT_DATA_UINT32); 830 kstat_named_init(&st->st_nbytes, "nbytes", KSTAT_DATA_UINT32); 831 kstat_named_init(&st->st_hidx, "hidx", KSTAT_DATA_UINT32); 832 kstat_named_init(&st->st_tidx, "tidx", KSTAT_DATA_UINT32); 833 kstat_named_init(&st->st_format, "format", KSTAT_DATA_UINT32); 834 kstat_named_init(&st->st_nchan, "channels", KSTAT_DATA_UINT32); 835 kstat_named_init(&st->st_rate, "rate", KSTAT_DATA_UINT32); 836 kstat_named_init(&st->st_intrs, "intrhz", KSTAT_DATA_UINT32); 837 kstat_named_init(&st->st_errors, "errors", KSTAT_DATA_UINT32); 838 kstat_named_init(&st->st_engine_overruns, "engine_overruns", 839 KSTAT_DATA_UINT32); 840 kstat_named_init(&st->st_engine_underruns, "engine_underruns", 841 KSTAT_DATA_UINT32); 842 kstat_named_init(&st->st_stream_overruns, "stream_overruns", 843 KSTAT_DATA_UINT32); 844 kstat_named_init(&st->st_stream_underruns, "stream_underruns", 845 KSTAT_DATA_UINT32); 846 kstat_named_init(&st->st_suspended, "suspended", KSTAT_DATA_UINT32); 847 kstat_install(e->e_ksp); 848 } 849 850 void 851 audio_dev_add_engine(audio_dev_t *d, audio_engine_t *e) 852 { 853 e->e_num = d->d_engno++; 854 855 mutex_enter(&d->d_lock); 856 857 auimpl_engine_ksinit(d, e); 858 859 /* check for duplex */ 860 if ((e->e_flags & ENGINE_OUTPUT_CAP) && (d->d_flags & DEV_INPUT_CAP)) { 861 d->d_flags |= DEV_DUPLEX_CAP; 862 } 863 if ((e->e_flags & ENGINE_INPUT_CAP) && (d->d_flags & DEV_OUTPUT_CAP)) { 864 d->d_flags |= DEV_DUPLEX_CAP; 865 } 866 /* add in the direction caps -- must be done after duplex above */ 867 if (e->e_flags & ENGINE_OUTPUT_CAP) { 868 d->d_flags |= DEV_OUTPUT_CAP; 869 } 870 if (e->e_flags & ENGINE_INPUT_CAP) { 871 d->d_flags |= DEV_INPUT_CAP; 872 } 873 874 list_insert_tail(&d->d_engines, e); 875 e->e_dev = d; 876 mutex_exit(&d->d_lock); 877 } 878 879 void 880 audio_dev_remove_engine(audio_dev_t *d, audio_engine_t *e) 881 { 882 mutex_enter(&d->d_lock); 883 list_remove(&d->d_engines, e); 884 e->e_dev = NULL; 885 if (e->e_ksp) 886 kstat_delete(e->e_ksp); 887 e->e_ksp = NULL; 888 mutex_exit(&d->d_lock); 889 } 890 891 /* 892 * Change the number. 893 */ 894 void 895 auclnt_set_dev_number(audio_dev_t *d, int num) 896 { 897 list_t *l = &auimpl_devs_by_number; 898 audio_dev_t *srch; 899 900 /* reorder our list */ 901 rw_enter(&auimpl_dev_lock, RW_WRITER); 902 d->d_number = num; 903 list_remove(l, d); 904 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 905 if (srch->d_number >= d->d_number) { 906 break; 907 } 908 } 909 list_insert_before(l, srch, d); 910 911 rw_exit(&auimpl_dev_lock); 912 } 913 914 void 915 auclnt_walk_devs(int (*walker)(audio_dev_t *, void *), void *arg) 916 { 917 audio_dev_t *d; 918 boolean_t cont; 919 list_t *l; 920 921 l = &auimpl_devs_by_index; 922 rw_enter(&auimpl_dev_lock, RW_READER); 923 for (d = list_head(l); d; d = list_next(l, d)) { 924 mutex_enter(&d->d_lock); 925 cont = walker(d, arg); 926 mutex_exit(&d->d_lock); 927 if (cont == AUDIO_WALK_STOP) 928 break; 929 } 930 rw_exit(&auimpl_dev_lock); 931 } 932 933 void 934 auclnt_walk_devs_by_number(int (*walker)(audio_dev_t *, void *), void *arg) 935 { 936 audio_dev_t *d; 937 boolean_t cont; 938 list_t *l; 939 940 l = &auimpl_devs_by_number; 941 rw_enter(&auimpl_dev_lock, RW_READER); 942 for (d = list_head(l); d; d = list_next(l, d)) { 943 mutex_enter(&d->d_lock); 944 cont = walker(d, arg); 945 mutex_exit(&d->d_lock); 946 if (cont == AUDIO_WALK_STOP) 947 break; 948 } 949 rw_exit(&auimpl_dev_lock); 950 } 951 952 void 953 auclnt_dev_walk_engines(audio_dev_t *d, 954 int (*walker)(audio_engine_t *, void *), 955 void *arg) 956 { 957 audio_engine_t *e; 958 list_t *l = &d->d_engines; 959 960 mutex_enter(&d->d_lock); 961 for (e = list_head(l); e != NULL; e = list_next(l, e)) { 962 if (walker(e, arg) == AUDIO_WALK_STOP) { 963 break; 964 } 965 } 966 mutex_exit(&d->d_lock); 967 } 968 969 int 970 auclnt_engine_get_format(audio_engine_t *e) 971 { 972 return (ENG_FORMAT(e)); 973 } 974 975 int 976 auclnt_engine_get_channels(audio_engine_t *e) 977 { 978 return (ENG_CHANNELS(e)); 979 } 980 981 int 982 auclnt_engine_get_rate(audio_engine_t *e) 983 { 984 return (ENG_RATE(e)); 985 } 986 987 unsigned 988 auclnt_engine_get_capab(audio_engine_t *e) 989 { 990 unsigned capab = 0; 991 992 if (e->e_flags & ENGINE_INPUT_CAP) { 993 capab |= AUDIO_CLIENT_CAP_RECORD; 994 } 995 if (e->e_flags & ENGINE_OUTPUT_CAP) { 996 capab |= AUDIO_CLIENT_CAP_PLAY; 997 } 998 return (capab); 999 } 1000 1001 static void 1002 auimpl_walk_engines(int (*walker)(audio_engine_t *, void *), void *arg) 1003 { 1004 audio_dev_t *d; 1005 audio_engine_t *e; 1006 list_t *l1; 1007 list_t *l2; 1008 boolean_t done = B_FALSE; 1009 1010 rw_enter(&auimpl_dev_lock, RW_READER); 1011 l1 = &auimpl_devs_by_index; 1012 for (d = list_head(l1); d; d = list_next(l1, d)) { 1013 mutex_enter(&d->d_lock); 1014 l2 = &d->d_engines; 1015 for (e = list_head(l2); e; e = list_next(l2, e)) { 1016 if (walker(e, arg) == AUDIO_WALK_STOP) { 1017 done = B_TRUE; 1018 break; 1019 } 1020 } 1021 mutex_exit(&d->d_lock); 1022 if (done) 1023 break; 1024 } 1025 rw_exit(&auimpl_dev_lock); 1026 } 1027 1028 /* 1029 * This function suspends an engine. The intent is to pause the 1030 * engine temporarily so that it does not underrun while user threads 1031 * are suspended. The driver is still responsible for actually doing 1032 * the driver suspend work -- all this does is put the engine in a 1033 * paused state. It does not prevent, for example, threads from 1034 * accessing the hardware. 1035 * 1036 * A properly implemented driver won't even be aware of the existence 1037 * of this routine -- the driver will just handle the suspend & 1038 * resume. At the point of suspend & resume, the driver will see that 1039 * the engines are not running (as if all threads had "paused" it). 1040 * 1041 * Failure to execute either of the routines below is not critical, 1042 * but will probably lead to underruns and overflows as the kernel 1043 * driver gets resumed well in advance of the time when user threads 1044 * are ready to start operation. 1045 */ 1046 static int 1047 auimpl_engine_suspend(audio_engine_t *e, void *dontcare) 1048 { 1049 _NOTE(ARGUNUSED(dontcare)); 1050 1051 mutex_enter(&e->e_lock); 1052 e->e_suspended = B_TRUE; 1053 mutex_exit(&e->e_lock); 1054 1055 return (AUDIO_WALK_CONTINUE); 1056 } 1057 1058 static int 1059 auimpl_engine_resume(audio_engine_t *e, void *dontcare) 1060 { 1061 _NOTE(ARGUNUSED(dontcare)); 1062 mutex_enter(&e->e_lock); 1063 e->e_suspended = B_FALSE; 1064 mutex_exit(&e->e_lock); 1065 return (AUDIO_WALK_CONTINUE); 1066 } 1067 1068 boolean_t 1069 auimpl_cpr(void *arg, int code) 1070 { 1071 _NOTE(ARGUNUSED(arg)); 1072 1073 switch (code) { 1074 case CB_CODE_CPR_CHKPT: 1075 auimpl_walk_engines(auimpl_engine_suspend, NULL); 1076 return (B_TRUE); 1077 1078 case CB_CODE_CPR_RESUME: 1079 auimpl_walk_engines(auimpl_engine_resume, NULL); 1080 return (B_TRUE); 1081 1082 default: 1083 return (B_FALSE); 1084 } 1085 } 1086 1087 static callb_id_t auimpl_cpr_id = 0; 1088 1089 void 1090 auimpl_dev_init(void) 1091 { 1092 rw_init(&auimpl_dev_lock, NULL, RW_DRIVER, NULL); 1093 list_create(&auimpl_devs_by_index, sizeof (struct audio_dev), 1094 offsetof(struct audio_dev, d_by_index)); 1095 list_create(&auimpl_devs_by_number, sizeof (struct audio_dev), 1096 offsetof(struct audio_dev, d_by_number)); 1097 1098 /* 1099 * We "borrow" the CB_CL_CPR_PM class, which gets executed at 1100 * about the right time for us. It would be nice to have a 1101 * new CB_CL_CPR_AUDIO class, but it isn't critical at this 1102 * point. 1103 * 1104 * Note that we don't care about our thread id. 1105 */ 1106 auimpl_cpr_id = callb_add(auimpl_cpr, NULL, CB_CL_CPR_PM, "audio_cpr"); 1107 } 1108 1109 void 1110 auimpl_dev_fini(void) 1111 { 1112 (void) callb_delete(auimpl_cpr_id); 1113 list_destroy(&auimpl_devs_by_index); 1114 list_destroy(&auimpl_devs_by_number); 1115 rw_destroy(&auimpl_dev_lock); 1116 } 1117 1118 void 1119 audio_engine_set_private(audio_engine_t *eng, void *prv) 1120 { 1121 eng->e_private = prv; 1122 } 1123 1124 void * 1125 audio_engine_get_private(audio_engine_t *eng) 1126 { 1127 return (eng->e_private); 1128 } 1129 1130 void 1131 audio_dump_bytes(const uint8_t *w, int dcount) 1132 { 1133 char line[64]; 1134 char *s; 1135 int i; 1136 const int wrap = 16; 1137 1138 s = line; 1139 line[0] = 0; 1140 1141 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1142 for (i = 0; i < dcount; i++) { 1143 1144 (void) sprintf(s, " %02x", *w); 1145 s += strlen(s); 1146 w++; 1147 1148 if ((i % wrap) == (wrap - 1)) { 1149 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1150 line[0] = 0; 1151 s = line; 1152 } 1153 } 1154 1155 if ((i % wrap) != 0) { 1156 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1157 } 1158 } 1159 1160 void 1161 audio_dump_words(const uint16_t *w, int dcount) 1162 { 1163 char line[64]; 1164 char *s; 1165 int i; 1166 const int wrap = 8; 1167 1168 s = line; 1169 line[0] = 0; 1170 1171 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1172 for (i = 0; i < dcount; i++) { 1173 1174 (void) sprintf(s, " %04x", *w); 1175 s += strlen(s); 1176 w++; 1177 1178 if ((i % wrap) == (wrap - 1)) { 1179 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1180 line[0] = 0; 1181 s = line; 1182 } 1183 } 1184 1185 if ((i % wrap) != 0) { 1186 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1187 } 1188 } 1189 1190 void 1191 audio_dump_dwords(const uint32_t *w, int dcount) 1192 { 1193 char line[128]; 1194 char *s; 1195 int i; 1196 const int wrap = 4; 1197 1198 s = line; 1199 line[0] = 0; 1200 1201 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1202 for (i = 0; i < dcount; i++) { 1203 1204 (void) sprintf(s, " %08x", *w); 1205 s += strlen(s); 1206 w++; 1207 1208 if ((i % wrap) == (wrap - 1)) { 1209 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1210 line[0] = 0; 1211 s = line; 1212 } 1213 } 1214 1215 if ((i % wrap) != 0) { 1216 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1217 } 1218 } 1219