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 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <sys/types.h>
29 #include <sys/sysmacros.h>
34 #include <sys/errno.h>
35 #include <sys/atomic.h>
37 #include <sys/sunddi.h>
39 #include "audio_impl.h"
42 * Audio Client implementation.
46 * Attenuation table for dB->linear conversion. Indexed in steps of
47 * 0.5 dB. Table size is 25 dB (first entry is handled as mute).
49 * Notably, the last item in table is taken as 0 dB (i.e. maximum volume).
51 * Table contents can be calculated as follows (requires sunmath library):
53 * scale = AUDIO_VOL_SCALE;
54 * for (i = -50; i <= 0; i++) {
55 * x = exp10(0.05 * i);
56 * printf("%d: %f %.0f\n", i, x, trunc(x * scale));
61 const uint16_t auimpl_db_table
[AUDIO_DB_SIZE
+ 1] = {
62 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
63 2, 2, 3, 3, 4, 4, 5, 5, 6, 7,
64 8, 9, 10, 11, 12, 14, 16, 18, 20, 22,
65 25, 28, 32, 36, 40, 45, 51, 57, 64, 72,
66 80, 90, 101, 114, 128, 143, 161, 181, 203, 228,
71 auclnt_get_private(audio_client_t
*c
)
73 return (c
->c_private
);
77 auclnt_set_private(audio_client_t
*c
, void *private)
79 c
->c_private
= private;
83 auclnt_set_rate(audio_stream_t
*sp
, int rate
)
88 /* basic sanity checks! */
89 if ((rate
< 5000) || (rate
> 192000)) {
92 mutex_enter(&sp
->s_lock
);
93 parms
= *sp
->s_user_parms
;
94 if (rate
!= parms
.p_rate
) {
96 rv
= auimpl_format_setup(sp
, &parms
);
98 mutex_exit(&sp
->s_lock
);
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
, unsigned frags
, unsigned 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
= (unsigned)(sp
->s_head
- sp
->s_tail
);
185 mutex_exit(&sp
->s_lock
);
191 auclnt_consume(audio_stream_t
*sp
, unsigned 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
, unsigned 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
, unsigned 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
, unsigned 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
;
336 loff
= uio
->uio_loffset
;
339 mutex_enter(&sp
->s_lock
);
341 if ((!sp
->s_paused
) && (!sp
->s_running
)) {
342 mutex_exit(&sp
->s_lock
);
344 mutex_enter(&sp
->s_lock
);
347 ASSERT(sp
->s_head
>= sp
->s_tail
);
348 ASSERT(sp
->s_tidx
< sp
->s_nframes
);
349 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
351 while (uio
->uio_resid
>= sp
->s_framesz
) {
353 while ((cnt
= (sp
->s_head
- sp
->s_tail
)) == 0) {
354 if (uio
->uio_fmode
& (FNONBLOCK
|FNDELAY
)) {
355 mutex_exit(&sp
->s_lock
);
358 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
359 mutex_exit(&sp
->s_lock
);
364 cnt
= min(cnt
, sp
->s_nframes
- sp
->s_tidx
);
365 cnt
= min(cnt
, (uio
->uio_resid
/ sp
->s_framesz
));
367 rv
= uiomove(sp
->s_data
+ (sp
->s_tidx
* sp
->s_framesz
),
368 cnt
* sp
->s_framesz
, UIO_READ
, uio
);
369 uio
->uio_loffset
= loff
;
373 mutex_exit(&sp
->s_lock
);
379 if (sp
->s_tidx
== sp
->s_nframes
) {
384 ASSERT(sp
->s_tail
<= sp
->s_head
);
385 ASSERT(sp
->s_tidx
< sp
->s_nframes
);
387 /* round off any remaining partial bits */
390 mutex_exit(&sp
->s_lock
);
396 auclnt_write(audio_client_t
*c
, struct uio
*uio
)
398 audio_stream_t
*sp
= &c
->c_ostream
;
404 loff
= uio
->uio_loffset
;
407 mutex_enter(&sp
->s_lock
);
409 ASSERT(sp
->s_head
>= sp
->s_tail
);
410 ASSERT(sp
->s_tidx
< sp
->s_nframes
);
411 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
413 while (uio
->uio_resid
>= sp
->s_framesz
) {
415 while ((cnt
= sp
->s_nframes
- (sp
->s_head
- sp
->s_tail
)) == 0) {
416 if (uio
->uio_fmode
& (FNONBLOCK
|FNDELAY
)) {
417 mutex_exit(&sp
->s_lock
);
420 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
421 mutex_exit(&sp
->s_lock
);
426 cnt
= min(cnt
, sp
->s_nframes
- sp
->s_hidx
);
427 cnt
= min(cnt
, (uio
->uio_resid
/ sp
->s_framesz
));
429 rv
= uiomove(sp
->s_data
+ (sp
->s_hidx
* sp
->s_framesz
),
430 cnt
* sp
->s_framesz
, UIO_WRITE
, uio
);
431 uio
->uio_loffset
= loff
;
435 mutex_exit(&sp
->s_lock
);
441 if (sp
->s_hidx
== sp
->s_nframes
) {
445 if ((!sp
->s_paused
) && (!sp
->s_running
) &&
446 ((sp
->s_head
- sp
->s_tail
) > sp
->s_fragfr
)) {
447 mutex_exit(&sp
->s_lock
);
449 mutex_enter(&sp
->s_lock
);
453 ASSERT(sp
->s_tail
<= sp
->s_head
);
454 ASSERT(sp
->s_hidx
< sp
->s_nframes
);
456 /* round off any remaining partial bits */
459 mutex_exit(&sp
->s_lock
);
465 auclnt_chpoll(audio_client_t
*c
, short events
, int anyyet
, short *reventsp
,
466 struct pollhead
**phpp
)
471 if (events
& (POLLIN
| POLLRDNORM
)) {
473 mutex_enter(&sp
->s_lock
);
474 if ((sp
->s_head
- sp
->s_tail
) > sp
->s_fragfr
) {
475 nev
= POLLIN
| POLLRDNORM
;
477 mutex_exit(&sp
->s_lock
);
480 if (events
& POLLOUT
) {
482 mutex_enter(&sp
->s_lock
);
483 if ((sp
->s_nframes
- (sp
->s_head
- sp
->s_tail
)) >
487 mutex_exit(&sp
->s_lock
);
491 *reventsp
= nev
& events
;
495 *phpp
= &c
->c_pollhead
;
502 auclnt_pollwakeup(audio_client_t
*c
, short events
)
504 pollwakeup(&c
->c_pollhead
, events
);
508 auclnt_get_output_qlen(audio_client_t
*c
, unsigned *slen
, unsigned *flen
)
510 audio_stream_t
*sp
= &c
->c_ostream
;
511 audio_engine_t
*e
= sp
->s_engine
;
513 unsigned cnt
, er
, sr
;
516 /* if no output engine, can't do it! */
522 mutex_enter(&e
->e_lock
);
523 mutex_enter(&sp
->s_lock
);
524 el
= ENG_QLEN(e
) + (e
->e_head
- e
->e_tail
);
527 sr
= sp
->s_user_parms
->p_rate
;
528 cnt
= (unsigned)(sp
->s_head
- sp
->s_tail
);
529 mutex_exit(&sp
->s_lock
);
530 mutex_exit(&e
->e_lock
);
532 /* engine frames converted to stream rate, plus stream frames */
534 *flen
= ((unsigned)(((el
* sr
) / er
) + sl
));
538 auclnt_set_format(audio_stream_t
*sp
, int fmt
)
544 * AC3: If we select an AC3 format, then we have to allocate
545 * another engine. Normally this will be an output only
546 * engine. However, for now we aren't supporting AC3
551 case AUDIO_FORMAT_U8
:
552 case AUDIO_FORMAT_ULAW
:
553 case AUDIO_FORMAT_ALAW
:
554 case AUDIO_FORMAT_S8
:
555 case AUDIO_FORMAT_S16_LE
:
556 case AUDIO_FORMAT_S16_BE
:
557 case AUDIO_FORMAT_U16_LE
:
558 case AUDIO_FORMAT_U16_BE
:
559 case AUDIO_FORMAT_S24_LE
:
560 case AUDIO_FORMAT_S24_BE
:
561 case AUDIO_FORMAT_S32_LE
:
562 case AUDIO_FORMAT_S32_BE
:
563 case AUDIO_FORMAT_S24_PACKED
:
566 case AUDIO_FORMAT_AC3
: /* AC3: PASSTHRU */
572 mutex_enter(&sp
->s_lock
);
573 parms
= *sp
->s_user_parms
;
576 * Optimization. Some personalities send us the same format
577 * over and over again. (Sun personality does this
578 * repeatedly.) setup_src is potentially expensive, so we
579 * avoid doing it unless we really need to.
581 if (fmt
!= parms
.p_format
) {
583 * Note that setting the format doesn't check that the
584 * audio streams have been paused. As a result, any
585 * data still playing or recording will probably get
586 * misinterpreted. It would be smart if the client
587 * application paused/stopped playback before changing
590 parms
.p_format
= fmt
;
591 rv
= auimpl_format_setup(sp
, &parms
);
593 mutex_exit(&sp
->s_lock
);
599 auclnt_get_format(audio_stream_t
*sp
)
601 return (sp
->s_user_parms
->p_format
);
605 auclnt_get_output_format(audio_client_t
*c
)
607 return (c
->c_ostream
.s_user_parms
->p_format
);
611 auclnt_get_input_format(audio_client_t
*c
)
613 return (c
->c_istream
.s_user_parms
->p_format
);
617 auclnt_set_channels(audio_stream_t
*sp
, int nchan
)
622 /* Validate setting */
623 if ((nchan
> AUDIO_MAX_CHANNELS
) || (nchan
< 1)) {
627 mutex_enter(&sp
->s_lock
);
628 parms
= *sp
->s_user_parms
;
629 if (nchan
!= parms
.p_nchan
) {
630 parms
.p_nchan
= nchan
;
631 rv
= auimpl_format_setup(sp
, &parms
);
633 mutex_exit(&sp
->s_lock
);
639 auclnt_get_channels(audio_stream_t
*sp
)
641 return (sp
->s_user_parms
->p_nchan
);
645 auimpl_set_gain_master(audio_stream_t
*sp
, uint8_t gain
)
653 mutex_enter(&sp
->s_lock
);
654 if (sp
->s_gain_master
== gain
) {
655 mutex_exit(&sp
->s_lock
);
660 * calculate the scaled values. Done now to avoid calculations
663 scaled
= (gain
* sp
->s_gain_pct
* AUDIO_DB_SIZE
) / (100 * 100);
665 sp
->s_gain_master
= gain
;
666 sp
->s_gain_scaled
= auimpl_db_table
[scaled
];
669 sp
->s_gain_eff
= sp
->s_gain_scaled
;
671 mutex_exit(&sp
->s_lock
);
674 * No need to notify clients, since they can't see this update.
679 auclnt_set_gain(audio_stream_t
*sp
, uint8_t gain
)
687 mutex_enter(&sp
->s_lock
);
689 /* if no change, don't bother doing updates */
690 if (sp
->s_gain_pct
== gain
) {
691 mutex_exit(&sp
->s_lock
);
696 * calculate the scaled values. Done now to avoid calculations
699 scaled
= (gain
* sp
->s_gain_master
* AUDIO_DB_SIZE
) / (100 * 100);
701 sp
->s_gain_pct
= gain
;
702 sp
->s_gain_scaled
= auimpl_db_table
[scaled
];
705 sp
->s_gain_eff
= sp
->s_gain_scaled
;
707 mutex_exit(&sp
->s_lock
);
709 auclnt_notify_dev(sp
->s_client
->c_dev
);
713 auclnt_get_gain(audio_stream_t
*sp
)
715 return (sp
->s_gain_pct
);
719 auclnt_set_muted(audio_stream_t
*sp
, boolean_t muted
)
721 mutex_enter(&sp
->s_lock
);
723 /* if no work change, don't bother doing updates */
724 if (sp
->s_muted
== muted
) {
725 mutex_exit(&sp
->s_lock
);
733 sp
->s_gain_eff
= sp
->s_gain_scaled
;
735 mutex_exit(&sp
->s_lock
);
737 auclnt_notify_dev(sp
->s_client
->c_dev
);
741 auclnt_get_muted(audio_stream_t
*sp
)
743 return (sp
->s_muted
);
747 auclnt_is_running(audio_stream_t
*sp
)
749 return (sp
->s_running
);
753 auclnt_start(audio_stream_t
*sp
)
755 mutex_enter(&sp
->s_lock
);
756 sp
->s_running
= B_TRUE
;
757 mutex_exit(&sp
->s_lock
);
761 auclnt_stop(audio_stream_t
*sp
)
763 mutex_enter(&sp
->s_lock
);
764 /* if running, then stop it */
766 sp
->s_running
= B_FALSE
;
768 * if we stopped the engine, we might need to wake up
769 * a thread that is waiting for drain to complete.
771 cv_broadcast(&sp
->s_cv
);
773 mutex_exit(&sp
->s_lock
);
777 * When pausing, no new data will be played after the most recently
778 * mixed samples have played. However, the audio engine will continue
779 * to play (possibly just silence).
781 * Note that we don't reference count the device, or release/close the
782 * engine here. Once fired up, the engine continues running unil it
786 auclnt_set_paused(audio_stream_t
*sp
)
788 mutex_enter(&sp
->s_lock
);
790 mutex_exit(&sp
->s_lock
);
793 sp
->s_paused
= B_TRUE
;
794 mutex_exit(&sp
->s_lock
);
798 auclnt_notify_dev(sp
->s_client
->c_dev
);
802 auclnt_clear_paused(audio_stream_t
*sp
)
804 mutex_enter(&sp
->s_lock
);
806 mutex_exit(&sp
->s_lock
);
809 sp
->s_paused
= B_FALSE
;
810 mutex_exit(&sp
->s_lock
);
814 auclnt_is_paused(audio_stream_t
*sp
)
816 return (sp
->s_paused
);
820 auclnt_flush(audio_stream_t
*sp
)
822 mutex_enter(&sp
->s_lock
);
823 if (sp
== &sp
->s_client
->c_ostream
) {
824 sp
->s_tail
= sp
->s_head
;
825 sp
->s_tidx
= sp
->s_hidx
;
827 sp
->s_head
= sp
->s_tail
;
828 sp
->s_hidx
= sp
->s_tidx
;
831 mutex_exit(&sp
->s_lock
);
835 auclnt_get_oflag(audio_client_t
*c
)
841 * These routines should not be accessed by client "personality"
842 * implementations, but are for private framework use only.
845 static list_t auimpl_clients
;
846 static krwlock_t auimpl_client_lock
;
847 static audio_client_ops_t
*audio_client_ops
[AUDIO_MN_TYPE_MASK
+ 1];
850 auimpl_client_init(void)
852 rw_init(&auimpl_client_lock
, NULL
, RW_DRIVER
, NULL
);
853 list_create(&auimpl_clients
, sizeof (struct audio_client
),
854 offsetof(struct audio_client
, c_global_linkage
));
858 auimpl_client_fini(void)
860 rw_destroy(&auimpl_client_lock
);
861 list_destroy(&auimpl_clients
);
865 auimpl_stream_init(audio_stream_t
*sp
, audio_client_t
*c
)
867 mutex_init(&sp
->s_lock
, NULL
, MUTEX_DRIVER
, NULL
);
868 cv_init(&sp
->s_cv
, NULL
, CV_DRIVER
, NULL
);
871 if (sp
== &c
->c_ostream
) {
872 sp
->s_user_parms
= &sp
->s_cnv_src_parms
;
873 sp
->s_phys_parms
= &sp
->s_cnv_dst_parms
;
874 sp
->s_engcap
= ENGINE_OUTPUT_CAP
;
876 ASSERT(sp
== &c
->c_istream
);
877 sp
->s_user_parms
= &sp
->s_cnv_dst_parms
;
878 sp
->s_phys_parms
= &sp
->s_cnv_src_parms
;
879 sp
->s_engcap
= ENGINE_INPUT_CAP
;
882 /* for now initialize conversion parameters */
883 sp
->s_src_quality
= 3; /* reasonable compromise for now */
884 sp
->s_cnv_dst_nchan
= 2;
885 sp
->s_cnv_dst_format
= AUDIO_FORMAT_S24_NE
;
886 sp
->s_cnv_dst_rate
= 48000;
887 sp
->s_cnv_src_nchan
= 2;
888 sp
->s_cnv_src_format
= AUDIO_FORMAT_S24_NE
;
889 sp
->s_cnv_src_rate
= 48000;
891 /* set volume/gain all the way up */
892 sp
->s_muted
= B_FALSE
;
894 sp
->s_gain_scaled
= AUDIO_VOL_SCALE
;
895 sp
->s_gain_eff
= AUDIO_VOL_SCALE
;
898 * We have to start off with a reasonable buffer and
899 * interrupt configuration.
901 sp
->s_allocsz
= 65536;
902 sp
->s_data
= ddi_umem_alloc(sp
->s_allocsz
, DDI_UMEM_NOSLEEP
,
904 if (sp
->s_data
== NULL
) {
906 audio_dev_warn(c
->c_dev
, "ddi_umem_alloc failed");
909 /* make sure no stale data left in stream */
910 bzero(sp
->s_data
, sp
->s_allocsz
);
913 * Allocate SRC and data conversion state.
915 mutex_enter(&sp
->s_lock
);
916 if (auimpl_format_alloc(sp
) != 0) {
917 mutex_exit(&sp
->s_lock
);
921 mutex_exit(&sp
->s_lock
);
928 audio_stream_fini(audio_stream_t
*sp
)
930 auimpl_format_free(sp
);
932 kmem_free(sp
->s_cnv_buf0
, sp
->s_cnv_max
);
934 kmem_free(sp
->s_cnv_buf1
, sp
->s_cnv_max
);
935 mutex_destroy(&sp
->s_lock
);
936 cv_destroy(&sp
->s_cv
);
937 if (sp
->s_data
!= NULL
) {
938 ddi_umem_free(sp
->s_cookie
);
944 auimpl_client_task(void *arg
)
946 audio_client_t
*c
= arg
;
948 mutex_enter(&c
->c_lock
);
955 if (c
->c_do_output
) {
956 c
->c_do_output
= B_FALSE
;
958 mutex_exit(&c
->c_lock
);
959 if (c
->c_output
!= NULL
)
961 mutex_enter(&c
->c_lock
);
966 c
->c_do_input
= B_FALSE
;
968 mutex_exit(&c
->c_lock
);
969 if (c
->c_input
!= NULL
)
971 mutex_enter(&c
->c_lock
);
975 if (c
->c_do_notify
) {
976 c
->c_do_notify
= B_FALSE
;
978 mutex_exit(&c
->c_lock
);
979 if (c
->c_notify
!= NULL
)
981 mutex_enter(&c
->c_lock
);
986 c
->c_do_drain
= B_FALSE
;
988 mutex_exit(&c
->c_lock
);
989 if (c
->c_drain
!= NULL
)
991 mutex_enter(&c
->c_lock
);
995 /* if we got here, we had no work to do */
996 cv_wait(&c
->c_cv
, &c
->c_lock
);
998 mutex_exit(&c
->c_lock
);
1002 auclnt_start_drain(audio_client_t
*c
)
1009 /* start an asynchronous drain operation. */
1010 mutex_enter(&sp
->s_lock
);
1011 if (sp
->s_paused
|| !sp
->s_running
) {
1014 sp
->s_draining
= B_TRUE
;
1017 mutex_exit(&sp
->s_lock
);
1022 auclnt_drain(audio_client_t
*c
)
1029 * Note: Drain logic will automatically "stop" the stream when
1030 * the drain threshold has been reached. So all we have to do
1031 * is wait for the stream to stop.
1033 mutex_enter(&sp
->s_lock
);
1034 sp
->s_draining
= B_TRUE
;
1035 while (sp
->s_draining
&& sp
->s_running
&& !sp
->s_paused
) {
1036 if (cv_wait_sig(&sp
->s_cv
, &sp
->s_lock
) == 0) {
1037 mutex_exit(&sp
->s_lock
);
1041 mutex_exit(&sp
->s_lock
);
1046 auimpl_client_create(dev_t dev
)
1048 audio_client_ops_t
*ops
;
1050 audio_client_t
*next
;
1051 list_t
*list
= &auimpl_clients
;
1055 static uint64_t unique
= 0;
1057 /* validate minor number */
1058 minor
= getminor(dev
) & AUDIO_MN_TYPE_MASK
;
1059 if ((ops
= audio_client_ops
[minor
]) == NULL
) {
1063 /* lookup device instance */
1064 if ((d
= auimpl_dev_hold_by_devt(dev
)) == NULL
) {
1065 audio_dev_warn(NULL
, "no audio_dev for dev_t %d,%d",
1066 getmajor(dev
), getminor(dev
));
1070 if ((c
= kmem_zalloc(sizeof (*c
), KM_NOSLEEP
)) == NULL
) {
1071 audio_dev_warn(d
, "unable to allocate client structure");
1072 auimpl_dev_release(d
);
1077 mutex_init(&c
->c_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1078 cv_init(&c
->c_cv
, NULL
, CV_DRIVER
, NULL
);
1080 if ((auimpl_stream_init(&c
->c_ostream
, c
) != 0) ||
1081 (auimpl_stream_init(&c
->c_istream
, c
) != 0)) {
1085 c
->c_major
= getmajor(dev
);
1086 c
->c_origminor
= getminor(dev
);
1089 (void) snprintf(scratch
, sizeof (scratch
), "auclnt%" PRIx64
,
1090 atomic_inc_64_nv(&unique
));
1091 c
->c_tq
= ddi_taskq_create(NULL
, scratch
, 1, TASKQ_DEFAULTPRI
, 0);
1092 if (c
->c_tq
== NULL
) {
1093 audio_dev_warn(d
, "client taskq_create failed");
1098 * We hold the client lock here.
1100 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1102 minor
= AUDIO_MN_CLONE_MASK
;
1103 for (next
= list_head(list
); next
; next
= list_next(list
, next
)) {
1104 if (next
->c_minor
> minor
) {
1109 if (minor
>= MAXMIN32
) {
1110 rw_exit(&auimpl_client_lock
);
1114 list_insert_before(list
, next
, c
);
1116 rw_exit(&auimpl_client_lock
);
1122 auimpl_dev_release(d
);
1123 if (c
->c_tq
!= NULL
) {
1124 ddi_taskq_destroy(c
->c_tq
);
1126 audio_stream_fini(&c
->c_ostream
);
1127 audio_stream_fini(&c
->c_istream
);
1128 mutex_destroy(&c
->c_lock
);
1129 cv_destroy(&c
->c_cv
);
1130 kmem_free(c
, sizeof (*c
));
1135 auimpl_client_destroy(audio_client_t
*c
)
1137 /* remove us from the global list */
1138 rw_enter(&auimpl_client_lock
, RW_WRITER
);
1139 list_remove(&auimpl_clients
, c
);
1140 rw_exit(&auimpl_client_lock
);
1142 ASSERT(!c
->c_istream
.s_running
);
1143 ASSERT(!c
->c_istream
.s_running
);
1145 /* release the device reference count */
1146 auimpl_dev_release(c
->c_dev
);
1149 ddi_taskq_destroy(c
->c_tq
);
1151 mutex_destroy(&c
->c_lock
);
1152 cv_destroy(&c
->c_cv
);
1154 audio_stream_fini(&c
->c_istream
);
1155 audio_stream_fini(&c
->c_ostream
);
1156 kmem_free(c
, sizeof (*c
));
1160 auclnt_close(audio_client_t
*c
)
1162 audio_dev_t
*d
= c
->c_dev
;
1164 /* stop the engines if they are running */
1165 auclnt_stop(&c
->c_istream
);
1166 auclnt_stop(&c
->c_ostream
);
1168 rw_enter(&d
->d_clnt_lock
, RW_WRITER
);
1169 list_remove(&d
->d_clients
, c
);
1170 rw_exit(&d
->d_clnt_lock
);
1172 mutex_enter(&c
->c_lock
);
1173 /* if in transition need to wait for other thread to release */
1174 while (c
->c_refcnt
) {
1175 cv_wait(&c
->c_cv
, &c
->c_lock
);
1177 c
->c_closing
= B_TRUE
;
1178 cv_broadcast(&c
->c_cv
);
1179 mutex_exit(&c
->c_lock
);
1181 /* make sure taskq has drained */
1182 ddi_taskq_wait(c
->c_tq
);
1184 /* release any engines that we were holding */
1185 auimpl_engine_close(&c
->c_ostream
);
1186 auimpl_engine_close(&c
->c_istream
);
1190 auclnt_hold_dev_by_index(int index
)
1192 return (auimpl_dev_hold_by_index(index
));
1196 auclnt_release_dev(audio_dev_t
*dev
)
1198 auimpl_dev_release(dev
);
1202 auclnt_hold_by_devt(dev_t dev
)
1204 minor_t mn
= getminor(dev
);
1205 major_t mj
= getmajor(dev
);
1209 list
= &auimpl_clients
;
1210 /* linked list search is kind of inefficient, but it works */
1211 rw_enter(&auimpl_client_lock
, RW_READER
);
1212 for (c
= list_head(list
); c
!= NULL
; c
= list_next(list
, c
)) {
1213 if ((c
->c_major
== mj
) && (c
->c_minor
== mn
)) {
1214 mutex_enter(&c
->c_lock
);
1217 mutex_exit(&c
->c_lock
);
1219 mutex_exit(&c
->c_lock
);
1225 rw_exit(&auimpl_client_lock
);
1230 auclnt_release(audio_client_t
*c
)
1232 mutex_enter(&c
->c_lock
);
1233 ASSERT(c
->c_refcnt
> 0);
1235 if (c
->c_refcnt
== 0)
1236 cv_broadcast(&c
->c_cv
);
1237 mutex_exit(&c
->c_lock
);
1241 auclnt_dev_walk_clients(audio_dev_t
*d
,
1242 int (*walker
)(audio_client_t
*, void *),
1245 list_t
*l
= &d
->d_clients
;
1249 rw_enter(&d
->d_clnt_lock
, RW_READER
);
1251 for (c
= list_head(l
); c
!= NULL
; c
= list_next(l
, c
)) {
1252 rv
= (walker(c
, arg
));
1253 if (rv
== AUDIO_WALK_STOP
) {
1255 } else if (rv
== AUDIO_WALK_RESTART
) {
1259 rw_exit(&d
->d_clnt_lock
);
1264 auclnt_open(audio_client_t
*c
, unsigned fmts
, int oflag
)
1267 audio_dev_t
*d
= c
->c_dev
;
1270 audio_parms_t parms
;
1273 if (oflag
& FNDELAY
)
1274 flags
|= ENGINE_NDELAY
;
1276 if (oflag
& FWRITE
) {
1278 rv
= auimpl_engine_open(d
, fmts
, flags
| ENGINE_OUTPUT
, sp
);
1283 mutex_enter(&sp
->s_lock
);
1284 parms
= *sp
->s_user_parms
;
1285 rv
= auimpl_format_setup(sp
, &parms
);
1286 mutex_exit(&sp
->s_lock
);
1292 if (oflag
& FREAD
) {
1294 rv
= auimpl_engine_open(d
, fmts
, flags
| ENGINE_INPUT
, sp
);
1299 mutex_enter(&sp
->s_lock
);
1300 parms
= *sp
->s_user_parms
;
1301 rv
= auimpl_format_setup(sp
, &parms
);
1302 mutex_exit(&sp
->s_lock
);
1308 if (ddi_taskq_dispatch(c
->c_tq
, auimpl_client_task
, c
, DDI_NOSLEEP
) !=
1310 audio_dev_warn(d
, "unable to start client taskq");
1316 /* close any engines that we opened */
1317 auimpl_engine_close(&c
->c_ostream
);
1318 auimpl_engine_close(&c
->c_istream
);
1320 rw_enter(&d
->d_clnt_lock
, RW_WRITER
);
1321 list_insert_tail(&d
->d_clients
, c
);
1322 c
->c_ostream
.s_gain_master
= d
->d_pcmvol
;
1323 c
->c_istream
.s_gain_master
= 100;
1324 rw_exit(&d
->d_clnt_lock
);
1325 auclnt_set_gain(&c
->c_ostream
, 100);
1326 auclnt_set_gain(&c
->c_istream
, 100);
1333 auclnt_get_minor(audio_client_t
*c
)
1335 return (c
->c_minor
);
1339 auclnt_get_original_minor(audio_client_t
*c
)
1341 return (c
->c_origminor
);
1345 auclnt_get_minor_type(audio_client_t
*c
)
1347 return (c
->c_origminor
& AUDIO_MN_TYPE_MASK
);
1351 auclnt_get_rq(audio_client_t
*c
)
1357 auclnt_get_wq(audio_client_t
*c
)
1363 auclnt_get_pid(audio_client_t
*c
)
1369 auclnt_get_cred(audio_client_t
*c
)
1375 auclnt_get_dev(audio_client_t
*c
)
1381 auclnt_get_dev_number(audio_dev_t
*dev
)
1383 return (dev
->d_number
);
1387 auclnt_get_dev_index(audio_dev_t
*dev
)
1389 return (dev
->d_index
);
1393 auclnt_get_dev_name(audio_dev_t
*dev
)
1395 return (dev
->d_name
);
1399 auclnt_get_dev_driver(audio_dev_t
*dev
)
1401 return (ddi_driver_name(dev
->d_dip
));
1405 auclnt_get_dev_devinfo(audio_dev_t
*dev
)
1407 return (dev
->d_dip
);
1411 auclnt_get_dev_hw_info(audio_dev_t
*dev
, void **iter
)
1413 struct audio_infostr
*isp
= *iter
;
1415 isp
= list_head(&dev
->d_hwinfo
);
1417 isp
= list_next(&dev
->d_hwinfo
, isp
);
1421 return (isp
? isp
->i_line
: NULL
);
1425 auclnt_get_dev_instance(audio_dev_t
*dev
)
1427 return (dev
->d_instance
);
1431 auclnt_get_dev_description(audio_dev_t
*dev
)
1433 return (dev
->d_desc
);
1437 auclnt_get_dev_version(audio_dev_t
*dev
)
1439 return (dev
->d_vers
);
1443 auclnt_get_dev_capab(audio_dev_t
*dev
)
1448 flags
= dev
->d_flags
;
1450 if (flags
& DEV_OUTPUT_CAP
)
1451 caps
|= AUDIO_CLIENT_CAP_PLAY
;
1452 if (flags
& DEV_INPUT_CAP
)
1453 caps
|= AUDIO_CLIENT_CAP_RECORD
;
1454 if (flags
& DEV_DUPLEX_CAP
)
1455 caps
|= AUDIO_CLIENT_CAP_DUPLEX
;
1457 /* AC3: deal with formats that don't support mixing */
1463 auclnt_notify_dev(audio_dev_t
*dev
)
1465 list_t
*l
= &dev
->d_clients
;
1468 rw_enter(&dev
->d_clnt_lock
, RW_READER
);
1469 for (c
= list_head(l
); c
!= NULL
; c
= list_next(l
, c
)) {
1470 mutex_enter(&c
->c_lock
);
1471 c
->c_do_notify
= B_TRUE
;
1472 cv_broadcast(&c
->c_cv
);
1473 mutex_exit(&c
->c_lock
);
1475 rw_exit(&dev
->d_clnt_lock
);
1479 auclnt_get_samples(audio_stream_t
*sp
)
1483 mutex_enter(&sp
->s_lock
);
1485 mutex_exit(&sp
->s_lock
);
1490 auclnt_set_samples(audio_stream_t
*sp
, uint64_t n
)
1492 mutex_enter(&sp
->s_lock
);
1494 mutex_exit(&sp
->s_lock
);
1498 auclnt_get_errors(audio_stream_t
*sp
)
1501 mutex_enter(&sp
->s_lock
);
1503 mutex_exit(&sp
->s_lock
);
1508 auclnt_set_errors(audio_stream_t
*sp
, uint64_t n
)
1510 mutex_enter(&sp
->s_lock
);
1512 mutex_exit(&sp
->s_lock
);
1516 auclnt_register_ops(minor_t minor
, audio_client_ops_t
*ops
)
1518 /* we control minor number allocations, no need for runtime checks */
1519 ASSERT(minor
<= AUDIO_MN_TYPE_MASK
);
1521 audio_client_ops
[minor
] = ops
;
1525 auimpl_create_minors(audio_dev_t
*d
)
1527 char path
[MAXPATHLEN
];
1530 audio_client_ops_t
*ops
;
1533 for (int i
= 0; i
<= AUDIO_MN_TYPE_MASK
; i
++) {
1535 if ((ops
= audio_client_ops
[i
]) == NULL
)
1538 if (ops
->aco_dev_init
!= NULL
)
1539 d
->d_minor_data
[i
] = ops
->aco_dev_init(d
);
1542 case AUDIO_MINOR_SNDSTAT
:
1543 if (!(d
->d_flags
& DEV_SNDSTAT_CAP
)) {
1550 if (!(d
->d_flags
& (DEV_INPUT_CAP
| DEV_OUTPUT_CAP
))) {
1557 if (ops
->aco_minor_prefix
!= NULL
) {
1559 minor
= AUDIO_MKMN(d
->d_instance
, i
);
1560 (void) snprintf(path
, sizeof (path
),
1561 "%s%d", ops
->aco_minor_prefix
, d
->d_instance
);
1563 rv
= ddi_create_minor_node(d
->d_dip
, path
, S_IFCHR
,
1574 auimpl_remove_minors(audio_dev_t
*d
)
1576 char path
[MAXPATHLEN
];
1577 audio_client_ops_t
*ops
;
1579 for (int i
= 0; i
<= AUDIO_MN_TYPE_MASK
; i
++) {
1580 if ((ops
= audio_client_ops
[i
]) == NULL
)
1582 if (ops
->aco_minor_prefix
!= NULL
) {
1583 (void) snprintf(path
, sizeof (path
), "%s%d",
1584 ops
->aco_minor_prefix
, d
->d_instance
);
1585 (void) ddi_remove_minor_node(d
->d_dip
, path
);
1588 if (ops
->aco_dev_fini
!= NULL
)
1589 ops
->aco_dev_fini(d
->d_minor_data
[i
]);
1594 auclnt_get_dev_minor_data(audio_dev_t
*d
, minor_t mn
)
1596 ASSERT(mn
< (1U << AUDIO_MN_TYPE_NBITS
));
1597 return (d
->d_minor_data
[mn
]);
1601 auclnt_get_minor_data(audio_client_t
*c
, minor_t mn
)
1603 ASSERT(mn
< (1U << AUDIO_MN_TYPE_NBITS
));
1604 return (c
->c_dev
->d_minor_data
[mn
]);
1608 * This will walk all controls registered to a clients device and callback
1609 * to walker for each one with its audio_ctrl. Note this data
1610 * must be considered read only by walker.
1612 * Note that walk_func may return values to continue (AUDIO_WALK_CONTINUE)
1613 * or stop walk (AUDIO_WALK_STOP).
1617 auclnt_walk_controls(audio_dev_t
*d
,
1618 int (*walker
)(audio_ctrl_t
*, void *),
1623 rw_enter(&d
->d_ctrl_lock
, RW_READER
);
1624 for (ctrl
= list_head(&d
->d_controls
); ctrl
;
1625 ctrl
= list_next(&d
->d_controls
, ctrl
)) {
1626 if (walker(ctrl
, arg
) == AUDIO_WALK_STOP
)
1629 rw_exit(&d
->d_ctrl_lock
);
1633 * This will search all controls attached to an
1634 * audio device for a control with the desired name.
1636 * d - the audio device to look on
1637 * name - name of the control being looked for.
1639 * On successful return a ctrl handle will be returned. On
1640 * failure NULL is returned.
1643 auclnt_find_control(audio_dev_t
*d
, const char *name
)
1647 /* Verify argument */
1650 rw_enter(&d
->d_ctrl_lock
, RW_READER
);
1651 for (ctrl
= list_head(&d
->d_controls
); ctrl
;
1652 ctrl
= list_next(&d
->d_controls
, ctrl
)) {
1653 if (strcmp(ctrl
->ctrl_name
, name
) == 0) {
1654 rw_exit(&d
->d_ctrl_lock
);
1658 rw_exit(&d
->d_ctrl_lock
);
1663 * Given a known control, get its attributes.
1665 * The caller must supply a audio_ctrl_desc_t structure. Also the
1666 * values in the structure are ignored when making the call and filled
1667 * in by this function. All data pointed to by elements of desc should
1668 * be assumed read only.
1670 * If an error occurs then a non-zero is returned.
1674 auclnt_control_describe(audio_ctrl_t
*ctrl
, audio_ctrl_desc_t
*desc
)
1679 bcopy(&ctrl
->ctrl_des
, desc
, sizeof (*desc
));
1684 auclnt_control_read(audio_ctrl_t
*ctrl
, uint64_t *value
)
1686 return (audio_control_read(ctrl
, value
));
1690 auclnt_control_write(audio_ctrl_t
*ctrl
, uint64_t value
)
1692 return (audio_control_write(ctrl
, value
));
1696 auclnt_warn(audio_client_t
*c
, const char *fmt
, ...)
1701 auimpl_dev_vwarn(c
? c
->c_dev
: NULL
, fmt
, va
);