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.
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.
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]
22 * Copyright (C) 4Front Technologies 1996-2008.
24 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <sys/types.h>
28 #include <sys/sysmacros.h>
33 #include <sys/errno.h>
34 #include <sys/atomic.h>
36 #include <sys/sunddi.h>
38 #include "audio_impl.h"
41 * Audio Client implementation.
45 * Attenuation table for dB->linear conversion. Indexed in steps of
46 * 0.5 dB. Table size is 25 dB (first entry is handled as mute).
48 * Notably, the last item in table is taken as 0 dB (i.e. maximum volume).
50 * Table contents can be calculated as follows (requires sunmath library):
52 * scale = AUDIO_VOL_SCALE;
53 * for (i = -50; i <= 0; i++) {
54 * x = exp10(0.05 * i);
55 * printf("%d: %f %.0f\n", i, x, trunc(x * scale));
60 static const uint16_t auimpl_db_table
[AUDIO_DB_SIZE
+ 1] = {
61 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
62 2, 2, 3, 3, 4, 4, 5, 5, 6, 7,
63 8, 9, 10, 11, 12, 14, 16, 18, 20, 22,
64 25, 28, 32, 36, 40, 45, 51, 57, 64, 72,
65 80, 90, 101, 114, 128, 143, 161, 181, 203, 228,
69 static list_t auimpl_clients
;
70 static krwlock_t auimpl_client_lock
;
71 static audio_client_ops_t
*audio_client_ops
[AUDIO_MN_TYPE_MASK
+ 1];
74 auclnt_get_private(audio_client_t
*c
)
76 return (c
->c_private
);
80 auclnt_set_private(audio_client_t
*c
, void *private)
82 c
->c_private
= private;
86 auclnt_set_rate(audio_stream_t
*sp
, int rate
)
91 /* basic sanity checks! */
92 if ((rate
< 5000) || (rate
> 192000)) {
95 if (rate
!= sp
->s_user_parms
->p_rate
) {
97 rv
= auimpl_engine_setup(sp
, 0, &parms
, FORMAT_MSK_RATE
);
103 auclnt_get_rate(audio_stream_t
*sp
)
105 return (sp
->s_user_parms
->p_rate
);
109 auclnt_get_fragsz(audio_stream_t
*sp
)
111 return (sp
->s_fragbytes
);
115 auclnt_get_framesz(audio_stream_t
*sp
)
117 return (sp
->s_framesz
);
121 auclnt_get_nfrags(audio_stream_t
*sp
)
123 return (sp
->s_nfrags
);
127 auclnt_get_nframes(audio_stream_t
*sp
)
129 return (sp
->s_nframes
);
133 auclnt_set_latency(audio_stream_t
*sp
, uint_t frags
, uint_t bytes
)
135 mutex_enter(&sp
->s_lock
);
136 sp
->s_hintfrags
= (uint16_t)frags
;
137 sp
->s_hintsz
= bytes
;
138 mutex_exit(&sp
->s_lock
);
142 auclnt_get_head(audio_stream_t
*sp
)
148 auclnt_get_tail(audio_stream_t
*sp
)
154 auclnt_get_hidx(audio_stream_t
*sp
)
160 auclnt_get_tidx(audio_stream_t
*sp
)
166 auclnt_input_stream(audio_client_t
*c
)
168 return (&c
->c_istream
);
172 auclnt_output_stream(audio_client_t
*c
)
174 return (&c
->c_ostream
);
178 auclnt_get_count(audio_stream_t
*sp
)
182 mutex_enter(&sp
->s_lock
);
183 ASSERT((sp
->s_head
- sp
->s_tail
) <= sp
->s_nframes
);
184 count
= (uint_t
)(sp
->s_head
- sp
->s_tail
);
185 mutex_exit(&sp
->s_lock
);
191 auclnt_consume(audio_stream_t
*sp
, uint_t n
)
193 mutex_enter(&sp
->s_lock
);
195 ASSERT(sp
== &sp
->s_client
->c_istream
);
196 n
= max(n
, sp
->s_head
- sp
->s_tail
);
199 if (sp
->s_tidx
>= sp
->s_nframes
) {
200 sp
->s_tidx
-= sp
->s_nframes
;
203 ASSERT(sp
->s_tail
<= sp
->s_head
);
204 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
206 mutex_exit(&sp
->s_lock
);
212 auclnt_consume_data(audio_stream_t
*sp
, caddr_t dst
, uint_t n
)
219 mutex_enter(&sp
->s_lock
);
221 nframes
= sp
->s_nframes
;
222 framesz
= sp
->s_framesz
;
224 ASSERT(sp
== &sp
->s_client
->c_istream
);
225 ASSERT(sp
->s_head
>= sp
->s_tail
);
226 ASSERT(sp
->s_tidx
< nframes
);
227 ASSERT(sp
->s_hidx
< nframes
);
229 cnt
= n
= min(n
, sp
->s_head
- sp
->s_tail
);
230 data
= sp
->s_data
+ (sp
->s_tidx
* framesz
);
234 nf
= min(nframes
- sp
->s_tidx
, n
);
237 bcopy(data
, dst
, nb
);
244 if (sp
->s_tidx
== nframes
) {
250 ASSERT(sp
->s_tail
<= sp
->s_head
);
251 ASSERT(sp
->s_tidx
< nframes
);
253 mutex_exit(&sp
->s_lock
);
259 auclnt_produce(audio_stream_t
*sp
, uint_t n
)
261 mutex_enter(&sp
->s_lock
);
263 ASSERT(sp
== &sp
->s_client
->c_ostream
);
264 n
= max(n
, sp
->s_nframes
- (sp
->s_head
- sp
->s_tail
));
267 if (sp
->s_hidx
>= sp
->s_nframes
) {
268 sp
->s_hidx
-= sp
->s_nframes
;
271 ASSERT(sp
->s_tail
<= sp
->s_head
);
272 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
274 mutex_exit(&sp
->s_lock
);
280 auclnt_produce_data(audio_stream_t
*sp
, caddr_t src
, uint_t n
)
287 mutex_enter(&sp
->s_lock
);
289 nframes
= sp
->s_nframes
;
290 framesz
= sp
->s_framesz
;
292 ASSERT(sp
== &sp
->s_client
->c_ostream
);
293 ASSERT(sp
->s_head
>= sp
->s_tail
);
294 ASSERT(sp
->s_tidx
< nframes
);
295 ASSERT(sp
->s_hidx
< nframes
);
297 cnt
= n
= min(n
, nframes
- (sp
->s_head
- sp
->s_tail
));
298 data
= sp
->s_data
+ (sp
->s_hidx
* framesz
);
302 nf
= min(nframes
- sp
->s_hidx
, n
);
305 bcopy(src
, data
, nb
);
313 if (sp
->s_hidx
== nframes
) {
319 ASSERT(sp
->s_tail
<= sp
->s_head
);
320 ASSERT(sp
->s_hidx
< nframes
);
322 mutex_exit(&sp
->s_lock
);
328 auclnt_read(audio_client_t
*c
, struct uio
*uio
)
330 audio_stream_t
*sp
= &c
->c_istream
;
338 loff
= uio
->uio_loffset
;
341 mutex_enter(&sp
->s_lock
);
343 if ((!sp
->s_paused
) && (!sp
->s_running
)) {
344 mutex_exit(&sp
->s_lock
);
346 mutex_enter(&sp
->s_lock
);
350 framesz
= sp
->s_framesz
;
352 ASSERT(sp
->s_head
>= sp
->s_tail
);
353 ASSERT(sp
->s_tidx
< sp
->s_nframes
);
355 while (uio
->uio_resid
>= framesz
) {
357 while ((cnt
= (sp
->s_head
- sp
->s_tail
)) == 0) {
358 if (uio
->uio_fmode
& (FNONBLOCK
|FNDELAY
)) {
359 mutex_exit(&sp
->s_lock
);
362 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
363 mutex_exit(&sp
->s_lock
);
369 cnt
= min(cnt
, sp
->s_nframes
- tidx
);
370 cnt
= min(cnt
, (uio
->uio_resid
/ framesz
));
372 mutex_exit(&sp
->s_lock
);
373 rv
= uiomove(sp
->s_data
+ (tidx
* framesz
),
374 cnt
* framesz
, UIO_READ
, uio
);
376 uio
->uio_loffset
= loff
;
383 mutex_enter(&sp
->s_lock
);
386 if (sp
->s_tidx
== sp
->s_nframes
) {
391 ASSERT(sp
->s_tail
<= sp
->s_head
);
392 ASSERT(sp
->s_tidx
< sp
->s_nframes
);
394 /* round off any remaining partial bits */
397 mutex_exit(&sp
->s_lock
);
403 auclnt_write(audio_client_t
*c
, struct uio
*uio
)
405 audio_stream_t
*sp
= &c
->c_ostream
;
413 loff
= uio
->uio_loffset
;
416 mutex_enter(&sp
->s_lock
);
418 framesz
= sp
->s_framesz
;
420 ASSERT(sp
->s_head
>= sp
->s_tail
);
421 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
423 while (uio
->uio_resid
>= framesz
) {
425 while ((cnt
= sp
->s_nframes
- (sp
->s_head
- sp
->s_tail
)) == 0) {
426 if (uio
->uio_fmode
& (FNONBLOCK
|FNDELAY
)) {
427 mutex_exit(&sp
->s_lock
);
430 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
431 mutex_exit(&sp
->s_lock
);
437 cnt
= min(cnt
, sp
->s_nframes
- hidx
);
438 cnt
= min(cnt
, (uio
->uio_resid
/ framesz
));
441 * We have to drop the stream lock, because the
442 * uiomove might require doing a page in, which could
443 * get blocked behind the PIL of the audio processing
444 * thread which also grabs the s_lock. (Hence, there
445 * is a risk of deadlock due to priority inversion.)
447 mutex_exit(&sp
->s_lock
);
449 rv
= uiomove(sp
->s_data
+ (hidx
* framesz
),
450 cnt
* framesz
, UIO_WRITE
, uio
);
452 uio
->uio_loffset
= loff
;
459 mutex_enter(&sp
->s_lock
);
463 if (sp
->s_hidx
== sp
->s_nframes
) {
467 if ((!sp
->s_paused
) && (!sp
->s_running
) &&
468 ((sp
->s_head
- sp
->s_tail
) > sp
->s_fragfr
)) {
469 mutex_exit(&sp
->s_lock
);
471 mutex_enter(&sp
->s_lock
);
475 ASSERT(sp
->s_tail
<= sp
->s_head
);
476 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
478 /* round off any remaining partial bits */
481 mutex_exit(&sp
->s_lock
);
487 auclnt_chpoll(audio_client_t
*c
, short events
, int anyyet
, short *reventsp
,
488 struct pollhead
**phpp
)
493 if (events
& (POLLIN
| POLLRDNORM
)) {
495 mutex_enter(&sp
->s_lock
);
496 if ((sp
->s_head
- sp
->s_tail
) > sp
->s_fragfr
) {
497 nev
= POLLIN
| POLLRDNORM
;
499 mutex_exit(&sp
->s_lock
);
502 if (events
& POLLOUT
) {
504 mutex_enter(&sp
->s_lock
);
505 if ((sp
->s_nframes
- (sp
->s_head
- sp
->s_tail
)) >
509 mutex_exit(&sp
->s_lock
);
513 *reventsp
= nev
& events
;
517 *phpp
= &c
->c_pollhead
;
524 auclnt_pollwakeup(audio_client_t
*c
, short events
)
526 pollwakeup(&c
->c_pollhead
, events
);
530 auclnt_get_output_qlen(audio_client_t
*c
, uint_t
*slen
, uint_t
*flen
)
532 audio_stream_t
*sp
= &c
->c_ostream
;
533 audio_engine_t
*e
= sp
->s_engine
;
538 /* if no output engine, can't do it! */
544 mutex_enter(&e
->e_lock
);
545 mutex_enter(&sp
->s_lock
);
546 if (e
->e_ops
.audio_engine_qlen
!= NULL
) {
547 el
= ENG_QLEN(e
) + (e
->e_head
- e
->e_tail
);
549 el
= (e
->e_head
- e
->e_tail
);
553 sr
= sp
->s_user_parms
->p_rate
;
554 cnt
= (uint_t
)(sp
->s_head
- sp
->s_tail
);
555 mutex_exit(&sp
->s_lock
);
556 mutex_exit(&e
->e_lock
);
558 /* engine frames converted to stream rate, plus stream frames */
560 *flen
= ((uint_t
)(((el
* sr
) / er
) + sl
));
564 auclnt_set_format(audio_stream_t
*sp
, int fmt
)
570 * AC3: If we select an AC3 format, then we have to allocate
571 * another engine. Normally this will be an output only
572 * engine. However, for now we aren't supporting AC3
577 case AUDIO_FORMAT_U8
:
578 case AUDIO_FORMAT_ULAW
:
579 case AUDIO_FORMAT_ALAW
:
580 case AUDIO_FORMAT_S8
:
581 case AUDIO_FORMAT_S16_LE
:
582 case AUDIO_FORMAT_S16_BE
:
583 case AUDIO_FORMAT_U16_LE
:
584 case AUDIO_FORMAT_U16_BE
:
585 case AUDIO_FORMAT_S24_LE
:
586 case AUDIO_FORMAT_S24_BE
:
587 case AUDIO_FORMAT_S32_LE
:
588 case AUDIO_FORMAT_S32_BE
:
589 case AUDIO_FORMAT_S24_PACKED
:
592 case AUDIO_FORMAT_AC3
: /* AC3: PASSTHRU */
599 * Optimization. Some personalities send us the same format
600 * over and over again. (Sun personality does this
601 * repeatedly.) setup_src is potentially expensive, so we
602 * avoid doing it unless we really need to.
604 if (fmt
!= sp
->s_user_parms
->p_format
) {
606 * Note that setting the format doesn't check that the
607 * audio streams have been paused. As a result, any
608 * data still playing or recording will probably get
609 * misinterpreted. It would be smart if the client
610 * application paused/stopped playback before changing
613 parms
.p_format
= fmt
;
614 rv
= auimpl_engine_setup(sp
, 0, &parms
, FORMAT_MSK_FMT
);
621 auclnt_get_format(audio_stream_t
*sp
)
623 return (sp
->s_user_parms
->p_format
);
627 auclnt_get_output_format(audio_client_t
*c
)
629 return (c
->c_ostream
.s_user_parms
->p_format
);
633 auclnt_get_input_format(audio_client_t
*c
)
635 return (c
->c_istream
.s_user_parms
->p_format
);
639 auclnt_set_channels(audio_stream_t
*sp
, int nchan
)
644 /* Validate setting */
645 if ((nchan
> AUDIO_MAX_CHANNELS
) || (nchan
< 1)) {
649 if (nchan
!= sp
->s_user_parms
->p_nchan
) {
650 parms
.p_nchan
= nchan
;
651 rv
= auimpl_engine_setup(sp
, 0, &parms
, FORMAT_MSK_CHAN
);
658 auclnt_get_channels(audio_stream_t
*sp
)
660 return (sp
->s_user_parms
->p_nchan
);
665 auimpl_set_gain_master(audio_stream_t
*sp
, uint8_t gain
)
673 mutex_enter(&sp
->s_lock
);
674 if (sp
->s_gain_master
== gain
) {
675 mutex_exit(&sp
->s_lock
);
680 * calculate the scaled values. Done now to avoid calculations
683 scaled
= (gain
* sp
->s_gain_pct
* AUDIO_DB_SIZE
) / (100 * 100);
685 sp
->s_gain_master
= gain
;
686 sp
->s_gain_scaled
= auimpl_db_table
[scaled
];
689 sp
->s_gain_eff
= sp
->s_gain_scaled
;
691 mutex_exit(&sp
->s_lock
);
695 auimpl_set_pcmvol(void *arg
, uint64_t val
)
697 audio_dev_t
*d
= arg
;
698 list_t
*l
= &d
->d_clients
;
704 rw_enter(&auimpl_client_lock
, RW_WRITER
);
705 d
->d_pcmvol
= val
& 0xff;
706 rw_downgrade(&auimpl_client_lock
);
708 for (c
= list_head(l
); c
; c
= list_next(l
, c
)) {
709 /* don't need to check is_active here, its safe */
710 auimpl_set_gain_master(&c
->c_ostream
, (uint8_t)val
);
712 rw_exit(&auimpl_client_lock
);
718 auimpl_get_pcmvol(void *arg
, uint64_t *val
)
720 audio_dev_t
*d
= arg
;
727 auclnt_set_gain(audio_stream_t
*sp
, uint8_t gain
)
735 mutex_enter(&sp
->s_lock
);
737 /* if no change, don't bother doing updates */
738 if (sp
->s_gain_pct
== gain
) {
739 mutex_exit(&sp
->s_lock
);
744 * calculate the scaled values. Done now to avoid calculations
747 scaled
= (gain
* sp
->s_gain_master
* AUDIO_DB_SIZE
) / (100 * 100);
749 sp
->s_gain_pct
= gain
;
750 sp
->s_gain_scaled
= auimpl_db_table
[scaled
];
753 sp
->s_gain_eff
= sp
->s_gain_scaled
;
755 mutex_exit(&sp
->s_lock
);
757 atomic_inc_uint(&sp
->s_client
->c_dev
->d_serial
);
761 auclnt_get_gain(audio_stream_t
*sp
)
763 return (sp
->s_gain_pct
);
767 auclnt_set_muted(audio_stream_t
*sp
, boolean_t muted
)
769 mutex_enter(&sp
->s_lock
);
771 /* if no work change, don't bother doing updates */
772 if (sp
->s_muted
== muted
) {
773 mutex_exit(&sp
->s_lock
);
781 sp
->s_gain_eff
= sp
->s_gain_scaled
;
783 mutex_exit(&sp
->s_lock
);
785 atomic_inc_uint(&sp
->s_client
->c_dev
->d_serial
);
789 auclnt_get_muted(audio_stream_t
*sp
)
791 return (sp
->s_muted
);
795 auclnt_is_running(audio_stream_t
*sp
)
797 return (sp
->s_running
);
801 auclnt_start(audio_stream_t
*sp
)
803 mutex_enter(&sp
->s_lock
);
804 sp
->s_running
= B_TRUE
;
805 mutex_exit(&sp
->s_lock
);
809 auclnt_stop(audio_stream_t
*sp
)
811 mutex_enter(&sp
->s_lock
);
812 /* if running, then stop it */
814 sp
->s_running
= B_FALSE
;
816 * if we stopped the engine, we might need to wake up
817 * a thread that is waiting for drain to complete.
819 cv_broadcast(&sp
->s_cv
);
821 mutex_exit(&sp
->s_lock
);
825 * When pausing, no new data will be played after the most recently
826 * mixed samples have played. However, the audio engine will continue
827 * to play (possibly just silence).
829 * Note that we don't reference count the device, or release/close the
830 * engine here. Once fired up, the engine continues running unil it
834 auclnt_set_paused(audio_stream_t
*sp
)
836 mutex_enter(&sp
->s_lock
);
838 mutex_exit(&sp
->s_lock
);
841 sp
->s_paused
= B_TRUE
;
842 mutex_exit(&sp
->s_lock
);
846 atomic_inc_uint(&sp
->s_client
->c_dev
->d_serial
);
850 auclnt_clear_paused(audio_stream_t
*sp
)
852 mutex_enter(&sp
->s_lock
);
854 mutex_exit(&sp
->s_lock
);
857 sp
->s_paused
= B_FALSE
;
858 mutex_exit(&sp
->s_lock
);
862 auclnt_is_paused(audio_stream_t
*sp
)
864 return (sp
->s_paused
);
868 auclnt_flush(audio_stream_t
*sp
)
870 mutex_enter(&sp
->s_lock
);
871 if (sp
== &sp
->s_client
->c_ostream
) {
872 sp
->s_tail
= sp
->s_head
;
873 sp
->s_tidx
= sp
->s_hidx
;
875 sp
->s_head
= sp
->s_tail
;
876 sp
->s_hidx
= sp
->s_tidx
;
879 mutex_exit(&sp
->s_lock
);
883 auclnt_get_oflag(audio_client_t
*c
)
889 * These routines should not be accessed by client "personality"
890 * implementations, but are for private framework use only.
894 auimpl_client_init(void)
896 rw_init(&auimpl_client_lock
, NULL
, RW_DRIVER
, NULL
);
897 list_create(&auimpl_clients
, sizeof (struct audio_client
),
898 offsetof(struct audio_client
, c_global_linkage
));
902 auimpl_client_fini(void)
904 rw_destroy(&auimpl_client_lock
);
905 list_destroy(&auimpl_clients
);
909 auimpl_stream_init(audio_stream_t
*sp
, audio_client_t
*c
)
911 mutex_init(&sp
->s_lock
, NULL
, MUTEX_DRIVER
, NULL
);
912 cv_init(&sp
->s_cv
, NULL
, CV_DRIVER
, NULL
);
915 if (sp
== &c
->c_ostream
) {
916 sp
->s_user_parms
= &sp
->s_cnv_src_parms
;
917 sp
->s_phys_parms
= &sp
->s_cnv_dst_parms
;
918 sp
->s_engcap
= ENGINE_OUTPUT_CAP
;
920 ASSERT(sp
== &c
->c_istream
);
921 sp
->s_user_parms
= &sp
->s_cnv_dst_parms
;
922 sp
->s_phys_parms
= &sp
->s_cnv_src_parms
;
923 sp
->s_engcap
= ENGINE_INPUT_CAP
;
926 /* for now initialize conversion parameters */
927 sp
->s_src_quality
= 3; /* reasonable compromise for now */
928 sp
->s_cnv_dst_nchan
= 2;
929 sp
->s_cnv_dst_format
= AUDIO_FORMAT_S24_NE
;
930 sp
->s_cnv_dst_rate
= 48000;
931 sp
->s_cnv_src_nchan
= 2;
932 sp
->s_cnv_src_format
= AUDIO_FORMAT_S24_NE
;
933 sp
->s_cnv_src_rate
= 48000;
935 /* set volume/gain all the way up */
936 sp
->s_muted
= B_FALSE
;
938 sp
->s_gain_scaled
= AUDIO_VOL_SCALE
;
939 sp
->s_gain_eff
= AUDIO_VOL_SCALE
;
942 * We have to start off with a reasonable buffer and
943 * interrupt configuration.
945 sp
->s_allocsz
= 65536;
946 sp
->s_data
= ddi_umem_alloc(sp
->s_allocsz
, DDI_UMEM_NOSLEEP
,
948 if (sp
->s_data
== NULL
) {
950 audio_dev_warn(c
->c_dev
, "ddi_umem_alloc failed");
953 /* make sure no stale data left in stream */
954 bzero(sp
->s_data
, sp
->s_allocsz
);
957 * Allocate SRC and data conversion state.
959 mutex_enter(&sp
->s_lock
);
960 if (auimpl_format_alloc(sp
) != 0) {
961 mutex_exit(&sp
->s_lock
);
965 mutex_exit(&sp
->s_lock
);
972 audio_stream_fini(audio_stream_t
*sp
)
974 auimpl_format_free(sp
);
976 kmem_free(sp
->s_cnv_buf0
, sp
->s_cnv_max
);
978 kmem_free(sp
->s_cnv_buf1
, sp
->s_cnv_max
);
979 mutex_destroy(&sp
->s_lock
);
980 cv_destroy(&sp
->s_cv
);
981 if (sp
->s_data
!= NULL
) {
982 ddi_umem_free(sp
->s_cookie
);
988 auclnt_start_drain(audio_client_t
*c
)
995 /* start an asynchronous drain operation. */
996 mutex_enter(&sp
->s_lock
);
997 if (sp
->s_paused
|| !sp
->s_running
) {
1000 sp
->s_draining
= B_TRUE
;
1003 mutex_exit(&sp
->s_lock
);
1008 auclnt_drain(audio_client_t
*c
)
1015 * Note: Drain logic will automatically "stop" the stream when
1016 * the drain threshold has been reached. So all we have to do
1017 * is wait for the stream to stop.
1019 mutex_enter(&sp
->s_lock
);
1020 sp
->s_draining
= B_TRUE
;
1021 while (sp
->s_draining
&& sp
->s_running
&& !sp
->s_paused
) {
1022 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
1023 mutex_exit(&sp
->s_lock
);
1027 mutex_exit(&sp
->s_lock
);
1032 auimpl_client_create(dev_t dev
)
1034 audio_client_ops_t
*ops
;
1036 audio_client_t
*next
;
1037 list_t
*list
= &auimpl_clients
;
1041 /* validate minor number */
1042 minor
= getminor(dev
) & AUDIO_MN_TYPE_MASK
;
1043 if ((ops
= audio_client_ops
[minor
]) == NULL
) {
1047 /* lookup device instance */
1048 if ((d
= auimpl_dev_hold_by_devt(dev
)) == NULL
) {
1049 audio_dev_warn(NULL
, "no audio_dev for dev_t %d,%d",
1050 getmajor(dev
), getminor(dev
));
1054 if ((c
= kmem_zalloc(sizeof (*c
), KM_NOSLEEP
)) == NULL
) {
1055 audio_dev_warn(d
, "unable to allocate client structure");
1056 auimpl_dev_release(d
);
1061 mutex_init(&c
->c_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1062 cv_init(&c
->c_cv
, NULL
, CV_DRIVER
, NULL
);
1064 if ((auimpl_stream_init(&c
->c_ostream
, c
) != 0) ||
1065 (auimpl_stream_init(&c
->c_istream
, c
) != 0)) {
1069 c
->c_major
= getmajor(dev
);
1070 c
->c_origminor
= getminor(dev
);
1074 * We hold the client lock here.
1076 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1078 minor
= AUDIO_MN_CLONE_MASK
;
1079 for (next
= list_head(list
); next
; next
= list_next(list
, next
)) {
1080 if (next
->c_minor
> minor
) {
1085 if (minor
>= MAXMIN32
) {
1086 rw_exit(&auimpl_client_lock
);
1090 list_insert_before(list
, next
, c
);
1092 rw_exit(&auimpl_client_lock
);
1098 auimpl_dev_release(d
);
1099 audio_stream_fini(&c
->c_ostream
);
1100 audio_stream_fini(&c
->c_istream
);
1101 mutex_destroy(&c
->c_lock
);
1102 cv_destroy(&c
->c_cv
);
1103 kmem_free(c
, sizeof (*c
));
1108 auimpl_client_destroy(audio_client_t
*c
)
1110 /* remove us from the global list */
1111 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1112 list_remove(&auimpl_clients
, c
);
1113 rw_exit(&auimpl_client_lock
);
1115 ASSERT(!c
->c_istream
.s_running
);
1116 ASSERT(!c
->c_ostream
.s_running
);
1118 /* release the device reference count */
1119 auimpl_dev_release(c
->c_dev
);
1122 mutex_destroy(&c
->c_lock
);
1123 cv_destroy(&c
->c_cv
);
1125 audio_stream_fini(&c
->c_istream
);
1126 audio_stream_fini(&c
->c_ostream
);
1127 kmem_free(c
, sizeof (*c
));
1131 auimpl_client_activate(audio_client_t
*c
)
1133 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1134 c
->c_is_active
= B_TRUE
;
1135 rw_exit(&auimpl_client_lock
);
1139 auimpl_client_deactivate(audio_client_t
*c
)
1141 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1142 c
->c_is_active
= B_FALSE
;
1143 rw_exit(&auimpl_client_lock
);
1147 auclnt_close(audio_client_t
*c
)
1149 audio_dev_t
*d
= c
->c_dev
;
1151 /* stop the engines if they are running */
1152 auclnt_stop(&c
->c_istream
);
1153 auclnt_stop(&c
->c_ostream
);
1155 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1156 list_remove(&d
->d_clients
, c
);
1157 rw_exit(&auimpl_client_lock
);
1159 mutex_enter(&c
->c_lock
);
1160 /* if in transition need to wait for other thread to release */
1161 while (c
->c_refcnt
) {
1162 cv_wait(&c
->c_cv
, &c
->c_lock
);
1164 mutex_exit(&c
->c_lock
);
1166 /* release any engines that we were holding */
1167 auimpl_engine_close(&c
->c_ostream
);
1168 auimpl_engine_close(&c
->c_istream
);
1172 auclnt_hold_dev_by_index(int index
)
1174 return (auimpl_dev_hold_by_index(index
));
1178 auclnt_release_dev(audio_dev_t
*dev
)
1180 auimpl_dev_release(dev
);
1184 auclnt_hold_by_devt(dev_t dev
)
1186 minor_t mn
= getminor(dev
);
1187 major_t mj
= getmajor(dev
);
1191 list
= &auimpl_clients
;
1192 /* linked list search is kind of inefficient, but it works */
1193 rw_enter(&auimpl_client_lock
, RW_READER
);
1194 for (c
= list_head(list
); c
!= NULL
; c
= list_next(list
, c
)) {
1195 if ((c
->c_major
== mj
) && (c
->c_minor
== mn
)) {
1196 mutex_enter(&c
->c_lock
);
1197 if (c
->c_is_active
) {
1199 mutex_exit(&c
->c_lock
);
1201 mutex_exit(&c
->c_lock
);
1207 rw_exit(&auimpl_client_lock
);
1212 auclnt_serialize(audio_client_t
*c
)
1214 mutex_enter(&c
->c_lock
);
1215 while (c
->c_serialize
) {
1216 if (cv_wait_sig(&c
->c_cv
, &c
->c_lock
) == 0) {
1217 mutex_exit(&c
->c_lock
);
1221 c
->c_serialize
= B_TRUE
;
1222 mutex_exit(&c
->c_lock
);
1227 auclnt_unserialize(audio_client_t
*c
)
1229 mutex_enter(&c
->c_lock
);
1230 ASSERT(c
->c_serialize
);
1231 c
->c_serialize
= B_FALSE
;
1232 cv_broadcast(&c
->c_cv
);
1233 mutex_exit(&c
->c_lock
);
1237 auclnt_hold(audio_client_t
*c
)
1239 mutex_enter(&c
->c_lock
);
1241 mutex_exit(&c
->c_lock
);
1245 auclnt_release(audio_client_t
*c
)
1247 mutex_enter(&c
->c_lock
);
1248 ASSERT(c
->c_refcnt
> 0);
1250 if (c
->c_refcnt
== 0)
1251 cv_broadcast(&c
->c_cv
);
1252 mutex_exit(&c
->c_lock
);
1256 auclnt_dev_get_serial(audio_dev_t
*d
)
1258 return (d
->d_serial
);
1262 auclnt_dev_walk_clients(audio_dev_t
*d
,
1263 int (*walker
)(audio_client_t
*, void *),
1266 list_t
*l
= &d
->d_clients
;
1270 rw_enter(&auimpl_client_lock
, RW_READER
);
1272 for (c
= list_head(l
); c
!= NULL
; c
= list_next(l
, c
)) {
1273 if (!c
->c_is_active
)
1275 rv
= (walker(c
, arg
));
1276 if (rv
== AUDIO_WALK_STOP
) {
1278 } else if (rv
== AUDIO_WALK_RESTART
) {
1282 rw_exit(&auimpl_client_lock
);
1287 auclnt_open(audio_client_t
*c
, int oflag
)
1290 audio_dev_t
*d
= c
->c_dev
;
1295 if (oflag
& FNDELAY
)
1296 flags
|= ENGINE_NDELAY
;
1298 if (oflag
& FWRITE
) {
1300 if ((rv
= auimpl_engine_open(sp
, flags
| ENGINE_OUTPUT
)) != 0)
1304 if (oflag
& FREAD
) {
1306 if ((rv
= auimpl_engine_open(sp
, flags
| ENGINE_INPUT
)) != 0)
1312 /* close any engines that we opened */
1313 auimpl_engine_close(&c
->c_ostream
);
1314 auimpl_engine_close(&c
->c_istream
);
1316 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1317 list_insert_tail(&d
->d_clients
, c
);
1318 c
->c_ostream
.s_gain_master
= d
->d_pcmvol
;
1319 c
->c_istream
.s_gain_master
= 100;
1320 rw_exit(&auimpl_client_lock
);
1321 auclnt_set_gain(&c
->c_ostream
, 100);
1322 auclnt_set_gain(&c
->c_istream
, 100);
1329 auclnt_get_minor(audio_client_t
*c
)
1331 return (c
->c_minor
);
1335 auclnt_get_original_minor(audio_client_t
*c
)
1337 return (c
->c_origminor
);
1341 auclnt_get_minor_type(audio_client_t
*c
)
1343 return (c
->c_origminor
& AUDIO_MN_TYPE_MASK
);
1347 auclnt_get_rq(audio_client_t
*c
)
1353 auclnt_get_wq(audio_client_t
*c
)
1359 auclnt_get_pid(audio_client_t
*c
)
1365 auclnt_get_cred(audio_client_t
*c
)
1371 auclnt_get_dev(audio_client_t
*c
)
1377 auclnt_get_dev_number(audio_dev_t
*dev
)
1379 return (dev
->d_number
);
1383 auclnt_get_dev_index(audio_dev_t
*dev
)
1385 return (dev
->d_index
);
1389 auclnt_get_dev_name(audio_dev_t
*dev
)
1391 return (dev
->d_name
);
1395 auclnt_get_dev_driver(audio_dev_t
*dev
)
1397 return (ddi_driver_name(dev
->d_dip
));
1401 auclnt_get_dev_devinfo(audio_dev_t
*dev
)
1403 return (dev
->d_dip
);
1407 auclnt_get_dev_hw_info(audio_dev_t
*dev
, void **iter
)
1409 struct audio_infostr
*isp
= *iter
;
1411 isp
= list_head(&dev
->d_hwinfo
);
1413 isp
= list_next(&dev
->d_hwinfo
, isp
);
1417 return (isp
? isp
->i_line
: NULL
);
1421 auclnt_get_dev_instance(audio_dev_t
*dev
)
1423 return (dev
->d_instance
);
1427 auclnt_get_dev_description(audio_dev_t
*dev
)
1429 return (dev
->d_desc
);
1433 auclnt_get_dev_version(audio_dev_t
*dev
)
1435 return (dev
->d_vers
);
1439 auclnt_get_dev_capab(audio_dev_t
*dev
)
1444 flags
= dev
->d_flags
;
1446 if (flags
& DEV_OUTPUT_CAP
)
1447 caps
|= AUDIO_CLIENT_CAP_PLAY
;
1448 if (flags
& DEV_INPUT_CAP
)
1449 caps
|= AUDIO_CLIENT_CAP_RECORD
;
1450 if (flags
& DEV_DUPLEX_CAP
)
1451 caps
|= AUDIO_CLIENT_CAP_DUPLEX
;
1453 /* AC3: deal with formats that don't support mixing */
1459 auclnt_get_samples(audio_stream_t
*sp
)
1463 mutex_enter(&sp
->s_lock
);
1465 mutex_exit(&sp
->s_lock
);
1470 auclnt_set_samples(audio_stream_t
*sp
, uint64_t n
)
1472 mutex_enter(&sp
->s_lock
);
1474 mutex_exit(&sp
->s_lock
);
1478 auclnt_get_errors(audio_stream_t
*sp
)
1481 mutex_enter(&sp
->s_lock
);
1483 mutex_exit(&sp
->s_lock
);
1488 auclnt_set_errors(audio_stream_t
*sp
, uint64_t n
)
1490 mutex_enter(&sp
->s_lock
);
1492 mutex_exit(&sp
->s_lock
);
1496 auclnt_register_ops(minor_t minor
, audio_client_ops_t
*ops
)
1498 /* we control minor number allocations, no need for runtime checks */
1499 ASSERT(minor
<= AUDIO_MN_TYPE_MASK
);
1501 audio_client_ops
[minor
] = ops
;
1505 auimpl_create_minors(audio_dev_t
*d
)
1507 char path
[MAXPATHLEN
];
1510 audio_client_ops_t
*ops
;
1513 for (int i
= 0; i
<= AUDIO_MN_TYPE_MASK
; i
++) {
1515 if ((ops
= audio_client_ops
[i
]) == NULL
)
1518 if (ops
->aco_dev_init
!= NULL
)
1519 d
->d_minor_data
[i
] = ops
->aco_dev_init(d
);
1522 case AUDIO_MINOR_SNDSTAT
:
1523 if (!(d
->d_flags
& DEV_SNDSTAT_CAP
)) {
1530 if (!(d
->d_flags
& (DEV_INPUT_CAP
| DEV_OUTPUT_CAP
))) {
1537 if (ops
->aco_minor_prefix
!= NULL
) {
1539 minor
= AUDIO_MKMN(d
->d_instance
, i
);
1540 (void) snprintf(path
, sizeof (path
),
1541 "%s%d", ops
->aco_minor_prefix
, d
->d_instance
);
1543 rv
= ddi_create_minor_node(d
->d_dip
, path
, S_IFCHR
,
1554 auimpl_remove_minors(audio_dev_t
*d
)
1556 char path
[MAXPATHLEN
];
1557 audio_client_ops_t
*ops
;
1559 for (int i
= 0; i
<= AUDIO_MN_TYPE_MASK
; i
++) {
1560 if ((ops
= audio_client_ops
[i
]) == NULL
)
1562 if (ops
->aco_minor_prefix
!= NULL
) {
1563 (void) snprintf(path
, sizeof (path
), "%s%d",
1564 ops
->aco_minor_prefix
, d
->d_instance
);
1565 (void) ddi_remove_minor_node(d
->d_dip
, path
);
1568 if (ops
->aco_dev_fini
!= NULL
)
1569 ops
->aco_dev_fini(d
->d_minor_data
[i
]);
1574 auclnt_get_dev_minor_data(audio_dev_t
*d
, minor_t mn
)
1576 ASSERT(mn
< (1U << AUDIO_MN_TYPE_NBITS
));
1577 return (d
->d_minor_data
[mn
]);
1581 auclnt_get_minor_data(audio_client_t
*c
, minor_t mn
)
1583 ASSERT(mn
< (1U << AUDIO_MN_TYPE_NBITS
));
1584 return (c
->c_dev
->d_minor_data
[mn
]);
1588 * This will walk all controls registered to a clients device and callback
1589 * to walker for each one with its audio_ctrl. Note this data
1590 * must be considered read only by walker.
1592 * Note that walk_func may return values to continue (AUDIO_WALK_CONTINUE)
1593 * or stop walk (AUDIO_WALK_STOP).
1597 auclnt_walk_controls(audio_dev_t
*d
,
1598 int (*walker
)(audio_ctrl_t
*, void *),
1603 mutex_enter(&d
->d_ctrl_lock
);
1604 for (ctrl
= list_head(&d
->d_controls
); ctrl
;
1605 ctrl
= list_next(&d
->d_controls
, ctrl
)) {
1606 if (walker(ctrl
, arg
) == AUDIO_WALK_STOP
)
1609 mutex_exit(&d
->d_ctrl_lock
);
1613 * This will search all controls attached to an
1614 * audio device for a control with the desired name.
1616 * d - the audio device to look on
1617 * name - name of the control being looked for.
1619 * On successful return a ctrl handle will be returned. On
1620 * failure NULL is returned.
1623 auclnt_find_control(audio_dev_t
*d
, const char *name
)
1627 /* Verify argument */
1630 mutex_enter(&d
->d_ctrl_lock
);
1631 for (ctrl
= list_head(&d
->d_controls
); ctrl
;
1632 ctrl
= list_next(&d
->d_controls
, ctrl
)) {
1633 if (strcmp(ctrl
->ctrl_name
, name
) == 0) {
1634 mutex_exit(&d
->d_ctrl_lock
);
1638 mutex_exit(&d
->d_ctrl_lock
);
1643 * Given a known control, get its attributes.
1645 * The caller must supply a audio_ctrl_desc_t structure. Also the
1646 * values in the structure are ignored when making the call and filled
1647 * in by this function. All data pointed to by elements of desc should
1648 * be assumed read only.
1650 * If an error occurs then a non-zero is returned.
1654 auclnt_control_describe(audio_ctrl_t
*ctrl
, audio_ctrl_desc_t
*desc
)
1659 bcopy(&ctrl
->ctrl_des
, desc
, sizeof (*desc
));
1664 auclnt_control_read(audio_ctrl_t
*ctrl
, uint64_t *value
)
1666 return (audio_control_read(ctrl
, value
));
1670 auclnt_control_write(audio_ctrl_t
*ctrl
, uint64_t value
)
1672 return (audio_control_write(ctrl
, value
));
1676 auclnt_warn(audio_client_t
*c
, const char *fmt
, ...)
1681 auimpl_dev_vwarn(c
? c
->c_dev
: NULL
, fmt
, va
);