19484Sgarrett.damore@Sun.COM /*
29484Sgarrett.damore@Sun.COM * CDDL HEADER START
39484Sgarrett.damore@Sun.COM *
49484Sgarrett.damore@Sun.COM * The contents of this file are subject to the terms of the
59484Sgarrett.damore@Sun.COM * Common Development and Distribution License (the "License").
69484Sgarrett.damore@Sun.COM * You may not use this file except in compliance with the License.
79484Sgarrett.damore@Sun.COM *
89484Sgarrett.damore@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99484Sgarrett.damore@Sun.COM * or http://www.opensolaris.org/os/licensing.
109484Sgarrett.damore@Sun.COM * See the License for the specific language governing permissions
119484Sgarrett.damore@Sun.COM * and limitations under the License.
129484Sgarrett.damore@Sun.COM *
139484Sgarrett.damore@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149484Sgarrett.damore@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159484Sgarrett.damore@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169484Sgarrett.damore@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179484Sgarrett.damore@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189484Sgarrett.damore@Sun.COM *
199484Sgarrett.damore@Sun.COM * CDDL HEADER END
209484Sgarrett.damore@Sun.COM */
219484Sgarrett.damore@Sun.COM /*
229484Sgarrett.damore@Sun.COM * Copyright (C) 4Front Technologies 1996-2008.
239484Sgarrett.damore@Sun.COM *
2412165Sgdamore@opensolaris.org * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
259484Sgarrett.damore@Sun.COM */
269484Sgarrett.damore@Sun.COM
279484Sgarrett.damore@Sun.COM #include <sys/types.h>
289484Sgarrett.damore@Sun.COM #include <sys/sysmacros.h>
299484Sgarrett.damore@Sun.COM #include <sys/list.h>
309484Sgarrett.damore@Sun.COM #include <sys/file.h>
319484Sgarrett.damore@Sun.COM #include <sys/open.h>
329484Sgarrett.damore@Sun.COM #include <sys/stat.h>
339484Sgarrett.damore@Sun.COM #include <sys/errno.h>
349484Sgarrett.damore@Sun.COM #include <sys/atomic.h>
359484Sgarrett.damore@Sun.COM #include <sys/ddi.h>
369484Sgarrett.damore@Sun.COM #include <sys/sunddi.h>
379484Sgarrett.damore@Sun.COM
389484Sgarrett.damore@Sun.COM #include "audio_impl.h"
399484Sgarrett.damore@Sun.COM
409484Sgarrett.damore@Sun.COM /*
419484Sgarrett.damore@Sun.COM * Audio Client implementation.
429484Sgarrett.damore@Sun.COM */
439484Sgarrett.damore@Sun.COM
449484Sgarrett.damore@Sun.COM /*
459484Sgarrett.damore@Sun.COM * Attenuation table for dB->linear conversion. Indexed in steps of
469484Sgarrett.damore@Sun.COM * 0.5 dB. Table size is 25 dB (first entry is handled as mute).
479484Sgarrett.damore@Sun.COM *
489484Sgarrett.damore@Sun.COM * Notably, the last item in table is taken as 0 dB (i.e. maximum volume).
499484Sgarrett.damore@Sun.COM *
509484Sgarrett.damore@Sun.COM * Table contents can be calculated as follows (requires sunmath library):
519484Sgarrett.damore@Sun.COM *
529484Sgarrett.damore@Sun.COM * scale = AUDIO_VOL_SCALE;
539484Sgarrett.damore@Sun.COM * for (i = -50; i <= 0; i++) {
549484Sgarrett.damore@Sun.COM * x = exp10(0.05 * i);
559484Sgarrett.damore@Sun.COM * printf("%d: %f %.0f\n", i, x, trunc(x * scale));
569484Sgarrett.damore@Sun.COM * }
579484Sgarrett.damore@Sun.COM *
589484Sgarrett.damore@Sun.COM */
599484Sgarrett.damore@Sun.COM
6010570Sgdamore@opensolaris.org static const uint16_t auimpl_db_table[AUDIO_DB_SIZE + 1] = {
619484Sgarrett.damore@Sun.COM 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
629484Sgarrett.damore@Sun.COM 2, 2, 3, 3, 4, 4, 5, 5, 6, 7,
639484Sgarrett.damore@Sun.COM 8, 9, 10, 11, 12, 14, 16, 18, 20, 22,
649484Sgarrett.damore@Sun.COM 25, 28, 32, 36, 40, 45, 51, 57, 64, 72,
659484Sgarrett.damore@Sun.COM 80, 90, 101, 114, 128, 143, 161, 181, 203, 228,
669484Sgarrett.damore@Sun.COM 256
679484Sgarrett.damore@Sun.COM };
689484Sgarrett.damore@Sun.COM
6910570Sgdamore@opensolaris.org static list_t auimpl_clients;
7010570Sgdamore@opensolaris.org static krwlock_t auimpl_client_lock;
7110570Sgdamore@opensolaris.org static audio_client_ops_t *audio_client_ops[AUDIO_MN_TYPE_MASK + 1];
7210570Sgdamore@opensolaris.org
739484Sgarrett.damore@Sun.COM void *
auclnt_get_private(audio_client_t * c)749484Sgarrett.damore@Sun.COM auclnt_get_private(audio_client_t *c)
759484Sgarrett.damore@Sun.COM {
769484Sgarrett.damore@Sun.COM return (c->c_private);
779484Sgarrett.damore@Sun.COM }
789484Sgarrett.damore@Sun.COM
799484Sgarrett.damore@Sun.COM void
auclnt_set_private(audio_client_t * c,void * private)809484Sgarrett.damore@Sun.COM auclnt_set_private(audio_client_t *c, void *private)
819484Sgarrett.damore@Sun.COM {
829484Sgarrett.damore@Sun.COM c->c_private = private;
839484Sgarrett.damore@Sun.COM }
849484Sgarrett.damore@Sun.COM
859484Sgarrett.damore@Sun.COM int
auclnt_set_rate(audio_stream_t * sp,int rate)869484Sgarrett.damore@Sun.COM auclnt_set_rate(audio_stream_t *sp, int rate)
879484Sgarrett.damore@Sun.COM {
889484Sgarrett.damore@Sun.COM audio_parms_t parms;
899484Sgarrett.damore@Sun.COM int rv = 0;
909484Sgarrett.damore@Sun.COM
919484Sgarrett.damore@Sun.COM /* basic sanity checks! */
929484Sgarrett.damore@Sun.COM if ((rate < 5000) || (rate > 192000)) {
939484Sgarrett.damore@Sun.COM return (EINVAL);
949484Sgarrett.damore@Sun.COM }
9512165Sgdamore@opensolaris.org if (rate != sp->s_user_parms->p_rate) {
969484Sgarrett.damore@Sun.COM parms.p_rate = rate;
9712165Sgdamore@opensolaris.org rv = auimpl_engine_setup(sp, 0, &parms, FORMAT_MSK_RATE);
989484Sgarrett.damore@Sun.COM }
999484Sgarrett.damore@Sun.COM return (rv);
1009484Sgarrett.damore@Sun.COM }
1019484Sgarrett.damore@Sun.COM
1029484Sgarrett.damore@Sun.COM int
auclnt_get_rate(audio_stream_t * sp)1039484Sgarrett.damore@Sun.COM auclnt_get_rate(audio_stream_t *sp)
1049484Sgarrett.damore@Sun.COM {
1059484Sgarrett.damore@Sun.COM return (sp->s_user_parms->p_rate);
1069484Sgarrett.damore@Sun.COM }
1079484Sgarrett.damore@Sun.COM
10811936Sgdamore@opensolaris.org uint_t
auclnt_get_fragsz(audio_stream_t * sp)1099484Sgarrett.damore@Sun.COM auclnt_get_fragsz(audio_stream_t *sp)
1109484Sgarrett.damore@Sun.COM {
1119484Sgarrett.damore@Sun.COM return (sp->s_fragbytes);
1129484Sgarrett.damore@Sun.COM }
1139484Sgarrett.damore@Sun.COM
11411936Sgdamore@opensolaris.org uint_t
auclnt_get_framesz(audio_stream_t * sp)1159484Sgarrett.damore@Sun.COM auclnt_get_framesz(audio_stream_t *sp)
1169484Sgarrett.damore@Sun.COM {
1179484Sgarrett.damore@Sun.COM return (sp->s_framesz);
1189484Sgarrett.damore@Sun.COM }
1199484Sgarrett.damore@Sun.COM
12011936Sgdamore@opensolaris.org uint_t
auclnt_get_nfrags(audio_stream_t * sp)1219484Sgarrett.damore@Sun.COM auclnt_get_nfrags(audio_stream_t *sp)
1229484Sgarrett.damore@Sun.COM {
1239484Sgarrett.damore@Sun.COM return (sp->s_nfrags);
1249484Sgarrett.damore@Sun.COM }
1259484Sgarrett.damore@Sun.COM
12611936Sgdamore@opensolaris.org uint_t
auclnt_get_nframes(audio_stream_t * sp)1279484Sgarrett.damore@Sun.COM auclnt_get_nframes(audio_stream_t *sp)
1289484Sgarrett.damore@Sun.COM {
1299484Sgarrett.damore@Sun.COM return (sp->s_nframes);
1309484Sgarrett.damore@Sun.COM }
1319484Sgarrett.damore@Sun.COM
1329558Sgdamore@opensolaris.org void
auclnt_set_latency(audio_stream_t * sp,uint_t frags,uint_t bytes)13311936Sgdamore@opensolaris.org auclnt_set_latency(audio_stream_t *sp, uint_t frags, uint_t bytes)
1349558Sgdamore@opensolaris.org {
1359558Sgdamore@opensolaris.org mutex_enter(&sp->s_lock);
1369558Sgdamore@opensolaris.org sp->s_hintfrags = (uint16_t)frags;
1379558Sgdamore@opensolaris.org sp->s_hintsz = bytes;
1389558Sgdamore@opensolaris.org mutex_exit(&sp->s_lock);
1399558Sgdamore@opensolaris.org }
1409558Sgdamore@opensolaris.org
1419484Sgarrett.damore@Sun.COM uint64_t
auclnt_get_head(audio_stream_t * sp)1429484Sgarrett.damore@Sun.COM auclnt_get_head(audio_stream_t *sp)
1439484Sgarrett.damore@Sun.COM {
1449484Sgarrett.damore@Sun.COM return (sp->s_head);
1459484Sgarrett.damore@Sun.COM }
1469484Sgarrett.damore@Sun.COM
1479484Sgarrett.damore@Sun.COM uint64_t
auclnt_get_tail(audio_stream_t * sp)1489484Sgarrett.damore@Sun.COM auclnt_get_tail(audio_stream_t *sp)
1499484Sgarrett.damore@Sun.COM {
1509484Sgarrett.damore@Sun.COM return (sp->s_tail);
1519484Sgarrett.damore@Sun.COM }
1529484Sgarrett.damore@Sun.COM
15311936Sgdamore@opensolaris.org uint_t
auclnt_get_hidx(audio_stream_t * sp)1549484Sgarrett.damore@Sun.COM auclnt_get_hidx(audio_stream_t *sp)
1559484Sgarrett.damore@Sun.COM {
1569484Sgarrett.damore@Sun.COM return (sp->s_hidx);
1579484Sgarrett.damore@Sun.COM }
1589484Sgarrett.damore@Sun.COM
15911936Sgdamore@opensolaris.org uint_t
auclnt_get_tidx(audio_stream_t * sp)1609484Sgarrett.damore@Sun.COM auclnt_get_tidx(audio_stream_t *sp)
1619484Sgarrett.damore@Sun.COM {
1629484Sgarrett.damore@Sun.COM return (sp->s_tidx);
1639484Sgarrett.damore@Sun.COM }
1649484Sgarrett.damore@Sun.COM
1659484Sgarrett.damore@Sun.COM audio_stream_t *
auclnt_input_stream(audio_client_t * c)1669484Sgarrett.damore@Sun.COM auclnt_input_stream(audio_client_t *c)
1679484Sgarrett.damore@Sun.COM {
1689484Sgarrett.damore@Sun.COM return (&c->c_istream);
1699484Sgarrett.damore@Sun.COM }
1709484Sgarrett.damore@Sun.COM
1719484Sgarrett.damore@Sun.COM audio_stream_t *
auclnt_output_stream(audio_client_t * c)1729484Sgarrett.damore@Sun.COM auclnt_output_stream(audio_client_t *c)
1739484Sgarrett.damore@Sun.COM {
1749484Sgarrett.damore@Sun.COM return (&c->c_ostream);
1759484Sgarrett.damore@Sun.COM }
1769484Sgarrett.damore@Sun.COM
17711936Sgdamore@opensolaris.org uint_t
auclnt_get_count(audio_stream_t * sp)1789484Sgarrett.damore@Sun.COM auclnt_get_count(audio_stream_t *sp)
1799484Sgarrett.damore@Sun.COM {
18011936Sgdamore@opensolaris.org uint_t count;
1819484Sgarrett.damore@Sun.COM
1829484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
1839484Sgarrett.damore@Sun.COM ASSERT((sp->s_head - sp->s_tail) <= sp->s_nframes);
18411936Sgdamore@opensolaris.org count = (uint_t)(sp->s_head - sp->s_tail);
1859484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
1869484Sgarrett.damore@Sun.COM
1879484Sgarrett.damore@Sun.COM return (count);
1889484Sgarrett.damore@Sun.COM }
1899484Sgarrett.damore@Sun.COM
19011936Sgdamore@opensolaris.org uint_t
auclnt_consume(audio_stream_t * sp,uint_t n)19111936Sgdamore@opensolaris.org auclnt_consume(audio_stream_t *sp, uint_t n)
1929484Sgarrett.damore@Sun.COM {
1939484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
1949484Sgarrett.damore@Sun.COM
1959484Sgarrett.damore@Sun.COM ASSERT(sp == &sp->s_client->c_istream);
1969484Sgarrett.damore@Sun.COM n = max(n, sp->s_head - sp->s_tail);
1979484Sgarrett.damore@Sun.COM sp->s_tail += n;
1989484Sgarrett.damore@Sun.COM sp->s_tidx += n;
1999484Sgarrett.damore@Sun.COM if (sp->s_tidx >= sp->s_nframes) {
2009484Sgarrett.damore@Sun.COM sp->s_tidx -= sp->s_nframes;
2019484Sgarrett.damore@Sun.COM }
2029484Sgarrett.damore@Sun.COM
2039484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
2049484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < sp->s_nframes);
2059484Sgarrett.damore@Sun.COM
2069484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
2079484Sgarrett.damore@Sun.COM
2089484Sgarrett.damore@Sun.COM return (n);
2099484Sgarrett.damore@Sun.COM }
2109484Sgarrett.damore@Sun.COM
21111936Sgdamore@opensolaris.org uint_t
auclnt_consume_data(audio_stream_t * sp,caddr_t dst,uint_t n)21211936Sgdamore@opensolaris.org auclnt_consume_data(audio_stream_t *sp, caddr_t dst, uint_t n)
2139484Sgarrett.damore@Sun.COM {
21411936Sgdamore@opensolaris.org uint_t nframes;
21511936Sgdamore@opensolaris.org uint_t framesz;
21611936Sgdamore@opensolaris.org uint_t cnt;
2179484Sgarrett.damore@Sun.COM caddr_t data;
2189484Sgarrett.damore@Sun.COM
2199484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
2209484Sgarrett.damore@Sun.COM
2219484Sgarrett.damore@Sun.COM nframes = sp->s_nframes;
2229484Sgarrett.damore@Sun.COM framesz = sp->s_framesz;
2239484Sgarrett.damore@Sun.COM
2249484Sgarrett.damore@Sun.COM ASSERT(sp == &sp->s_client->c_istream);
2259484Sgarrett.damore@Sun.COM ASSERT(sp->s_head >= sp->s_tail);
2269484Sgarrett.damore@Sun.COM ASSERT(sp->s_tidx < nframes);
2279484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < nframes);
2289484Sgarrett.damore@Sun.COM
2299484Sgarrett.damore@Sun.COM cnt = n = min(n, sp->s_head - sp->s_tail);
2309484Sgarrett.damore@Sun.COM data = sp->s_data + (sp->s_tidx * framesz);
2319484Sgarrett.damore@Sun.COM do {
23211936Sgdamore@opensolaris.org uint_t nf, nb;
2339484Sgarrett.damore@Sun.COM
2349484Sgarrett.damore@Sun.COM nf = min(nframes - sp->s_tidx, n);
2359484Sgarrett.damore@Sun.COM nb = nf * framesz;
2369484Sgarrett.damore@Sun.COM
2379484Sgarrett.damore@Sun.COM bcopy(data, dst, nb);
2389484Sgarrett.damore@Sun.COM dst += nb;
2399484Sgarrett.damore@Sun.COM data += nb;
2409484Sgarrett.damore@Sun.COM
2419484Sgarrett.damore@Sun.COM n -= nf;
2429484Sgarrett.damore@Sun.COM sp->s_tail += nf;
2439484Sgarrett.damore@Sun.COM sp->s_tidx += nf;
2449484Sgarrett.damore@Sun.COM if (sp->s_tidx == nframes) {
2459484Sgarrett.damore@Sun.COM sp->s_tidx = 0;
2469484Sgarrett.damore@Sun.COM data = sp->s_data;
2479484Sgarrett.damore@Sun.COM }
2489484Sgarrett.damore@Sun.COM } while (n);
2499484Sgarrett.damore@Sun.COM
2509484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
2519484Sgarrett.damore@Sun.COM ASSERT(sp->s_tidx < nframes);
2529484Sgarrett.damore@Sun.COM
2539484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
2549484Sgarrett.damore@Sun.COM
2559484Sgarrett.damore@Sun.COM return (cnt);
2569484Sgarrett.damore@Sun.COM }
2579484Sgarrett.damore@Sun.COM
25811936Sgdamore@opensolaris.org uint_t
auclnt_produce(audio_stream_t * sp,uint_t n)25911936Sgdamore@opensolaris.org auclnt_produce(audio_stream_t *sp, uint_t n)
2609484Sgarrett.damore@Sun.COM {
2619484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
2629484Sgarrett.damore@Sun.COM
2639484Sgarrett.damore@Sun.COM ASSERT(sp == &sp->s_client->c_ostream);
2649484Sgarrett.damore@Sun.COM n = max(n, sp->s_nframes - (sp->s_head - sp->s_tail));
2659484Sgarrett.damore@Sun.COM sp->s_head += n;
2669484Sgarrett.damore@Sun.COM sp->s_hidx += n;
2679484Sgarrett.damore@Sun.COM if (sp->s_hidx >= sp->s_nframes) {
2689484Sgarrett.damore@Sun.COM sp->s_hidx -= sp->s_nframes;
2699484Sgarrett.damore@Sun.COM }
2709484Sgarrett.damore@Sun.COM
2719484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
2729484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < sp->s_nframes);
2739484Sgarrett.damore@Sun.COM
2749484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
2759484Sgarrett.damore@Sun.COM
2769484Sgarrett.damore@Sun.COM return (n);
2779484Sgarrett.damore@Sun.COM }
2789484Sgarrett.damore@Sun.COM
27911936Sgdamore@opensolaris.org uint_t
auclnt_produce_data(audio_stream_t * sp,caddr_t src,uint_t n)28011936Sgdamore@opensolaris.org auclnt_produce_data(audio_stream_t *sp, caddr_t src, uint_t n)
2819484Sgarrett.damore@Sun.COM {
28211936Sgdamore@opensolaris.org uint_t nframes;
28311936Sgdamore@opensolaris.org uint_t framesz;
28411936Sgdamore@opensolaris.org uint_t cnt;
2859484Sgarrett.damore@Sun.COM caddr_t data;
2869484Sgarrett.damore@Sun.COM
2879484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
2889484Sgarrett.damore@Sun.COM
2899484Sgarrett.damore@Sun.COM nframes = sp->s_nframes;
2909484Sgarrett.damore@Sun.COM framesz = sp->s_framesz;
2919484Sgarrett.damore@Sun.COM
2929484Sgarrett.damore@Sun.COM ASSERT(sp == &sp->s_client->c_ostream);
2939484Sgarrett.damore@Sun.COM ASSERT(sp->s_head >= sp->s_tail);
2949484Sgarrett.damore@Sun.COM ASSERT(sp->s_tidx < nframes);
2959484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < nframes);
2969484Sgarrett.damore@Sun.COM
2979484Sgarrett.damore@Sun.COM cnt = n = min(n, nframes - (sp->s_head - sp->s_tail));
2989484Sgarrett.damore@Sun.COM data = sp->s_data + (sp->s_hidx * framesz);
2999484Sgarrett.damore@Sun.COM do {
30011936Sgdamore@opensolaris.org uint_t nf, nb;
3019484Sgarrett.damore@Sun.COM
3029484Sgarrett.damore@Sun.COM nf = min(nframes - sp->s_hidx, n);
3039484Sgarrett.damore@Sun.COM nb = nf * framesz;
3049484Sgarrett.damore@Sun.COM
3059484Sgarrett.damore@Sun.COM bcopy(src, data, nb);
3069484Sgarrett.damore@Sun.COM
3079484Sgarrett.damore@Sun.COM src += nb;
3089484Sgarrett.damore@Sun.COM data += nb;
3099484Sgarrett.damore@Sun.COM
3109484Sgarrett.damore@Sun.COM n -= nf;
3119484Sgarrett.damore@Sun.COM sp->s_head += nf;
3129484Sgarrett.damore@Sun.COM sp->s_hidx += nf;
3139484Sgarrett.damore@Sun.COM if (sp->s_hidx == nframes) {
3149484Sgarrett.damore@Sun.COM sp->s_hidx = 0;
3159484Sgarrett.damore@Sun.COM data = sp->s_data;
3169484Sgarrett.damore@Sun.COM }
3179484Sgarrett.damore@Sun.COM } while (n);
3189484Sgarrett.damore@Sun.COM
3199484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
3209484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < nframes);
3219484Sgarrett.damore@Sun.COM
3229484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
3239484Sgarrett.damore@Sun.COM
3249484Sgarrett.damore@Sun.COM return (cnt);
3259484Sgarrett.damore@Sun.COM }
3269484Sgarrett.damore@Sun.COM
3279484Sgarrett.damore@Sun.COM int
auclnt_read(audio_client_t * c,struct uio * uio)3289484Sgarrett.damore@Sun.COM auclnt_read(audio_client_t *c, struct uio *uio)
3299484Sgarrett.damore@Sun.COM {
3309484Sgarrett.damore@Sun.COM audio_stream_t *sp = &c->c_istream;
33111936Sgdamore@opensolaris.org uint_t cnt;
3329484Sgarrett.damore@Sun.COM int rv = 0;
3339484Sgarrett.damore@Sun.COM offset_t loff;
3349484Sgarrett.damore@Sun.COM int eagain;
33511936Sgdamore@opensolaris.org uint_t tidx;
33611936Sgdamore@opensolaris.org uint_t framesz;
3379484Sgarrett.damore@Sun.COM
3389484Sgarrett.damore@Sun.COM loff = uio->uio_loffset;
3399484Sgarrett.damore@Sun.COM eagain = EAGAIN;
3409484Sgarrett.damore@Sun.COM
3419484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
3429484Sgarrett.damore@Sun.COM
3439484Sgarrett.damore@Sun.COM if ((!sp->s_paused) && (!sp->s_running)) {
3449484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
3459484Sgarrett.damore@Sun.COM auclnt_start(sp);
3469484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
3479484Sgarrett.damore@Sun.COM }
3489484Sgarrett.damore@Sun.COM
34911936Sgdamore@opensolaris.org
35011936Sgdamore@opensolaris.org framesz = sp->s_framesz;
35111936Sgdamore@opensolaris.org
3529484Sgarrett.damore@Sun.COM ASSERT(sp->s_head >= sp->s_tail);
3539484Sgarrett.damore@Sun.COM ASSERT(sp->s_tidx < sp->s_nframes);
3549484Sgarrett.damore@Sun.COM
35511936Sgdamore@opensolaris.org while (uio->uio_resid >= framesz) {
3569484Sgarrett.damore@Sun.COM
3579484Sgarrett.damore@Sun.COM while ((cnt = (sp->s_head - sp->s_tail)) == 0) {
3589484Sgarrett.damore@Sun.COM if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
3599484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
3609484Sgarrett.damore@Sun.COM return (eagain);
3619484Sgarrett.damore@Sun.COM }
3629484Sgarrett.damore@Sun.COM if (cv_wait_sig(&sp->s_cv, &sp->s_lock) == 0) {
3639484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
3649484Sgarrett.damore@Sun.COM return (EINTR);
3659484Sgarrett.damore@Sun.COM }
3669484Sgarrett.damore@Sun.COM }
3679484Sgarrett.damore@Sun.COM
36811936Sgdamore@opensolaris.org tidx = sp->s_tidx;
36911936Sgdamore@opensolaris.org cnt = min(cnt, sp->s_nframes - tidx);
37011936Sgdamore@opensolaris.org cnt = min(cnt, (uio->uio_resid / framesz));
3719484Sgarrett.damore@Sun.COM
37211936Sgdamore@opensolaris.org mutex_exit(&sp->s_lock);
37311936Sgdamore@opensolaris.org rv = uiomove(sp->s_data + (tidx * framesz),
37411936Sgdamore@opensolaris.org cnt * framesz, UIO_READ, uio);
37511936Sgdamore@opensolaris.org
3769484Sgarrett.damore@Sun.COM uio->uio_loffset = loff;
3779484Sgarrett.damore@Sun.COM eagain = 0;
3789484Sgarrett.damore@Sun.COM
3799484Sgarrett.damore@Sun.COM if (rv != 0) {
3809484Sgarrett.damore@Sun.COM return (rv);
3819484Sgarrett.damore@Sun.COM }
3829484Sgarrett.damore@Sun.COM
38311936Sgdamore@opensolaris.org mutex_enter(&sp->s_lock);
3849484Sgarrett.damore@Sun.COM sp->s_tail += cnt;
3859484Sgarrett.damore@Sun.COM sp->s_tidx += cnt;
3869484Sgarrett.damore@Sun.COM if (sp->s_tidx == sp->s_nframes) {
3879484Sgarrett.damore@Sun.COM sp->s_tidx = 0;
3889484Sgarrett.damore@Sun.COM }
3899484Sgarrett.damore@Sun.COM }
3909484Sgarrett.damore@Sun.COM
3919484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
3929484Sgarrett.damore@Sun.COM ASSERT(sp->s_tidx < sp->s_nframes);
3939484Sgarrett.damore@Sun.COM
3949484Sgarrett.damore@Sun.COM /* round off any remaining partial bits */
3959484Sgarrett.damore@Sun.COM uio->uio_resid = 0;
3969484Sgarrett.damore@Sun.COM
3979484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
3989484Sgarrett.damore@Sun.COM
3999484Sgarrett.damore@Sun.COM return (rv);
4009484Sgarrett.damore@Sun.COM }
4019484Sgarrett.damore@Sun.COM
4029484Sgarrett.damore@Sun.COM int
auclnt_write(audio_client_t * c,struct uio * uio)4039484Sgarrett.damore@Sun.COM auclnt_write(audio_client_t *c, struct uio *uio)
4049484Sgarrett.damore@Sun.COM {
4059484Sgarrett.damore@Sun.COM audio_stream_t *sp = &c->c_ostream;
40611936Sgdamore@opensolaris.org uint_t cnt;
4079484Sgarrett.damore@Sun.COM int rv = 0;
4089484Sgarrett.damore@Sun.COM offset_t loff;
4099484Sgarrett.damore@Sun.COM int eagain;
41011936Sgdamore@opensolaris.org uint_t framesz;
41111936Sgdamore@opensolaris.org uint_t hidx;
4129484Sgarrett.damore@Sun.COM
4139484Sgarrett.damore@Sun.COM loff = uio->uio_loffset;
4149484Sgarrett.damore@Sun.COM eagain = EAGAIN;
4159484Sgarrett.damore@Sun.COM
4169484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
4179484Sgarrett.damore@Sun.COM
41811936Sgdamore@opensolaris.org framesz = sp->s_framesz;
41911936Sgdamore@opensolaris.org
4209484Sgarrett.damore@Sun.COM ASSERT(sp->s_head >= sp->s_tail);
4219484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < sp->s_nframes);
4229484Sgarrett.damore@Sun.COM
42311936Sgdamore@opensolaris.org while (uio->uio_resid >= framesz) {
4249484Sgarrett.damore@Sun.COM
4259484Sgarrett.damore@Sun.COM while ((cnt = sp->s_nframes - (sp->s_head - sp->s_tail)) == 0) {
4269484Sgarrett.damore@Sun.COM if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
4279484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
4289484Sgarrett.damore@Sun.COM return (eagain);
4299484Sgarrett.damore@Sun.COM }
4309484Sgarrett.damore@Sun.COM if (cv_wait_sig(&sp->s_cv, &sp->s_lock) == 0) {
4319484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
4329484Sgarrett.damore@Sun.COM return (EINTR);
4339484Sgarrett.damore@Sun.COM }
4349484Sgarrett.damore@Sun.COM }
4359484Sgarrett.damore@Sun.COM
43611936Sgdamore@opensolaris.org hidx = sp->s_hidx;
43711936Sgdamore@opensolaris.org cnt = min(cnt, sp->s_nframes - hidx);
43811936Sgdamore@opensolaris.org cnt = min(cnt, (uio->uio_resid / framesz));
4399484Sgarrett.damore@Sun.COM
44011936Sgdamore@opensolaris.org /*
44111936Sgdamore@opensolaris.org * We have to drop the stream lock, because the
44211936Sgdamore@opensolaris.org * uiomove might require doing a page in, which could
44311936Sgdamore@opensolaris.org * get blocked behind the PIL of the audio processing
44411936Sgdamore@opensolaris.org * thread which also grabs the s_lock. (Hence, there
44511936Sgdamore@opensolaris.org * is a risk of deadlock due to priority inversion.)
44611936Sgdamore@opensolaris.org */
44711936Sgdamore@opensolaris.org mutex_exit(&sp->s_lock);
44811936Sgdamore@opensolaris.org
44911936Sgdamore@opensolaris.org rv = uiomove(sp->s_data + (hidx * framesz),
45011936Sgdamore@opensolaris.org cnt * framesz, UIO_WRITE, uio);
45111936Sgdamore@opensolaris.org
4529484Sgarrett.damore@Sun.COM uio->uio_loffset = loff;
4539484Sgarrett.damore@Sun.COM eagain = 0;
4549484Sgarrett.damore@Sun.COM
4559484Sgarrett.damore@Sun.COM if (rv != 0) {
4569484Sgarrett.damore@Sun.COM return (rv);
4579484Sgarrett.damore@Sun.COM }
4589484Sgarrett.damore@Sun.COM
45911936Sgdamore@opensolaris.org mutex_enter(&sp->s_lock);
46011936Sgdamore@opensolaris.org
4619484Sgarrett.damore@Sun.COM sp->s_head += cnt;
4629484Sgarrett.damore@Sun.COM sp->s_hidx += cnt;
4639484Sgarrett.damore@Sun.COM if (sp->s_hidx == sp->s_nframes) {
4649484Sgarrett.damore@Sun.COM sp->s_hidx = 0;
4659484Sgarrett.damore@Sun.COM }
4669484Sgarrett.damore@Sun.COM
4679484Sgarrett.damore@Sun.COM if ((!sp->s_paused) && (!sp->s_running) &&
4689484Sgarrett.damore@Sun.COM ((sp->s_head - sp->s_tail) > sp->s_fragfr)) {
4699484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
4709484Sgarrett.damore@Sun.COM auclnt_start(sp);
4719484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
4729484Sgarrett.damore@Sun.COM }
4739484Sgarrett.damore@Sun.COM }
4749484Sgarrett.damore@Sun.COM
4759484Sgarrett.damore@Sun.COM ASSERT(sp->s_tail <= sp->s_head);
4769484Sgarrett.damore@Sun.COM ASSERT(sp->s_hidx < sp->s_nframes);
4779484Sgarrett.damore@Sun.COM
4789484Sgarrett.damore@Sun.COM /* round off any remaining partial bits */
4799484Sgarrett.damore@Sun.COM uio->uio_resid = 0;
4809484Sgarrett.damore@Sun.COM
4819484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
4829484Sgarrett.damore@Sun.COM
4839484Sgarrett.damore@Sun.COM return (rv);
4849484Sgarrett.damore@Sun.COM }
4859484Sgarrett.damore@Sun.COM
4869484Sgarrett.damore@Sun.COM int
auclnt_chpoll(audio_client_t * c,short events,int anyyet,short * reventsp,struct pollhead ** phpp)4879484Sgarrett.damore@Sun.COM auclnt_chpoll(audio_client_t *c, short events, int anyyet, short *reventsp,
4889484Sgarrett.damore@Sun.COM struct pollhead **phpp)
4899484Sgarrett.damore@Sun.COM {
4909484Sgarrett.damore@Sun.COM audio_stream_t *sp;
4919484Sgarrett.damore@Sun.COM short nev = 0;
4929484Sgarrett.damore@Sun.COM
4939484Sgarrett.damore@Sun.COM if (events & (POLLIN | POLLRDNORM)) {
4949484Sgarrett.damore@Sun.COM sp = &c->c_istream;
4959484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
4969484Sgarrett.damore@Sun.COM if ((sp->s_head - sp->s_tail) > sp->s_fragfr) {
4979484Sgarrett.damore@Sun.COM nev = POLLIN | POLLRDNORM;
4989484Sgarrett.damore@Sun.COM }
4999484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
5009484Sgarrett.damore@Sun.COM }
5019484Sgarrett.damore@Sun.COM
5029484Sgarrett.damore@Sun.COM if (events & POLLOUT) {
5039484Sgarrett.damore@Sun.COM sp = &c->c_ostream;
5049484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
5059484Sgarrett.damore@Sun.COM if ((sp->s_nframes - (sp->s_head - sp->s_tail)) >
5069484Sgarrett.damore@Sun.COM sp->s_fragfr) {
5079484Sgarrett.damore@Sun.COM nev = POLLOUT;
5089484Sgarrett.damore@Sun.COM }
5099484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
5109484Sgarrett.damore@Sun.COM }
5119484Sgarrett.damore@Sun.COM
5129484Sgarrett.damore@Sun.COM if (nev) {
5139484Sgarrett.damore@Sun.COM *reventsp = nev & events;
5149484Sgarrett.damore@Sun.COM } else {
5159484Sgarrett.damore@Sun.COM *reventsp = 0;
5169484Sgarrett.damore@Sun.COM if (!anyyet) {
5179484Sgarrett.damore@Sun.COM *phpp = &c->c_pollhead;
5189484Sgarrett.damore@Sun.COM }
5199484Sgarrett.damore@Sun.COM }
5209484Sgarrett.damore@Sun.COM return (0);
5219484Sgarrett.damore@Sun.COM }
5229484Sgarrett.damore@Sun.COM
5239484Sgarrett.damore@Sun.COM void
auclnt_pollwakeup(audio_client_t * c,short events)5249484Sgarrett.damore@Sun.COM auclnt_pollwakeup(audio_client_t *c, short events)
5259484Sgarrett.damore@Sun.COM {
5269484Sgarrett.damore@Sun.COM pollwakeup(&c->c_pollhead, events);
5279484Sgarrett.damore@Sun.COM }
5289484Sgarrett.damore@Sun.COM
5299484Sgarrett.damore@Sun.COM void
auclnt_get_output_qlen(audio_client_t * c,uint_t * slen,uint_t * flen)53011936Sgdamore@opensolaris.org auclnt_get_output_qlen(audio_client_t *c, uint_t *slen, uint_t *flen)
5319484Sgarrett.damore@Sun.COM {
5329484Sgarrett.damore@Sun.COM audio_stream_t *sp = &c->c_ostream;
5339484Sgarrett.damore@Sun.COM audio_engine_t *e = sp->s_engine;
5349484Sgarrett.damore@Sun.COM uint64_t el, sl;
53511936Sgdamore@opensolaris.org uint_t cnt, er, sr;
5369484Sgarrett.damore@Sun.COM
5379484Sgarrett.damore@Sun.COM if (e == NULL) {
5389484Sgarrett.damore@Sun.COM /* if no output engine, can't do it! */
5399484Sgarrett.damore@Sun.COM *slen = 0;
5409484Sgarrett.damore@Sun.COM *flen = 0;
5419484Sgarrett.damore@Sun.COM return;
5429484Sgarrett.damore@Sun.COM }
5439484Sgarrett.damore@Sun.COM
5449484Sgarrett.damore@Sun.COM mutex_enter(&e->e_lock);
5459484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
54611213Sgdamore@opensolaris.org if (e->e_ops.audio_engine_qlen != NULL) {
54711213Sgdamore@opensolaris.org el = ENG_QLEN(e) + (e->e_head - e->e_tail);
54811213Sgdamore@opensolaris.org } else {
54911213Sgdamore@opensolaris.org el = (e->e_head - e->e_tail);
55011213Sgdamore@opensolaris.org }
5519484Sgarrett.damore@Sun.COM er = e->e_rate;
5529484Sgarrett.damore@Sun.COM sl = sp->s_cnv_cnt;
5539484Sgarrett.damore@Sun.COM sr = sp->s_user_parms->p_rate;
55411936Sgdamore@opensolaris.org cnt = (uint_t)(sp->s_head - sp->s_tail);
5559484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
5569484Sgarrett.damore@Sun.COM mutex_exit(&e->e_lock);
5579484Sgarrett.damore@Sun.COM
5589484Sgarrett.damore@Sun.COM /* engine frames converted to stream rate, plus stream frames */
5599484Sgarrett.damore@Sun.COM *slen = cnt;
56011936Sgdamore@opensolaris.org *flen = ((uint_t)(((el * sr) / er) + sl));
5619484Sgarrett.damore@Sun.COM }
5629484Sgarrett.damore@Sun.COM
5639484Sgarrett.damore@Sun.COM int
auclnt_set_format(audio_stream_t * sp,int fmt)5649484Sgarrett.damore@Sun.COM auclnt_set_format(audio_stream_t *sp, int fmt)
5659484Sgarrett.damore@Sun.COM {
5669484Sgarrett.damore@Sun.COM audio_parms_t parms;
5679484Sgarrett.damore@Sun.COM int rv = 0;
5689484Sgarrett.damore@Sun.COM
5699484Sgarrett.damore@Sun.COM /*
5709484Sgarrett.damore@Sun.COM * AC3: If we select an AC3 format, then we have to allocate
5719484Sgarrett.damore@Sun.COM * another engine. Normally this will be an output only
5729484Sgarrett.damore@Sun.COM * engine. However, for now we aren't supporting AC3
5739484Sgarrett.damore@Sun.COM * passthru.
5749484Sgarrett.damore@Sun.COM */
5759484Sgarrett.damore@Sun.COM
5769484Sgarrett.damore@Sun.COM switch (fmt) {
5779484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_U8:
5789484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_ULAW:
5799484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_ALAW:
5809484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S8:
5819484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S16_LE:
5829484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S16_BE:
5839484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_U16_LE:
5849484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_U16_BE:
5859484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S24_LE:
5869484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S24_BE:
5879484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S32_LE:
5889484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S32_BE:
5899484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_S24_PACKED:
5909484Sgarrett.damore@Sun.COM break;
5919484Sgarrett.damore@Sun.COM
5929484Sgarrett.damore@Sun.COM case AUDIO_FORMAT_AC3: /* AC3: PASSTHRU */
5939484Sgarrett.damore@Sun.COM default:
5949484Sgarrett.damore@Sun.COM return (ENOTSUP);
5959484Sgarrett.damore@Sun.COM }
5969484Sgarrett.damore@Sun.COM
5979484Sgarrett.damore@Sun.COM
5989484Sgarrett.damore@Sun.COM /*
5999484Sgarrett.damore@Sun.COM * Optimization. Some personalities send us the same format
6009484Sgarrett.damore@Sun.COM * over and over again. (Sun personality does this
6019484Sgarrett.damore@Sun.COM * repeatedly.) setup_src is potentially expensive, so we
6029484Sgarrett.damore@Sun.COM * avoid doing it unless we really need to.
6039484Sgarrett.damore@Sun.COM */
60412165Sgdamore@opensolaris.org if (fmt != sp->s_user_parms->p_format) {
6059484Sgarrett.damore@Sun.COM /*
6069484Sgarrett.damore@Sun.COM * Note that setting the format doesn't check that the
6079484Sgarrett.damore@Sun.COM * audio streams have been paused. As a result, any
6089484Sgarrett.damore@Sun.COM * data still playing or recording will probably get
6099484Sgarrett.damore@Sun.COM * misinterpreted. It would be smart if the client
6109484Sgarrett.damore@Sun.COM * application paused/stopped playback before changing
6119484Sgarrett.damore@Sun.COM * formats.
6129484Sgarrett.damore@Sun.COM */
6139484Sgarrett.damore@Sun.COM parms.p_format = fmt;
61412165Sgdamore@opensolaris.org rv = auimpl_engine_setup(sp, 0, &parms, FORMAT_MSK_FMT);
6159484Sgarrett.damore@Sun.COM }
6169484Sgarrett.damore@Sun.COM
6179484Sgarrett.damore@Sun.COM return (rv);
6189484Sgarrett.damore@Sun.COM }
6199484Sgarrett.damore@Sun.COM
6209484Sgarrett.damore@Sun.COM int
auclnt_get_format(audio_stream_t * sp)6219484Sgarrett.damore@Sun.COM auclnt_get_format(audio_stream_t *sp)
6229484Sgarrett.damore@Sun.COM {
6239484Sgarrett.damore@Sun.COM return (sp->s_user_parms->p_format);
6249484Sgarrett.damore@Sun.COM }
6259484Sgarrett.damore@Sun.COM
6269484Sgarrett.damore@Sun.COM int
auclnt_get_output_format(audio_client_t * c)6279484Sgarrett.damore@Sun.COM auclnt_get_output_format(audio_client_t *c)
6289484Sgarrett.damore@Sun.COM {
6299484Sgarrett.damore@Sun.COM return (c->c_ostream.s_user_parms->p_format);
6309484Sgarrett.damore@Sun.COM }
6319484Sgarrett.damore@Sun.COM
6329484Sgarrett.damore@Sun.COM int
auclnt_get_input_format(audio_client_t * c)6339484Sgarrett.damore@Sun.COM auclnt_get_input_format(audio_client_t *c)
6349484Sgarrett.damore@Sun.COM {
6359484Sgarrett.damore@Sun.COM return (c->c_istream.s_user_parms->p_format);
6369484Sgarrett.damore@Sun.COM }
6379484Sgarrett.damore@Sun.COM
6389484Sgarrett.damore@Sun.COM int
auclnt_set_channels(audio_stream_t * sp,int nchan)6399484Sgarrett.damore@Sun.COM auclnt_set_channels(audio_stream_t *sp, int nchan)
6409484Sgarrett.damore@Sun.COM {
6419484Sgarrett.damore@Sun.COM audio_parms_t parms;
6429484Sgarrett.damore@Sun.COM int rv = 0;
6439484Sgarrett.damore@Sun.COM
6449484Sgarrett.damore@Sun.COM /* Validate setting */
6459484Sgarrett.damore@Sun.COM if ((nchan > AUDIO_MAX_CHANNELS) || (nchan < 1)) {
6469484Sgarrett.damore@Sun.COM return (EINVAL);
6479484Sgarrett.damore@Sun.COM }
6489484Sgarrett.damore@Sun.COM
64912165Sgdamore@opensolaris.org if (nchan != sp->s_user_parms->p_nchan) {
6509484Sgarrett.damore@Sun.COM parms.p_nchan = nchan;
65112165Sgdamore@opensolaris.org rv = auimpl_engine_setup(sp, 0, &parms, FORMAT_MSK_CHAN);
6529484Sgarrett.damore@Sun.COM }
6539484Sgarrett.damore@Sun.COM
6549484Sgarrett.damore@Sun.COM return (rv);
6559484Sgarrett.damore@Sun.COM }
6569484Sgarrett.damore@Sun.COM
6579484Sgarrett.damore@Sun.COM int
auclnt_get_channels(audio_stream_t * sp)6589484Sgarrett.damore@Sun.COM auclnt_get_channels(audio_stream_t *sp)
6599484Sgarrett.damore@Sun.COM {
6609484Sgarrett.damore@Sun.COM return (sp->s_user_parms->p_nchan);
6619484Sgarrett.damore@Sun.COM }
6629484Sgarrett.damore@Sun.COM
66310570Sgdamore@opensolaris.org
66410570Sgdamore@opensolaris.org static void
auimpl_set_gain_master(audio_stream_t * sp,uint8_t gain)6659484Sgarrett.damore@Sun.COM auimpl_set_gain_master(audio_stream_t *sp, uint8_t gain)
6669484Sgarrett.damore@Sun.COM {
6679484Sgarrett.damore@Sun.COM uint32_t scaled;
6689484Sgarrett.damore@Sun.COM
6699484Sgarrett.damore@Sun.COM if (gain > 100) {
6709484Sgarrett.damore@Sun.COM gain = 0;
6719484Sgarrett.damore@Sun.COM }
6729484Sgarrett.damore@Sun.COM
6739484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
6749484Sgarrett.damore@Sun.COM if (sp->s_gain_master == gain) {
6759484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
6769484Sgarrett.damore@Sun.COM return;
6779484Sgarrett.damore@Sun.COM }
6789484Sgarrett.damore@Sun.COM
6799484Sgarrett.damore@Sun.COM /*
6809484Sgarrett.damore@Sun.COM * calculate the scaled values. Done now to avoid calculations
6819484Sgarrett.damore@Sun.COM * later.
6829484Sgarrett.damore@Sun.COM */
6839484Sgarrett.damore@Sun.COM scaled = (gain * sp->s_gain_pct * AUDIO_DB_SIZE) / (100 * 100);
6849484Sgarrett.damore@Sun.COM
6859484Sgarrett.damore@Sun.COM sp->s_gain_master = gain;
6869484Sgarrett.damore@Sun.COM sp->s_gain_scaled = auimpl_db_table[scaled];
6879484Sgarrett.damore@Sun.COM
6889484Sgarrett.damore@Sun.COM if (!sp->s_muted) {
6899484Sgarrett.damore@Sun.COM sp->s_gain_eff = sp->s_gain_scaled;
6909484Sgarrett.damore@Sun.COM }
6919484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
6929484Sgarrett.damore@Sun.COM }
6939484Sgarrett.damore@Sun.COM
69410570Sgdamore@opensolaris.org int
auimpl_set_pcmvol(void * arg,uint64_t val)69510570Sgdamore@opensolaris.org auimpl_set_pcmvol(void *arg, uint64_t val)
69610570Sgdamore@opensolaris.org {
69710570Sgdamore@opensolaris.org audio_dev_t *d = arg;
69810570Sgdamore@opensolaris.org list_t *l = &d->d_clients;
69910570Sgdamore@opensolaris.org audio_client_t *c;
70010570Sgdamore@opensolaris.org
70110570Sgdamore@opensolaris.org if (val > 100) {
70210570Sgdamore@opensolaris.org return (EINVAL);
70310570Sgdamore@opensolaris.org }
70410570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_WRITER);
70510570Sgdamore@opensolaris.org d->d_pcmvol = val & 0xff;
70610570Sgdamore@opensolaris.org rw_downgrade(&auimpl_client_lock);
70710570Sgdamore@opensolaris.org
70810570Sgdamore@opensolaris.org for (c = list_head(l); c; c = list_next(l, c)) {
70910570Sgdamore@opensolaris.org /* don't need to check is_active here, its safe */
71010570Sgdamore@opensolaris.org auimpl_set_gain_master(&c->c_ostream, (uint8_t)val);
71110570Sgdamore@opensolaris.org }
71210570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
71310570Sgdamore@opensolaris.org
71410570Sgdamore@opensolaris.org return (0);
71510570Sgdamore@opensolaris.org }
71610570Sgdamore@opensolaris.org
71710570Sgdamore@opensolaris.org int
auimpl_get_pcmvol(void * arg,uint64_t * val)71810570Sgdamore@opensolaris.org auimpl_get_pcmvol(void *arg, uint64_t *val)
71910570Sgdamore@opensolaris.org {
72010570Sgdamore@opensolaris.org audio_dev_t *d = arg;
72110570Sgdamore@opensolaris.org
72210570Sgdamore@opensolaris.org *val = d->d_pcmvol;
72310570Sgdamore@opensolaris.org return (0);
72410570Sgdamore@opensolaris.org }
72510570Sgdamore@opensolaris.org
7269484Sgarrett.damore@Sun.COM void
auclnt_set_gain(audio_stream_t * sp,uint8_t gain)7279484Sgarrett.damore@Sun.COM auclnt_set_gain(audio_stream_t *sp, uint8_t gain)
7289484Sgarrett.damore@Sun.COM {
7299484Sgarrett.damore@Sun.COM uint32_t scaled;
7309484Sgarrett.damore@Sun.COM
7319484Sgarrett.damore@Sun.COM if (gain > 100) {
7329484Sgarrett.damore@Sun.COM gain = 0;
7339484Sgarrett.damore@Sun.COM }
7349484Sgarrett.damore@Sun.COM
7359484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
7369484Sgarrett.damore@Sun.COM
7379484Sgarrett.damore@Sun.COM /* if no change, don't bother doing updates */
7389484Sgarrett.damore@Sun.COM if (sp->s_gain_pct == gain) {
7399484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
7409484Sgarrett.damore@Sun.COM return;
7419484Sgarrett.damore@Sun.COM }
7429484Sgarrett.damore@Sun.COM
7439484Sgarrett.damore@Sun.COM /*
7449484Sgarrett.damore@Sun.COM * calculate the scaled values. Done now to avoid calculations
7459484Sgarrett.damore@Sun.COM * later.
7469484Sgarrett.damore@Sun.COM */
7479484Sgarrett.damore@Sun.COM scaled = (gain * sp->s_gain_master * AUDIO_DB_SIZE) / (100 * 100);
7489484Sgarrett.damore@Sun.COM
7499484Sgarrett.damore@Sun.COM sp->s_gain_pct = gain;
7509484Sgarrett.damore@Sun.COM sp->s_gain_scaled = auimpl_db_table[scaled];
7519484Sgarrett.damore@Sun.COM
7529484Sgarrett.damore@Sun.COM if (!sp->s_muted) {
7539484Sgarrett.damore@Sun.COM sp->s_gain_eff = sp->s_gain_scaled;
7549484Sgarrett.damore@Sun.COM }
7559484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
7569484Sgarrett.damore@Sun.COM
75710632Sgdamore@opensolaris.org atomic_inc_uint(&sp->s_client->c_dev->d_serial);
7589484Sgarrett.damore@Sun.COM }
7599484Sgarrett.damore@Sun.COM
7609484Sgarrett.damore@Sun.COM uint8_t
auclnt_get_gain(audio_stream_t * sp)7619484Sgarrett.damore@Sun.COM auclnt_get_gain(audio_stream_t *sp)
7629484Sgarrett.damore@Sun.COM {
7639484Sgarrett.damore@Sun.COM return (sp->s_gain_pct);
7649484Sgarrett.damore@Sun.COM }
7659484Sgarrett.damore@Sun.COM
7669484Sgarrett.damore@Sun.COM void
auclnt_set_muted(audio_stream_t * sp,boolean_t muted)7679484Sgarrett.damore@Sun.COM auclnt_set_muted(audio_stream_t *sp, boolean_t muted)
7689484Sgarrett.damore@Sun.COM {
7699484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
7709484Sgarrett.damore@Sun.COM
7719484Sgarrett.damore@Sun.COM /* if no work change, don't bother doing updates */
7729484Sgarrett.damore@Sun.COM if (sp->s_muted == muted) {
7739484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
7749484Sgarrett.damore@Sun.COM return;
7759484Sgarrett.damore@Sun.COM }
7769484Sgarrett.damore@Sun.COM
7779484Sgarrett.damore@Sun.COM sp->s_muted = muted;
7789484Sgarrett.damore@Sun.COM if (muted) {
7799484Sgarrett.damore@Sun.COM sp->s_gain_eff = 0;
7809484Sgarrett.damore@Sun.COM } else {
7819484Sgarrett.damore@Sun.COM sp->s_gain_eff = sp->s_gain_scaled;
7829484Sgarrett.damore@Sun.COM }
7839484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
7849484Sgarrett.damore@Sun.COM
78510632Sgdamore@opensolaris.org atomic_inc_uint(&sp->s_client->c_dev->d_serial);
7869484Sgarrett.damore@Sun.COM }
7879484Sgarrett.damore@Sun.COM
7889484Sgarrett.damore@Sun.COM boolean_t
auclnt_get_muted(audio_stream_t * sp)7899484Sgarrett.damore@Sun.COM auclnt_get_muted(audio_stream_t *sp)
7909484Sgarrett.damore@Sun.COM {
7919484Sgarrett.damore@Sun.COM return (sp->s_muted);
7929484Sgarrett.damore@Sun.COM }
7939484Sgarrett.damore@Sun.COM
79410172Sgdamore@opensolaris.org boolean_t
auclnt_is_running(audio_stream_t * sp)79510172Sgdamore@opensolaris.org auclnt_is_running(audio_stream_t *sp)
79610172Sgdamore@opensolaris.org {
79710172Sgdamore@opensolaris.org return (sp->s_running);
79810172Sgdamore@opensolaris.org }
79910172Sgdamore@opensolaris.org
8009484Sgarrett.damore@Sun.COM void
auclnt_start(audio_stream_t * sp)8019484Sgarrett.damore@Sun.COM auclnt_start(audio_stream_t *sp)
8029484Sgarrett.damore@Sun.COM {
8039484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
8049484Sgarrett.damore@Sun.COM sp->s_running = B_TRUE;
8059484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8069484Sgarrett.damore@Sun.COM }
8079484Sgarrett.damore@Sun.COM
8089484Sgarrett.damore@Sun.COM void
auclnt_stop(audio_stream_t * sp)8099484Sgarrett.damore@Sun.COM auclnt_stop(audio_stream_t *sp)
8109484Sgarrett.damore@Sun.COM {
8119484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
8129484Sgarrett.damore@Sun.COM /* if running, then stop it */
8139484Sgarrett.damore@Sun.COM if (sp->s_running) {
8149484Sgarrett.damore@Sun.COM sp->s_running = B_FALSE;
8159484Sgarrett.damore@Sun.COM /*
8169484Sgarrett.damore@Sun.COM * if we stopped the engine, we might need to wake up
8179484Sgarrett.damore@Sun.COM * a thread that is waiting for drain to complete.
8189484Sgarrett.damore@Sun.COM */
8199484Sgarrett.damore@Sun.COM cv_broadcast(&sp->s_cv);
8209484Sgarrett.damore@Sun.COM }
8219484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8229484Sgarrett.damore@Sun.COM }
8239484Sgarrett.damore@Sun.COM
8249484Sgarrett.damore@Sun.COM /*
8259484Sgarrett.damore@Sun.COM * When pausing, no new data will be played after the most recently
8269484Sgarrett.damore@Sun.COM * mixed samples have played. However, the audio engine will continue
8279484Sgarrett.damore@Sun.COM * to play (possibly just silence).
8289484Sgarrett.damore@Sun.COM *
8299484Sgarrett.damore@Sun.COM * Note that we don't reference count the device, or release/close the
8309484Sgarrett.damore@Sun.COM * engine here. Once fired up, the engine continues running unil it
8319484Sgarrett.damore@Sun.COM * is closed.
8329484Sgarrett.damore@Sun.COM */
8339484Sgarrett.damore@Sun.COM void
auclnt_set_paused(audio_stream_t * sp)8349484Sgarrett.damore@Sun.COM auclnt_set_paused(audio_stream_t *sp)
8359484Sgarrett.damore@Sun.COM {
8369484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
8379484Sgarrett.damore@Sun.COM if (sp->s_paused) {
8389484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8399484Sgarrett.damore@Sun.COM return;
8409484Sgarrett.damore@Sun.COM }
8419484Sgarrett.damore@Sun.COM sp->s_paused = B_TRUE;
8429484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8439484Sgarrett.damore@Sun.COM
8449484Sgarrett.damore@Sun.COM auclnt_stop(sp);
8459484Sgarrett.damore@Sun.COM
84610632Sgdamore@opensolaris.org atomic_inc_uint(&sp->s_client->c_dev->d_serial);
8479484Sgarrett.damore@Sun.COM }
8489484Sgarrett.damore@Sun.COM
8499484Sgarrett.damore@Sun.COM void
auclnt_clear_paused(audio_stream_t * sp)8509484Sgarrett.damore@Sun.COM auclnt_clear_paused(audio_stream_t *sp)
8519484Sgarrett.damore@Sun.COM {
8529484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
8539484Sgarrett.damore@Sun.COM if (!sp->s_paused) {
8549484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8559484Sgarrett.damore@Sun.COM return;
8569484Sgarrett.damore@Sun.COM }
8579484Sgarrett.damore@Sun.COM sp->s_paused = B_FALSE;
8589484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8599484Sgarrett.damore@Sun.COM }
8609484Sgarrett.damore@Sun.COM
8619484Sgarrett.damore@Sun.COM boolean_t
auclnt_is_paused(audio_stream_t * sp)8629484Sgarrett.damore@Sun.COM auclnt_is_paused(audio_stream_t *sp)
8639484Sgarrett.damore@Sun.COM {
8649484Sgarrett.damore@Sun.COM return (sp->s_paused);
8659484Sgarrett.damore@Sun.COM }
8669484Sgarrett.damore@Sun.COM
8679484Sgarrett.damore@Sun.COM void
auclnt_flush(audio_stream_t * sp)8689484Sgarrett.damore@Sun.COM auclnt_flush(audio_stream_t *sp)
8699484Sgarrett.damore@Sun.COM {
8709484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
8719484Sgarrett.damore@Sun.COM if (sp == &sp->s_client->c_ostream) {
8729484Sgarrett.damore@Sun.COM sp->s_tail = sp->s_head;
8739484Sgarrett.damore@Sun.COM sp->s_tidx = sp->s_hidx;
8749484Sgarrett.damore@Sun.COM } else {
8759484Sgarrett.damore@Sun.COM sp->s_head = sp->s_tail;
8769484Sgarrett.damore@Sun.COM sp->s_hidx = sp->s_tidx;
8779484Sgarrett.damore@Sun.COM }
8789484Sgarrett.damore@Sun.COM sp->s_cnv_cnt = 0;
8799484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
8809484Sgarrett.damore@Sun.COM }
8819484Sgarrett.damore@Sun.COM
8829484Sgarrett.damore@Sun.COM int
auclnt_get_oflag(audio_client_t * c)8839484Sgarrett.damore@Sun.COM auclnt_get_oflag(audio_client_t *c)
8849484Sgarrett.damore@Sun.COM {
8859484Sgarrett.damore@Sun.COM return (c->c_omode);
8869484Sgarrett.damore@Sun.COM }
8879484Sgarrett.damore@Sun.COM
8889484Sgarrett.damore@Sun.COM /*
8899484Sgarrett.damore@Sun.COM * These routines should not be accessed by client "personality"
8909484Sgarrett.damore@Sun.COM * implementations, but are for private framework use only.
8919484Sgarrett.damore@Sun.COM */
8929484Sgarrett.damore@Sun.COM
8939484Sgarrett.damore@Sun.COM void
auimpl_client_init(void)8949484Sgarrett.damore@Sun.COM auimpl_client_init(void)
8959484Sgarrett.damore@Sun.COM {
8969484Sgarrett.damore@Sun.COM rw_init(&auimpl_client_lock, NULL, RW_DRIVER, NULL);
8979484Sgarrett.damore@Sun.COM list_create(&auimpl_clients, sizeof (struct audio_client),
8989484Sgarrett.damore@Sun.COM offsetof(struct audio_client, c_global_linkage));
8999484Sgarrett.damore@Sun.COM }
9009484Sgarrett.damore@Sun.COM
9019484Sgarrett.damore@Sun.COM void
auimpl_client_fini(void)9029484Sgarrett.damore@Sun.COM auimpl_client_fini(void)
9039484Sgarrett.damore@Sun.COM {
9049484Sgarrett.damore@Sun.COM rw_destroy(&auimpl_client_lock);
9059484Sgarrett.damore@Sun.COM list_destroy(&auimpl_clients);
9069484Sgarrett.damore@Sun.COM }
9079484Sgarrett.damore@Sun.COM
9089484Sgarrett.damore@Sun.COM static int
auimpl_stream_init(audio_stream_t * sp,audio_client_t * c)9099484Sgarrett.damore@Sun.COM auimpl_stream_init(audio_stream_t *sp, audio_client_t *c)
9109484Sgarrett.damore@Sun.COM {
9119484Sgarrett.damore@Sun.COM mutex_init(&sp->s_lock, NULL, MUTEX_DRIVER, NULL);
9129484Sgarrett.damore@Sun.COM cv_init(&sp->s_cv, NULL, CV_DRIVER, NULL);
9139484Sgarrett.damore@Sun.COM sp->s_client = c;
9149484Sgarrett.damore@Sun.COM
9159484Sgarrett.damore@Sun.COM if (sp == &c->c_ostream) {
9169484Sgarrett.damore@Sun.COM sp->s_user_parms = &sp->s_cnv_src_parms;
9179484Sgarrett.damore@Sun.COM sp->s_phys_parms = &sp->s_cnv_dst_parms;
9189484Sgarrett.damore@Sun.COM sp->s_engcap = ENGINE_OUTPUT_CAP;
9199484Sgarrett.damore@Sun.COM } else {
9209484Sgarrett.damore@Sun.COM ASSERT(sp == &c->c_istream);
9219484Sgarrett.damore@Sun.COM sp->s_user_parms = &sp->s_cnv_dst_parms;
9229484Sgarrett.damore@Sun.COM sp->s_phys_parms = &sp->s_cnv_src_parms;
9239484Sgarrett.damore@Sun.COM sp->s_engcap = ENGINE_INPUT_CAP;
9249484Sgarrett.damore@Sun.COM }
9259484Sgarrett.damore@Sun.COM
9269484Sgarrett.damore@Sun.COM /* for now initialize conversion parameters */
9279484Sgarrett.damore@Sun.COM sp->s_src_quality = 3; /* reasonable compromise for now */
9289484Sgarrett.damore@Sun.COM sp->s_cnv_dst_nchan = 2;
9299484Sgarrett.damore@Sun.COM sp->s_cnv_dst_format = AUDIO_FORMAT_S24_NE;
9309484Sgarrett.damore@Sun.COM sp->s_cnv_dst_rate = 48000;
9319484Sgarrett.damore@Sun.COM sp->s_cnv_src_nchan = 2;
9329484Sgarrett.damore@Sun.COM sp->s_cnv_src_format = AUDIO_FORMAT_S24_NE;
9339484Sgarrett.damore@Sun.COM sp->s_cnv_src_rate = 48000;
9349484Sgarrett.damore@Sun.COM
9359484Sgarrett.damore@Sun.COM /* set volume/gain all the way up */
9369484Sgarrett.damore@Sun.COM sp->s_muted = B_FALSE;
9379484Sgarrett.damore@Sun.COM sp->s_gain_pct = 0;
9389484Sgarrett.damore@Sun.COM sp->s_gain_scaled = AUDIO_VOL_SCALE;
9399484Sgarrett.damore@Sun.COM sp->s_gain_eff = AUDIO_VOL_SCALE;
9409484Sgarrett.damore@Sun.COM
9419484Sgarrett.damore@Sun.COM /*
9429484Sgarrett.damore@Sun.COM * We have to start off with a reasonable buffer and
9439484Sgarrett.damore@Sun.COM * interrupt configuration.
9449484Sgarrett.damore@Sun.COM */
9459484Sgarrett.damore@Sun.COM sp->s_allocsz = 65536;
9469484Sgarrett.damore@Sun.COM sp->s_data = ddi_umem_alloc(sp->s_allocsz, DDI_UMEM_NOSLEEP,
9479484Sgarrett.damore@Sun.COM &sp->s_cookie);
9489484Sgarrett.damore@Sun.COM if (sp->s_data == NULL) {
9499484Sgarrett.damore@Sun.COM sp->s_allocsz = 0;
9509484Sgarrett.damore@Sun.COM audio_dev_warn(c->c_dev, "ddi_umem_alloc failed");
9519484Sgarrett.damore@Sun.COM return (ENOMEM);
9529484Sgarrett.damore@Sun.COM }
9539484Sgarrett.damore@Sun.COM /* make sure no stale data left in stream */
9549484Sgarrett.damore@Sun.COM bzero(sp->s_data, sp->s_allocsz);
9559484Sgarrett.damore@Sun.COM
9569484Sgarrett.damore@Sun.COM /*
9579484Sgarrett.damore@Sun.COM * Allocate SRC and data conversion state.
9589484Sgarrett.damore@Sun.COM */
9599484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
9609484Sgarrett.damore@Sun.COM if (auimpl_format_alloc(sp) != 0) {
9619484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
9629484Sgarrett.damore@Sun.COM return (ENOMEM);
9639484Sgarrett.damore@Sun.COM }
9649484Sgarrett.damore@Sun.COM
9659484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
9669484Sgarrett.damore@Sun.COM
9679484Sgarrett.damore@Sun.COM return (0);
9689484Sgarrett.damore@Sun.COM }
9699484Sgarrett.damore@Sun.COM
9709484Sgarrett.damore@Sun.COM
9719484Sgarrett.damore@Sun.COM static void
audio_stream_fini(audio_stream_t * sp)9729484Sgarrett.damore@Sun.COM audio_stream_fini(audio_stream_t *sp)
9739484Sgarrett.damore@Sun.COM {
9749484Sgarrett.damore@Sun.COM auimpl_format_free(sp);
9759484Sgarrett.damore@Sun.COM if (sp->s_cnv_buf0)
9769484Sgarrett.damore@Sun.COM kmem_free(sp->s_cnv_buf0, sp->s_cnv_max);
9779484Sgarrett.damore@Sun.COM if (sp->s_cnv_buf1)
9789484Sgarrett.damore@Sun.COM kmem_free(sp->s_cnv_buf1, sp->s_cnv_max);
9799484Sgarrett.damore@Sun.COM mutex_destroy(&sp->s_lock);
9809484Sgarrett.damore@Sun.COM cv_destroy(&sp->s_cv);
9819484Sgarrett.damore@Sun.COM if (sp->s_data != NULL) {
9829484Sgarrett.damore@Sun.COM ddi_umem_free(sp->s_cookie);
9839484Sgarrett.damore@Sun.COM sp->s_data = NULL;
9849484Sgarrett.damore@Sun.COM }
9859484Sgarrett.damore@Sun.COM }
9869484Sgarrett.damore@Sun.COM
9879484Sgarrett.damore@Sun.COM int
auclnt_start_drain(audio_client_t * c)9889484Sgarrett.damore@Sun.COM auclnt_start_drain(audio_client_t *c)
9899484Sgarrett.damore@Sun.COM {
9909484Sgarrett.damore@Sun.COM audio_stream_t *sp;
9919484Sgarrett.damore@Sun.COM int rv;
9929484Sgarrett.damore@Sun.COM
9939484Sgarrett.damore@Sun.COM sp = &c->c_ostream;
9949484Sgarrett.damore@Sun.COM
9959484Sgarrett.damore@Sun.COM /* start an asynchronous drain operation. */
9969484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
9979484Sgarrett.damore@Sun.COM if (sp->s_paused || !sp->s_running) {
9989484Sgarrett.damore@Sun.COM rv = EALREADY;
9999484Sgarrett.damore@Sun.COM } else {
10009484Sgarrett.damore@Sun.COM sp->s_draining = B_TRUE;
10019484Sgarrett.damore@Sun.COM rv = 0;
10029484Sgarrett.damore@Sun.COM }
10039484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
10049484Sgarrett.damore@Sun.COM return (rv);
10059484Sgarrett.damore@Sun.COM }
10069484Sgarrett.damore@Sun.COM
10079484Sgarrett.damore@Sun.COM int
auclnt_drain(audio_client_t * c)10089484Sgarrett.damore@Sun.COM auclnt_drain(audio_client_t *c)
10099484Sgarrett.damore@Sun.COM {
10109484Sgarrett.damore@Sun.COM audio_stream_t *sp;
10119484Sgarrett.damore@Sun.COM
10129484Sgarrett.damore@Sun.COM sp = &c->c_ostream;
10139484Sgarrett.damore@Sun.COM
10149484Sgarrett.damore@Sun.COM /*
10159484Sgarrett.damore@Sun.COM * Note: Drain logic will automatically "stop" the stream when
10169484Sgarrett.damore@Sun.COM * the drain threshold has been reached. So all we have to do
10179484Sgarrett.damore@Sun.COM * is wait for the stream to stop.
10189484Sgarrett.damore@Sun.COM */
10199484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
10209484Sgarrett.damore@Sun.COM sp->s_draining = B_TRUE;
10219484Sgarrett.damore@Sun.COM while (sp->s_draining && sp->s_running && !sp->s_paused) {
10229484Sgarrett.damore@Sun.COM if (cv_wait_sig(&sp->s_cv, &sp->s_lock) == 0) {
10239484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
10249484Sgarrett.damore@Sun.COM return (EINTR);
10259484Sgarrett.damore@Sun.COM }
10269484Sgarrett.damore@Sun.COM }
10279484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
10289484Sgarrett.damore@Sun.COM return (0);
10299484Sgarrett.damore@Sun.COM }
10309484Sgarrett.damore@Sun.COM
10319484Sgarrett.damore@Sun.COM audio_client_t *
auimpl_client_create(dev_t dev)10329484Sgarrett.damore@Sun.COM auimpl_client_create(dev_t dev)
10339484Sgarrett.damore@Sun.COM {
10349484Sgarrett.damore@Sun.COM audio_client_ops_t *ops;
10359484Sgarrett.damore@Sun.COM audio_client_t *c;
10369484Sgarrett.damore@Sun.COM audio_client_t *next;
10379484Sgarrett.damore@Sun.COM list_t *list = &auimpl_clients;
10389484Sgarrett.damore@Sun.COM minor_t minor;
10399484Sgarrett.damore@Sun.COM audio_dev_t *d;
10409484Sgarrett.damore@Sun.COM
10419484Sgarrett.damore@Sun.COM /* validate minor number */
10429484Sgarrett.damore@Sun.COM minor = getminor(dev) & AUDIO_MN_TYPE_MASK;
10439484Sgarrett.damore@Sun.COM if ((ops = audio_client_ops[minor]) == NULL) {
10449484Sgarrett.damore@Sun.COM return (NULL);
10459484Sgarrett.damore@Sun.COM }
10469484Sgarrett.damore@Sun.COM
10479484Sgarrett.damore@Sun.COM /* lookup device instance */
10489484Sgarrett.damore@Sun.COM if ((d = auimpl_dev_hold_by_devt(dev)) == NULL) {
10499484Sgarrett.damore@Sun.COM audio_dev_warn(NULL, "no audio_dev for dev_t %d,%d",
10509484Sgarrett.damore@Sun.COM getmajor(dev), getminor(dev));
10519484Sgarrett.damore@Sun.COM return (NULL);
10529484Sgarrett.damore@Sun.COM }
10539484Sgarrett.damore@Sun.COM
10549484Sgarrett.damore@Sun.COM if ((c = kmem_zalloc(sizeof (*c), KM_NOSLEEP)) == NULL) {
10559484Sgarrett.damore@Sun.COM audio_dev_warn(d, "unable to allocate client structure");
10569484Sgarrett.damore@Sun.COM auimpl_dev_release(d);
10579484Sgarrett.damore@Sun.COM return (NULL);
10589484Sgarrett.damore@Sun.COM }
10599484Sgarrett.damore@Sun.COM c->c_dev = d;
10609484Sgarrett.damore@Sun.COM
10619484Sgarrett.damore@Sun.COM mutex_init(&c->c_lock, NULL, MUTEX_DRIVER, NULL);
10629484Sgarrett.damore@Sun.COM cv_init(&c->c_cv, NULL, CV_DRIVER, NULL);
10639484Sgarrett.damore@Sun.COM
10649484Sgarrett.damore@Sun.COM if ((auimpl_stream_init(&c->c_ostream, c) != 0) ||
10659484Sgarrett.damore@Sun.COM (auimpl_stream_init(&c->c_istream, c) != 0)) {
10669484Sgarrett.damore@Sun.COM goto failed;
10679484Sgarrett.damore@Sun.COM }
10689484Sgarrett.damore@Sun.COM
10699484Sgarrett.damore@Sun.COM c->c_major = getmajor(dev);
10709484Sgarrett.damore@Sun.COM c->c_origminor = getminor(dev);
10719484Sgarrett.damore@Sun.COM c->c_ops = *ops;
10729484Sgarrett.damore@Sun.COM
10739484Sgarrett.damore@Sun.COM /*
10749484Sgarrett.damore@Sun.COM * We hold the client lock here.
10759484Sgarrett.damore@Sun.COM */
10769484Sgarrett.damore@Sun.COM rw_enter(&auimpl_client_lock, RW_WRITER);
10779484Sgarrett.damore@Sun.COM
10789484Sgarrett.damore@Sun.COM minor = AUDIO_MN_CLONE_MASK;
10799484Sgarrett.damore@Sun.COM for (next = list_head(list); next; next = list_next(list, next)) {
10809484Sgarrett.damore@Sun.COM if (next->c_minor > minor) {
10819484Sgarrett.damore@Sun.COM break;
10829484Sgarrett.damore@Sun.COM }
10839484Sgarrett.damore@Sun.COM minor++;
10849484Sgarrett.damore@Sun.COM }
10859484Sgarrett.damore@Sun.COM if (minor >= MAXMIN32) {
10869484Sgarrett.damore@Sun.COM rw_exit(&auimpl_client_lock);
10879484Sgarrett.damore@Sun.COM goto failed;
10889484Sgarrett.damore@Sun.COM }
10899484Sgarrett.damore@Sun.COM c->c_minor = minor;
10909484Sgarrett.damore@Sun.COM list_insert_before(list, next, c);
10919484Sgarrett.damore@Sun.COM
10929484Sgarrett.damore@Sun.COM rw_exit(&auimpl_client_lock);
10939484Sgarrett.damore@Sun.COM
10949484Sgarrett.damore@Sun.COM
10959484Sgarrett.damore@Sun.COM return (c);
10969484Sgarrett.damore@Sun.COM
10979484Sgarrett.damore@Sun.COM failed:
10989484Sgarrett.damore@Sun.COM auimpl_dev_release(d);
10999484Sgarrett.damore@Sun.COM audio_stream_fini(&c->c_ostream);
11009484Sgarrett.damore@Sun.COM audio_stream_fini(&c->c_istream);
11019484Sgarrett.damore@Sun.COM mutex_destroy(&c->c_lock);
11029484Sgarrett.damore@Sun.COM cv_destroy(&c->c_cv);
11039484Sgarrett.damore@Sun.COM kmem_free(c, sizeof (*c));
11049484Sgarrett.damore@Sun.COM return (NULL);
11059484Sgarrett.damore@Sun.COM }
11069484Sgarrett.damore@Sun.COM
11079484Sgarrett.damore@Sun.COM void
auimpl_client_destroy(audio_client_t * c)11089484Sgarrett.damore@Sun.COM auimpl_client_destroy(audio_client_t *c)
11099484Sgarrett.damore@Sun.COM {
11109484Sgarrett.damore@Sun.COM /* remove us from the global list */
11119484Sgarrett.damore@Sun.COM rw_enter(&auimpl_client_lock, RW_WRITER);
11129484Sgarrett.damore@Sun.COM list_remove(&auimpl_clients, c);
11139484Sgarrett.damore@Sun.COM rw_exit(&auimpl_client_lock);
11149484Sgarrett.damore@Sun.COM
11159484Sgarrett.damore@Sun.COM ASSERT(!c->c_istream.s_running);
1116*12979SEdgar.Liu@Sun.COM ASSERT(!c->c_ostream.s_running);
11179484Sgarrett.damore@Sun.COM
11189484Sgarrett.damore@Sun.COM /* release the device reference count */
11199484Sgarrett.damore@Sun.COM auimpl_dev_release(c->c_dev);
11209484Sgarrett.damore@Sun.COM c->c_dev = NULL;
11219484Sgarrett.damore@Sun.COM
11229484Sgarrett.damore@Sun.COM mutex_destroy(&c->c_lock);
11239484Sgarrett.damore@Sun.COM cv_destroy(&c->c_cv);
11249484Sgarrett.damore@Sun.COM
11259484Sgarrett.damore@Sun.COM audio_stream_fini(&c->c_istream);
11269484Sgarrett.damore@Sun.COM audio_stream_fini(&c->c_ostream);
11279484Sgarrett.damore@Sun.COM kmem_free(c, sizeof (*c));
11289484Sgarrett.damore@Sun.COM }
11299484Sgarrett.damore@Sun.COM
11309484Sgarrett.damore@Sun.COM void
auimpl_client_activate(audio_client_t * c)113110570Sgdamore@opensolaris.org auimpl_client_activate(audio_client_t *c)
113210570Sgdamore@opensolaris.org {
113310570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_WRITER);
113410570Sgdamore@opensolaris.org c->c_is_active = B_TRUE;
113510570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
113610570Sgdamore@opensolaris.org }
113710570Sgdamore@opensolaris.org
113810570Sgdamore@opensolaris.org void
auimpl_client_deactivate(audio_client_t * c)113910570Sgdamore@opensolaris.org auimpl_client_deactivate(audio_client_t *c)
114010570Sgdamore@opensolaris.org {
114110570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_WRITER);
114210570Sgdamore@opensolaris.org c->c_is_active = B_FALSE;
114310570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
114410570Sgdamore@opensolaris.org }
114510570Sgdamore@opensolaris.org
114610570Sgdamore@opensolaris.org void
auclnt_close(audio_client_t * c)11479484Sgarrett.damore@Sun.COM auclnt_close(audio_client_t *c)
11489484Sgarrett.damore@Sun.COM {
11499484Sgarrett.damore@Sun.COM audio_dev_t *d = c->c_dev;
11509484Sgarrett.damore@Sun.COM
11519484Sgarrett.damore@Sun.COM /* stop the engines if they are running */
11529484Sgarrett.damore@Sun.COM auclnt_stop(&c->c_istream);
11539484Sgarrett.damore@Sun.COM auclnt_stop(&c->c_ostream);
11549484Sgarrett.damore@Sun.COM
115510570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_WRITER);
11569484Sgarrett.damore@Sun.COM list_remove(&d->d_clients, c);
115710570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
11589484Sgarrett.damore@Sun.COM
11599484Sgarrett.damore@Sun.COM mutex_enter(&c->c_lock);
11609484Sgarrett.damore@Sun.COM /* if in transition need to wait for other thread to release */
11619484Sgarrett.damore@Sun.COM while (c->c_refcnt) {
11629484Sgarrett.damore@Sun.COM cv_wait(&c->c_cv, &c->c_lock);
11639484Sgarrett.damore@Sun.COM }
11649484Sgarrett.damore@Sun.COM mutex_exit(&c->c_lock);
11659484Sgarrett.damore@Sun.COM
11669484Sgarrett.damore@Sun.COM /* release any engines that we were holding */
11679484Sgarrett.damore@Sun.COM auimpl_engine_close(&c->c_ostream);
11689484Sgarrett.damore@Sun.COM auimpl_engine_close(&c->c_istream);
11699484Sgarrett.damore@Sun.COM }
11709484Sgarrett.damore@Sun.COM
11719484Sgarrett.damore@Sun.COM audio_dev_t *
auclnt_hold_dev_by_index(int index)11729484Sgarrett.damore@Sun.COM auclnt_hold_dev_by_index(int index)
11739484Sgarrett.damore@Sun.COM {
11749484Sgarrett.damore@Sun.COM return (auimpl_dev_hold_by_index(index));
11759484Sgarrett.damore@Sun.COM }
11769484Sgarrett.damore@Sun.COM
11779484Sgarrett.damore@Sun.COM void
auclnt_release_dev(audio_dev_t * dev)11789484Sgarrett.damore@Sun.COM auclnt_release_dev(audio_dev_t *dev)
11799484Sgarrett.damore@Sun.COM {
11809484Sgarrett.damore@Sun.COM auimpl_dev_release(dev);
11819484Sgarrett.damore@Sun.COM }
11829484Sgarrett.damore@Sun.COM
11839484Sgarrett.damore@Sun.COM audio_client_t *
auclnt_hold_by_devt(dev_t dev)11849484Sgarrett.damore@Sun.COM auclnt_hold_by_devt(dev_t dev)
11859484Sgarrett.damore@Sun.COM {
11869484Sgarrett.damore@Sun.COM minor_t mn = getminor(dev);
11879484Sgarrett.damore@Sun.COM major_t mj = getmajor(dev);
11889484Sgarrett.damore@Sun.COM list_t *list;
11899484Sgarrett.damore@Sun.COM audio_client_t *c;
11909484Sgarrett.damore@Sun.COM
11919484Sgarrett.damore@Sun.COM list = &auimpl_clients;
11929484Sgarrett.damore@Sun.COM /* linked list search is kind of inefficient, but it works */
11939484Sgarrett.damore@Sun.COM rw_enter(&auimpl_client_lock, RW_READER);
11949484Sgarrett.damore@Sun.COM for (c = list_head(list); c != NULL; c = list_next(list, c)) {
11959484Sgarrett.damore@Sun.COM if ((c->c_major == mj) && (c->c_minor == mn)) {
11969484Sgarrett.damore@Sun.COM mutex_enter(&c->c_lock);
119710570Sgdamore@opensolaris.org if (c->c_is_active) {
11989484Sgarrett.damore@Sun.COM c->c_refcnt++;
11999484Sgarrett.damore@Sun.COM mutex_exit(&c->c_lock);
12009484Sgarrett.damore@Sun.COM } else {
12019484Sgarrett.damore@Sun.COM mutex_exit(&c->c_lock);
12029484Sgarrett.damore@Sun.COM c = NULL;
12039484Sgarrett.damore@Sun.COM }
12049484Sgarrett.damore@Sun.COM break;
12059484Sgarrett.damore@Sun.COM }
12069484Sgarrett.damore@Sun.COM }
12079484Sgarrett.damore@Sun.COM rw_exit(&auimpl_client_lock);
12089484Sgarrett.damore@Sun.COM return (c);
12099484Sgarrett.damore@Sun.COM }
12109484Sgarrett.damore@Sun.COM
121111936Sgdamore@opensolaris.org int
auclnt_serialize(audio_client_t * c)121211936Sgdamore@opensolaris.org auclnt_serialize(audio_client_t *c)
121311936Sgdamore@opensolaris.org {
121411936Sgdamore@opensolaris.org mutex_enter(&c->c_lock);
121511936Sgdamore@opensolaris.org while (c->c_serialize) {
121611936Sgdamore@opensolaris.org if (cv_wait_sig(&c->c_cv, &c->c_lock) == 0) {
121711936Sgdamore@opensolaris.org mutex_exit(&c->c_lock);
121811936Sgdamore@opensolaris.org return (EINTR);
121911936Sgdamore@opensolaris.org }
122011936Sgdamore@opensolaris.org }
122111936Sgdamore@opensolaris.org c->c_serialize = B_TRUE;
122211936Sgdamore@opensolaris.org mutex_exit(&c->c_lock);
122311936Sgdamore@opensolaris.org return (0);
122411936Sgdamore@opensolaris.org }
122511936Sgdamore@opensolaris.org
122611936Sgdamore@opensolaris.org void
auclnt_unserialize(audio_client_t * c)122711936Sgdamore@opensolaris.org auclnt_unserialize(audio_client_t *c)
122811936Sgdamore@opensolaris.org {
122911936Sgdamore@opensolaris.org mutex_enter(&c->c_lock);
123011936Sgdamore@opensolaris.org ASSERT(c->c_serialize);
123111936Sgdamore@opensolaris.org c->c_serialize = B_FALSE;
123211936Sgdamore@opensolaris.org cv_broadcast(&c->c_cv);
123311936Sgdamore@opensolaris.org mutex_exit(&c->c_lock);
123411936Sgdamore@opensolaris.org }
123511936Sgdamore@opensolaris.org
123611936Sgdamore@opensolaris.org void
auclnt_hold(audio_client_t * c)123711936Sgdamore@opensolaris.org auclnt_hold(audio_client_t *c)
123811936Sgdamore@opensolaris.org {
123911936Sgdamore@opensolaris.org mutex_enter(&c->c_lock);
124011936Sgdamore@opensolaris.org c->c_refcnt++;
124111936Sgdamore@opensolaris.org mutex_exit(&c->c_lock);
124211936Sgdamore@opensolaris.org }
124311936Sgdamore@opensolaris.org
12449484Sgarrett.damore@Sun.COM void
auclnt_release(audio_client_t * c)12459484Sgarrett.damore@Sun.COM auclnt_release(audio_client_t *c)
12469484Sgarrett.damore@Sun.COM {
12479484Sgarrett.damore@Sun.COM mutex_enter(&c->c_lock);
124810157Sgdamore@opensolaris.org ASSERT(c->c_refcnt > 0);
12499484Sgarrett.damore@Sun.COM c->c_refcnt--;
12509484Sgarrett.damore@Sun.COM if (c->c_refcnt == 0)
12519484Sgarrett.damore@Sun.COM cv_broadcast(&c->c_cv);
12529484Sgarrett.damore@Sun.COM mutex_exit(&c->c_lock);
12539484Sgarrett.damore@Sun.COM }
12549484Sgarrett.damore@Sun.COM
125511936Sgdamore@opensolaris.org uint_t
auclnt_dev_get_serial(audio_dev_t * d)125610632Sgdamore@opensolaris.org auclnt_dev_get_serial(audio_dev_t *d)
125710632Sgdamore@opensolaris.org {
125810632Sgdamore@opensolaris.org return (d->d_serial);
125910632Sgdamore@opensolaris.org }
126010632Sgdamore@opensolaris.org
12619484Sgarrett.damore@Sun.COM void
auclnt_dev_walk_clients(audio_dev_t * d,int (* walker)(audio_client_t *,void *),void * arg)12629484Sgarrett.damore@Sun.COM auclnt_dev_walk_clients(audio_dev_t *d,
12639484Sgarrett.damore@Sun.COM int (*walker)(audio_client_t *, void *),
12649484Sgarrett.damore@Sun.COM void *arg)
12659484Sgarrett.damore@Sun.COM {
12669484Sgarrett.damore@Sun.COM list_t *l = &d->d_clients;
12679484Sgarrett.damore@Sun.COM audio_client_t *c;
12689484Sgarrett.damore@Sun.COM int rv;
12699484Sgarrett.damore@Sun.COM
127010570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_READER);
12719484Sgarrett.damore@Sun.COM restart:
12729484Sgarrett.damore@Sun.COM for (c = list_head(l); c != NULL; c = list_next(l, c)) {
127310570Sgdamore@opensolaris.org if (!c->c_is_active)
127410570Sgdamore@opensolaris.org continue;
12759484Sgarrett.damore@Sun.COM rv = (walker(c, arg));
12769484Sgarrett.damore@Sun.COM if (rv == AUDIO_WALK_STOP) {
12779484Sgarrett.damore@Sun.COM break;
12789484Sgarrett.damore@Sun.COM } else if (rv == AUDIO_WALK_RESTART) {
12799484Sgarrett.damore@Sun.COM goto restart;
12809484Sgarrett.damore@Sun.COM }
12819484Sgarrett.damore@Sun.COM }
128210570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
12839484Sgarrett.damore@Sun.COM }
12849484Sgarrett.damore@Sun.COM
12859484Sgarrett.damore@Sun.COM
12869484Sgarrett.damore@Sun.COM int
auclnt_open(audio_client_t * c,int oflag)128712165Sgdamore@opensolaris.org auclnt_open(audio_client_t *c, int oflag)
12889484Sgarrett.damore@Sun.COM {
12899484Sgarrett.damore@Sun.COM audio_stream_t *sp;
12909484Sgarrett.damore@Sun.COM audio_dev_t *d = c->c_dev;
12919484Sgarrett.damore@Sun.COM int rv = 0;
12929484Sgarrett.damore@Sun.COM int flags;
12939484Sgarrett.damore@Sun.COM
12949484Sgarrett.damore@Sun.COM flags = 0;
12959484Sgarrett.damore@Sun.COM if (oflag & FNDELAY)
12969484Sgarrett.damore@Sun.COM flags |= ENGINE_NDELAY;
12979484Sgarrett.damore@Sun.COM
12989484Sgarrett.damore@Sun.COM if (oflag & FWRITE) {
12999484Sgarrett.damore@Sun.COM sp = &c->c_ostream;
130012165Sgdamore@opensolaris.org if ((rv = auimpl_engine_open(sp, flags | ENGINE_OUTPUT)) != 0)
13019484Sgarrett.damore@Sun.COM goto done;
13029484Sgarrett.damore@Sun.COM }
13039484Sgarrett.damore@Sun.COM
13049484Sgarrett.damore@Sun.COM if (oflag & FREAD) {
13059484Sgarrett.damore@Sun.COM sp = &c->c_istream;
130612165Sgdamore@opensolaris.org if ((rv = auimpl_engine_open(sp, flags | ENGINE_INPUT)) != 0)
13079484Sgarrett.damore@Sun.COM goto done;
13089484Sgarrett.damore@Sun.COM }
13099484Sgarrett.damore@Sun.COM
13109484Sgarrett.damore@Sun.COM done:
13119484Sgarrett.damore@Sun.COM if (rv != 0) {
13129484Sgarrett.damore@Sun.COM /* close any engines that we opened */
13139484Sgarrett.damore@Sun.COM auimpl_engine_close(&c->c_ostream);
13149484Sgarrett.damore@Sun.COM auimpl_engine_close(&c->c_istream);
13159484Sgarrett.damore@Sun.COM } else {
131610570Sgdamore@opensolaris.org rw_enter(&auimpl_client_lock, RW_WRITER);
13179484Sgarrett.damore@Sun.COM list_insert_tail(&d->d_clients, c);
13189484Sgarrett.damore@Sun.COM c->c_ostream.s_gain_master = d->d_pcmvol;
13199484Sgarrett.damore@Sun.COM c->c_istream.s_gain_master = 100;
132010570Sgdamore@opensolaris.org rw_exit(&auimpl_client_lock);
13219484Sgarrett.damore@Sun.COM auclnt_set_gain(&c->c_ostream, 100);
13229484Sgarrett.damore@Sun.COM auclnt_set_gain(&c->c_istream, 100);
13239484Sgarrett.damore@Sun.COM }
13249484Sgarrett.damore@Sun.COM
13259484Sgarrett.damore@Sun.COM return (rv);
13269484Sgarrett.damore@Sun.COM }
13279484Sgarrett.damore@Sun.COM
13289484Sgarrett.damore@Sun.COM minor_t
auclnt_get_minor(audio_client_t * c)13299484Sgarrett.damore@Sun.COM auclnt_get_minor(audio_client_t *c)
13309484Sgarrett.damore@Sun.COM {
13319484Sgarrett.damore@Sun.COM return (c->c_minor);
13329484Sgarrett.damore@Sun.COM }
13339484Sgarrett.damore@Sun.COM
13349484Sgarrett.damore@Sun.COM minor_t
auclnt_get_original_minor(audio_client_t * c)13359484Sgarrett.damore@Sun.COM auclnt_get_original_minor(audio_client_t *c)
13369484Sgarrett.damore@Sun.COM {
13379484Sgarrett.damore@Sun.COM return (c->c_origminor);
13389484Sgarrett.damore@Sun.COM }
13399484Sgarrett.damore@Sun.COM
13409484Sgarrett.damore@Sun.COM minor_t
auclnt_get_minor_type(audio_client_t * c)13419484Sgarrett.damore@Sun.COM auclnt_get_minor_type(audio_client_t *c)
13429484Sgarrett.damore@Sun.COM {
13439484Sgarrett.damore@Sun.COM return (c->c_origminor & AUDIO_MN_TYPE_MASK);
13449484Sgarrett.damore@Sun.COM }
13459484Sgarrett.damore@Sun.COM
134610157Sgdamore@opensolaris.org queue_t *
auclnt_get_rq(audio_client_t * c)134710157Sgdamore@opensolaris.org auclnt_get_rq(audio_client_t *c)
134810157Sgdamore@opensolaris.org {
134910157Sgdamore@opensolaris.org return (c->c_rq);
135010157Sgdamore@opensolaris.org }
135110157Sgdamore@opensolaris.org
135210157Sgdamore@opensolaris.org queue_t *
auclnt_get_wq(audio_client_t * c)135310157Sgdamore@opensolaris.org auclnt_get_wq(audio_client_t *c)
135410157Sgdamore@opensolaris.org {
135510157Sgdamore@opensolaris.org return (c->c_wq);
135610157Sgdamore@opensolaris.org }
135710157Sgdamore@opensolaris.org
13589484Sgarrett.damore@Sun.COM pid_t
auclnt_get_pid(audio_client_t * c)13599484Sgarrett.damore@Sun.COM auclnt_get_pid(audio_client_t *c)
13609484Sgarrett.damore@Sun.COM {
13619484Sgarrett.damore@Sun.COM return (c->c_pid);
13629484Sgarrett.damore@Sun.COM }
13639484Sgarrett.damore@Sun.COM
13649484Sgarrett.damore@Sun.COM cred_t *
auclnt_get_cred(audio_client_t * c)13659484Sgarrett.damore@Sun.COM auclnt_get_cred(audio_client_t *c)
13669484Sgarrett.damore@Sun.COM {
13679484Sgarrett.damore@Sun.COM return (c->c_cred);
13689484Sgarrett.damore@Sun.COM }
13699484Sgarrett.damore@Sun.COM
13709484Sgarrett.damore@Sun.COM audio_dev_t *
auclnt_get_dev(audio_client_t * c)13719484Sgarrett.damore@Sun.COM auclnt_get_dev(audio_client_t *c)
13729484Sgarrett.damore@Sun.COM {
13739484Sgarrett.damore@Sun.COM return (c->c_dev);
13749484Sgarrett.damore@Sun.COM }
13759484Sgarrett.damore@Sun.COM
13769484Sgarrett.damore@Sun.COM int
auclnt_get_dev_number(audio_dev_t * dev)13779484Sgarrett.damore@Sun.COM auclnt_get_dev_number(audio_dev_t *dev)
13789484Sgarrett.damore@Sun.COM {
13799484Sgarrett.damore@Sun.COM return (dev->d_number);
13809484Sgarrett.damore@Sun.COM }
13819484Sgarrett.damore@Sun.COM
13829484Sgarrett.damore@Sun.COM int
auclnt_get_dev_index(audio_dev_t * dev)13839484Sgarrett.damore@Sun.COM auclnt_get_dev_index(audio_dev_t *dev)
13849484Sgarrett.damore@Sun.COM {
13859484Sgarrett.damore@Sun.COM return (dev->d_index);
13869484Sgarrett.damore@Sun.COM }
13879484Sgarrett.damore@Sun.COM
13889484Sgarrett.damore@Sun.COM const char *
auclnt_get_dev_name(audio_dev_t * dev)13899484Sgarrett.damore@Sun.COM auclnt_get_dev_name(audio_dev_t *dev)
13909484Sgarrett.damore@Sun.COM {
13919484Sgarrett.damore@Sun.COM return (dev->d_name);
13929484Sgarrett.damore@Sun.COM }
13939484Sgarrett.damore@Sun.COM
13949484Sgarrett.damore@Sun.COM const char *
auclnt_get_dev_driver(audio_dev_t * dev)13959484Sgarrett.damore@Sun.COM auclnt_get_dev_driver(audio_dev_t *dev)
13969484Sgarrett.damore@Sun.COM {
13979484Sgarrett.damore@Sun.COM return (ddi_driver_name(dev->d_dip));
13989484Sgarrett.damore@Sun.COM }
13999484Sgarrett.damore@Sun.COM
14009484Sgarrett.damore@Sun.COM dev_info_t *
auclnt_get_dev_devinfo(audio_dev_t * dev)14019484Sgarrett.damore@Sun.COM auclnt_get_dev_devinfo(audio_dev_t *dev)
14029484Sgarrett.damore@Sun.COM {
14039484Sgarrett.damore@Sun.COM return (dev->d_dip);
14049484Sgarrett.damore@Sun.COM }
14059484Sgarrett.damore@Sun.COM
14069484Sgarrett.damore@Sun.COM const char *
auclnt_get_dev_hw_info(audio_dev_t * dev,void ** iter)14079484Sgarrett.damore@Sun.COM auclnt_get_dev_hw_info(audio_dev_t *dev, void **iter)
14089484Sgarrett.damore@Sun.COM {
14099484Sgarrett.damore@Sun.COM struct audio_infostr *isp = *iter;
14109484Sgarrett.damore@Sun.COM if (isp == NULL) {
14119484Sgarrett.damore@Sun.COM isp = list_head(&dev->d_hwinfo);
14129484Sgarrett.damore@Sun.COM } else {
14139484Sgarrett.damore@Sun.COM isp = list_next(&dev->d_hwinfo, isp);
14149484Sgarrett.damore@Sun.COM }
14159484Sgarrett.damore@Sun.COM
14169484Sgarrett.damore@Sun.COM *iter = isp;
14179484Sgarrett.damore@Sun.COM return (isp ? isp->i_line : NULL);
14189484Sgarrett.damore@Sun.COM }
14199484Sgarrett.damore@Sun.COM
14209484Sgarrett.damore@Sun.COM int
auclnt_get_dev_instance(audio_dev_t * dev)14219484Sgarrett.damore@Sun.COM auclnt_get_dev_instance(audio_dev_t *dev)
14229484Sgarrett.damore@Sun.COM {
14239484Sgarrett.damore@Sun.COM return (dev->d_instance);
14249484Sgarrett.damore@Sun.COM }
14259484Sgarrett.damore@Sun.COM
14269484Sgarrett.damore@Sun.COM const char *
auclnt_get_dev_description(audio_dev_t * dev)14279484Sgarrett.damore@Sun.COM auclnt_get_dev_description(audio_dev_t *dev)
14289484Sgarrett.damore@Sun.COM {
14299484Sgarrett.damore@Sun.COM return (dev->d_desc);
14309484Sgarrett.damore@Sun.COM }
14319484Sgarrett.damore@Sun.COM
14329484Sgarrett.damore@Sun.COM const char *
auclnt_get_dev_version(audio_dev_t * dev)14339484Sgarrett.damore@Sun.COM auclnt_get_dev_version(audio_dev_t *dev)
14349484Sgarrett.damore@Sun.COM {
14359484Sgarrett.damore@Sun.COM return (dev->d_vers);
14369484Sgarrett.damore@Sun.COM }
14379484Sgarrett.damore@Sun.COM
143811936Sgdamore@opensolaris.org uint_t
auclnt_get_dev_capab(audio_dev_t * dev)14399484Sgarrett.damore@Sun.COM auclnt_get_dev_capab(audio_dev_t *dev)
14409484Sgarrett.damore@Sun.COM {
14419484Sgarrett.damore@Sun.COM uint32_t flags;
144211936Sgdamore@opensolaris.org uint_t caps = 0;
14439484Sgarrett.damore@Sun.COM
14449484Sgarrett.damore@Sun.COM flags = dev->d_flags;
14459484Sgarrett.damore@Sun.COM
14469484Sgarrett.damore@Sun.COM if (flags & DEV_OUTPUT_CAP)
14479484Sgarrett.damore@Sun.COM caps |= AUDIO_CLIENT_CAP_PLAY;
14489484Sgarrett.damore@Sun.COM if (flags & DEV_INPUT_CAP)
14499484Sgarrett.damore@Sun.COM caps |= AUDIO_CLIENT_CAP_RECORD;
14509484Sgarrett.damore@Sun.COM if (flags & DEV_DUPLEX_CAP)
14519484Sgarrett.damore@Sun.COM caps |= AUDIO_CLIENT_CAP_DUPLEX;
14529484Sgarrett.damore@Sun.COM
14539484Sgarrett.damore@Sun.COM /* AC3: deal with formats that don't support mixing */
14549484Sgarrett.damore@Sun.COM
14559484Sgarrett.damore@Sun.COM return (caps);
14569484Sgarrett.damore@Sun.COM }
14579484Sgarrett.damore@Sun.COM
14589484Sgarrett.damore@Sun.COM uint64_t
auclnt_get_samples(audio_stream_t * sp)14599484Sgarrett.damore@Sun.COM auclnt_get_samples(audio_stream_t *sp)
14609484Sgarrett.damore@Sun.COM {
14619484Sgarrett.damore@Sun.COM uint64_t n;
14629484Sgarrett.damore@Sun.COM
14639484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
14649484Sgarrett.damore@Sun.COM n = sp->s_samples;
14659484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
14669484Sgarrett.damore@Sun.COM return (n);
14679484Sgarrett.damore@Sun.COM }
14689484Sgarrett.damore@Sun.COM
14699484Sgarrett.damore@Sun.COM void
auclnt_set_samples(audio_stream_t * sp,uint64_t n)14709484Sgarrett.damore@Sun.COM auclnt_set_samples(audio_stream_t *sp, uint64_t n)
14719484Sgarrett.damore@Sun.COM {
14729484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
14739484Sgarrett.damore@Sun.COM sp->s_samples = n;
14749484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
14759484Sgarrett.damore@Sun.COM }
14769484Sgarrett.damore@Sun.COM
14779484Sgarrett.damore@Sun.COM uint64_t
auclnt_get_errors(audio_stream_t * sp)14789484Sgarrett.damore@Sun.COM auclnt_get_errors(audio_stream_t *sp)
14799484Sgarrett.damore@Sun.COM {
14809484Sgarrett.damore@Sun.COM uint64_t n;
14819484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
14829484Sgarrett.damore@Sun.COM n = sp->s_errors;
14839484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
14849484Sgarrett.damore@Sun.COM return (n);
14859484Sgarrett.damore@Sun.COM }
14869484Sgarrett.damore@Sun.COM
14879484Sgarrett.damore@Sun.COM void
auclnt_set_errors(audio_stream_t * sp,uint64_t n)14889484Sgarrett.damore@Sun.COM auclnt_set_errors(audio_stream_t *sp, uint64_t n)
14899484Sgarrett.damore@Sun.COM {
14909484Sgarrett.damore@Sun.COM mutex_enter(&sp->s_lock);
14919484Sgarrett.damore@Sun.COM sp->s_errors = n;
14929484Sgarrett.damore@Sun.COM mutex_exit(&sp->s_lock);
14939484Sgarrett.damore@Sun.COM }
14949484Sgarrett.damore@Sun.COM
14959484Sgarrett.damore@Sun.COM void
auclnt_register_ops(minor_t minor,audio_client_ops_t * ops)14969484Sgarrett.damore@Sun.COM auclnt_register_ops(minor_t minor, audio_client_ops_t *ops)
14979484Sgarrett.damore@Sun.COM {
14989484Sgarrett.damore@Sun.COM /* we control minor number allocations, no need for runtime checks */
14999484Sgarrett.damore@Sun.COM ASSERT(minor <= AUDIO_MN_TYPE_MASK);
15009484Sgarrett.damore@Sun.COM
15019484Sgarrett.damore@Sun.COM audio_client_ops[minor] = ops;
15029484Sgarrett.damore@Sun.COM }
15039484Sgarrett.damore@Sun.COM
15049484Sgarrett.damore@Sun.COM int
auimpl_create_minors(audio_dev_t * d)15059484Sgarrett.damore@Sun.COM auimpl_create_minors(audio_dev_t *d)
15069484Sgarrett.damore@Sun.COM {
15079484Sgarrett.damore@Sun.COM char path[MAXPATHLEN];
15089484Sgarrett.damore@Sun.COM int rv = 0;
15099484Sgarrett.damore@Sun.COM minor_t minor;
15109484Sgarrett.damore@Sun.COM audio_client_ops_t *ops;
15119484Sgarrett.damore@Sun.COM char *nt;
15129484Sgarrett.damore@Sun.COM
15139484Sgarrett.damore@Sun.COM for (int i = 0; i <= AUDIO_MN_TYPE_MASK; i++) {
15149484Sgarrett.damore@Sun.COM
15159484Sgarrett.damore@Sun.COM if ((ops = audio_client_ops[i]) == NULL)
15169484Sgarrett.damore@Sun.COM continue;
15179484Sgarrett.damore@Sun.COM
15189484Sgarrett.damore@Sun.COM if (ops->aco_dev_init != NULL)
15199484Sgarrett.damore@Sun.COM d->d_minor_data[i] = ops->aco_dev_init(d);
15209484Sgarrett.damore@Sun.COM
15219484Sgarrett.damore@Sun.COM switch (i) {
15229484Sgarrett.damore@Sun.COM case AUDIO_MINOR_SNDSTAT:
15239484Sgarrett.damore@Sun.COM if (!(d->d_flags & DEV_SNDSTAT_CAP)) {
15249484Sgarrett.damore@Sun.COM continue;
15259484Sgarrett.damore@Sun.COM }
15269484Sgarrett.damore@Sun.COM nt = DDI_PSEUDO;
15279484Sgarrett.damore@Sun.COM break;
15289484Sgarrett.damore@Sun.COM
15299484Sgarrett.damore@Sun.COM default:
15309484Sgarrett.damore@Sun.COM if (!(d->d_flags & (DEV_INPUT_CAP| DEV_OUTPUT_CAP))) {
15319484Sgarrett.damore@Sun.COM continue;
15329484Sgarrett.damore@Sun.COM }
15339484Sgarrett.damore@Sun.COM nt = DDI_NT_AUDIO;
15349484Sgarrett.damore@Sun.COM break;
15359484Sgarrett.damore@Sun.COM }
15369484Sgarrett.damore@Sun.COM
15379484Sgarrett.damore@Sun.COM if (ops->aco_minor_prefix != NULL) {
15389484Sgarrett.damore@Sun.COM
15399484Sgarrett.damore@Sun.COM minor = AUDIO_MKMN(d->d_instance, i);
15409484Sgarrett.damore@Sun.COM (void) snprintf(path, sizeof (path),
15419484Sgarrett.damore@Sun.COM "%s%d", ops->aco_minor_prefix, d->d_instance);
15429484Sgarrett.damore@Sun.COM
15439484Sgarrett.damore@Sun.COM rv = ddi_create_minor_node(d->d_dip, path, S_IFCHR,
15449484Sgarrett.damore@Sun.COM minor, nt, 0);
15459484Sgarrett.damore@Sun.COM
15469484Sgarrett.damore@Sun.COM if (rv != 0)
15479484Sgarrett.damore@Sun.COM break;
15489484Sgarrett.damore@Sun.COM }
15499484Sgarrett.damore@Sun.COM }
15509484Sgarrett.damore@Sun.COM return (rv);
15519484Sgarrett.damore@Sun.COM }
15529484Sgarrett.damore@Sun.COM
15539484Sgarrett.damore@Sun.COM void
auimpl_remove_minors(audio_dev_t * d)15549484Sgarrett.damore@Sun.COM auimpl_remove_minors(audio_dev_t *d)
15559484Sgarrett.damore@Sun.COM {
15569484Sgarrett.damore@Sun.COM char path[MAXPATHLEN];
15579484Sgarrett.damore@Sun.COM audio_client_ops_t *ops;
15589484Sgarrett.damore@Sun.COM
15599484Sgarrett.damore@Sun.COM for (int i = 0; i <= AUDIO_MN_TYPE_MASK; i++) {
15609484Sgarrett.damore@Sun.COM if ((ops = audio_client_ops[i]) == NULL)
15619484Sgarrett.damore@Sun.COM continue;
15629484Sgarrett.damore@Sun.COM if (ops->aco_minor_prefix != NULL) {
15639484Sgarrett.damore@Sun.COM (void) snprintf(path, sizeof (path), "%s%d",
15649484Sgarrett.damore@Sun.COM ops->aco_minor_prefix, d->d_instance);
15659484Sgarrett.damore@Sun.COM (void) ddi_remove_minor_node(d->d_dip, path);
15669484Sgarrett.damore@Sun.COM }
15679484Sgarrett.damore@Sun.COM
15689484Sgarrett.damore@Sun.COM if (ops->aco_dev_fini != NULL)
15699484Sgarrett.damore@Sun.COM ops->aco_dev_fini(d->d_minor_data[i]);
15709484Sgarrett.damore@Sun.COM }
15719484Sgarrett.damore@Sun.COM }
15729484Sgarrett.damore@Sun.COM
15739484Sgarrett.damore@Sun.COM void *
auclnt_get_dev_minor_data(audio_dev_t * d,minor_t mn)15749484Sgarrett.damore@Sun.COM auclnt_get_dev_minor_data(audio_dev_t *d, minor_t mn)
15759484Sgarrett.damore@Sun.COM {
15769484Sgarrett.damore@Sun.COM ASSERT(mn < (1U << AUDIO_MN_TYPE_NBITS));
15779484Sgarrett.damore@Sun.COM return (d->d_minor_data[mn]);
15789484Sgarrett.damore@Sun.COM }
15799484Sgarrett.damore@Sun.COM
15809484Sgarrett.damore@Sun.COM void *
auclnt_get_minor_data(audio_client_t * c,minor_t mn)15819484Sgarrett.damore@Sun.COM auclnt_get_minor_data(audio_client_t *c, minor_t mn)
15829484Sgarrett.damore@Sun.COM {
15839484Sgarrett.damore@Sun.COM ASSERT(mn < (1U << AUDIO_MN_TYPE_NBITS));
15849484Sgarrett.damore@Sun.COM return (c->c_dev->d_minor_data[mn]);
15859484Sgarrett.damore@Sun.COM }
15869484Sgarrett.damore@Sun.COM
15879484Sgarrett.damore@Sun.COM /*
15889484Sgarrett.damore@Sun.COM * This will walk all controls registered to a clients device and callback
15899484Sgarrett.damore@Sun.COM * to walker for each one with its audio_ctrl. Note this data
15909484Sgarrett.damore@Sun.COM * must be considered read only by walker.
15919484Sgarrett.damore@Sun.COM *
15929484Sgarrett.damore@Sun.COM * Note that walk_func may return values to continue (AUDIO_WALK_CONTINUE)
15939484Sgarrett.damore@Sun.COM * or stop walk (AUDIO_WALK_STOP).
15949484Sgarrett.damore@Sun.COM *
15959484Sgarrett.damore@Sun.COM */
15969484Sgarrett.damore@Sun.COM void
auclnt_walk_controls(audio_dev_t * d,int (* walker)(audio_ctrl_t *,void *),void * arg)15979484Sgarrett.damore@Sun.COM auclnt_walk_controls(audio_dev_t *d,
15989484Sgarrett.damore@Sun.COM int (*walker)(audio_ctrl_t *, void *),
15999484Sgarrett.damore@Sun.COM void *arg)
16009484Sgarrett.damore@Sun.COM {
16019484Sgarrett.damore@Sun.COM audio_ctrl_t *ctrl;
16029484Sgarrett.damore@Sun.COM
160311936Sgdamore@opensolaris.org mutex_enter(&d->d_ctrl_lock);
16049484Sgarrett.damore@Sun.COM for (ctrl = list_head(&d->d_controls); ctrl;
16059484Sgarrett.damore@Sun.COM ctrl = list_next(&d->d_controls, ctrl)) {
16069484Sgarrett.damore@Sun.COM if (walker(ctrl, arg) == AUDIO_WALK_STOP)
16079484Sgarrett.damore@Sun.COM break;
16089484Sgarrett.damore@Sun.COM }
160911936Sgdamore@opensolaris.org mutex_exit(&d->d_ctrl_lock);
16109484Sgarrett.damore@Sun.COM }
16119484Sgarrett.damore@Sun.COM
16129484Sgarrett.damore@Sun.COM /*
16139484Sgarrett.damore@Sun.COM * This will search all controls attached to an
16149484Sgarrett.damore@Sun.COM * audio device for a control with the desired name.
16159484Sgarrett.damore@Sun.COM *
16169484Sgarrett.damore@Sun.COM * d - the audio device to look on
16179484Sgarrett.damore@Sun.COM * name - name of the control being looked for.
16189484Sgarrett.damore@Sun.COM *
16199484Sgarrett.damore@Sun.COM * On successful return a ctrl handle will be returned. On
16209484Sgarrett.damore@Sun.COM * failure NULL is returned.
16219484Sgarrett.damore@Sun.COM */
16229484Sgarrett.damore@Sun.COM audio_ctrl_t *
auclnt_find_control(audio_dev_t * d,const char * name)16239484Sgarrett.damore@Sun.COM auclnt_find_control(audio_dev_t *d, const char *name)
16249484Sgarrett.damore@Sun.COM {
16259484Sgarrett.damore@Sun.COM audio_ctrl_t *ctrl;
16269484Sgarrett.damore@Sun.COM
16279484Sgarrett.damore@Sun.COM /* Verify argument */
16289484Sgarrett.damore@Sun.COM ASSERT(d);
16299484Sgarrett.damore@Sun.COM
163011936Sgdamore@opensolaris.org mutex_enter(&d->d_ctrl_lock);
16319484Sgarrett.damore@Sun.COM for (ctrl = list_head(&d->d_controls); ctrl;
16329484Sgarrett.damore@Sun.COM ctrl = list_next(&d->d_controls, ctrl)) {
16339484Sgarrett.damore@Sun.COM if (strcmp(ctrl->ctrl_name, name) == 0) {
163411936Sgdamore@opensolaris.org mutex_exit(&d->d_ctrl_lock);
16359484Sgarrett.damore@Sun.COM return (ctrl);
16369484Sgarrett.damore@Sun.COM }
16379484Sgarrett.damore@Sun.COM }
163811936Sgdamore@opensolaris.org mutex_exit(&d->d_ctrl_lock);
16399484Sgarrett.damore@Sun.COM return (NULL);
16409484Sgarrett.damore@Sun.COM }
16419484Sgarrett.damore@Sun.COM
16429484Sgarrett.damore@Sun.COM /*
16439484Sgarrett.damore@Sun.COM * Given a known control, get its attributes.
16449484Sgarrett.damore@Sun.COM *
16459484Sgarrett.damore@Sun.COM * The caller must supply a audio_ctrl_desc_t structure. Also the
16469484Sgarrett.damore@Sun.COM * values in the structure are ignored when making the call and filled
16479484Sgarrett.damore@Sun.COM * in by this function. All data pointed to by elements of desc should
16489484Sgarrett.damore@Sun.COM * be assumed read only.
16499484Sgarrett.damore@Sun.COM *
16509484Sgarrett.damore@Sun.COM * If an error occurs then a non-zero is returned.
16519484Sgarrett.damore@Sun.COM *
16529484Sgarrett.damore@Sun.COM */
16539484Sgarrett.damore@Sun.COM int
auclnt_control_describe(audio_ctrl_t * ctrl,audio_ctrl_desc_t * desc)16549484Sgarrett.damore@Sun.COM auclnt_control_describe(audio_ctrl_t *ctrl, audio_ctrl_desc_t *desc)
16559484Sgarrett.damore@Sun.COM {
16569484Sgarrett.damore@Sun.COM ASSERT(ctrl);
16579484Sgarrett.damore@Sun.COM ASSERT(desc);
16589484Sgarrett.damore@Sun.COM
16599484Sgarrett.damore@Sun.COM bcopy(&ctrl->ctrl_des, desc, sizeof (*desc));
16609484Sgarrett.damore@Sun.COM return (0);
16619484Sgarrett.damore@Sun.COM }
16629484Sgarrett.damore@Sun.COM
16639484Sgarrett.damore@Sun.COM int
auclnt_control_read(audio_ctrl_t * ctrl,uint64_t * value)16649484Sgarrett.damore@Sun.COM auclnt_control_read(audio_ctrl_t *ctrl, uint64_t *value)
16659484Sgarrett.damore@Sun.COM {
16669484Sgarrett.damore@Sun.COM return (audio_control_read(ctrl, value));
16679484Sgarrett.damore@Sun.COM }
16689484Sgarrett.damore@Sun.COM
16699484Sgarrett.damore@Sun.COM int
auclnt_control_write(audio_ctrl_t * ctrl,uint64_t value)16709484Sgarrett.damore@Sun.COM auclnt_control_write(audio_ctrl_t *ctrl, uint64_t value)
16719484Sgarrett.damore@Sun.COM {
16729484Sgarrett.damore@Sun.COM return (audio_control_write(ctrl, value));
16739484Sgarrett.damore@Sun.COM }
16749484Sgarrett.damore@Sun.COM
16759484Sgarrett.damore@Sun.COM void
auclnt_warn(audio_client_t * c,const char * fmt,...)16769484Sgarrett.damore@Sun.COM auclnt_warn(audio_client_t *c, const char *fmt, ...)
16779484Sgarrett.damore@Sun.COM {
16789484Sgarrett.damore@Sun.COM va_list va;
16799484Sgarrett.damore@Sun.COM
16809484Sgarrett.damore@Sun.COM va_start(va, fmt);
16819484Sgarrett.damore@Sun.COM auimpl_dev_vwarn(c ? c->c_dev : NULL, fmt, va);
16829484Sgarrett.damore@Sun.COM va_end(va);
16839484Sgarrett.damore@Sun.COM }
1684