blob: 7caa55e873ee2a59807fc79a8e2d77aa3f21b09e [file] [log] [blame]
jasmine cha270b7762018-03-30 15:41:33 +08001/*
2 * Copyright (C) 2018 The Android Open Source Project
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#define LOG_TAG "audio_hw_waves"
18/*#define LOG_NDEBUG 0*/
19
jasmine cha270b7762018-03-30 15:41:33 +080020#include <audio_hw.h>
Jasmine Cha70771b62018-05-15 15:02:43 +080021#include <cutils/str_parms.h>
22#include <dlfcn.h>
23#include <log/log.h>
jasmine cha270b7762018-03-30 15:41:33 +080024#include <math.h>
Jasmine Cha70771b62018-05-15 15:02:43 +080025#include <platform_api.h>
26#include <pthread.h>
27#include <stdlib.h>
28#include <string.h>
29#include <system/audio.h>
30#include <unistd.h>
31
jasmine cha270b7762018-03-30 15:41:33 +080032#include "audio_extn.h"
33#include "maxxaudio.h"
34
Jasmine Cha70771b62018-05-15 15:02:43 +080035#define LIB_MA_PARAM "libmaxxaudioqdsp.so"
jasmine cha270b7762018-03-30 15:41:33 +080036#define LIB_MA_PATH "vendor/lib/"
Jasmine Cha70771b62018-05-15 15:02:43 +080037#define PRESET_PATH "/vendor/etc"
38#define MPS_BASE_STRING "default"
jasmine cha270b7762018-03-30 15:41:33 +080039#define USER_PRESET_PATH ""
Jasmine Cha6d945d22018-06-19 09:49:04 -070040#define CONFIG_BASE_STRING "maxx_conf"
jasmine cha270b7762018-03-30 15:41:33 +080041#define CAL_PRESIST_STR "cal_persist"
42#define CAL_SAMPLERATE_STR "cal_samplerate"
43
Jasmine Cha70771b62018-05-15 15:02:43 +080044#define MA_QDSP_PARAM_INIT "maxxaudio_qdsp_initialize"
45#define MA_QDSP_PARAM_DEINIT "maxxaudio_qdsp_uninitialize"
jasmine cha270b7762018-03-30 15:41:33 +080046#define MA_QDSP_SET_LR_SWAP "maxxaudio_qdsp_set_lr_swap"
47#define MA_QDSP_SET_MODE "maxxaudio_qdsp_set_sound_mode"
48#define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume"
49#define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table"
50
51#define SUPPORT_DEV "Blackbird"
Jasmine Cha70771b62018-05-15 15:02:43 +080052#define SUPPORTED_USB 0x01
jasmine cha270b7762018-03-30 15:41:33 +080053
54struct ma_audio_cal_settings {
jasmine cha270b7762018-03-30 15:41:33 +080055 int app_type;
56 audio_devices_t device;
57};
58
59struct ma_state {
60 float vol;
61 bool active;
62};
63
64typedef enum MA_STREAM_TYPE {
Jasmine Chafc63f342018-06-27 10:55:06 -070065 STREAM_MIN_TYPES = 0,
66 STREAM_VOICE = STREAM_MIN_TYPES,
jasmine cha270b7762018-03-30 15:41:33 +080067 STREAM_SYSTEM,
68 STREAM_RING,
69 STREAM_MUSIC,
70 STREAM_ALARM,
71 STREAM_NOTIFICATION ,
72 STREAM_MAX_TYPES,
73} ma_stream_type_t;
74
75typedef enum MA_CMD {
76 MA_CMD_VOL,
77 MA_CMD_SWAP_ENABLE,
78 MA_CMD_SWAP_DISABLE,
79} ma_cmd_t;
80
81typedef void *ma_audio_cal_handle_t;
Jasmine Cha70771b62018-05-15 15:02:43 +080082typedef int (*set_audio_cal_t)(const char *);
jasmine cha270b7762018-03-30 15:41:33 +080083
Jasmine Cha70771b62018-05-15 15:02:43 +080084typedef bool (*ma_param_init_t)(ma_audio_cal_handle_t *, const char *,
85 const char *, const char *, set_audio_cal_t);
jasmine cha270b7762018-03-30 15:41:33 +080086
Jasmine Cha70771b62018-05-15 15:02:43 +080087typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
jasmine cha270b7762018-03-30 15:41:33 +080088
Jasmine Cha70771b62018-05-15 15:02:43 +080089typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
90 const struct ma_audio_cal_settings *, bool);
jasmine cha270b7762018-03-30 15:41:33 +080091
Jasmine Cha70771b62018-05-15 15:02:43 +080092typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
93 const struct ma_audio_cal_settings *,
94 unsigned int);
jasmine cha270b7762018-03-30 15:41:33 +080095
Jasmine Cha70771b62018-05-15 15:02:43 +080096typedef bool (*ma_set_volume_t)(ma_audio_cal_handle_t,
97 const struct ma_audio_cal_settings *, double);
jasmine cha270b7762018-03-30 15:41:33 +080098
Jasmine Cha70771b62018-05-15 15:02:43 +080099typedef bool (*ma_set_volume_table_t)(ma_audio_cal_handle_t,
100 const struct ma_audio_cal_settings *,
101 size_t, struct ma_state *);
jasmine cha270b7762018-03-30 15:41:33 +0800102
103struct ma_platform_data {
104 void *waves_handle;
Jasmine Cha70771b62018-05-15 15:02:43 +0800105 void *platform;
jasmine cha270b7762018-03-30 15:41:33 +0800106 pthread_mutex_t lock;
107 ma_param_init_t ma_param_init;
108 ma_param_deinit_t ma_param_deinit;
109 ma_set_lr_swap_t ma_set_lr_swap;
110 ma_set_sound_mode_t ma_set_sound_mode;
111 ma_set_volume_t ma_set_volume;
112 ma_set_volume_table_t ma_set_volume_table;
113};
114
115ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL;
116static uint16_t g_supported_dev = 0;
117static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES];
118static struct ma_platform_data *my_data = NULL;
119
Jasmine Cha70771b62018-05-15 15:02:43 +0800120static int set_audio_cal(const char *audio_cal)
jasmine cha270b7762018-03-30 15:41:33 +0800121{
122 ALOGV("set_audio_cal: %s", audio_cal);
123
Jasmine Cha70771b62018-05-15 15:02:43 +0800124 return platform_set_parameters(my_data->platform,
jasmine cha270b7762018-03-30 15:41:33 +0800125 str_parms_create_str(audio_cal));
126}
127
128static bool ma_set_lr_swap_l(
Jasmine Cha70771b62018-05-15 15:02:43 +0800129 const struct ma_audio_cal_settings *audio_cal_settings, bool swap)
jasmine cha270b7762018-03-30 15:41:33 +0800130{
Jasmine Cha70771b62018-05-15 15:02:43 +0800131 return my_data->ma_set_lr_swap(g_ma_audio_cal_handle,
132 audio_cal_settings, swap);
jasmine cha270b7762018-03-30 15:41:33 +0800133}
134
135static bool ma_set_sound_mode_l(
Jasmine Cha70771b62018-05-15 15:02:43 +0800136 const struct ma_audio_cal_settings *audio_cal_settings, int sound_mode)
jasmine cha270b7762018-03-30 15:41:33 +0800137{
138 return my_data->ma_set_sound_mode(g_ma_audio_cal_handle,
Jasmine Cha70771b62018-05-15 15:02:43 +0800139 audio_cal_settings, sound_mode);
jasmine cha270b7762018-03-30 15:41:33 +0800140}
141
142static bool ma_set_volume_l(
Jasmine Cha70771b62018-05-15 15:02:43 +0800143 const struct ma_audio_cal_settings *audio_cal_settings, double volume)
jasmine cha270b7762018-03-30 15:41:33 +0800144{
Jasmine Cha70771b62018-05-15 15:02:43 +0800145 return my_data->ma_set_volume(g_ma_audio_cal_handle, audio_cal_settings,
146 volume);
jasmine cha270b7762018-03-30 15:41:33 +0800147}
148
149static bool ma_set_volume_table_l(
Jasmine Cha70771b62018-05-15 15:02:43 +0800150 const struct ma_audio_cal_settings *audio_cal_settings,
151 size_t num_streams, struct ma_state *volume_table)
jasmine cha270b7762018-03-30 15:41:33 +0800152{
Jasmine Cha70771b62018-05-15 15:02:43 +0800153 return my_data->ma_set_volume_table(g_ma_audio_cal_handle,
154 audio_cal_settings, num_streams,
155 volume_table);
jasmine cha270b7762018-03-30 15:41:33 +0800156}
157
158static inline bool valid_usecase(struct audio_usecase *usecase)
159{
160 if ((usecase->type == PCM_PLAYBACK) &&
161 /* supported usecases */
162 ((usecase->id == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) ||
163 (usecase->id == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) ||
164 (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD)) &&
165 /* support devices */
166 ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
167 (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
Jasmine Cha70771b62018-05-15 15:02:43 +0800168 /* TODO: enable A2DP when it is ready */
jasmine cha270b7762018-03-30 15:41:33 +0800169 (usecase->devices & AUDIO_DEVICE_OUT_ALL_USB)))
170
171 return true;
172
173 ALOGV("%s: not support type %d usecase %d device %d",
174 __func__, usecase->type, usecase->id, usecase->devices);
175
176 return false;
177}
178
179// already hold lock
180static inline bool is_active()
181{
182 ma_stream_type_t i = 0;
183
184 for (i = 0; i < STREAM_MAX_TYPES; i++)
185 if (ma_cur_state_table[i].active &&
186 (ma_cur_state_table[i].vol != 0))
187 return true;
188
189 return false;
190}
191
192static bool check_and_send_all_audio_cal(struct audio_device *adev, ma_cmd_t cmd)
193{
194 int i = 0;
195 bool ret = false;
196 float vol = 0;
197 struct listnode *node;
198 struct audio_usecase *usecase;
199 struct ma_audio_cal_settings *ma_cal = NULL;
200
201 // alloct
202 ma_cal = (struct ma_audio_cal_settings *)malloc(sizeof(struct ma_audio_cal_settings));
203
204 if (ma_cal == NULL) {
205 ALOGE("%s: ma_cal alloct fail", __func__);
206 return ret;
207 }
208
209 list_for_each(node, &adev->usecase_list) {
210 usecase = node_to_item(node, struct audio_usecase, list);
211 if (valid_usecase(usecase)) {
jasmine cha270b7762018-03-30 15:41:33 +0800212 ma_cal->app_type = usecase->stream.out->app_type_cfg.app_type;
213 ma_cal->device = usecase->stream.out->devices;
214 ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
215 __func__, usecase->id, ma_cal->app_type, ma_cal->device);
216
217 switch (cmd) {
218 case MA_CMD_VOL:
219 ret = ma_set_volume_table_l(ma_cal, STREAM_MAX_TYPES,
Jasmine Cha70771b62018-05-15 15:02:43 +0800220 ma_cur_state_table);
jasmine cha270b7762018-03-30 15:41:33 +0800221 if (ret)
222 ALOGV("Waves: ma_set_volume_table_l success");
223 else
224 ALOGE("Waves: ma_set_volume_table_l %f returned with error.", vol);
225
226 ALOGV("%s: send volume table === Start", __func__);
227 for (i = 0; i < STREAM_MAX_TYPES; i++)
Jasmine Cha70771b62018-05-15 15:02:43 +0800228 ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__,
229 i, ma_cur_state_table[i].vol,
230 ma_cur_state_table[i].active ? "T" : "F");
jasmine cha270b7762018-03-30 15:41:33 +0800231 ALOGV("%s: send volume table === End", __func__);
232 break;
233 case MA_CMD_SWAP_ENABLE:
234 ret = ma_set_lr_swap_l(ma_cal, true);
235 if (ret)
236 ALOGV("Waves: ma_set_lr_swap_l enable returned with success.");
237 else
238 ALOGE("Waves: ma_set_lr_swap_l enable returned with error.");
239 break;
240 case MA_CMD_SWAP_DISABLE:
241 ret = ma_set_lr_swap_l(ma_cal, false);
242 if (ret)
243 ALOGV("Waves: ma_set_lr_swap_l disable returned with success.");
244 else
245 ALOGE("Waves: ma_set_lr_swap_l disable returned with error.");
246 break;
247 default:
248 ALOGE("%s: unsupported cmd %d", __func__, cmd);
249 }
jasmine cha270b7762018-03-30 15:41:33 +0800250 }
251 }
252 free(ma_cal);
253
254 return ret;
255}
256
257static bool find_sup_dev(char *name)
258{
259 char *token;
260 const char s[2] = ",";
261 bool ret = false;
262 char sup_devs[128];
263
264 // the rule of comforming suppored dev's name
265 // 1. Both string len are equal
266 // 2. Both string content are equal
267
268 strncpy(sup_devs, SUPPORT_DEV, sizeof(sup_devs));
269 token = strtok(sup_devs, s);
270 while (token != NULL) {
271 if (strncmp(token, name, strlen(token)) == 0 &&
272 strlen(token) == strlen(name)) {
273 ALOGD("%s: support dev %s", __func__, token);
274 ret = true;
275 break;
276 }
277 token = strtok(NULL, s);
278 }
279
280 return ret;
281}
282
283static void ma_set_swap_l(struct audio_device *adev, bool enable)
284{
Jasmine Cha70771b62018-05-15 15:02:43 +0800285 // do platform LR swap if it enables on Waves effect
286 // but there is no Waves implementation
jasmine cha270b7762018-03-30 15:41:33 +0800287 if (!my_data) {
Jasmine Cha70771b62018-05-15 15:02:43 +0800288 platform_check_and_set_swap_lr_channels(adev, enable);
289 ALOGV("%s: maxxaudio isn't initialized.", __func__);
jasmine cha270b7762018-03-30 15:41:33 +0800290 return;
291 }
Jasmine Cha70771b62018-05-15 15:02:43 +0800292
jasmine cha270b7762018-03-30 15:41:33 +0800293 if (enable)
294 check_and_send_all_audio_cal(adev, MA_CMD_SWAP_ENABLE);
295 else
296 check_and_send_all_audio_cal(adev, MA_CMD_SWAP_DISABLE);
297}
298
299static void ma_support_usb(bool enable, int card)
300{
301 char path[128];
302 char id[32];
303 int ret = 0;
304 int32_t fd = -1;
305 char *idd;
306
307 if (enable) {
308 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/id", card);
309 if (ret < 0) {
310 ALOGE("%s: failed on snprintf (%d) to path %s\n",
Jasmine Cha70771b62018-05-15 15:02:43 +0800311 __func__, ret, path);
jasmine cha270b7762018-03-30 15:41:33 +0800312 goto done;
313 }
314 fd = open(path, O_RDONLY);
315 if (fd < 0) {
316 ALOGE("%s: error failed to open id file %s error: %d\n",
317 __func__, path, errno);
318 goto done;
319 }
320 if (read(fd, id, sizeof(id)) < 0) {
321 ALOGE("%s: file read error", __func__);
322 goto done;
323 }
324 //replace '\n' to '\0'
325 idd = strtok(id, "\n");
326
327 if (find_sup_dev(idd)) {
328 ALOGV("%s: support device name is %s", __func__, id);
329 g_supported_dev |= SUPPORTED_USB;
330 } else
331 ALOGV("%s: device %s isn't found from %s", __func__, id, SUPPORT_DEV);
332 } else {
333 g_supported_dev &= ~SUPPORTED_USB;
334 }
335
336done:
337 if (fd >= 0) close(fd);
338}
339
340// adev_init lock held
341void audio_extn_ma_init(void *platform)
342{
343 ma_stream_type_t i = 0;
344 int ret = 0;
Jasmine Cha70771b62018-05-15 15:02:43 +0800345 char lib_path[128] = {0};
346 char mps_path[128] = {0};
Jasmine Cha6d945d22018-06-19 09:49:04 -0700347 char cnf_path[128] = {0};
Jasmine Cha70771b62018-05-15 15:02:43 +0800348 struct snd_card_split *snd_split_handle = NULL;
349 snd_split_handle = audio_extn_get_snd_card_split();
jasmine cha270b7762018-03-30 15:41:33 +0800350
351 if (platform == NULL) {
352 ALOGE("%s: platform is NULL", __func__);
353 goto error;
354 }
355
356 if (my_data) { free(my_data); }
357 my_data = calloc(1, sizeof(struct ma_platform_data));
358 if (my_data == NULL) {
359 ALOGE("%s: ma_cal alloct fail", __func__);
360 goto error;
361 }
362
363 pthread_mutex_init(&my_data->lock, NULL);
364
Jasmine Cha70771b62018-05-15 15:02:43 +0800365 my_data->platform = platform;
jasmine cha270b7762018-03-30 15:41:33 +0800366 ret = snprintf(lib_path, sizeof(lib_path), "%s/%s", LIB_MA_PATH, LIB_MA_PARAM);
367 if (ret < 0) {
368 ALOGE("%s: snprintf failed for lib %s, ret %d", __func__, LIB_MA_PARAM, ret);
369 goto error;
370 }
371
372 my_data->waves_handle = dlopen(lib_path, RTLD_NOW);
373 if (my_data->waves_handle == NULL) {
374 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_MA_PARAM);
375 goto error;
376 } else {
377 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM);
378
379 my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle,
Jasmine Cha70771b62018-05-15 15:02:43 +0800380 MA_QDSP_PARAM_INIT);
jasmine cha270b7762018-03-30 15:41:33 +0800381 if (!my_data->ma_param_init) {
382 ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror());
383 goto error;
384 }
385
Jasmine Cha70771b62018-05-15 15:02:43 +0800386 my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(
387 my_data->waves_handle, MA_QDSP_PARAM_DEINIT);
jasmine cha270b7762018-03-30 15:41:33 +0800388 if (!my_data->ma_param_deinit) {
389 ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror());
390 goto error;
391 }
392
393 my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
Jasmine Cha70771b62018-05-15 15:02:43 +0800394 MA_QDSP_SET_LR_SWAP);
jasmine cha270b7762018-03-30 15:41:33 +0800395 if (!my_data->ma_set_lr_swap) {
396 ALOGE("%s: dlsym error %s for ma_set_lr_swap", __func__, dlerror());
397 goto error;
398 }
399
Jasmine Cha70771b62018-05-15 15:02:43 +0800400 my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(
401 my_data->waves_handle, MA_QDSP_SET_MODE);
jasmine cha270b7762018-03-30 15:41:33 +0800402 if (!my_data->ma_set_sound_mode) {
403 ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror());
404 goto error;
405 }
406
407 my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle,
Jasmine Cha70771b62018-05-15 15:02:43 +0800408 MA_QDSP_SET_VOL);
jasmine cha270b7762018-03-30 15:41:33 +0800409 if (!my_data->ma_set_volume) {
410 ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror());
411 goto error;
412 }
413
Jasmine Cha70771b62018-05-15 15:02:43 +0800414 my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(
415 my_data->waves_handle, MA_QDSP_SET_VOLT);
jasmine cha270b7762018-03-30 15:41:33 +0800416 if (!my_data->ma_set_volume_table) {
417 ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror());
418 goto error;
419 }
420 }
421
Jasmine Cha70771b62018-05-15 15:02:43 +0800422 /* get preset table */
423 if (snd_split_handle == NULL) {
424 snprintf(mps_path, sizeof(mps_path), "%s/%s.mps",
425 PRESET_PATH, MPS_BASE_STRING);
426 } else {
427 snprintf(mps_path, sizeof(mps_path), "%s/%s_%s.mps",
428 PRESET_PATH, MPS_BASE_STRING, snd_split_handle->form_factor);
jasmine cha270b7762018-03-30 15:41:33 +0800429 }
Jasmine Cha70771b62018-05-15 15:02:43 +0800430
Jasmine Cha6d945d22018-06-19 09:49:04 -0700431 /* get config files */
432 if (snd_split_handle == NULL) {
433 snprintf(cnf_path, sizeof(cnf_path), "%s/%s.ini",
434 PRESET_PATH, CONFIG_BASE_STRING);
435 } else {
436 snprintf(cnf_path, sizeof(cnf_path), "%s/%s_%s.ini",
437 PRESET_PATH, CONFIG_BASE_STRING, snd_split_handle->form_factor);
438 }
439
Jasmine Cha70771b62018-05-15 15:02:43 +0800440 /* check file */
Jasmine Cha6d945d22018-06-19 09:49:04 -0700441 if (access(mps_path, R_OK) < 0) {
Jasmine Cha70771b62018-05-15 15:02:43 +0800442 ALOGW("%s: file %s isn't existed.", __func__, mps_path);
443 goto error;
444 } else
445 ALOGD("%s: Loading mps file: %s", __func__, mps_path);
446
jasmine cha270b7762018-03-30 15:41:33 +0800447 /* TODO: check user preset table once the feature is enabled
448 if (access(USER_PRESET_PATH, F_OK) < 0 ){
449 ALOGW("%s: file %s isn't existed.", __func__, USER_PRESET_PATH);
450 goto error;
451 }
452 */
Jasmine Cha6d945d22018-06-19 09:49:04 -0700453
454 if (access(cnf_path, R_OK) < 0) {
455 ALOGW("%s: file %s isn't existed.", __func__, cnf_path);
jasmine cha270b7762018-03-30 15:41:33 +0800456 goto error;
Jasmine Cha6d945d22018-06-19 09:49:04 -0700457 } else
458 ALOGD("%s: Loading ini file: %s", __func__, cnf_path);
jasmine cha270b7762018-03-30 15:41:33 +0800459
460 /* init ma parameter */
461 if (my_data->ma_param_init(&g_ma_audio_cal_handle,
Jasmine Cha70771b62018-05-15 15:02:43 +0800462 mps_path,
463 USER_PRESET_PATH, /* unused */
Jasmine Cha6d945d22018-06-19 09:49:04 -0700464 cnf_path,
Jasmine Cha70771b62018-05-15 15:02:43 +0800465 &set_audio_cal)) {
jasmine cha270b7762018-03-30 15:41:33 +0800466 if (!g_ma_audio_cal_handle) {
467 ALOGE("%s: ma parameters initialize failed", __func__);
468 my_data->ma_param_deinit(&g_ma_audio_cal_handle);
469 goto error;
470 }
471 ALOGD("%s: ma parameters initialize successful", __func__);
472 } else {
473 ALOGE("%s: ma parameters initialize failed", __func__);
474 goto error;
475 }
476
477 /* init volume table */
478 for (i = 0; i < STREAM_MAX_TYPES; i++) {
479 ma_cur_state_table[i].vol = 0.0;
480 ma_cur_state_table[i].active = false;
481 }
482
483 return;
484
485error:
486 if (my_data) { free(my_data); }
487 my_data = NULL;
488}
489
490//adev_init lock held
491void audio_extn_ma_deinit()
492{
493 if (my_data) {
494 /* deinit ma parameter */
495 if (my_data->ma_param_deinit &&
496 my_data->ma_param_deinit(&g_ma_audio_cal_handle))
497 ALOGD("%s: ma parameters uninitialize successful", __func__);
498 else
499 ALOGD("%s: ma parameters uninitialize failed", __func__);
500
501 pthread_mutex_destroy(&my_data->lock);
502 free(my_data);
503 my_data = NULL;
504 }
505}
506
507// adev_init and adev lock held
Jasmine Cha70771b62018-05-15 15:02:43 +0800508bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type,
509 float vol, bool active)
jasmine cha270b7762018-03-30 15:41:33 +0800510{
511 bool ret = false;
Jasmine Chafc63f342018-06-27 10:55:06 -0700512 ma_stream_type_t stype;
jasmine cha270b7762018-03-30 15:41:33 +0800513
Jasmine Chafc63f342018-06-27 10:55:06 -0700514 if (stream_type >= STREAM_MAX_TYPES ||
515 stream_type < STREAM_MIN_TYPES) {
516 ALOGE("%s: stream_type %d out of range.", __func__, stream_type);
517 return ret;
518 }
jasmine cha270b7762018-03-30 15:41:33 +0800519
520 if (!my_data) {
Jasmine Cha70771b62018-05-15 15:02:43 +0800521 ALOGV("%s: maxxaudio isn't initialized.", __func__);
jasmine cha270b7762018-03-30 15:41:33 +0800522 return ret;
523 }
524
Jasmine Chafc63f342018-06-27 10:55:06 -0700525 ALOGV("%s: stream[%d] vol[%f] active[%s]",
526 __func__, stream_type, vol, active ? "true" : "false");
527
jasmine cha270b7762018-03-30 15:41:33 +0800528 // update condition
529 // 1. start track: active and volume isn't zero
530 // 2. stop track: no tracks are active
531 if ((active && vol != 0) ||
Jasmine Cha70771b62018-05-15 15:02:43 +0800532 (!active)) {
Jasmine Chafc63f342018-06-27 10:55:06 -0700533 stype = (ma_stream_type_t)stream_type;
jasmine cha270b7762018-03-30 15:41:33 +0800534 pthread_mutex_lock(&my_data->lock);
535
536 ma_cur_state_table[stype].vol = vol;
537 ma_cur_state_table[stype].active = active;
538 if (is_active())
539 ret = check_and_send_all_audio_cal(adev, MA_CMD_VOL);
540
541 pthread_mutex_unlock(&my_data->lock);
542 }
543
544 return ret;
545}
546
Jasmine Cha70771b62018-05-15 15:02:43 +0800547void audio_extn_ma_set_device(struct audio_usecase *usecase)
jasmine cha270b7762018-03-30 15:41:33 +0800548{
549 int i = 0;
550 int u_index = -1;
551 float vol = 0;
552 struct ma_audio_cal_settings *ma_cal = NULL;
553
554 if (!my_data) {
555 ALOGV("%s: maxxaudio isn't initialized.", __func__);
556 return;
557 }
558
559 if (!valid_usecase(usecase)) {
560 ALOGV("%s: %d is not supported usecase", __func__, usecase->id);
561 return;
562 }
563
564 ma_cal = (struct ma_audio_cal_settings *)malloc(sizeof(struct ma_audio_cal_settings));
565
566 /* update audio_cal and send it */
567 if (ma_cal != NULL){
jasmine cha270b7762018-03-30 15:41:33 +0800568 ma_cal->app_type = usecase->stream.out->app_type_cfg.app_type;
569 ma_cal->device = usecase->stream.out->devices;
570 ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
571 __func__, usecase->id, ma_cal->app_type, ma_cal->device);
572
573 pthread_mutex_lock(&my_data->lock);
574
575 if (is_active()) {
576 ALOGV("%s: send volume table === Start", __func__);
577 for (i = 0; i < STREAM_MAX_TYPES; i++)
578 ALOGV("%s: stream(%d) volume(%f) active(%s)", __func__, i,
579 ma_cur_state_table[i].vol,
580 ma_cur_state_table[i].active ? "T" : "F");
581 ALOGV("%s: send volume table === End", __func__);
582
583 if (!ma_set_volume_table_l(ma_cal,
Jasmine Cha70771b62018-05-15 15:02:43 +0800584 STREAM_MAX_TYPES,
585 ma_cur_state_table))
jasmine cha270b7762018-03-30 15:41:33 +0800586 ALOGE("Waves: ma_set_volume_table_l %f returned with error.", vol);
587 else
588 ALOGV("Waves: ma_set_volume_table_l success");
589
590 }
591 pthread_mutex_unlock(&my_data->lock);
592 free(ma_cal);
593 } else {
594 ALOGE("%s: ma_cal alloct fail", __func__);
595 }
596}
597
Jasmine Cha70771b62018-05-15 15:02:43 +0800598void audio_extn_ma_set_parameters(struct audio_device *adev,
599 struct str_parms *parms)
jasmine cha270b7762018-03-30 15:41:33 +0800600{
601 int ret;
602 bool ret_b;
603 int val;
604 char value[128];
605
606 // do LR swap and usb recognition
607 ret = str_parms_get_int(parms, "rotation", &val);
608 if (ret >= 0) {
609 switch (val) {
610 case 270:
611 ma_set_swap_l(adev, true);
612 break;
613 case 0:
614 case 90:
615 case 180:
616 ma_set_swap_l(adev, false);
617 break;
618 }
619 }
620
621 // check connect status
Jasmine Cha70771b62018-05-15 15:02:43 +0800622 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
623 sizeof(value));
jasmine cha270b7762018-03-30 15:41:33 +0800624 if (ret >= 0) {
625 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
626 if (audio_is_usb_out_device(device)) {
627 ret = str_parms_get_str(parms, "card", value, sizeof(value));
628 if (ret >= 0) {
629 const int card = atoi(value);
630 ma_support_usb(true, card);
631 }
632 }
633 }
634
635 // check disconnect status
Jasmine Cha70771b62018-05-15 15:02:43 +0800636 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
637 sizeof(value));
jasmine cha270b7762018-03-30 15:41:33 +0800638 if (ret >= 0) {
639 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
640 if (audio_is_usb_out_device(device)) {
641 ret = str_parms_get_str(parms, "card", value, sizeof(value));
642 if (ret >= 0) {
643 const int card = atoi(value);
644 ma_support_usb(false, card /*useless*/);
645 }
646 }
647 }
648}
649
650bool audio_extn_ma_supported_usb()
651{
652 ALOGV("%s: current support 0x%x", __func__, g_supported_dev);
653 return (g_supported_dev & SUPPORTED_USB) ? true : false;
654}