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 |
23 | int 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 | |
47 | int |
48 | get_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'; |
79 | OUT: |
80 | free(read_buf); |
81 | close(fd); |
82 | return card; |
83 | } |
84 | |
85 | int |
86 | get_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'; |
116 | OUT: |
117 | free(read_buf); |
118 | close(fd); |
119 | return port; |
120 | } |
121 | |
122 | |
123 | /* |
124 | CodingType MaxChannels SamplingFreq SampleSize |
125 | PCM, 2 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16/20/24 bit |
126 | PCM, 8 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16/20/24 bit |
127 | AC-3, 8 ch, 32/44.1/48 kHz, bit |
128 | DTS, 8 ch, 44.1/48 kHz, bit |
129 | OneBitAudio, 2 ch, 44.1 kHz, bit |
130 | Dobly_Digital+, 8 ch, 44.1/48 kHz, 16 bit |
131 | DTS-HD, 8 ch, 44.1/48/88.2/96/176.4/192 kHz, 16 bit |
132 | MAT, 8 ch, 32/44.1/48/88.2/96/176.4/192 kHz, 16 bit |
133 | */ |
134 | char* 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; |
209 | fail: |
210 | if (aud_cap) { |
211 | free(aud_cap); |
212 | } |
213 | if (infobuf) { |
214 | free(infobuf); |
215 | } |
216 | return NULL; |
217 | } |
218 | char* 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; |
303 | fail: |
304 | if (aud_cap) { |
305 | free(aud_cap); |
306 | } |
307 | return NULL; |
308 | } |
309 | |
310 |