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