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