xref: /illumos-gate/usr/src/uts/common/io/audio/impl/audio_engine.c (revision e84b06c37938f78f92152e488295ec2634d8ebca)
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  */
46 uint_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  */
51 int		audio_priority = DDI_IPL_8;
52 
53 audio_dev_t *
54 audio_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 
103 void
104 audio_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 
125 void
126 audio_dev_set_description(audio_dev_t *d, const char *desc)
127 {
128 	(void) strlcpy(d->d_desc, desc, sizeof (d->d_desc));
129 }
130 
131 void
132 audio_dev_set_version(audio_dev_t *d, const char *vers)
133 {
134 	(void) strlcpy(d->d_vers, vers, sizeof (d->d_vers));
135 }
136 
137 void
138 audio_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 
152 static void
153 auimpl_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 
197 static volatile uint_t auimpl_engno = 0;
198 
199 audio_engine_t *
200 audio_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 
244 void
245 audio_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 
262 static list_t auimpl_devs_by_index;
263 static list_t auimpl_devs_by_number;
264 static krwlock_t auimpl_dev_lock;
265 
266 /*
267  * Not for public consumption: Private interfaces.
268  */
269 void
270 auimpl_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 
278 audio_dev_t *
279 auimpl_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 
302 audio_dev_t *
303 auimpl_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 
321 void
322 auimpl_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 
329 int
330 auimpl_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 
362 int
363 auimpl_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 
407 again:
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 
657 ok:
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 
664 done:
665 	mutex_exit(&e->e_lock);
666 	mutex_exit(&d->d_lock);
667 	return (rv);
668 }
669 
670 void
671 auimpl_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 
703 int
704 audio_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 
773 int
774 audio_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 
795 static int
796 auimpl_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 
830 static void
831 auimpl_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 
878 void
879 audio_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 
907 void
908 audio_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  */
922 void
923 auclnt_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 
942 void
943 auclnt_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 
959 void
960 auclnt_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 
976 void
977 auclnt_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 
993 int
994 auclnt_engine_get_format(audio_engine_t *e)
995 {
996 	return (ENG_FORMAT(e));
997 }
998 
999 int
1000 auclnt_engine_get_channels(audio_engine_t *e)
1001 {
1002 	return (ENG_CHANNELS(e));
1003 }
1004 
1005 int
1006 auclnt_engine_get_rate(audio_engine_t *e)
1007 {
1008 	return (ENG_RATE(e));
1009 }
1010 
1011 uint_t
1012 auclnt_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  */
1043 static void
1044 auimpl_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 
1063 static void
1064 auimpl_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 
1089 static int
1090 auimpl_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 
1122 static int
1123 auimpl_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 
1156 boolean_t
1157 auimpl_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 
1175 void
1176 audio_dev_suspend(audio_dev_t *d)
1177 {
1178 	(void) auimpl_dev_suspend(d, NULL);
1179 }
1180 
1181 void
1182 audio_dev_resume(audio_dev_t *d)
1183 {
1184 	(void) auimpl_dev_resume(d, NULL);
1185 }
1186 
1187 static callb_id_t	auimpl_cpr_id = 0;
1188 
1189 void
1190 auimpl_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 
1209 void
1210 auimpl_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 
1218 void
1219 audio_engine_set_private(audio_engine_t *eng, void *prv)
1220 {
1221 	eng->e_private = prv;
1222 }
1223 
1224 void *
1225 audio_engine_get_private(audio_engine_t *eng)
1226 {
1227 	return (eng->e_private);
1228 }
1229 
1230 void
1231 audio_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 
1260 void
1261 audio_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 
1290 void
1291 audio_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