Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / audio / impl / audio_format.c
blob9656cbad3fee337f2079a249d75f526555e23f4a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (C) 4Front Technologies 1996-2008.
24 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Purpose: Audio format conversion routines used by audio.c
31 #include <sys/types.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/audio/g711.h>
36 #include "audio_impl.h"
37 #include "audio_grc3.h"
39 extern uint_t audio_intrhz;
42 * Note: In the function below, the division by the number of channels is
43 * probably fairly expensive. It turns out that we usually deal with stereo
44 * or mono data, so perhaps it would be useful to build custom versions of
45 * this function that only dealt with stereo or mono.
47 static int
48 do_src(audio_stream_t *sp, void *p1, void *p2, int len, int nchan)
50 int ch, size;
53 * Note that we presume that we are doing sample rate
54 * conversions on AUDIO_FORMAT_S24_NE, which means that have 4
55 * byte and 32-bit samples.
57 size = sp->s_cnv_max / 4; /* sample size is 4 */
58 size /= nchan;
60 for (ch = 0; ch < nchan; ch++) {
61 grc3_convert(sp->s_src_state[ch], sp->s_src_quality,
62 p1, p2, len, size, nchan, ch);
64 return (((grc3state_t *)sp->s_src_state[0])->outsz);
67 static void
68 setup_src(audio_stream_t *sp, int srate, int trate, int sch, int tch)
70 int ch, nch;
72 nch = min(sch, tch);
74 ASSERT(nch <= AUDIO_MAX_CHANNELS);
76 if (sp->s_src_quality < 1)
77 sp->s_src_quality = 1;
78 if (sp->s_src_quality > 5)
79 sp->s_src_quality = 5;
81 for (ch = 0; ch < nch; ch++) {
82 grc3_reset(sp->s_src_state[ch]);
83 grc3_setup(sp->s_src_state[ch], srate, trate);
87 static int
88 cnv_srconly(audio_stream_t *sp, int len)
90 void *src = sp->s_cnv_src;
91 void *dst = sp->s_cnv_dst;
94 * We must be using 24-bit native signed.
96 len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
98 sp->s_cnv_src = dst;
99 sp->s_cnv_dst = src;
101 return (len);
104 static int
105 cnv_s24oe(audio_stream_t *sp, int len)
108 * Endian switch works in both directions. We do it in place.
110 int32_t *src = sp->s_cnv_src;
112 for (int i = len * sp->s_cnv_src_nchan; i; i--) {
113 *src = ddi_swap32(*src);
114 src++;
117 return (len);
121 static int
122 cnv_from_s8(audio_stream_t *sp, int len)
124 void *s = sp->s_cnv_src;
125 void *d = sp->s_cnv_dst;
126 int8_t *src = s;
127 int32_t *dst = d;
129 for (int i = len * sp->s_cnv_src_nchan; i; i--)
130 *dst++ = (*src++) << 16;
132 sp->s_cnv_src = d;
133 sp->s_cnv_dst = s;
134 return (len);
137 static int
138 cnv_from_u8(audio_stream_t *sp, int len)
140 void *s = sp->s_cnv_src;
141 void *d = sp->s_cnv_dst;
142 uint8_t *src = s;
143 int32_t *dst = d;
145 for (int i = len * sp->s_cnv_src_nchan; i; i--)
146 *dst++ = (int8_t)((*src++) ^ 0x80) << 16;
148 sp->s_cnv_src = d;
149 sp->s_cnv_dst = s;
150 return (len);
153 static int
154 cnv_from_ulaw(audio_stream_t *sp, int len)
156 void *s = sp->s_cnv_src;
157 void *d = sp->s_cnv_dst;
158 uint8_t *src = s;
159 int32_t *dst = d;
161 for (int i = len * sp->s_cnv_src_nchan; i; i--) {
162 *dst++ = _8ulaw2linear16[(*src++)] << 8;
164 sp->s_cnv_src = d;
165 sp->s_cnv_dst = s;
166 return (len);
169 static int
170 cnv_from_alaw(audio_stream_t *sp, int len)
172 void *s = sp->s_cnv_src;
173 void *d = sp->s_cnv_dst;
174 uint8_t *src = s;
175 int32_t *dst = d;
177 for (int i = len * sp->s_cnv_src_nchan; i; i--) {
178 *dst++ = _8alaw2linear16[(*src++)] << 8;
180 sp->s_cnv_src = d;
181 sp->s_cnv_dst = s;
182 return (len);
185 static int
186 cnv_from_s16ne(audio_stream_t *sp, int len)
188 void *s = sp->s_cnv_src;
189 void *d = sp->s_cnv_dst;
190 int16_t *src = s;
191 int32_t *dst = d;
193 for (int i = len * sp->s_cnv_src_nchan; i; i--)
194 *dst++ = (*src++) << 8;
196 sp->s_cnv_src = d;
197 sp->s_cnv_dst = s;
198 return (len);
201 static int
202 cnv_from_s16oe(audio_stream_t *sp, int len)
204 void *s = sp->s_cnv_src;
205 void *d = sp->s_cnv_dst;
206 int16_t *src = s;
207 int32_t *dst = d;
209 for (int i = len * sp->s_cnv_src_nchan; i; i--)
210 *dst++ = (int16_t)(ddi_swap16(*src++)) << 8;
212 sp->s_cnv_src = d;
213 sp->s_cnv_dst = s;
214 return (len);
217 static int
218 cnv_from_u16ne(audio_stream_t *sp, int len)
220 void *s = sp->s_cnv_src;
221 void *d = sp->s_cnv_dst;
222 uint16_t *src = s;
223 int32_t *dst = d;
225 for (int i = len * sp->s_cnv_src_nchan; i; i--)
226 *dst++ = (int16_t)((*src++) ^ 0x8000) << 8;
228 sp->s_cnv_src = d;
229 sp->s_cnv_dst = s;
230 return (len);
233 static int
234 cnv_from_u16oe(audio_stream_t *sp, int len)
236 void *s = sp->s_cnv_src;
237 void *d = sp->s_cnv_dst;
238 uint16_t *src = s;
239 int32_t *dst = d;
241 for (int i = len * sp->s_cnv_src_nchan; i; i--)
242 *dst++ = (int16_t)(ddi_swap16((*src++) ^ 0x8000)) << 8;
244 sp->s_cnv_src = d;
245 sp->s_cnv_dst = s;
246 return (len);
249 static int
250 cnv_from_s24p(audio_stream_t *sp, int len)
252 void *s = sp->s_cnv_src;
253 void *d = sp->s_cnv_dst;
254 uint8_t *src = s;
255 int32_t *dst = d;
256 int32_t tmp;
258 for (int i = len * sp->s_cnv_src_nchan; i; i--) {
259 /* NB: this is a little endian format */
260 tmp = (*src++);
261 tmp |= (*src++) << 8;
262 tmp |= (*src++) << 16;
263 *dst++ = tmp;
266 sp->s_cnv_src = d;
267 sp->s_cnv_dst = s;
268 return (len);
271 static int
272 cnv_from_s32ne(audio_stream_t *sp, int len)
274 /* 32-bit conversions can be done in place */
275 int32_t *src = sp->s_cnv_src;
277 for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
278 *src = *src >> 8;
280 return (len);
283 static int
284 cnv_from_s32oe(audio_stream_t *sp, int len)
286 /* 32-bit conversions can be done in place */
287 int32_t *src = sp->s_cnv_src;
289 for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
290 *src = (int32_t)(ddi_swap32(*src)) >> 8;
292 return (len);
296 * NB: All the destination format conversions use the same or fewer
297 * bytes as the 24-bit unpacked (32-bits used per sample), so we can
298 * convert all of them in place.
301 static int
302 cnv_to_u8(audio_stream_t *sp, int len)
304 int32_t *src = sp->s_cnv_src;
305 uint8_t *dst = (void *)src;
307 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
308 *dst++ = (*src++ >> 16) ^ 0x80;
310 return (len);
313 static int
314 cnv_to_s8(audio_stream_t *sp, int len)
316 int32_t *src = sp->s_cnv_src;
317 int8_t *dst = (void *)src;
319 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
320 *dst++ = *src++ >> 16;
322 return (len);
325 static int
326 cnv_to_ulaw(audio_stream_t *sp, int len)
328 int32_t *src = sp->s_cnv_src;
329 uint8_t *dst = (void *)src;
331 for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
332 int idx = *src++;
333 idx >>= 10;
334 idx += G711_ULAW_MIDPOINT;
335 idx &= 0x3fff; /* safety precaution */
336 *dst++ = _14linear2ulaw8[idx];
339 return (len);
342 static int
343 cnv_to_alaw(audio_stream_t *sp, int len)
345 int32_t *src = sp->s_cnv_src;
346 uint8_t *dst = (void *)src;
348 for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
349 int idx = *src++;
350 idx >>= 11;
351 idx += G711_ALAW_MIDPOINT;
352 idx &= 0x1fff; /* safety precaution */
353 *dst++ = _13linear2alaw8[idx];
356 return (len);
359 static int
360 cnv_to_s16ne(audio_stream_t *sp, int len)
362 int32_t *src = sp->s_cnv_src;
363 int16_t *dst = (void *)src;
365 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
366 *dst++ = *src++ >> 8;
368 return (len);
371 static int
372 cnv_to_s16oe(audio_stream_t *sp, int len)
374 int32_t *src = sp->s_cnv_src;
375 int16_t *dst = (void *)src;
377 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
378 *dst++ = ddi_swap16(*src++ >> 8);
380 return (len);
383 static int
384 cnv_to_u16ne(audio_stream_t *sp, int len)
386 int32_t *src = sp->s_cnv_src;
387 uint16_t *dst = (void *)src;
389 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
390 *dst++ = (*src++ >> 8) ^ 0x8000;
392 return (len);
395 static int
396 cnv_to_u16oe(audio_stream_t *sp, int len)
398 int32_t *src = sp->s_cnv_src;
399 uint16_t *dst = (void *)src;
401 for (int i = len * sp->s_cnv_dst_nchan; i; i--)
402 *dst++ = ddi_swap16(*src++ >> 8) ^ 0x8000;
404 return (len);
407 static int
408 cnv_to_s24p(audio_stream_t *sp, int len)
410 int32_t *src = sp->s_cnv_src;
411 uint8_t *dst = (void *)src;
412 int32_t d;
414 for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
415 /* NB: this is a little endian format */
416 d = *src++;
417 *dst++ = d & 0xff;
418 *dst++ = (d >> 8) & 0xff;
419 *dst++ = (d >> 16) & 0xff;
422 return (len);
425 static int
426 cnv_to_s32ne(audio_stream_t *sp, int len)
428 int32_t *src = sp->s_cnv_src;
430 for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
431 *src = *src << 8;
433 return (len);
436 static int
437 cnv_to_s32oe(audio_stream_t *sp, int len)
439 int32_t *src = sp->s_cnv_src;
441 for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
442 *src = ddi_swap32(*src << 8);
444 return (len);
447 static int
448 cnv_default(audio_stream_t *sp, int len)
451 * Note that the formats were already preverified during
452 * select_converter, to ensure that only supported formats are
453 * used.
457 * Convert samples to 24 bit (32 bit lsb aligned) if
458 * necessary.
461 switch (sp->s_cnv_src_format) {
463 case AUDIO_FORMAT_U8:
464 len = cnv_from_u8(sp, len);
465 break;
467 case AUDIO_FORMAT_S8:
468 len = cnv_from_s8(sp, len);
469 break;
471 case AUDIO_FORMAT_ULAW:
472 len = cnv_from_ulaw(sp, len);
473 break;
475 case AUDIO_FORMAT_ALAW:
476 len = cnv_from_alaw(sp, len);
477 break;
479 case AUDIO_FORMAT_S16_NE:
480 len = cnv_from_s16ne(sp, len);
481 break;
483 case AUDIO_FORMAT_S16_OE:
484 len = cnv_from_s16oe(sp, len);
485 break;
487 case AUDIO_FORMAT_U16_NE:
488 len = cnv_from_u16ne(sp, len);
489 break;
491 case AUDIO_FORMAT_U16_OE:
492 len = cnv_from_u16oe(sp, len);
493 break;
495 case AUDIO_FORMAT_S32_NE:
496 len = cnv_from_s32ne(sp, len);
497 break;
499 case AUDIO_FORMAT_S32_OE:
500 len = cnv_from_s32oe(sp, len);
501 break;
503 case AUDIO_FORMAT_S24_OE:
504 len = cnv_s24oe(sp, len);
505 break;
507 case AUDIO_FORMAT_S24_PACKED:
508 len = cnv_from_s24p(sp, len);
509 break;
513 * If we aren't decreasing the number of channels, then do the
514 * SRC now. (We prefer to do SRC on the smaller number of channels.)
516 if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
517 sp->s_cnv_src_nchan <= sp->s_cnv_dst_nchan) {
518 int32_t *src = sp->s_cnv_src;
519 int32_t *dst = sp->s_cnv_dst;
521 len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
523 sp->s_cnv_src = dst;
524 sp->s_cnv_dst = src;
528 * Convert between mono and stereo
531 if (sp->s_cnv_src_nchan != sp->s_cnv_dst_nchan) {
532 int32_t *src = sp->s_cnv_src;
533 int32_t *dst = sp->s_cnv_dst;
534 int tc = sp->s_cnv_dst_nchan;
535 int sc = sp->s_cnv_src_nchan;
536 int nc;
537 int i;
539 sp->s_cnv_src = dst;
540 sp->s_cnv_dst = src;
542 if (sc == 1) {
544 * Mono expansion. We expand into the stereo
545 * channel, and leave other channels silent.
547 for (i = len; i; i--) {
548 *dst++ = *src;
549 *dst++ = *src++;
550 for (int j = tc - 2; j > 0; j--) {
551 *dst++ = 0;
556 } else if (sc == 2 && tc == 1) {
558 * Stereo -> mono. We do stereo separately to make
559 * the division fast (div by const 2 is just shift).
561 for (i = len; i; i--) {
563 * Take just the left channel sample,
564 * discard the right channel.
566 *dst++ = *src++; /* left */
567 src++; /* right */
569 } else {
571 * Multi channel conversions. We just copy the
572 * minimum number of channels.
575 /* Calculate number of frames */
577 nc = min(sc, tc);
579 /* Clear destination */
580 bzero(dst, (len * tc * sizeof (int32_t)));
582 for (i = len; i; i--) {
583 int c;
585 for (c = 0; c < nc; c++)
586 dst[c] = src[c];
588 src += sc;
589 dst += tc;
595 * If we didn't do SRC pre-conversion, then do it now.
597 if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
598 sp->s_cnv_src_nchan > sp->s_cnv_dst_nchan) {
600 int32_t *src = sp->s_cnv_src;
601 int32_t *dst = sp->s_cnv_dst;
603 len = do_src(sp, src, dst, len, sp->s_cnv_dst_nchan);
605 sp->s_cnv_src = dst;
606 sp->s_cnv_dst = src;
610 * Finally convert samples from internal 24 bit format to target format
613 switch (sp->s_cnv_dst_format) {
614 case AUDIO_FORMAT_U8:
615 len = cnv_to_u8(sp, len);
616 break;
618 case AUDIO_FORMAT_S8:
619 len = cnv_to_s8(sp, len);
620 break;
622 case AUDIO_FORMAT_S16_NE:
623 len = cnv_to_s16ne(sp, len);
624 break;
626 case AUDIO_FORMAT_S16_OE:
627 len = cnv_to_s16oe(sp, len);
628 break;
630 case AUDIO_FORMAT_U16_NE:
631 len = cnv_to_u16ne(sp, len);
632 break;
634 case AUDIO_FORMAT_U16_OE:
635 len = cnv_to_u16oe(sp, len);
636 break;
638 case AUDIO_FORMAT_S24_OE:
639 len = cnv_s24oe(sp, len);
640 break;
642 case AUDIO_FORMAT_S24_PACKED:
643 len = cnv_to_s24p(sp, len);
644 break;
646 case AUDIO_FORMAT_S32_NE:
647 len = cnv_to_s32ne(sp, len);
648 break;
650 case AUDIO_FORMAT_S32_OE:
651 len = cnv_to_s32oe(sp, len);
652 break;
654 case AUDIO_FORMAT_ULAW:
655 len = cnv_to_ulaw(sp, len);
656 break;
658 case AUDIO_FORMAT_ALAW:
659 len = cnv_to_alaw(sp, len);
660 break;
663 return (len);
666 static const struct audio_format_info {
667 unsigned format;
668 int sampsize;
669 audio_cnv_func_t from;
670 audio_cnv_func_t to;
671 } audio_format_info[] = {
672 { AUDIO_FORMAT_S8, 1, cnv_from_s8, cnv_to_s8 },
673 { AUDIO_FORMAT_U8, 1, cnv_from_u8, cnv_to_u8 },
674 { AUDIO_FORMAT_ULAW, 1, cnv_from_ulaw, cnv_to_ulaw },
675 { AUDIO_FORMAT_ALAW, 1, cnv_from_alaw, cnv_to_alaw },
676 { AUDIO_FORMAT_S16_NE, 2, cnv_from_s16ne, cnv_to_s16ne },
677 { AUDIO_FORMAT_S16_OE, 2, cnv_from_s16oe, cnv_to_s16oe },
678 { AUDIO_FORMAT_U16_NE, 2, cnv_from_u16ne, cnv_to_u16ne },
679 { AUDIO_FORMAT_U16_OE, 2, cnv_from_u16oe, cnv_to_u16oe },
680 { AUDIO_FORMAT_S32_NE, 4, cnv_from_s32ne, cnv_to_s32ne },
681 { AUDIO_FORMAT_S32_OE, 4, cnv_from_s32oe, cnv_to_s32oe },
683 /* 24-bit formats are "special" */
684 { AUDIO_FORMAT_S24_NE, 4, NULL, NULL },
685 { AUDIO_FORMAT_S24_OE, 4, cnv_s24oe, cnv_s24oe },
686 { AUDIO_FORMAT_S24_PACKED, 3, cnv_from_s24p, cnv_to_s24p },
688 /* sentinel */
689 { AUDIO_FORMAT_NONE, 0, NULL, NULL }
693 auimpl_format_setup(audio_stream_t *sp, audio_parms_t *parms, uint_t mask)
695 audio_parms_t source;
696 audio_parms_t target;
697 audio_parms_t *uparms;
698 audio_cnv_func_t converter = NULL;
699 const struct audio_format_info *info;
700 int expand = AUDIO_UNIT_EXPAND;
701 unsigned cnv_sampsz = sizeof (uint32_t);
702 unsigned cnv_max;
703 boolean_t needsrc = B_FALSE;
705 uint_t framesz;
706 uint_t fragfr;
707 uint_t fragbytes;
708 uint_t nfrags;
710 ASSERT(mutex_owned(&sp->s_lock));
712 source = sp->s_cnv_src_parms;
713 target = sp->s_cnv_dst_parms;
715 if (sp == &sp->s_client->c_ostream) {
716 if (mask & FORMAT_MSK_FMT)
717 source.p_format = parms->p_format;
718 if (mask & FORMAT_MSK_RATE)
719 source.p_rate = parms->p_rate;
720 if (mask & FORMAT_MSK_CHAN)
721 source.p_nchan = parms->p_nchan;
722 uparms = &source;
723 } else {
724 if (mask & FORMAT_MSK_FMT)
725 target.p_format = parms->p_format;
726 if (mask & FORMAT_MSK_RATE)
727 target.p_rate = parms->p_rate;
728 if (mask & FORMAT_MSK_CHAN)
729 target.p_nchan = parms->p_nchan;
730 uparms = &target;
734 * At least one of the source or target are S24_NE.
736 * If we have a signed/native endian format, then pick an
737 * optimized converter. While at it, ensure that a valid
738 * format is selected.
740 * After this function executes, "info" will point to the
741 * format information for the user parameters.
743 if (source.p_format != AUDIO_FORMAT_S24_NE) {
744 for (info = &audio_format_info[0]; info->sampsize; info++) {
745 if (source.p_format == info->format) {
746 converter = info->from;
747 expand *= sizeof (int32_t);
748 expand /= info->sampsize;
749 /* save source frame size */
750 cnv_sampsz = info->sampsize;
751 break;
754 } else {
756 * Target format. Note that this case is also taken
757 * if we're operating on S24_NE data. In that case
758 * the converter will be NULL and expand will not be
759 * altered.
761 for (info = &audio_format_info[0]; info->sampsize; info++) {
762 if (target.p_format == info->format) {
763 converter = info->to;
764 expand *= info->sampsize;
765 expand /= sizeof (int32_t);
766 break;
770 if (info->format == AUDIO_FORMAT_NONE) {
771 audio_dev_warn(sp->s_client->c_dev, "invalid format selected");
772 return (EINVAL);
776 ASSERT(info->sampsize);
778 if (source.p_nchan != target.p_nchan) {
780 * if channels need conversion, then we must use the
781 * default.
783 converter = cnv_default;
784 expand *= target.p_nchan;
785 expand /= source.p_nchan;
788 if (source.p_rate != target.p_rate) {
789 needsrc = B_TRUE;
790 converter = (converter == NULL) ? cnv_srconly : cnv_default;
792 expand *= target.p_rate;
793 expand /= source.p_rate;
797 * Figure out the size of the conversion buffer we need. We
798 * assume room for two full source fragments, which ought to
799 * be enough, even with rounding errors.
801 cnv_max = 2 * (source.p_rate / audio_intrhz) *
802 cnv_sampsz * source.p_nchan;
805 * If the conversion will cause us to expand fragments, then
806 * we need to increase cnv_max. Scale by AUDIO_UNIT_EXPAND to
807 * avoid rouding errors or losing bits when doing reducing
808 * conversions.
810 if (expand > AUDIO_UNIT_EXPAND) {
811 cnv_max *= expand;
812 cnv_max /= AUDIO_UNIT_EXPAND;
815 framesz = info->sampsize * uparms->p_nchan;
816 fragfr = (uparms->p_rate / audio_intrhz);
817 fragbytes = fragfr * framesz;
820 * We need to "tune" the buffer and fragment counts for some
821 * uses... OSS applications may like to configure a low
822 * latency, and they rely upon write() to block to prevent too
823 * much data from being queued up.
825 if (sp->s_hintsz) {
826 nfrags = sp->s_hintsz / fragbytes;
827 } else if (sp->s_hintfrags) {
828 nfrags = sp->s_hintfrags;
829 } else {
830 nfrags = sp->s_allocsz / fragbytes;
834 * Now make sure that the hint works -- we need at least 2 fragments,
835 * and we need to fit within the room allocated to us.
837 if (nfrags < 2) {
838 nfrags = 2;
840 while ((nfrags * fragbytes) > sp->s_allocsz) {
841 nfrags--;
843 /* if the resulting configuration is invalid, note it */
844 if (nfrags < 2) {
845 return (EINVAL);
849 * Now we need to allocate space.
851 * NB: Once the allocation succeeds, we must not fail. We are
852 * modifying the the stream settings and these changes must be
853 * made atomically.
855 if (sp->s_cnv_max < cnv_max) {
856 uint32_t *buf0, *buf1;
858 buf0 = kmem_alloc(cnv_max, KM_NOSLEEP);
859 buf1 = kmem_alloc(cnv_max, KM_NOSLEEP);
860 if ((buf0 == NULL) || (buf1 == NULL)) {
861 audio_dev_warn(sp->s_client->c_dev,
862 "failed to allocate audio conversion buffer "
863 "(%u bytes)", cnv_max);
864 if (buf0)
865 kmem_free(buf0, cnv_max);
866 if (buf1)
867 kmem_free(buf1, cnv_max);
868 return (ENOMEM);
871 if (sp->s_cnv_buf0)
872 kmem_free(sp->s_cnv_buf0, sp->s_cnv_max);
873 if (sp->s_cnv_buf1)
874 kmem_free(sp->s_cnv_buf1, sp->s_cnv_max);
876 sp->s_cnv_buf0 = buf0;
877 sp->s_cnv_buf1 = buf1;
878 sp->s_cnv_max = cnv_max;
881 /* Set up the SRC state if we will be using SRC. */
882 if (needsrc) {
883 setup_src(sp, source.p_rate, target.p_rate,
884 source.p_nchan, target.p_nchan);
888 sp->s_framesz = framesz;
889 sp->s_fragfr = fragfr;
890 sp->s_fragbytes = fragbytes;
891 sp->s_nfrags = nfrags;
892 sp->s_nframes = nfrags * fragfr;
893 sp->s_nbytes = sp->s_nframes * framesz;
894 *sp->s_user_parms = *uparms;
895 sp->s_converter = converter;
898 * Ensure that we toss any stale data -- probably wrong format.
899 * Note that as a consequence of this, all of the offsets and
900 * counters get reset. Clients should not rely on these values
901 * being preserved when changing formats.
903 * Its critical that we reset the indices, in particular,
904 * because not only will the data be the wrong format, but the
905 * indices themselves are quite possibly going to be invalid.
907 sp->s_cnv_cnt = 0;
908 sp->s_tail = sp->s_head = 0;
909 sp->s_tidx = sp->s_hidx = 0;
911 return (0);
915 auimpl_format_alloc(audio_stream_t *sp)
917 int i;
919 ASSERT(mutex_owned(&sp->s_lock));
920 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
921 sp->s_src_state[i] =
922 kmem_zalloc(sizeof (grc3state_t), KM_NOSLEEP);
923 if (sp->s_src_state[i] == NULL) {
924 audio_dev_warn(sp->s_client->c_dev,
925 "unable to allocate SRC state structures");
926 return (ENOMEM);
929 return (0);
932 void
933 auimpl_format_free(audio_stream_t *sp)
935 int i;
937 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
938 if (sp->s_src_state[i] != NULL) {
939 kmem_free(sp->s_src_state[i], sizeof (grc3state_t));
940 sp->s_src_state[i] = NULL;