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