/*-
 * Copyright (c) 2008 Ariff Abdullah <ariff@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#ifndef __SND_OSS_COMPAT_H__
#define __SND_OSS_COMPAT_H__

#ifdef __FreeBSD__
#include <sys/soundcard.h>
#else
#define AFMT_MU_LAW     0x00000001  /* Logarithmic mu-law */
#define AFMT_A_LAW      0x00000002   /* Logarithmic A-law */
#define AFMT_U8         0x00000008     /* Unsigned 8-bit */
#define AFMT_S16_LE     0x00000010  /* Little endian signed 16-bit */
#define AFMT_S16_BE     0x00000020  /* Big endian signed 16-bit */
#define AFMT_S8         0x00000040     /* Signed 8-bit */
#define AFMT_U16_LE     0x00000080  /* Little endian unsigned 16-bit */
#define AFMT_U16_BE     0x00000100  /* Big endian unsigned 16-bit */
#if BYTE_ORDER == LITTLE_ENDIAN
#define AFMT_S16_NE     AFMT_S16_LE     /* native endian signed 16 */
#else
#define AFMT_S16_NE     AFMT_S16_BE
#endif
#define AFMT_S32_LE     0x00001000  /* Little endian signed 32-bit */
#define AFMT_S32_BE     0x00002000  /* Big endian signed 32-bit */
#define AFMT_U32_LE     0x00004000  /* Little endian unsigned 32-bit */
#define AFMT_U32_BE     0x00008000  /* Big endian unsigned 32-bit */
#define AFMT_S24_LE     0x00010000  /* Little endian signed 24-bit */
#define AFMT_S24_BE     0x00020000  /* Big endian signed 24-bit */
#define AFMT_U24_LE     0x00040000  /* Little endian unsigned 24-bit */
#define AFMT_U24_BE     0x00080000  /* Big endian unsigned 24-bit */
#define AFMT_STEREO     0x10000000  /* can do/want stereo    */

#endif  /* __FreeBSD__ */

#ifndef AFMT_S24_LE
#define AFMT_S24_LE     0x00010000
#endif

#ifndef AFMT_S24_BE
#define AFMT_S24_BE     0x00020000
#endif

#ifndef AFMT_U24_LE
#define AFMT_U24_LE     0x00040000
#endif

#ifndef AFMT_U24_BE
#define AFMT_U24_BE     0x00080000
#endif

#define AFMT_32BIT      (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE)

#define AFMT_24BIT      (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE)

#define AFMT_16BIT      (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)

#define AFMT_G711       (AFMT_MU_LAW | AFMT_A_LAW)

#define AFMT_8BIT       (AFMT_G711 | AFMT_U8 | AFMT_S8)

#define AFMT_SIGNED     (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE |      \
                         AFMT_S24_BE | AFMT_S16_LE | AFMT_S16_BE |      \
                         AFMT_S8)

#define AFMT_BIGENDIAN  (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE |      \
                         AFMT_U24_BE | AFMT_S16_BE | AFMT_U16_BE)

#define AFMT_BIT(v)     (((v) & AFMT_32BIT) ? 32 :                  \
                        (((v) & AFMT_24BIT) ? 24 :                   \
                        (((v) & AFMT_16BIT) ? 16 : 8)))

#define AFMT_BPS(v)     (AFMT_BIT(v) >> 3)

#define AFMT_CONVERTIBLE        (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT |  \
                                 AFMT_32BIT)

/*
 * We're simply using unused, contiguous bits from various AFMT_ definitions.
 * ~(0xb00ff7ff)
 */
#define AFMT_ENCODING_MASK      0xf00fffff
#define AFMT_CHANNEL_MASK       0x01f00000
#define AFMT_CHANNEL_SHIFT      20
#define AFMT_EXTCHANNEL_MASK    0x0e000000
#define AFMT_EXTCHANNEL_SHIFT   25

#define AFMT_ENCODING(v)        ((v) & AFMT_ENCODING_MASK)

#define AFMT_EXTCHANNEL(v)      (((v) & AFMT_EXTCHANNEL_MASK) >>        \
                                AFMT_EXTCHANNEL_SHIFT)

#define AFMT_CHANNEL(v)         (((v) & AFMT_CHANNEL_MASK) >>           \
                                AFMT_CHANNEL_SHIFT)


#define SND_FORMAT(f, c, m)     (AFMT_ENCODING(f) |             \
                                (((c) << AFMT_CHANNEL_SHIFT) &          \
                                AFMT_CHANNEL_MASK) |                    \
                                (((m) << AFMT_EXTCHANNEL_SHIFT) &       \
                                AFMT_EXTCHANNEL_MASK))

#define AFMT_ALIGN(v)           (AFMT_BPS(v) * AFMT_CHANNEL(v))

#define AFMT_U8_NE      AFMT_U8
#define AFMT_S8_NE      AFMT_S8

#undef AFMT_S16_NE

#if BYTE_ORDER == LITTLE_ENDIAN
#define AFMT_S16_NE     AFMT_S16_LE
#define AFMT_S24_NE     AFMT_S24_LE
#define AFMT_S32_NE     AFMT_S32_LE
#define AFMT_U16_NE     AFMT_U16_LE
#define AFMT_U24_NE     AFMT_U24_LE
#define AFMT_U32_NE     AFMT_U32_LE
#define AFMT_S16_OE     AFMT_S16_BE
#define AFMT_S24_OE     AFMT_S24_BE
#define AFMT_S32_OE     AFMT_S32_BE
#define AFMT_U16_OE     AFMT_U16_BE
#define AFMT_U24_OE     AFMT_U24_BE
#define AFMT_U32_OE     AFMT_U32_BE
#else
#define AFMT_S16_OE     AFMT_S16_LE
#define AFMT_S24_OE     AFMT_S24_LE
#define AFMT_S32_OE     AFMT_S32_LE
#define AFMT_U16_OE     AFMT_U16_LE
#define AFMT_U24_OE     AFMT_U24_LE
#define AFMT_U32_OE     AFMT_U32_LE
#define AFMT_S16_NE     AFMT_S16_BE
#define AFMT_S24_NE     AFMT_S24_BE
#define AFMT_S32_NE     AFMT_S32_BE
#define AFMT_U16_NE     AFMT_U16_BE
#define AFMT_U24_NE     AFMT_U24_BE
#define AFMT_U32_NE     AFMT_U32_BE
#endif

#define AFMT_SIGNED_NE  (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | AFMT_S32_NE)

#define AFMT_NE         (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE |    \
                         AFMT_U24_NE | AFMT_U32_NE)

#endif  /* !__SND_OSS_COMPAT_H__ */