1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "pcm_local.h"
34
snd_pcm_format_signed(snd_pcm_format_t format)35 int snd_pcm_format_signed(snd_pcm_format_t format)
36 {
37 switch (format) {
38 case SND_PCM_FORMAT_S8:
39 case SND_PCM_FORMAT_S16_LE:
40 case SND_PCM_FORMAT_S16_BE:
41 case SND_PCM_FORMAT_S24_LE:
42 case SND_PCM_FORMAT_S24_BE:
43 case SND_PCM_FORMAT_S32_LE:
44 case SND_PCM_FORMAT_S32_BE:
45 return 1;
46 case SND_PCM_FORMAT_U8:
47 case SND_PCM_FORMAT_U16_LE:
48 case SND_PCM_FORMAT_U16_BE:
49 case SND_PCM_FORMAT_U24_LE:
50 case SND_PCM_FORMAT_U24_BE:
51 case SND_PCM_FORMAT_U32_LE:
52 case SND_PCM_FORMAT_U32_BE:
53 return 0;
54 default:
55 return -EINVAL;
56 }
57 }
58
snd_pcm_format_unsigned(snd_pcm_format_t format)59 int snd_pcm_format_unsigned(snd_pcm_format_t format)
60 {
61 int val;
62
63 val = snd_pcm_format_signed(format);
64 if (val < 0)
65 return val;
66 return !val;
67 }
68
snd_pcm_format_linear(snd_pcm_format_t format)69 int snd_pcm_format_linear(snd_pcm_format_t format)
70 {
71 return snd_pcm_format_signed(format) >= 0;
72 }
73
snd_pcm_format_little_endian(snd_pcm_format_t format)74 int snd_pcm_format_little_endian(snd_pcm_format_t format)
75 {
76 switch (format) {
77 case SND_PCM_FORMAT_S16_LE:
78 case SND_PCM_FORMAT_U16_LE:
79 case SND_PCM_FORMAT_S24_LE:
80 case SND_PCM_FORMAT_U24_LE:
81 case SND_PCM_FORMAT_S32_LE:
82 case SND_PCM_FORMAT_U32_LE:
83 return 1;
84 case SND_PCM_FORMAT_S16_BE:
85 case SND_PCM_FORMAT_U16_BE:
86 case SND_PCM_FORMAT_S24_BE:
87 case SND_PCM_FORMAT_U24_BE:
88 case SND_PCM_FORMAT_S32_BE:
89 case SND_PCM_FORMAT_U32_BE:
90 return 0;
91 default:
92 return -EINVAL;
93 }
94 }
95
snd_pcm_format_big_endian(snd_pcm_format_t format)96 int snd_pcm_format_big_endian(snd_pcm_format_t format)
97 {
98 int val;
99
100 val = snd_pcm_format_little_endian(format);
101 if (val < 0)
102 return val;
103 return !val;
104 }
105
snd_pcm_format_width(snd_pcm_format_t format)106 int snd_pcm_format_width(snd_pcm_format_t format)
107 {
108 switch (format) {
109 case SND_PCM_FORMAT_S8:
110 case SND_PCM_FORMAT_U8:
111 return 8;
112 case SND_PCM_FORMAT_S16_LE:
113 case SND_PCM_FORMAT_S16_BE:
114 case SND_PCM_FORMAT_U16_LE:
115 case SND_PCM_FORMAT_U16_BE:
116 return 16;
117 case SND_PCM_FORMAT_S24_LE:
118 case SND_PCM_FORMAT_S24_BE:
119 case SND_PCM_FORMAT_U24_LE:
120 case SND_PCM_FORMAT_U24_BE:
121 return 24;
122 case SND_PCM_FORMAT_S32_LE:
123 case SND_PCM_FORMAT_S32_BE:
124 case SND_PCM_FORMAT_U32_LE:
125 case SND_PCM_FORMAT_U32_BE:
126 return 32;
127 default:
128 return -EINVAL;
129 }
130 }
131
132 static const int linear_formats[4][2][2] = {
133 { { SND_PCM_FORMAT_S8, SND_PCM_FORMAT_S8 },
134 { SND_PCM_FORMAT_U8, SND_PCM_FORMAT_U8 } },
135 { { SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE },
136 { SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE } },
137 { { SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE },
138 { SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE } },
139 { { SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE },
140 { SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE } }
141 };
142
143 /**
144 * \brief Compose a PCM sample linear format
145 * \param width Nominal bits per sample
146 * \param pwidth Physical bit width of the format
147 * \param unsignd Sign: 0 signed, 1 unsigned
148 * \param big_endian Endian: 0 little endian, 1 big endian
149 * \return The matching format type, or #SND_PCM_FORMAT_UNKNOWN if no match
150 */
snd_pcm_build_linear_format(int width,int pwidth,int unsignd,int big_endian)151 snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, int big_endian)
152 {
153 if (pwidth == 24) {
154 #if 0
155 switch (width) {
156 case 24:
157 width = 0;
158 break;
159 case 20:
160 width = 1;
161 break;
162 case 18:
163 width = 2;
164 break;
165 default:
166 return SND_PCM_FORMAT_UNKNOWN;
167 }
168 return linear24_formats[width][!!unsignd][!!big_endian];
169 #else
170 return SND_PCM_FORMAT_UNKNOWN;
171 #endif
172 } else {
173 switch (width) {
174 case 8:
175 width = 0;
176 break;
177 case 16:
178 width = 1;
179 break;
180 case 24:
181 width = 2;
182 break;
183 case 32:
184 width = 3;
185 break;
186 default:
187 return SND_PCM_FORMAT_UNKNOWN;
188 }
189 return linear_formats[width][!!unsignd][!!big_endian];
190 }
191 }
192