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 rw_init(&d->d_clnt_lock, NULL, RW_DRIVER, NULL); 79 list_create(&d->d_clients, sizeof (struct audio_client), 80 offsetof(struct audio_client, c_dev_linkage)); 81 list_create(&d->d_engines, sizeof (struct audio_engine), 82 offsetof(struct audio_engine, e_dev_linkage)); 83 list_create(&d->d_controls, sizeof (struct audio_ctrl), 84 offsetof(struct audio_ctrl, ctrl_linkage)); 85 list_create(&d->d_hwinfo, sizeof (struct audio_infostr), 86 offsetof(struct audio_infostr, i_linkage)); 87 (void) snprintf(d->d_name, sizeof (d->d_name), "%s#%d", 88 ddi_driver_name(dip), instance); 89 90 return (d); 91 } 92 93 void 94 audio_dev_free(audio_dev_t *d) 95 { 96 struct audio_infostr *isp; 97 while ((isp = list_remove_head(&d->d_hwinfo)) != NULL) { 98 kmem_free(isp, sizeof (*isp)); 99 } 100 if (d->d_pcmvol_ctrl != NULL) { 101 audio_dev_del_control(d->d_pcmvol_ctrl); 102 } 103 list_destroy(&d->d_hwinfo); 104 list_destroy(&d->d_engines); 105 list_destroy(&d->d_controls); 106 list_destroy(&d->d_clients); 107 rw_destroy(&d->d_ctrl_lock); 108 mutex_destroy(&d->d_lock); 109 cv_destroy(&d->d_cv); 110 rw_destroy(&d->d_clnt_lock); 111 kmem_free(d, sizeof (*d)); 112 } 113 114 void 115 audio_dev_set_description(audio_dev_t *d, const char *desc) 116 { 117 (void) strlcpy(d->d_desc, desc, sizeof (d->d_desc)); 118 } 119 120 void 121 audio_dev_set_version(audio_dev_t *d, const char *vers) 122 { 123 (void) strlcpy(d->d_vers, vers, sizeof (d->d_vers)); 124 } 125 126 void 127 audio_dev_add_info(audio_dev_t *d, const char *info) 128 { 129 struct audio_infostr *isp; 130 131 /* failure to add information structure is not critical */ 132 isp = kmem_zalloc(sizeof (*isp), KM_NOSLEEP); 133 if (isp == NULL) { 134 audio_dev_warn(d, "unable to allocate information structure"); 135 } else { 136 (void) snprintf(isp->i_line, sizeof (isp->i_line), info); 137 list_insert_tail(&d->d_hwinfo, isp); 138 } 139 } 140 141 void 142 audio_engine_consume(audio_engine_t *e) 143 { 144 mutex_enter(&e->e_lock); 145 e->e_tail = ENG_COUNT(e); 146 if (e->e_tail > e->e_head) { 147 /* want more data than we have, not much we can do */ 148 e->e_errors++; 149 } 150 auimpl_output_callback(e); 151 mutex_exit(&e->e_lock); 152 } 153 154 void 155 audio_engine_produce(audio_engine_t *e) 156 { 157 mutex_enter(&e->e_lock); 158 e->e_head = ENG_COUNT(e); 159 if ((e->e_head - e->e_tail) > e->e_nframes) { 160 /* no room for engine data, not much we can do */ 161 e->e_errors++; 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 engine up now. 611 * 612 * AC3: Note that this will need to be modified for AC3, since 613 * for AC3 we can't start the device until we actually have 614 * some data for it from the application. Probably the best 615 * way to do this would be to add a flag, ENGINE_DEFERRED or 616 * somesuch. 617 */ 618 if (e->e_ops.audio_engine_start != NULL) { 619 rv = ENG_START(e); 620 if (rv != 0) { 621 ENG_CLOSE(e); 622 goto done; 623 } 624 } 625 626 ok: 627 sp->s_phys_parms->p_rate = e->e_rate; 628 sp->s_phys_parms->p_nchan = e->e_nchan; 629 630 list_insert_tail(&e->e_streams, sp); 631 sp->s_engine = e; 632 633 done: 634 mutex_exit(&e->e_lock); 635 mutex_exit(&d->d_lock); 636 return (rv); 637 } 638 639 void 640 auimpl_engine_close(audio_stream_t *sp) 641 { 642 audio_engine_t *e = sp->s_engine; 643 audio_dev_t *d; 644 645 if (e == NULL) 646 return; 647 648 d = e->e_dev; 649 650 mutex_enter(&d->d_lock); 651 mutex_enter(&e->e_lock); 652 sp->s_engine = NULL; 653 list_remove(&e->e_streams, sp); 654 if (list_is_empty(&e->e_streams)) { 655 /* if last client holding engine open, close it all down */ 656 if (e->e_ops.audio_engine_stop != NULL) 657 ENG_STOP(e); 658 e->e_flags &= ENGINE_DRIVER_FLAGS; 659 ENG_CLOSE(e); 660 } 661 mutex_exit(&e->e_lock); 662 663 cv_broadcast(&d->d_cv); 664 mutex_exit(&d->d_lock); 665 } 666 667 int 668 audio_dev_register(audio_dev_t *d) 669 { 670 list_t *l; 671 audio_dev_t *srch; 672 int start; 673 674 /* 675 * Make sure we don't automatically unload. This prevents 676 * loss of hardware settings when no audio clients are 677 * running. 678 */ 679 (void) ddi_prop_update_int(DDI_DEV_T_NONE, d->d_dip, 680 DDI_NO_AUTODETACH, 1); 681 682 /* 683 * This does an in-order insertion, finding the first available 684 * free index. "Special" devices (ones without any actual engines) 685 * are all numbered 0. There should only be one of them anyway. 686 * All others start at one. 687 */ 688 if (d->d_flags & DEV_SNDSTAT_CAP) { 689 start = 0; 690 } else { 691 start = 1; 692 } 693 d->d_index = start; 694 rw_enter(&auimpl_dev_lock, RW_WRITER); 695 l = &auimpl_devs_by_index; 696 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 697 /* skip over special nodes */ 698 if (srch->d_index < start) 699 continue; 700 if (srch->d_index > d->d_index) { 701 /* found a free spot! */ 702 break; 703 } 704 d->d_index++; 705 } 706 /* 707 * NB: If srch is NULL, then list_insert_before puts 708 * it on the tail of the list. So if we didn't find a 709 * hole, then that's where we want it. 710 */ 711 list_insert_before(l, srch, d); 712 713 /* insert in order by number */ 714 l = &auimpl_devs_by_number; 715 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 716 if (srch->d_number >= d->d_number) { 717 break; 718 } 719 } 720 list_insert_before(l, srch, d); 721 722 rw_exit(&auimpl_dev_lock); 723 724 if (auimpl_create_minors(d) != 0) { 725 rw_enter(&auimpl_dev_lock, RW_WRITER); 726 auimpl_remove_minors(d); 727 list_remove(&auimpl_devs_by_index, d); 728 list_remove(&auimpl_devs_by_number, d); 729 rw_exit(&auimpl_dev_lock); 730 return (DDI_FAILURE); 731 } 732 733 return (DDI_SUCCESS); 734 } 735 736 int 737 audio_dev_unregister(audio_dev_t *d) 738 { 739 rw_enter(&auimpl_dev_lock, RW_WRITER); 740 741 mutex_enter(&d->d_lock); 742 /* if we are still in use, we can't unregister */ 743 if (d->d_refcnt) { 744 mutex_exit(&d->d_lock); 745 rw_exit(&auimpl_dev_lock); 746 return (DDI_FAILURE); 747 } 748 auimpl_remove_minors(d); 749 list_remove(&auimpl_devs_by_index, d); 750 list_remove(&auimpl_devs_by_number, d); 751 mutex_exit(&d->d_lock); 752 753 rw_exit(&auimpl_dev_lock); 754 755 return (DDI_SUCCESS); 756 } 757 758 static int 759 auimpl_engine_ksupdate(kstat_t *ksp, int rw) 760 { 761 audio_engine_t *e = ksp->ks_private; 762 struct audio_stats *st = &e->e_stats; 763 764 if (rw == KSTAT_WRITE) { 765 return (EACCES); 766 } 767 768 mutex_enter(&e->e_lock); 769 st->st_head.value.ui64 = e->e_head; 770 st->st_tail.value.ui64 = e->e_tail; 771 st->st_flags.value.ui32 = e->e_flags; 772 st->st_fragfr.value.ui32 = e->e_fragfr; 773 st->st_nfrags.value.ui32 = e->e_nfrags; 774 st->st_framesz.value.ui32 = e->e_framesz; 775 st->st_nbytes.value.ui32 = e->e_nbytes; 776 st->st_hidx.value.ui32 = e->e_hidx; 777 st->st_tidx.value.ui32 = e->e_tidx; 778 st->st_format.value.ui32 = e->e_format; 779 st->st_nchan.value.ui32 = e->e_nchan; 780 st->st_rate.value.ui32 = e->e_rate; 781 st->st_intrs.value.ui32 = e->e_intrs; 782 st->st_errors.value.ui32 = e->e_errors; 783 st->st_suspended.value.ui32 = e->e_suspended; 784 mutex_exit(&e->e_lock); 785 786 return (0); 787 } 788 789 static void 790 auimpl_engine_ksinit(audio_dev_t *d, audio_engine_t *e) 791 { 792 char name[32]; 793 struct audio_stats *st; 794 795 (void) snprintf(name, sizeof (name), "engine_%d", e->e_num); 796 797 e->e_ksp = kstat_create(ddi_driver_name(d->d_dip), d->d_instance, 798 name, "misc", KSTAT_TYPE_NAMED, 799 sizeof (struct audio_stats) / sizeof (kstat_named_t), 0); 800 801 if (e->e_ksp == NULL) { 802 audio_dev_warn(d, "unable to initialize kstats"); 803 return; 804 } 805 806 st = &e->e_stats; 807 e->e_ksp->ks_data = st; 808 e->e_ksp->ks_private = e; 809 e->e_ksp->ks_lock = NULL; 810 e->e_ksp->ks_update = auimpl_engine_ksupdate; 811 kstat_named_init(&st->st_head, "head", KSTAT_DATA_UINT64); 812 kstat_named_init(&st->st_tail, "tail", KSTAT_DATA_UINT64); 813 kstat_named_init(&st->st_flags, "flags", KSTAT_DATA_UINT32); 814 kstat_named_init(&st->st_fragfr, "fragfr", KSTAT_DATA_UINT32); 815 kstat_named_init(&st->st_nfrags, "nfrags", KSTAT_DATA_UINT32); 816 kstat_named_init(&st->st_framesz, "framesz", KSTAT_DATA_UINT32); 817 kstat_named_init(&st->st_nbytes, "nbytes", KSTAT_DATA_UINT32); 818 kstat_named_init(&st->st_hidx, "hidx", KSTAT_DATA_UINT32); 819 kstat_named_init(&st->st_tidx, "tidx", KSTAT_DATA_UINT32); 820 kstat_named_init(&st->st_format, "format", KSTAT_DATA_UINT32); 821 kstat_named_init(&st->st_nchan, "channels", KSTAT_DATA_UINT32); 822 kstat_named_init(&st->st_rate, "rate", KSTAT_DATA_UINT32); 823 kstat_named_init(&st->st_intrs, "intrhz", KSTAT_DATA_UINT32); 824 kstat_named_init(&st->st_errors, "errors", KSTAT_DATA_UINT32); 825 kstat_named_init(&st->st_suspended, "suspended", KSTAT_DATA_UINT32); 826 kstat_install(e->e_ksp); 827 } 828 829 void 830 audio_dev_add_engine(audio_dev_t *d, audio_engine_t *e) 831 { 832 e->e_num = d->d_engno++; 833 834 mutex_enter(&d->d_lock); 835 836 auimpl_engine_ksinit(d, e); 837 838 /* check for duplex */ 839 if ((e->e_flags & ENGINE_OUTPUT_CAP) && (d->d_flags & DEV_INPUT_CAP)) { 840 d->d_flags |= DEV_DUPLEX_CAP; 841 } 842 if ((e->e_flags & ENGINE_INPUT_CAP) && (d->d_flags & DEV_OUTPUT_CAP)) { 843 d->d_flags |= DEV_DUPLEX_CAP; 844 } 845 /* add in the direction caps -- must be done after duplex above */ 846 if (e->e_flags & ENGINE_OUTPUT_CAP) { 847 d->d_flags |= DEV_OUTPUT_CAP; 848 } 849 if (e->e_flags & ENGINE_INPUT_CAP) { 850 d->d_flags |= DEV_INPUT_CAP; 851 } 852 853 list_insert_tail(&d->d_engines, e); 854 e->e_dev = d; 855 mutex_exit(&d->d_lock); 856 } 857 858 void 859 audio_dev_remove_engine(audio_dev_t *d, audio_engine_t *e) 860 { 861 mutex_enter(&d->d_lock); 862 list_remove(&d->d_engines, e); 863 e->e_dev = NULL; 864 if (e->e_ksp) 865 kstat_delete(e->e_ksp); 866 e->e_ksp = NULL; 867 mutex_exit(&d->d_lock); 868 } 869 870 /* 871 * Change the number. 872 */ 873 void 874 auclnt_set_dev_number(audio_dev_t *d, int num) 875 { 876 list_t *l = &auimpl_devs_by_number; 877 audio_dev_t *srch; 878 879 /* reorder our list */ 880 rw_enter(&auimpl_dev_lock, RW_WRITER); 881 d->d_number = num; 882 list_remove(l, d); 883 for (srch = list_head(l); srch; srch = list_next(l, srch)) { 884 if (srch->d_number >= d->d_number) { 885 break; 886 } 887 } 888 list_insert_before(l, srch, d); 889 890 rw_exit(&auimpl_dev_lock); 891 } 892 893 void 894 auclnt_walk_devs(int (*walker)(audio_dev_t *, void *), void *arg) 895 { 896 audio_dev_t *d; 897 boolean_t cont; 898 list_t *l; 899 900 l = &auimpl_devs_by_index; 901 rw_enter(&auimpl_dev_lock, RW_READER); 902 for (d = list_head(l); d; d = list_next(l, d)) { 903 mutex_enter(&d->d_lock); 904 cont = walker(d, arg); 905 mutex_exit(&d->d_lock); 906 if (cont == AUDIO_WALK_STOP) 907 break; 908 } 909 rw_exit(&auimpl_dev_lock); 910 } 911 912 void 913 auclnt_walk_devs_by_number(int (*walker)(audio_dev_t *, void *), void *arg) 914 { 915 audio_dev_t *d; 916 boolean_t cont; 917 list_t *l; 918 919 l = &auimpl_devs_by_number; 920 rw_enter(&auimpl_dev_lock, RW_READER); 921 for (d = list_head(l); d; d = list_next(l, d)) { 922 mutex_enter(&d->d_lock); 923 cont = walker(d, arg); 924 mutex_exit(&d->d_lock); 925 if (cont == AUDIO_WALK_STOP) 926 break; 927 } 928 rw_exit(&auimpl_dev_lock); 929 } 930 931 void 932 auclnt_dev_walk_engines(audio_dev_t *d, 933 int (*walker)(audio_engine_t *, void *), 934 void *arg) 935 { 936 audio_engine_t *e; 937 list_t *l = &d->d_engines; 938 939 mutex_enter(&d->d_lock); 940 for (e = list_head(l); e != NULL; e = list_next(l, e)) { 941 if (walker(e, arg) == AUDIO_WALK_STOP) { 942 break; 943 } 944 } 945 mutex_exit(&d->d_lock); 946 } 947 948 int 949 auclnt_engine_get_format(audio_engine_t *e) 950 { 951 return (ENG_FORMAT(e)); 952 } 953 954 int 955 auclnt_engine_get_channels(audio_engine_t *e) 956 { 957 return (ENG_CHANNELS(e)); 958 } 959 960 int 961 auclnt_engine_get_rate(audio_engine_t *e) 962 { 963 return (ENG_RATE(e)); 964 } 965 966 unsigned 967 auclnt_engine_get_capab(audio_engine_t *e) 968 { 969 unsigned capab = 0; 970 971 if (e->e_flags & ENGINE_INPUT_CAP) { 972 capab |= AUDIO_CLIENT_CAP_RECORD; 973 } 974 if (e->e_flags & ENGINE_OUTPUT_CAP) { 975 capab |= AUDIO_CLIENT_CAP_PLAY; 976 } 977 return (capab); 978 } 979 980 static void 981 auimpl_walk_engines(int (*walker)(audio_engine_t *, void *), void *arg) 982 { 983 audio_dev_t *d; 984 audio_engine_t *e; 985 list_t *l1; 986 list_t *l2; 987 boolean_t done = B_FALSE; 988 989 rw_enter(&auimpl_dev_lock, RW_READER); 990 l1 = &auimpl_devs_by_index; 991 for (d = list_head(l1); d; d = list_next(l1, d)) { 992 mutex_enter(&d->d_lock); 993 l2 = &d->d_engines; 994 for (e = list_head(l2); e; e = list_next(l2, e)) { 995 if (walker(e, arg) == AUDIO_WALK_STOP) { 996 done = B_TRUE; 997 break; 998 } 999 } 1000 mutex_exit(&d->d_lock); 1001 if (done) 1002 break; 1003 } 1004 rw_exit(&auimpl_dev_lock); 1005 } 1006 1007 /* 1008 * This function suspends an engine. The intent is to pause the 1009 * engine temporarily so that it does not underrun while user threads 1010 * are suspended. The driver is still responsible for actually doing 1011 * the driver suspend work -- all this does is put the engine in a 1012 * paused state. It does not prevent, for example, threads from 1013 * accessing the hardware. 1014 * 1015 * A properly implemented driver won't even be aware of the existence 1016 * of this routine -- the driver will just handle the suspend & 1017 * resume. At the point of suspend & resume, the driver will see that 1018 * the engines are not running (as if all threads had "paused" it). 1019 * 1020 * Failure to execute either of the routines below is not critical, 1021 * but will probably lead to underruns and overflows as the kernel 1022 * driver gets resumed well in advance of the time when user threads 1023 * are ready to start operation. 1024 */ 1025 static int 1026 auimpl_engine_suspend(audio_engine_t *e, void *dontcare) 1027 { 1028 _NOTE(ARGUNUSED(dontcare)); 1029 1030 mutex_enter(&e->e_lock); 1031 e->e_suspended = B_TRUE; 1032 mutex_exit(&e->e_lock); 1033 1034 return (AUDIO_WALK_CONTINUE); 1035 } 1036 1037 static int 1038 auimpl_engine_resume(audio_engine_t *e, void *dontcare) 1039 { 1040 _NOTE(ARGUNUSED(dontcare)); 1041 mutex_enter(&e->e_lock); 1042 e->e_suspended = B_FALSE; 1043 mutex_exit(&e->e_lock); 1044 return (AUDIO_WALK_CONTINUE); 1045 } 1046 1047 boolean_t 1048 auimpl_cpr(void *arg, int code) 1049 { 1050 _NOTE(ARGUNUSED(arg)); 1051 1052 switch (code) { 1053 case CB_CODE_CPR_CHKPT: 1054 auimpl_walk_engines(auimpl_engine_suspend, NULL); 1055 return (B_TRUE); 1056 1057 case CB_CODE_CPR_RESUME: 1058 auimpl_walk_engines(auimpl_engine_resume, NULL); 1059 return (B_TRUE); 1060 1061 default: 1062 return (B_FALSE); 1063 } 1064 } 1065 1066 static callb_id_t auimpl_cpr_id = 0; 1067 1068 void 1069 auimpl_dev_init(void) 1070 { 1071 rw_init(&auimpl_dev_lock, NULL, RW_DRIVER, NULL); 1072 list_create(&auimpl_devs_by_index, sizeof (struct audio_dev), 1073 offsetof(struct audio_dev, d_by_index)); 1074 list_create(&auimpl_devs_by_number, sizeof (struct audio_dev), 1075 offsetof(struct audio_dev, d_by_number)); 1076 1077 /* 1078 * We "borrow" the CB_CL_CPR_PM class, which gets executed at 1079 * about the right time for us. It would be nice to have a 1080 * new CB_CL_CPR_AUDIO class, but it isn't critical at this 1081 * point. 1082 * 1083 * Note that we don't care about our thread id. 1084 */ 1085 auimpl_cpr_id = callb_add(auimpl_cpr, NULL, CB_CL_CPR_PM, "audio_cpr"); 1086 } 1087 1088 void 1089 auimpl_dev_fini(void) 1090 { 1091 (void) callb_delete(auimpl_cpr_id); 1092 list_destroy(&auimpl_devs_by_index); 1093 list_destroy(&auimpl_devs_by_number); 1094 rw_destroy(&auimpl_dev_lock); 1095 } 1096 1097 void 1098 audio_engine_set_private(audio_engine_t *eng, void *prv) 1099 { 1100 eng->e_private = prv; 1101 } 1102 1103 void * 1104 audio_engine_get_private(audio_engine_t *eng) 1105 { 1106 return (eng->e_private); 1107 } 1108 1109 void 1110 audio_dump_bytes(const uint8_t *w, int dcount) 1111 { 1112 char line[64]; 1113 char *s; 1114 int i; 1115 const int wrap = 16; 1116 1117 s = line; 1118 line[0] = 0; 1119 1120 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1121 for (i = 0; i < dcount; i++) { 1122 1123 (void) sprintf(s, " %02x", *w); 1124 s += strlen(s); 1125 w++; 1126 1127 if ((i % wrap) == (wrap - 1)) { 1128 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1129 line[0] = 0; 1130 s = line; 1131 } 1132 } 1133 1134 if ((i % wrap) != 0) { 1135 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1136 } 1137 } 1138 1139 void 1140 audio_dump_words(const uint16_t *w, int dcount) 1141 { 1142 char line[64]; 1143 char *s; 1144 int i; 1145 const int wrap = 8; 1146 1147 s = line; 1148 line[0] = 0; 1149 1150 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1151 for (i = 0; i < dcount; i++) { 1152 1153 (void) sprintf(s, " %04x", *w); 1154 s += strlen(s); 1155 w++; 1156 1157 if ((i % wrap) == (wrap - 1)) { 1158 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1159 line[0] = 0; 1160 s = line; 1161 } 1162 } 1163 1164 if ((i % wrap) != 0) { 1165 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1166 } 1167 } 1168 1169 void 1170 audio_dump_dwords(const uint32_t *w, int dcount) 1171 { 1172 char line[128]; 1173 char *s; 1174 int i; 1175 const int wrap = 4; 1176 1177 s = line; 1178 line[0] = 0; 1179 1180 cmn_err(CE_NOTE, "starting @ %p", (void *)w); 1181 for (i = 0; i < dcount; i++) { 1182 1183 (void) sprintf(s, " %08x", *w); 1184 s += strlen(s); 1185 w++; 1186 1187 if ((i % wrap) == (wrap - 1)) { 1188 cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line); 1189 line[0] = 0; 1190 s = line; 1191 } 1192 } 1193 1194 if ((i % wrap) != 0) { 1195 cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line); 1196 } 1197 } 1198