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