summaryrefslogtreecommitdiff
path: root/audio_hw_profile.c (plain)
blob: 81bb83fecf9e9cc2eb5d1689743d86701dc5c50c
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_profile"
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <sys/time.h>
24#include <stdlib.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <math.h>
28#include <cutils/log.h>
29#include <cutils/str_parms.h>
30#include <cutils/properties.h>
31#include <hardware/hardware.h>
32#include <system/audio.h>
33#include <hardware/audio.h>
34
35#include "audio_hw_utils.h"
36
37/*
38 type : 0 -> playback, 1 -> capture
39*/
40#define MAX_CARD_NUM 2
41int get_external_card(int type)
42{
43 int card_num = 1; // start num, 0 is defualt sound card.
44 struct stat card_stat;
45 char fpath[256];
46 int ret;
47 while (card_num <= MAX_CARD_NUM) {
48 snprintf(fpath, sizeof(fpath), "/proc/asound/card%d", card_num);
49 ret = stat(fpath, &card_stat);
50 if (ret < 0) {
51 ret = -1;
52 } else {
53 snprintf(fpath, sizeof(fpath), "/dev/snd/pcmC%uD0%c", card_num,
54 type ? 'c' : 'p');
55 ret = stat(fpath, &card_stat);
56 if (ret == 0) {
57 return card_num;
58 }
59 }
60 card_num++;
61 }
62 return ret;
63}
64
65int
66get_aml_card()
67{
68 int card = -1, err = 0;
69 int fd = -1;
70 unsigned fileSize = 512;
71 char *read_buf = NULL, *pd = NULL;
72 static const char *const SOUND_CARDS_PATH = "/proc/asound/cards";
73 fd = open(SOUND_CARDS_PATH, O_RDONLY);
74 if (fd < 0) {
75 ALOGE("ERROR: failed to open config file %s error: %d\n",
76 SOUND_CARDS_PATH, errno);
77 close(fd);
78 return -EINVAL;
79 }
80
81 read_buf = (char *) malloc(fileSize);
82 if (!read_buf) {
83 ALOGE("Failed to malloc read_buf");
84 close(fd);
85 return -ENOMEM;
86 }
87 memset(read_buf, 0x0, fileSize);
88 err = read(fd, read_buf, fileSize);
89 if (fd < 0) {
90 ALOGE("ERROR: failed to read config file %s error: %d\n",
91 SOUND_CARDS_PATH, errno);
92 close(fd);
93 return -EINVAL;
94 }
95 pd = strstr(read_buf, "AML");
96 card = *(pd - 3) - '0';
97OUT:
98 free(read_buf);
99 close(fd);
100 return card;
101}
102
103int
104get_spdif_port()
105{
106 int port = -1, err = 0;
107 int fd = -1;
108 unsigned fileSize = 512;
109 char *read_buf = NULL, *pd = NULL;
110 static const char *const SOUND_PCM_PATH = "/proc/asound/pcm";
111 fd = open(SOUND_PCM_PATH, O_RDONLY);
112 if (fd < 0) {
113 ALOGE("ERROR: failed to open config file %s error: %d\n",
114 SOUND_PCM_PATH, errno);
115 close(fd);
116 return -EINVAL;
117 }
118 read_buf = (char *) malloc(fileSize);
119 if (!read_buf) {
120 ALOGE("Failed to malloc read_buf");
121 close(fd);
122 return -ENOMEM;
123 }
124 memset(read_buf, 0x0, fileSize);
125 err = read(fd, read_buf, fileSize);
126 if (fd < 0) {
127 ALOGE("ERROR: failed to read config file %s error: %d\n",
128 SOUND_PCM_PATH, errno);
129 close(fd);
130 return -EINVAL;
131 }
132 pd = strstr(read_buf, "SPDIF");
133 port = *(pd - 3) - '0';
134OUT:
135 free(read_buf);
136 close(fd);
137 return port;
138}
139
140
141/*
142CodingType MaxChannels SamplingFreq SampleSize
143PCM, 2 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16/20/24 bit
144PCM, 8 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16/20/24 bit
145AC-3, 8 ch, 32/44.1/48 kHz, bit
146DTS, 8 ch, 44.1/48 kHz, bit
147OneBitAudio, 2 ch, 44.1 kHz, bit
148Dobly_Digital+, 8 ch, 44.1/48 kHz, 16 bit
149DTS-HD, 8 ch, 44.1/48/88.2/96/176.4/192 kHz, 16 bit
150MAT, 8 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16 bit
151*/
152char* get_hdmi_sink_cap(const char *keys,audio_format_t format)
153{
154 int i = 0;
155 char * infobuf = NULL;
156 int channel = 0;
157 int dgraw = 0;
158 int fd = -1;
159 int size = 0;
160 char *aud_cap = NULL;
161 infobuf = (char *)malloc(1024 * sizeof(char));
162 if (infobuf == NULL) {
163 ALOGE("malloc buffer failed\n");
164 goto fail;
165 }
166 aud_cap = (char*)malloc(1024);
167 if (aud_cap == NULL) {
168 ALOGE("malloc buffer failed\n");
169 goto fail;
170 }
171 memset(aud_cap, 0, 1024);
172 memset(infobuf, 0, 1024);
173 fd = open("/sys/class/amhdmitx/amhdmitx0/aud_cap", O_RDONLY);
174 if (fd >= 0) {
175 int nread = read(fd, infobuf, 1024);
176 /* check the format cap */
177 if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
178 size += sprintf(aud_cap, "sup_formats=%s", "AUDIO_FORMAT_PCM_16_BIT");
179 if (mystrstr(infobuf, "Dobly_Digital+")) {
180 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_E_AC3");
181 }
182 if (mystrstr(infobuf, "AC-3")) {
183 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_AC3");
184 }
185 if (mystrstr(infobuf, "DTS-HD")) {
186 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD");
187 } else if (mystrstr(infobuf, "DTS")) {
188 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS");
189 }
190 if (mystrstr(infobuf, "MAT")) {
191 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_TRUEHD");
192 }
193 }
194 /*check the channel cap */
195 else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
196 /* take the 2ch suppported as default */
197 size += sprintf(aud_cap, "sup_channels=%s", "AUDIO_CHANNEL_OUT_STEREO");
198 if (mystrstr(infobuf, "PCM, 8 ch")) {
199 size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1");
200 } else if (mystrstr(infobuf, "PCM, 6 ch")) {
201 size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1");
202 }
203 } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
204 /* take the 32/44.1/48 khz suppported as default */
205 size += sprintf(aud_cap, "sup_sampling_rates=%s", "32000|44100|48000");
206 if (mystrstr(infobuf, "88.2")) {
207 size += sprintf(aud_cap + size, "|%s", "88200");
208 }
209 if (mystrstr(infobuf, "96")) {
210 size += sprintf(aud_cap + size, "|%s", "96000");
211 }
212 if (mystrstr(infobuf, "176.4")) {
213 size += sprintf(aud_cap + size, "|%s", "176400");
214 }
215 if (mystrstr(infobuf, "192") || (mystrstr(infobuf, "Dobly_Digital+") &&
216 format == AUDIO_FORMAT_IEC61937)) {
217 size += sprintf(aud_cap + size, "|%s", "192000");
218 }
219 }
220 }
221 if (infobuf) {
222 free(infobuf);
223 }
224 if (fd >= 0) {
225 close(fd);
226 }
227 return aud_cap;
228fail:
229 if (aud_cap) {
230 free(aud_cap);
231 }
232 if (infobuf) {
233 free(infobuf);
234 }
235 return NULL;
236}
237char* get_hdmi_arc_cap(unsigned *ad, int maxsize, const char *keys)
238{
239 int i = 0;
240 int channel = 0;
241 int dgraw = 0;
242 int fd = -1;
243 int size = 0;
244 int raw_support = 0;
245 int iec_added = 0;
246 char *aud_cap = NULL;
247 unsigned char format, ch, sr;
248 aud_cap = (char*)malloc(1024);
249 if (aud_cap == NULL) {
250 ALOGE("malloc buffer failed\n");
251 goto fail;
252 }
253 memset(aud_cap, 0, 1024);
254 ALOGI("get_hdmi_arc_cap\n");
255 /* check the format cap */
256 if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
257 size += sprintf(aud_cap, "sup_formats=%s", "AUDIO_FORMAT_PCM_16_BIT");
258 }
259 /*check the channel cap */
260 else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
261 //ALOGI("check channels\n");
262 /* take the 2ch suppported as default */
263 size += sprintf(aud_cap, "sup_channels=%s", "AUDIO_CHANNEL_OUT_STEREO");
264 } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
265 /* take the 32/44.1/48 khz suppported as default */
266 size += sprintf(aud_cap, "sup_sampling_rates=%s", "32000|44100|48000");
267 //ALOGI("check sample rate\n");
268 }
269 for (i = 0; i < maxsize; i++) {
270 if (ad[i] != 0) {
271 format = (ad[i] >> 19) & 0xf;
272 ch = (ad[i] >> 16) & 0x7;
273 sr = (ad[i] > 8) & 0xf;
274 ALOGI("ad %x,format %d,ch %d,sr %d\n", ad[i], format, ch, sr);
275 /* check the format cap */
276 if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
277 //ALOGI("check format\n");
278 if (format == 10) {
279 raw_support = 1;
280 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_E_AC3");
281 }
282 else if (format == 2) {
283 raw_support = 1;
284 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_AC3");
285 }
286 else if (format == 11) {
287 raw_support = 1;
288 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTSHD");
289 } else if (format == 7) {
290 raw_support = 1;
291 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_DTS");
292 }
293 else if (format == 12) {
294 raw_support = 1;
295 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_TRUEHD");
296 }
297 if (raw_support == 1 && iec_added == 0) {
298 size += sprintf(aud_cap + size, "|%s", "AUDIO_FORMAT_IEC61937");
299 }
300 }
301 /*check the channel cap */
302 else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
303 //ALOGI("check channels\n");
304 if (/*format == 1 && */ch == 7) {
305 size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1");
306 } else if (/*format == 1 && */ch == 5) {
307 size += sprintf(aud_cap + size, "|%s", "AUDIO_CHANNEL_OUT_5POINT1");
308 }
309 } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
310 ALOGI("check sample rate\n");
311 if (format == 1 && sr == 4) {
312 size += sprintf(aud_cap + size, "|%s", "88200");
313 }
314 if (format == 1 && sr == 5) {
315 size += sprintf(aud_cap + size, "|%s", "96000");
316 }
317 if (format == 1 && sr == 6) {
318 size += sprintf(aud_cap + size, "|%s", "176400");
319 }
320 if (format == 1 && sr == 7) {
321 size += sprintf(aud_cap + size, "|%s", "192000");
322 }
323 }
324
325 } else {
326 format = 0;
327 ch = 0;
328 sr = 0;
329 }
330 }
331 return aud_cap;
332fail:
333 if (aud_cap) {
334 free(aud_cap);
335 }
336 return NULL;
337}
338
339