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