summaryrefslogtreecommitdiff
path: root/audio_hw_utils.c (plain)
blob: 6eb4bd63c83ce71e9ae977bba0ceca198a86dcd3
1/*
2 * Copyright (C) 2010 Amlogic Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18
19#define LOG_TAG "audio_hw_utils"
20#define LOG_NDEBUG 0
21
22#include <errno.h>
23#include <pthread.h>
24#include <stdint.h>
25#include <sys/time.h>
26#include <stdlib.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <time.h>
30#include <utils/Timers.h>
31#include <cutils/log.h>
32#include <cutils/str_parms.h>
33#include <cutils/properties.h>
34#include <linux/ioctl.h>
35#include <hardware/hardware.h>
36#include <system/audio.h>
37#include <hardware/audio.h>
38#include <sound/asound.h>
39#include <tinyalsa/asoundlib.h>
40
41#include "audio_hw_utils.h"
42
43#include "audio_hwsync.h"
44#include "audio_hw.h"
45#include <audio_utils/primitives.h>
46
47#ifdef LOG_NDEBUG_FUNCTION
48#define LOGFUNC(...) ((void)0)
49#else
50#define LOGFUNC(...) (ALOGD(__VA_ARGS__))
51#endif
52int get_sysfs_uint(const char *path, uint *value)
53{
54 int fd;
55 char valstr[64];
56 uint val = 0;
57 fd = open(path, O_RDONLY);
58 if (fd >= 0) {
59 memset(valstr, 0, 64);
60 read(fd, valstr, 64 - 1);
61 valstr[strlen(valstr)] = '\0';
62 close(fd);
63 } else {
64 ALOGE("unable to open file %s\n", path);
65 return -1;
66 }
67 if (sscanf(valstr, "0x%x", &val) < 1) {
68 ALOGE("unable to get pts from: %s", valstr);
69 return -1;
70 }
71 *value = val;
72 return 0;
73}
74
75int sysfs_set_sysfs_str(const char *path, const char *val)
76{
77 int fd;
78 int bytes;
79 fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
80 if (fd >= 0) {
81 bytes = write(fd, val, strlen(val));
82 close(fd);
83 return 0;
84 } else {
85 ALOGE("unable to open file %s,err: %s", path, strerror(errno));
86 }
87 return -1;
88}
89
90int get_sysfs_int (const char *path)
91{
92 int val = 0;
93 int fd = open (path, O_RDONLY);
94 if (fd >= 0)
95 {
96 char bcmd[16];
97 read (fd, bcmd, sizeof (bcmd));
98 val = strtol (bcmd, NULL, 10);
99 close (fd);
100 }
101 else
102 {
103 LOGFUNC ("[%s]open %s node failed! return 0\n", path, __FUNCTION__);
104 }
105 return val;
106}
107int mystrstr(char *mystr,char *substr) {
108 int i=0;
109 int j=0;
110 int score = 0;
111 int substrlen = strlen(substr);
112 int ok = 0;
113 for (i =0;i < 1024 - substrlen;i++) {
114 for (j = 0;j < substrlen;j++) {
115 score += (substr[j] == mystr[i+j])?1:0;
116 }
117 if (score == substrlen) {
118 ok = 1;
119 break;
120 }
121 score = 0;
122 }
123 return ok;
124}
125void set_codec_type(int type)
126{
127 char buf[16];
128 int fd = open ("/sys/class/audiodsp/digital_codec", O_WRONLY);
129
130 if (fd >= 0) {
131 memset(buf, 0, sizeof(buf));
132 snprintf(buf, sizeof(buf), "%d", type);
133
134 write(fd, buf, sizeof(buf));
135 close(fd);
136 }
137}
138unsigned char codec_type_is_raw_data(int type)
139{
140 switch (type) {
141 case TYPE_AC3:
142 case TYPE_EAC3:
143 case TYPE_TRUE_HD:
144 case TYPE_DTS:
145 case TYPE_DTS_HD:
146 case TYPE_DTS_HD_MA:
147 return 1;
148 default:
149 return 0;
150 }
151}
152
153int get_codec_type(int format)
154{
155 switch (format) {
156 case AUDIO_FORMAT_AC3:
157 return TYPE_AC3;
158 case AUDIO_FORMAT_E_AC3:
159 return TYPE_EAC3;
160 case AUDIO_FORMAT_DTS:
161 return TYPE_DTS;
162 case AUDIO_FORMAT_DTS_HD:
163 return TYPE_DTS_HD_MA;
164 case AUDIO_FORMAT_DOLBY_TRUEHD:
165 return TYPE_TRUE_HD;
166 case AUDIO_FORMAT_PCM:
167 return TYPE_PCM;
168 default:
169 return TYPE_PCM;
170 }
171}
172int getprop_bool (const char *path)
173{
174 char buf[PROPERTY_VALUE_MAX];
175 int ret = -1;
176
177 ret = property_get (path, buf, NULL);
178 if (ret > 0)
179 {
180 if (strcasecmp (buf, "true") == 0 || strcmp (buf, "1") == 0)
181 return 1;
182 }
183 return 0;
184}
185
186/*
187convert audio formats to supported audio format
1888 ch goes to 32 bit
1892 ch can be 16 bit or 32 bit
190@return input buffer used by alsa drivers to do the data write
191*/
192void *convert_audio_sample_for_output(int input_frames, int input_format, int input_ch, void *input_buf, int *out_size)
193{
194 float lvol = 1.0;
195 int *out_buf = NULL;
196 short *p16 = (short*)input_buf;
197 int *p32 = (int*)input_buf;
198 int max_ch = input_ch;
199 int i;
200 //ALOGV("intput frame %d,input ch %d,buf ptr %p,vol %f\n", input_frames, input_ch, input_buf, lvol);
201 ALOG_ASSERT(input_buf);
202 if (input_ch > 2)
203 max_ch = 8;
204 //our HW need round the frames to 8 channels
205 out_buf = malloc(sizeof(int) * max_ch * input_frames);
206 if (out_buf == NULL) {
207 ALOGE("malloc buffer failed\n");
208 return NULL;
209 }
210 switch (input_format) {
211 case AUDIO_FORMAT_PCM_16_BIT:
212 break;
213 case AUDIO_FORMAT_PCM_32_BIT:
214 break;
215 case AUDIO_FORMAT_PCM_8_24_BIT:
216 for (i = 0; i < input_frames * input_ch; i++) {
217 p32[i] = p32[i] << 8;
218 }
219 break;
220 case AUDIO_FORMAT_PCM_FLOAT:
221 memcpy_to_i16_from_float(out_buf, input_buf, input_frames * input_ch);
222 memcpy(input_buf, out_buf, sizeof(short)*input_frames * input_ch);
223 break;
224 }
225 //current all the data are in the input buffer
226 if (input_ch == 8) {
227 short *p16_temp;
228 int i, NumSamps;
229 int *p32_temp = out_buf;
230 float m_vol = lvol;
231 NumSamps = input_frames * input_ch;
232 //here to swap the channnl data here
233 //actual now:L,missing,R,RS,RRS,,LS,LRS,missing
234 //expect L,C,R,RS,RRS,LRS,LS,LFE (LFE comes from to center)
235 //actual audio data layout L,R,C,none/LFE,LRS,RRS,LS,RS
236 if (input_format == AUDIO_FORMAT_PCM_16_BIT) {
237 p16_temp = (short*)out_buf;
238 for (i = 0; i < NumSamps; i = i + 8) {
239 p16_temp[0 + i]/*L*/ = m_vol * p16[0 + i];
240 p16_temp[1 + i]/*R*/ = m_vol * p16[1 + i];
241 p16_temp[2 + i] /*LFE*/ = m_vol * p16[3 + i];
242 p16_temp[3 + i] /*C*/ = m_vol * p16[2 + i];
243 p16_temp[4 + i] /*LS*/ = m_vol * p16[6 + i];
244 p16_temp[5 + i] /*RS*/ = m_vol * p16[7 + i];
245 p16_temp[6 + i] /*LRS*/ = m_vol * p16[4 + i];
246 p16_temp[7 + i]/*RRS*/ = m_vol * p16[5 + i];
247 }
248 memcpy(p16, p16_temp, NumSamps * sizeof(short));
249 for (i = 0; i < NumSamps; i++) { //suppose 16bit/8ch PCM
250 p32_temp[i] = p16[i] << 16;
251 }
252 } else {
253 p32_temp = out_buf;
254 for (i = 0; i < NumSamps; i = i + 8) {
255 p32_temp[0 + i]/*L*/ = m_vol * p32[0 + i];
256 p32_temp[1 + i]/*R*/ = m_vol * p32[1 + i];
257 p32_temp[2 + i] /*LFE*/ = m_vol * p32[3 + i];
258 p32_temp[3 + i] /*C*/ = m_vol * p32[2 + i];
259 p32_temp[4 + i] /*LS*/ = m_vol * p32[6 + i];
260 p32_temp[5 + i] /*RS*/ = m_vol * p32[7 + i];
261 p32_temp[6 + i] /*LRS*/ = m_vol * p32[4 + i];
262 p32_temp[7 + i]/*RRS*/ = m_vol * p32[5 + i];
263 }
264
265 }
266 *out_size = NumSamps * sizeof(int);
267
268 } else if (input_ch == 6) {
269 int j, NumSamps, real_samples;
270 short *p16_temp;
271 int *p32_temp = out_buf;
272 float m_vol = lvol;
273 NumSamps = input_frames * input_ch;
274 real_samples = NumSamps;
275 NumSamps = real_samples * 8 / 6;
276 //ALOGI("6ch to 8 ch real %d, to %d\n",real_samples,NumSamps);
277 if (input_format == AUDIO_FORMAT_PCM_16_BIT) {
278 p16_temp = (short*)out_buf;
279 for (i = 0; i < real_samples; i = i + 6) {
280 p16_temp[0 + i]/*L*/ = m_vol * p16[0 + i];
281 p16_temp[1 + i]/*R*/ = m_vol * p16[1 + i];
282 p16_temp[2 + i] /*LFE*/ = m_vol * p16[3 + i];
283 p16_temp[3 + i] /*C*/ = m_vol * p16[2 + i];
284 p16_temp[4 + i] /*LS*/ = m_vol * p16[4 + i];
285 p16_temp[5 + i] /*RS*/ = m_vol * p16[5 + i];
286 }
287 memcpy(p16, p16_temp, real_samples * sizeof(short));
288 memset(p32_temp, 0, NumSamps * sizeof(int));
289 for (i = 0, j = 0; j < NumSamps; i = i + 6, j = j + 8) { //suppose 16bit/8ch PCM
290 p32_temp[j + 0] = p16[i] << 16;
291 p32_temp[j + 1] = p16[i + 1] << 16;
292 p32_temp[j + 2] = p16[i + 2] << 16;
293 p32_temp[j + 3] = p16[i + 3] << 16;
294 p32_temp[j + 4] = p16[i + 4] << 16;
295 p32_temp[j + 5] = p16[i + 5] << 16;
296 }
297 } else {
298 p32_temp = out_buf;
299 memset(p32_temp, 0, NumSamps * sizeof(int));
300 for (i = 0, j = 0; j < NumSamps; i = i + 6, j = j + 8) { //suppose 16bit/8ch PCM
301 p32_temp[j + 0] = m_vol * p32[i + 0];
302 p32_temp[j + 1] = m_vol * p32[i + 1] ;
303 p32_temp[j + 2] = m_vol * p32[i + 2] ;
304 p32_temp[j + 3] = m_vol * p32[i + 3] ;
305 p32_temp[j + 4] = m_vol * p32[i + 4] ;
306 p32_temp[j + 5] = m_vol * p32[i + 5] ;
307 }
308 }
309 *out_size = NumSamps * sizeof(int);
310 } else {
311 //2ch with 24 bit/32/float audio
312 int *p32_temp = out_buf;
313 short *p16_temp = (short*)out_buf;
314 for (i = 0; i < input_frames; i++) {
315 p16_temp[2 * i + 0] = lvol * p16[2 * i + 0];
316 p16_temp[2 * i + 1] = lvol * p16[2 * i + 1];
317 }
318 *out_size = sizeof(short) * input_frames * input_ch;
319 }
320 return out_buf;
321
322}
323
324