1 /*
2 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #define LOG_TAG "audio_hw_extn"
21 /*#define LOG_NDEBUG 0*/
22 #define LOG_NDDEBUG 0
23
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <dlfcn.h>
27 #include <cutils/properties.h>
28 #include <cutils/log.h>
29
30 #include "audio_hw.h"
31 #include "audio_extn.h"
32 #include "platform.h"
33 #include "platform_api.h"
34
35 #include "sound/compress_params.h"
36
37 #define MAX_SLEEP_RETRY 100
38 #define WIFI_INIT_WAIT_SLEEP 50
39
40 struct audio_extn_module {
41 bool anc_enabled;
42 bool aanc_enabled;
43 bool custom_stereo_enabled;
44 uint32_t proxy_channel_num;
45 };
46
47 static struct audio_extn_module aextnmod = {
48 .anc_enabled = 0,
49 .aanc_enabled = 0,
50 .custom_stereo_enabled = 0,
51 .proxy_channel_num = 2,
52 };
53
54 #define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
55 #define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap"
56 #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy"
57 #define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono"
58 /* Query offload playback instances count */
59 #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
60 #define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE "asphere_enable"
61 #define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
62
63 #ifndef FM_POWER_OPT
64 #define audio_extn_fm_set_parameters(adev, parms) (0)
65 #else
66 void audio_extn_fm_set_parameters(struct audio_device *adev,
67 struct str_parms *parms);
68 #endif
69 #ifndef HFP_ENABLED
70 #define audio_extn_hfp_set_parameters(adev, parms) (0)
71 #else
72 void audio_extn_hfp_set_parameters(struct audio_device *adev,
73 struct str_parms *parms);
74 #endif
75
76 #ifndef SOURCE_TRACKING_ENABLED
77 #define audio_extn_source_track_set_parameters(adev, parms) (0)
78 #define audio_extn_source_track_get_parameters(adev, query, reply) (0)
79 #else
80 void audio_extn_source_track_set_parameters(struct audio_device *adev,
81 struct str_parms *parms);
82 void audio_extn_source_track_get_parameters(struct audio_device *adev,
83 struct str_parms *query,
84 struct str_parms *reply);
85 #endif
86
87 #ifndef CUSTOM_STEREO_ENABLED
88 #define audio_extn_customstereo_set_parameters(adev, parms) (0)
89 #else
audio_extn_customstereo_set_parameters(struct audio_device * adev,struct str_parms * parms)90 void audio_extn_customstereo_set_parameters(struct audio_device *adev,
91 struct str_parms *parms)
92 {
93 int ret = 0;
94 char value[32]={0};
95 bool custom_stereo_state = false;
96 const char *mixer_ctl_name = "Set Custom Stereo OnOff";
97 struct mixer_ctl *ctl;
98
99 ALOGV("%s", __func__);
100 ret = str_parms_get_str(parms, AUDIO_PARAMETER_CUSTOM_STEREO, value,
101 sizeof(value));
102 if (ret >= 0) {
103 if (!strncmp("true", value, sizeof("true")) || atoi(value))
104 custom_stereo_state = true;
105
106 if (custom_stereo_state == aextnmod.custom_stereo_enabled)
107 return;
108
109 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
110 if (!ctl) {
111 ALOGE("%s: Could not get ctl for mixer cmd - %s",
112 __func__, mixer_ctl_name);
113 return;
114 }
115 if (mixer_ctl_set_value(ctl, 0, custom_stereo_state) < 0) {
116 ALOGE("%s: Could not set custom stereo state %d",
117 __func__, custom_stereo_state);
118 return;
119 }
120 aextnmod.custom_stereo_enabled = custom_stereo_state;
121 ALOGV("%s: Setting custom stereo state success", __func__);
122 }
123 }
124 #endif /* CUSTOM_STEREO_ENABLED */
125
126 #ifndef ANC_HEADSET_ENABLED
127 #define audio_extn_set_anc_parameters(adev, parms) (0)
128 #else
audio_extn_get_anc_enabled(void)129 bool audio_extn_get_anc_enabled(void)
130 {
131 ALOGD("%s: anc_enabled:%d", __func__, aextnmod.anc_enabled);
132 return (aextnmod.anc_enabled ? true: false);
133 }
134
audio_extn_should_use_handset_anc(int in_channels)135 bool audio_extn_should_use_handset_anc(int in_channels)
136 {
137 char prop_aanc[PROPERTY_VALUE_MAX] = "false";
138
139 property_get("persist.aanc.enable", prop_aanc, "0");
140 if (!strncmp("true", prop_aanc, 4)) {
141 ALOGD("%s: AANC enabled in the property", __func__);
142 aextnmod.aanc_enabled = 1;
143 }
144
145 return (aextnmod.aanc_enabled && aextnmod.anc_enabled
146 && (in_channels == 1));
147 }
148
audio_extn_should_use_fb_anc(void)149 bool audio_extn_should_use_fb_anc(void)
150 {
151 char prop_anc[PROPERTY_VALUE_MAX] = "feedforward";
152
153 property_get("persist.headset.anc.type", prop_anc, "0");
154 if (!strncmp("feedback", prop_anc, sizeof("feedback"))) {
155 ALOGD("%s: FB ANC headset type enabled\n", __func__);
156 return true;
157 }
158 return false;
159 }
160
audio_extn_set_anc_parameters(struct audio_device * adev,struct str_parms * parms)161 void audio_extn_set_anc_parameters(struct audio_device *adev,
162 struct str_parms *parms)
163 {
164 int ret;
165 char value[32] ={0};
166 struct listnode *node;
167 struct audio_usecase *usecase;
168
169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_ANC, value,
170 sizeof(value));
171 if (ret >= 0) {
172 if (strcmp(value, "true") == 0)
173 aextnmod.anc_enabled = true;
174 else
175 aextnmod.anc_enabled = false;
176
177 list_for_each(node, &adev->usecase_list) {
178 usecase = node_to_item(node, struct audio_usecase, list);
179 if (usecase->type == PCM_PLAYBACK) {
180 if (usecase->stream.out->devices == \
181 AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
182 usecase->stream.out->devices == \
183 AUDIO_DEVICE_OUT_WIRED_HEADSET) {
184 select_devices(adev, usecase->id);
185 ALOGV("%s: switching device", __func__);
186 break;
187 }
188 }
189 }
190 }
191
192 ALOGD("%s: anc_enabled:%d", __func__, aextnmod.anc_enabled);
193 }
194 #endif /* ANC_HEADSET_ENABLED */
195
196 #ifndef FLUENCE_ENABLED
197 #define audio_extn_set_fluence_parameters(adev, parms) (0)
198 #define audio_extn_get_fluence_parameters(adev, query, reply) (0)
199 #else
audio_extn_set_fluence_parameters(struct audio_device * adev,struct str_parms * parms)200 void audio_extn_set_fluence_parameters(struct audio_device *adev,
201 struct str_parms *parms)
202 {
203 int ret = 0, err;
204 char value[32];
205 struct listnode *node;
206 struct audio_usecase *usecase;
207
208 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FLUENCE,
209 value, sizeof(value));
210 ALOGV_IF(err >= 0, "%s: Set Fluence Type to %s", __func__, value);
211 if (err >= 0) {
212 ret = platform_set_fluence_type(adev->platform, value);
213 if (ret != 0) {
214 ALOGE("platform_set_fluence_type returned error: %d", ret);
215 } else {
216 /*
217 *If the fluence is manually set/reset, devices
218 *need to get updated for all the usecases
219 *i.e. audio and voice.
220 */
221 list_for_each(node, &adev->usecase_list) {
222 usecase = node_to_item(node, struct audio_usecase, list);
223 select_devices(adev, usecase->id);
224 }
225 }
226 }
227 }
228
audio_extn_get_fluence_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)229 int audio_extn_get_fluence_parameters(const struct audio_device *adev,
230 struct str_parms *query, struct str_parms *reply)
231 {
232 int ret = 0, err;
233 char value[256] = {0};
234
235 err = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE, value,
236 sizeof(value));
237 if (err >= 0) {
238 ret = platform_get_fluence_type(adev->platform, value, sizeof(value));
239 if (ret >= 0) {
240 ALOGV("%s: Fluence Type is %s", __func__, value);
241 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE, value);
242 } else
243 goto done;
244 }
245 done:
246 return ret;
247 }
248 #endif /* FLUENCE_ENABLED */
249
250 #ifndef AFE_PROXY_ENABLED
251 #define audio_extn_set_afe_proxy_parameters(adev, parms) (0)
252 #define audio_extn_get_afe_proxy_parameters(query, reply) (0)
253 #else
254 /* Front left channel. */
255 #define PCM_CHANNEL_FL 1
256
257 /* Front right channel. */
258 #define PCM_CHANNEL_FR 2
259
260 /* Front center channel. */
261 #define PCM_CHANNEL_FC 3
262
263 /* Left surround channel.*/
264 #define PCM_CHANNEL_LS 4
265
266 /* Right surround channel.*/
267 #define PCM_CHANNEL_RS 5
268
269 /* Low frequency effect channel. */
270 #define PCM_CHANNEL_LFE 6
271
272 /* Left back channel; Rear left channel. */
273 #define PCM_CHANNEL_LB 8
274
275 /* Right back channel; Rear right channel. */
276 #define PCM_CHANNEL_RB 9
277
afe_proxy_set_channel_mapping(struct audio_device * adev,int channel_count)278 static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
279 int channel_count)
280 {
281 struct mixer_ctl *ctl;
282 const char *mixer_ctl_name = "Playback Channel Map";
283 int set_values[8] = {0};
284 int ret;
285 ALOGV("%s channel_count:%d",__func__, channel_count);
286
287 switch (channel_count) {
288 case 2:
289 set_values[0] = PCM_CHANNEL_FL;
290 set_values[1] = PCM_CHANNEL_FR;
291 break;
292 case 6:
293 set_values[0] = PCM_CHANNEL_FL;
294 set_values[1] = PCM_CHANNEL_FR;
295 set_values[2] = PCM_CHANNEL_FC;
296 set_values[3] = PCM_CHANNEL_LFE;
297 set_values[4] = PCM_CHANNEL_LS;
298 set_values[5] = PCM_CHANNEL_RS;
299 break;
300 case 8:
301 set_values[0] = PCM_CHANNEL_FL;
302 set_values[1] = PCM_CHANNEL_FR;
303 set_values[2] = PCM_CHANNEL_FC;
304 set_values[3] = PCM_CHANNEL_LFE;
305 set_values[4] = PCM_CHANNEL_LS;
306 set_values[5] = PCM_CHANNEL_RS;
307 set_values[6] = PCM_CHANNEL_LB;
308 set_values[7] = PCM_CHANNEL_RB;
309 break;
310 default:
311 ALOGE("unsupported channels(%d) for setting channel map",
312 channel_count);
313 return -EINVAL;
314 }
315
316 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
317 if (!ctl) {
318 ALOGE("%s: Could not get ctl for mixer cmd - %s",
319 __func__, mixer_ctl_name);
320 return -EINVAL;
321 }
322 ALOGV("AFE: set mapping(%d %d %d %d %d %d %d %d) for channel:%d",
323 set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
324 set_values[5], set_values[6], set_values[7], channel_count);
325 ret = mixer_ctl_set_array(ctl, set_values, channel_count);
326 return ret;
327 }
328
audio_extn_set_afe_proxy_channel_mixer(struct audio_device * adev,int channel_count)329 int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev,
330 int channel_count)
331 {
332 int32_t ret = 0;
333 const char *channel_cnt_str = NULL;
334 struct mixer_ctl *ctl = NULL;
335 const char *mixer_ctl_name = "PROXY_RX Channels";
336
337 ALOGD("%s: entry", __func__);
338 /* use the existing channel count set by hardware params to
339 configure the back end for stereo as usb/a2dp would be
340 stereo by default */
341 ALOGD("%s: channels = %d", __func__, channel_count);
342 switch (channel_count) {
343 case 8: channel_cnt_str = "Eight"; break;
344 case 7: channel_cnt_str = "Seven"; break;
345 case 6: channel_cnt_str = "Six"; break;
346 case 5: channel_cnt_str = "Five"; break;
347 case 4: channel_cnt_str = "Four"; break;
348 case 3: channel_cnt_str = "Three"; break;
349 default: channel_cnt_str = "Two"; break;
350 }
351
352 if(channel_count >= 2 && channel_count <= 8) {
353 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
354 if (!ctl) {
355 ALOGE("%s: could not get ctl for mixer cmd - %s",
356 __func__, mixer_ctl_name);
357 return -EINVAL;
358 }
359 }
360 mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
361
362 if (channel_count == 6 || channel_count == 8 || channel_count == 2) {
363 ret = afe_proxy_set_channel_mapping(adev, channel_count);
364 } else {
365 ALOGE("%s: set unsupported channel count(%d)", __func__, channel_count);
366 ret = -EINVAL;
367 }
368
369 ALOGD("%s: exit", __func__);
370 return ret;
371 }
372
audio_extn_set_afe_proxy_parameters(struct audio_device * adev,struct str_parms * parms)373 void audio_extn_set_afe_proxy_parameters(struct audio_device *adev,
374 struct str_parms *parms)
375 {
376 int ret, val;
377 char value[32]={0};
378
379 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_WFD, value,
380 sizeof(value));
381 if (ret >= 0) {
382 val = atoi(value);
383 aextnmod.proxy_channel_num = val;
384 adev->cur_wfd_channels = val;
385 ALOGD("%s: channel capability set to: %d", __func__,
386 aextnmod.proxy_channel_num);
387 }
388 }
389
audio_extn_get_afe_proxy_parameters(struct str_parms * query,struct str_parms * reply)390 int audio_extn_get_afe_proxy_parameters(struct str_parms *query,
391 struct str_parms *reply)
392 {
393 int ret, val;
394 char value[32]={0};
395 char *str = NULL;
396
397 ret = str_parms_get_str(query, AUDIO_PARAMETER_CAN_OPEN_PROXY, value,
398 sizeof(value));
399 if (ret >= 0) {
400 if (audio_extn_usb_is_proxy_inuse())
401 val = 0;
402 else
403 val = 1;
404 str_parms_add_int(reply, AUDIO_PARAMETER_CAN_OPEN_PROXY, val);
405 }
406
407 return 0;
408 }
409
410 /* must be called with hw device mutex locked */
audio_extn_read_afe_proxy_channel_masks(struct stream_out * out)411 int32_t audio_extn_read_afe_proxy_channel_masks(struct stream_out *out)
412 {
413 int ret = 0;
414 int channels = aextnmod.proxy_channel_num;
415
416 switch (channels) {
417 /*
418 * Do not handle stereo output in Multi-channel cases
419 * Stereo case is handled in normal playback path
420 */
421 case 6:
422 ALOGV("%s: AFE PROXY supports 5.1", __func__);
423 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
424 break;
425 case 8:
426 ALOGV("%s: AFE PROXY supports 5.1 and 7.1 channels", __func__);
427 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
428 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
429 break;
430 default:
431 ALOGE("AFE PROXY does not support multi channel playback");
432 ret = -ENOSYS;
433 break;
434 }
435 return ret;
436 }
437
audio_extn_get_afe_proxy_channel_count()438 int32_t audio_extn_get_afe_proxy_channel_count()
439 {
440 return aextnmod.proxy_channel_num;
441 }
442
443 #endif /* AFE_PROXY_ENABLED */
444
get_active_offload_usecases(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)445 static int get_active_offload_usecases(const struct audio_device *adev,
446 struct str_parms *query,
447 struct str_parms *reply)
448 {
449 int ret, count = 0;
450 char value[32]={0};
451 struct listnode *node;
452 struct audio_usecase *usecase;
453
454 ALOGV("%s", __func__);
455 ret = str_parms_get_str(query, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, value,
456 sizeof(value));
457 if (ret >= 0) {
458 list_for_each(node, &adev->usecase_list) {
459 usecase = node_to_item(node, struct audio_usecase, list);
460 if (is_offload_usecase(usecase->id))
461 count++;
462 }
463 ALOGV("%s, number of active offload usecases: %d", __func__, count);
464 str_parms_add_int(reply, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, count);
465 }
466 return ret;
467 }
468
469 #ifndef AUDIOSPHERE_ENABLED
470 #define audio_extn_asphere_set_parameters(adev, parms) (0)
471 #define audio_extn_asphere_get_parameters(adev, query, reply) (0)
472 #else
audio_extn_asphere_set_parameters(const struct audio_device * adev,struct str_parms * parms)473 int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
474 struct str_parms *parms)
475 {
476 int ret = 0, val[2];
477 char value[32] = {0};
478 int set_enable, set_strength;
479 int enable = -1, strength = -1;
480 struct mixer_ctl *ctl = NULL;
481 const char *mixer_ctl_name = "MSM ASphere Set Param";
482 char propValue[PROPERTY_VALUE_MAX] = {0};
483 bool asphere_prop_enabled = false;
484
485 if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
486 if (!strncmp("true", propValue, 4))
487 asphere_prop_enabled = true;
488 }
489
490 if (!asphere_prop_enabled) {
491 ALOGV("%s: property not set!!! not doing anything", __func__);
492 return ret;
493 }
494
495 set_enable = str_parms_get_str(parms,
496 AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
497 value, sizeof(value));
498 if (set_enable > 0)
499 enable = atoi(value);
500
501 set_strength = str_parms_get_str(parms,
502 AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
503 value, sizeof(value));
504 if (set_strength > 0)
505 strength = atoi(value);
506
507 if (set_enable >= 0 || set_strength >= 0) {
508 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
509 if (!ctl) {
510 ALOGE("%s: could not get ctl for mixer cmd - %s",
511 __func__, mixer_ctl_name);
512 return -EINVAL;
513 }
514 ALOGD("%s: set ctl \"%s:%d,%d\"",
515 __func__, mixer_ctl_name, enable, strength);
516 val[0] = enable;
517 val[1] = strength;
518 ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
519 if (ret)
520 ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
521 __func__, mixer_ctl_name, enable, strength);
522 }
523 ALOGV("%s: exit ret %d", __func__, ret);
524 return ret;
525 }
526
audio_extn_asphere_get_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)527 int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
528 struct str_parms *query,
529 struct str_parms *reply)
530 {
531 int ret = 0, val[2] = {-1, -1};
532 char value[32] = {0};
533 int get_enable, get_strength;
534 struct mixer_ctl *ctl = NULL;
535 const char *mixer_ctl_name = "MSM ASphere Set Param";
536
537 get_enable = str_parms_get_str(query,
538 AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
539 value, sizeof(value));
540 get_strength = str_parms_get_str(query,
541 AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
542 value, sizeof(value));
543 if (get_enable > 0 || get_strength > 0) {
544 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
545 if (!ctl) {
546 ALOGE("%s: could not get ctl for mixer cmd - %s",
547 __func__, mixer_ctl_name);
548 return -EINVAL;
549 }
550 ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
551 if (ret)
552 ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
553 __func__, mixer_ctl_name, val[0], val[1]);
554 if (get_enable > 0)
555 str_parms_add_int(reply,
556 AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
557 if (get_strength > 0)
558 str_parms_add_int(reply,
559 AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
560 }
561 ALOGV("%s: exit ret %d", __func__, ret);
562 return ret;
563 }
564 #endif
565
audio_extn_set_parameters(struct audio_device * adev,struct str_parms * parms)566 void audio_extn_set_parameters(struct audio_device *adev,
567 struct str_parms *parms)
568 {
569 audio_extn_set_anc_parameters(adev, parms);
570 audio_extn_set_fluence_parameters(adev, parms);
571 audio_extn_set_afe_proxy_parameters(adev, parms);
572 audio_extn_fm_set_parameters(adev, parms);
573 audio_extn_sound_trigger_set_parameters(adev, parms);
574 audio_extn_listen_set_parameters(adev, parms);
575 audio_extn_hfp_set_parameters(adev, parms);
576 audio_extn_a2dp_set_parameters(parms);
577 audio_extn_ddp_set_parameters(adev, parms);
578 audio_extn_ds2_set_parameters(adev, parms);
579 audio_extn_customstereo_set_parameters(adev, parms);
580 audio_extn_pm_set_parameters(parms);
581 audio_extn_source_track_set_parameters(adev, parms);
582 audio_extn_asphere_set_parameters(adev, parms);
583 }
584
audio_extn_get_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)585 void audio_extn_get_parameters(const struct audio_device *adev,
586 struct str_parms *query,
587 struct str_parms *reply)
588 {
589 char *kv_pairs = NULL;
590 audio_extn_get_afe_proxy_parameters(query, reply);
591 audio_extn_get_fluence_parameters(adev, query, reply);
592 get_active_offload_usecases(adev, query, reply);
593 audio_extn_source_track_get_parameters(adev, query, reply);
594 audio_extn_asphere_get_parameters(adev, query, reply);
595 kv_pairs = str_parms_to_str(reply);
596 ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
597 free(kv_pairs);
598 }
599
600 #ifndef COMPRESS_METADATA_NEEDED
601 #define audio_extn_parse_compress_metadata(out, parms) (0)
602 #else
audio_extn_parse_compress_metadata(struct stream_out * out,struct str_parms * parms)603 int audio_extn_parse_compress_metadata(struct stream_out *out,
604 struct str_parms *parms)
605 {
606 int ret = 0;
607 char value[32];
608
609 if (out->format == AUDIO_FORMAT_FLAC) {
610 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
611 if (ret >= 0) {
612 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
613 out->send_new_metadata = 1;
614 }
615 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
616 if (ret >= 0) {
617 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
618 out->send_new_metadata = 1;
619 }
620 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
621 if (ret >= 0) {
622 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
623 out->send_new_metadata = 1;
624 }
625 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
626 if (ret >= 0) {
627 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
628 out->send_new_metadata = 1;
629 }
630 ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
631 out->compr_config.codec->options.flac_dec.min_blk_size,
632 out->compr_config.codec->options.flac_dec.max_blk_size,
633 out->compr_config.codec->options.flac_dec.min_frame_size,
634 out->compr_config.codec->options.flac_dec.max_frame_size);
635 }
636
637 else if (out->format == AUDIO_FORMAT_ALAC) {
638 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
639 if (ret >= 0) {
640 out->compr_config.codec->options.alac.frame_length = atoi(value);
641 out->send_new_metadata = 1;
642 }
643 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
644 if (ret >= 0) {
645 out->compr_config.codec->options.alac.compatible_version = atoi(value);
646 out->send_new_metadata = 1;
647 }
648 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
649 if (ret >= 0) {
650 out->compr_config.codec->options.alac.bit_depth = atoi(value);
651 out->send_new_metadata = 1;
652 }
653 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
654 if (ret >= 0) {
655 out->compr_config.codec->options.alac.pb = atoi(value);
656 out->send_new_metadata = 1;
657 }
658 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
659 if (ret >= 0) {
660 out->compr_config.codec->options.alac.mb = atoi(value);
661 out->send_new_metadata = 1;
662 }
663
664 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
665 if (ret >= 0) {
666 out->compr_config.codec->options.alac.kb = atoi(value);
667 out->send_new_metadata = 1;
668 }
669 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
670 if (ret >= 0) {
671 out->compr_config.codec->options.alac.num_channels = atoi(value);
672 out->send_new_metadata = 1;
673 }
674 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
675 if (ret >= 0) {
676 out->compr_config.codec->options.alac.max_run = atoi(value);
677 out->send_new_metadata = 1;
678 }
679 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
680 if (ret >= 0) {
681 out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
682 out->send_new_metadata = 1;
683 }
684 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
685 if (ret >= 0) {
686 out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
687 out->send_new_metadata = 1;
688 }
689 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
690 if (ret >= 0) {
691 out->compr_config.codec->options.alac.sample_rate = atoi(value);
692 out->send_new_metadata = 1;
693 }
694 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
695 if (ret >= 0) {
696 out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
697 out->send_new_metadata = 1;
698 }
699 ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
700 " maxFrameBytes %d, avgBitRate %d, sampleRate %d",
701 out->compr_config.codec->options.alac.frame_length,
702 out->compr_config.codec->options.alac.bit_depth,
703 out->compr_config.codec->options.alac.num_channels,
704 out->compr_config.codec->options.alac.max_frame_bytes,
705 out->compr_config.codec->options.alac.avg_bit_rate,
706 out->compr_config.codec->options.alac.sample_rate);
707 }
708
709 else if (out->format == AUDIO_FORMAT_APE) {
710 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
711 if (ret >= 0) {
712 out->compr_config.codec->options.ape.compatible_version = atoi(value);
713 out->send_new_metadata = 1;
714 }
715 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
716 if (ret >= 0) {
717 out->compr_config.codec->options.ape.compression_level = atoi(value);
718 out->send_new_metadata = 1;
719 }
720 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
721 if (ret >= 0) {
722 out->compr_config.codec->options.ape.format_flags = atoi(value);
723 out->send_new_metadata = 1;
724 }
725 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
726 if (ret >= 0) {
727 out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
728 out->send_new_metadata = 1;
729 }
730 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
731 if (ret >= 0) {
732 out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
733 out->send_new_metadata = 1;
734 }
735 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
736 if (ret >= 0) {
737 out->compr_config.codec->options.ape.total_frames = atoi(value);
738 out->send_new_metadata = 1;
739 }
740 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
741 if (ret >= 0) {
742 out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
743 out->send_new_metadata = 1;
744 }
745 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
746 if (ret >= 0) {
747 out->compr_config.codec->options.ape.num_channels = atoi(value);
748 out->send_new_metadata = 1;
749 }
750 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
751 if (ret >= 0) {
752 out->compr_config.codec->options.ape.sample_rate = atoi(value);
753 out->send_new_metadata = 1;
754 }
755 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
756 if (ret >= 0) {
757 out->compr_config.codec->options.ape.seek_table_present = atoi(value);
758 out->send_new_metadata = 1;
759 }
760 ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
761 " formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
762 " totalFrames %d bitsPerSample %d numChannels %d"
763 " sampleRate %d seekTablePresent %d",
764 out->compr_config.codec->options.ape.compatible_version,
765 out->compr_config.codec->options.ape.compression_level,
766 out->compr_config.codec->options.ape.format_flags,
767 out->compr_config.codec->options.ape.blocks_per_frame,
768 out->compr_config.codec->options.ape.final_frame_blocks,
769 out->compr_config.codec->options.ape.total_frames,
770 out->compr_config.codec->options.ape.bits_per_sample,
771 out->compr_config.codec->options.ape.num_channels,
772 out->compr_config.codec->options.ape.sample_rate,
773 out->compr_config.codec->options.ape.seek_table_present);
774 }
775
776 else if (out->format == AUDIO_FORMAT_VORBIS) {
777 // transcoded bitstream mode
778 out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
779 out->send_new_metadata = 1;
780 }
781
782 else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
783 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
784 if (ret >= 0) {
785 out->compr_config.codec->format = atoi(value);
786 out->send_new_metadata = 1;
787 }
788 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
789 if (ret >= 0) {
790 out->compr_config.codec->options.wma.super_block_align = atoi(value);
791 out->send_new_metadata = 1;
792 }
793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
794 if (ret >= 0) {
795 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
796 out->send_new_metadata = 1;
797 }
798 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
799 if (ret >= 0) {
800 out->compr_config.codec->options.wma.channelmask = atoi(value);
801 out->send_new_metadata = 1;
802 }
803 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
804 if (ret >= 0) {
805 out->compr_config.codec->options.wma.encodeopt = atoi(value);
806 out->send_new_metadata = 1;
807 }
808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
809 if (ret >= 0) {
810 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
811 out->send_new_metadata = 1;
812 }
813 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
814 if (ret >= 0) {
815 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
816 out->send_new_metadata = 1;
817 }
818 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
819 out->compr_config.codec->format,
820 out->compr_config.codec->options.wma.super_block_align,
821 out->compr_config.codec->options.wma.bits_per_sample,
822 out->compr_config.codec->options.wma.channelmask,
823 out->compr_config.codec->options.wma.encodeopt,
824 out->compr_config.codec->options.wma.encodeopt1,
825 out->compr_config.codec->options.wma.encodeopt2);
826 }
827
828 return ret;
829 }
830 #endif
831
832 #ifdef AUXPCM_BT_ENABLED
audio_extn_read_xml(struct audio_device * adev,uint32_t mixer_card,const char * mixer_xml_path,const char * mixer_xml_path_auxpcm)833 int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
834 const char* mixer_xml_path,
835 const char* mixer_xml_path_auxpcm)
836 {
837 char bt_soc[128];
838 bool wifi_init_complete = false;
839 int sleep_retry = 0;
840
841 while (!wifi_init_complete && sleep_retry < MAX_SLEEP_RETRY) {
842 property_get("qcom.bluetooth.soc", bt_soc, NULL);
843 if (strncmp(bt_soc, "unknown", sizeof("unknown"))) {
844 wifi_init_complete = true;
845 } else {
846 usleep(WIFI_INIT_WAIT_SLEEP*1000);
847 sleep_retry++;
848 }
849 }
850
851 if (!strncmp(bt_soc, "ath3k", sizeof("ath3k")))
852 adev->audio_route = audio_route_init(mixer_card, mixer_xml_path_auxpcm);
853 else
854 adev->audio_route = audio_route_init(mixer_card, mixer_xml_path);
855
856 return 0;
857 }
858 #endif /* AUXPCM_BT_ENABLED */
859
860 #ifdef KPI_OPTIMIZE_ENABLED
861 typedef int (*perf_lock_acquire_t)(int, int, int*, int);
862 typedef int (*perf_lock_release_t)(int);
863
864 static void *qcopt_handle;
865 static perf_lock_acquire_t perf_lock_acq;
866 static perf_lock_release_t perf_lock_rel;
867
868 static int perf_lock_handle;
869 char opt_lib_path[512] = {0};
870 int perf_lock_opts[1] = {0x20E};
871
audio_extn_perf_lock_init(void)872 int audio_extn_perf_lock_init(void)
873 {
874 int ret = 0;
875 if (qcopt_handle == NULL) {
876 if (property_get("ro.vendor.extension_library",
877 opt_lib_path, NULL) <= 0) {
878 ALOGE("%s: Failed getting perf property \n", __func__);
879 ret = -EINVAL;
880 goto err;
881 }
882 if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
883 ALOGE("%s: Failed to open perf handle \n", __func__);
884 ret = -EINVAL;
885 goto err;
886 } else {
887 perf_lock_acq = (perf_lock_acquire_t)dlsym(qcopt_handle,
888 "perf_lock_acq");
889 if (perf_lock_acq == NULL) {
890 ALOGE("%s: Perf lock Acquire NULL \n", __func__);
891 ret = -EINVAL;
892 goto err;
893 }
894 perf_lock_rel = (perf_lock_release_t)dlsym(qcopt_handle,
895 "perf_lock_rel");
896 if (perf_lock_rel == NULL) {
897 ALOGE("%s: Perf lock Release NULL \n", __func__);
898 ret = -EINVAL;
899 goto err;
900 }
901 ALOGE("%s: Perf lock handles Success \n", __func__);
902 }
903 }
904 err:
905 return ret;
906 }
907
audio_extn_perf_lock_acquire(void)908 void audio_extn_perf_lock_acquire(void)
909 {
910 if (perf_lock_acq)
911 perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 1);
912 else
913 ALOGE("%s: Perf lock acquire error \n", __func__);
914 }
915
audio_extn_perf_lock_release(void)916 void audio_extn_perf_lock_release(void)
917 {
918 if (perf_lock_rel && perf_lock_handle)
919 perf_lock_rel(perf_lock_handle);
920 else
921 ALOGE("%s: Perf lock release error \n", __func__);
922 }
923 #endif /* KPI_OPTIMIZE_ENABLED */
924