blob: a8f09fc95af4d646dc2ba50ee38c20219f1fb499 [file] [log] [blame]
jasmine cha75fa6f02018-03-30 15:41:33 +08001/*
Vatsal Bucha7fe95a82019-05-06 15:25:58 +05302 * Copyright (C) 2018 The Android Open Source Project
jasmine cha75fa6f02018-03-30 15:41:33 +08003 *
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 cha75fa6f02018-03-30 15:41:33 +080020#include <audio_hw.h>
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -080021#include <cutils/str_parms.h>
22#include <dlfcn.h>
23#include <log/log.h>
jasmine cha75fa6f02018-03-30 15:41:33 +080024#include <math.h>
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -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 cha75fa6f02018-03-30 15:41:33 +080032#include "audio_extn.h"
33#include "maxxaudio.h"
34
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -080035#define LIB_MA_PARAM "libmaxxaudioqdsp.so"
jasmine cha75fa6f02018-03-30 15:41:33 +080036#define LIB_MA_PATH "vendor/lib/"
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -080037#define PRESET_PATH "/vendor/etc"
38#define MPS_BASE_STRING "default"
jasmine cha75fa6f02018-03-30 15:41:33 +080039#define USER_PRESET_PATH ""
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -080040#define CONFIG_BASE_STRING "maxx_conf"
jasmine cha75fa6f02018-03-30 15:41:33 +080041#define CAL_PRESIST_STR "cal_persist"
42#define CAL_SAMPLERATE_STR "cal_samplerate"
43
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080044#define MA_QDSP_PARAM_INIT "maxxaudio_qdsp_initialize"
45#define MA_QDSP_PARAM_DEINIT "maxxaudio_qdsp_uninitialize"
justinwengbbffa622019-01-11 14:38:06 +080046#define MA_QDSP_IS_FEATURE_USED "maxxaudio_qdsp_is_feature_supported"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080047#define MA_QDSP_SET_LR_SWAP "maxxaudio_qdsp_set_lr_swap"
justinwengbbffa622019-01-11 14:38:06 +080048#define MA_QDSP_SET_ORIENTATION "maxxaudio_qdsp_set_orientation"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080049#define MA_QDSP_SET_MODE "maxxaudio_qdsp_set_sound_mode"
50#define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume"
51#define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table"
52#define MA_QDSP_SET_PARAM "maxxaudio_qdsp_set_parameter"
jasmine cha75fa6f02018-03-30 15:41:33 +080053
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080054#define SUPPORT_DEV "18d1:5033" // Blackbird usbid
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -080055#define SUPPORTED_USB 0x01
jasmine cha75fa6f02018-03-30 15:41:33 +080056
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080057typedef unsigned int effective_scope_flag_t;
58const effective_scope_flag_t EFFECTIVE_SCOPE_RTC = 1 << 0; /* RTC */
59const effective_scope_flag_t EFFECTIVE_SCOPE_ACDB = 1 << 1; /* ACDB */
60const effective_scope_flag_t EFFECTIVE_SCOPE_ALL = EFFECTIVE_SCOPE_RTC | EFFECTIVE_SCOPE_ACDB;
61const effective_scope_flag_t EFFECTIVE_SCOPE_NONE = 0;
62const effective_scope_flag_t EFFECTIVE_SCOPE_DEFAULT = EFFECTIVE_SCOPE_NONE;
jasmine cha75fa6f02018-03-30 15:41:33 +080063
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080064const unsigned int AUDIO_CAL_SETTINGS_VERSION_MAJOR = 2;
65const unsigned int AUDIO_CAL_SETTINGS_VERSION_MINOR = 0;
66const unsigned int AUDIO_CAL_SETTINGS_VERSION_MAJOR_DEFAULT = AUDIO_CAL_SETTINGS_VERSION_MAJOR;
67const unsigned int AUDIO_CAL_SETTINGS_VERSION_MINOR_DEFAULT = AUDIO_CAL_SETTINGS_VERSION_MINOR;
68
69const unsigned int VALUE_AUTO = 0xFFFFFFFF;
70const unsigned int APP_TYPE_AUTO = VALUE_AUTO;
71const unsigned int APP_TYPE_DEFAULT = APP_TYPE_AUTO;
72const unsigned int DEVICE_AUTO = VALUE_AUTO;
73const unsigned int DEVICE_DEFAULT = DEVICE_AUTO;
74
75const unsigned int MAAP_OUTPUT_GAIN = 27;
jasmine cha75fa6f02018-03-30 15:41:33 +080076
77typedef enum MA_STREAM_TYPE {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080078 STREAM_MIN_TYPES = 0,
79 STREAM_VOICE = STREAM_MIN_TYPES,
jasmine cha75fa6f02018-03-30 15:41:33 +080080 STREAM_SYSTEM,
81 STREAM_RING,
82 STREAM_MUSIC,
83 STREAM_ALARM,
84 STREAM_NOTIFICATION ,
85 STREAM_MAX_TYPES,
86} ma_stream_type_t;
87
88typedef enum MA_CMD {
89 MA_CMD_VOL,
90 MA_CMD_SWAP_ENABLE,
91 MA_CMD_SWAP_DISABLE,
justinwengbbffa622019-01-11 14:38:06 +080092 MA_CMD_ROTATE_ENABLE,
93 MA_CMD_ROTATE_DISABLE,
jasmine cha75fa6f02018-03-30 15:41:33 +080094} ma_cmd_t;
95
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080096typedef struct ma_audio_cal_version {
97 unsigned int major;
98 unsigned int minor;
99} ma_audio_cal_version_t;
100
101typedef struct ma_audio_cal_common_settings {
102 unsigned int app_type;
103 unsigned int device;
104} ma_audio_cal_common_settings_t;
105
106struct ma_audio_cal_settings {
107 ma_audio_cal_version_t version;
108 ma_audio_cal_common_settings_t common;
109 effective_scope_flag_t effect_scope_flag;
110};
111
112struct ma_state {
113 float vol;
114 bool active;
115};
116
jasmine cha75fa6f02018-03-30 15:41:33 +0800117typedef void *ma_audio_cal_handle_t;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800118typedef int (*set_audio_cal_t)(const char *);
jasmine cha75fa6f02018-03-30 15:41:33 +0800119
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800120typedef bool (*ma_param_init_t)(ma_audio_cal_handle_t *, const char *,
121 const char *, const char *, set_audio_cal_t);
jasmine cha75fa6f02018-03-30 15:41:33 +0800122
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800123typedef bool (*ma_param_deinit_t)(ma_audio_cal_handle_t *);
jasmine cha75fa6f02018-03-30 15:41:33 +0800124
justinwengbbffa622019-01-11 14:38:06 +0800125typedef bool (*ma_is_feature_used_t)(ma_audio_cal_handle_t, const char *);
126
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800127typedef bool (*ma_set_lr_swap_t)(ma_audio_cal_handle_t,
128 const struct ma_audio_cal_settings *, bool);
jasmine cha75fa6f02018-03-30 15:41:33 +0800129
justinwengbbffa622019-01-11 14:38:06 +0800130typedef bool (*ma_set_orientation_t)(ma_audio_cal_handle_t,
131 const struct ma_audio_cal_settings *, int);
132
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800133typedef bool (*ma_set_sound_mode_t)(ma_audio_cal_handle_t,
134 const struct ma_audio_cal_settings *,
135 unsigned int);
jasmine cha75fa6f02018-03-30 15:41:33 +0800136
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800137typedef bool (*ma_set_volume_t)(ma_audio_cal_handle_t,
138 const struct ma_audio_cal_settings *, double);
jasmine cha75fa6f02018-03-30 15:41:33 +0800139
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800140typedef bool (*ma_set_volume_table_t)(ma_audio_cal_handle_t,
141 const struct ma_audio_cal_settings *,
142 size_t, struct ma_state *);
jasmine cha75fa6f02018-03-30 15:41:33 +0800143
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800144typedef bool (*ma_set_param_t)(ma_audio_cal_handle_t,
145 const struct ma_audio_cal_settings *,
146 unsigned int, double);
147
jasmine cha75fa6f02018-03-30 15:41:33 +0800148struct ma_platform_data {
149 void *waves_handle;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800150 void *platform;
jasmine cha75fa6f02018-03-30 15:41:33 +0800151 pthread_mutex_t lock;
152 ma_param_init_t ma_param_init;
153 ma_param_deinit_t ma_param_deinit;
justinwengbbffa622019-01-11 14:38:06 +0800154 ma_is_feature_used_t ma_is_feature_used;
jasmine cha75fa6f02018-03-30 15:41:33 +0800155 ma_set_lr_swap_t ma_set_lr_swap;
justinwengbbffa622019-01-11 14:38:06 +0800156 ma_set_orientation_t ma_set_orientation;
jasmine cha75fa6f02018-03-30 15:41:33 +0800157 ma_set_sound_mode_t ma_set_sound_mode;
158 ma_set_volume_t ma_set_volume;
159 ma_set_volume_table_t ma_set_volume_table;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800160 ma_set_param_t ma_set_param;
161 bool speaker_lr_swap;
justinwengbbffa622019-01-11 14:38:06 +0800162 bool orientation_used;
163 int dispaly_orientation;
jasmine cha75fa6f02018-03-30 15:41:33 +0800164};
165
166ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL;
167static uint16_t g_supported_dev = 0;
168static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES];
169static struct ma_platform_data *my_data = NULL;
Arun Mirpurid750ac52019-04-12 18:33:55 -0700170// --- external function dependency ---
171fp_platform_set_parameters_t fp_platform_set_parameters;
172fp_audio_extn_get_snd_card_split_t fp_audio_extn_get_snd_card_split;
jasmine cha75fa6f02018-03-30 15:41:33 +0800173
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800174static int set_audio_cal(const char *audio_cal)
jasmine cha75fa6f02018-03-30 15:41:33 +0800175{
176 ALOGV("set_audio_cal: %s", audio_cal);
177
Arun Mirpurid750ac52019-04-12 18:33:55 -0700178 return fp_platform_set_parameters(my_data->platform,
jasmine cha75fa6f02018-03-30 15:41:33 +0800179 str_parms_create_str(audio_cal));
180}
181
182static bool ma_set_lr_swap_l(
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800183 const struct ma_audio_cal_settings *audio_cal_settings, bool swap)
jasmine cha75fa6f02018-03-30 15:41:33 +0800184{
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800185 return my_data->ma_set_lr_swap(g_ma_audio_cal_handle,
186 audio_cal_settings, swap);
jasmine cha75fa6f02018-03-30 15:41:33 +0800187}
188
justinwengbbffa622019-01-11 14:38:06 +0800189static bool ma_set_orientation_l(
190 const struct ma_audio_cal_settings *audio_cal_settings, int orientation)
191{
192 return my_data->ma_set_orientation(g_ma_audio_cal_handle,
193 audio_cal_settings, orientation);
194}
195
jasmine cha75fa6f02018-03-30 15:41:33 +0800196static bool ma_set_volume_table_l(
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800197 const struct ma_audio_cal_settings *audio_cal_settings,
198 size_t num_streams, struct ma_state *volume_table)
jasmine cha75fa6f02018-03-30 15:41:33 +0800199{
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800200 return my_data->ma_set_volume_table(g_ma_audio_cal_handle,
201 audio_cal_settings, num_streams,
202 volume_table);
jasmine cha75fa6f02018-03-30 15:41:33 +0800203}
204
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800205static bool ma_set_param_l(
206 const struct ma_audio_cal_settings *audio_cal_settings,
207 unsigned int index, double value)
208{
209 return my_data->ma_set_param(g_ma_audio_cal_handle,
210 audio_cal_settings, index, value);
211}
212
Jasmine Cha0ad09772019-02-25 20:09:34 +0800213static void print_state_log()
214{
215 ALOGD("%s: send volume table -(%i,%f,%s),(%i,%f,%s),(%i,%f,%s),(%i,%f,%s),"
216 "(%i,%f,%s),(%i,%f,%s)", __func__,
217 STREAM_VOICE, ma_cur_state_table[STREAM_VOICE].vol,
218 ma_cur_state_table[STREAM_VOICE].active ? "T" : "F",
219 STREAM_SYSTEM, ma_cur_state_table[STREAM_SYSTEM].vol,
220 ma_cur_state_table[STREAM_SYSTEM].active ? "T" : "F",
221 STREAM_RING, ma_cur_state_table[STREAM_RING].vol,
222 ma_cur_state_table[STREAM_RING].active ? "T" : "F",
223 STREAM_MUSIC, ma_cur_state_table[STREAM_MUSIC].vol,
224 ma_cur_state_table[STREAM_MUSIC].active ? "T" : "F",
225 STREAM_ALARM, ma_cur_state_table[STREAM_ALARM].vol,
226 ma_cur_state_table[STREAM_ALARM].active ? "T" : "F",
227 STREAM_NOTIFICATION, ma_cur_state_table[STREAM_NOTIFICATION].vol,
228 ma_cur_state_table[STREAM_NOTIFICATION].active ? "T" : "F");
229
230}
231
jasmine cha75fa6f02018-03-30 15:41:33 +0800232static inline bool valid_usecase(struct audio_usecase *usecase)
233{
234 if ((usecase->type == PCM_PLAYBACK) &&
235 /* supported usecases */
236 ((usecase->id == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) ||
237 (usecase->id == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) ||
238 (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD)) &&
239 /* support devices */
240 ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
241 (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800242 (audio_is_usb_out_device(usecase->devices) &&
Arun Mirpurid750ac52019-04-12 18:33:55 -0700243 ma_supported_usb())))
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800244 /* TODO: enable A2DP when it is ready */
jasmine cha75fa6f02018-03-30 15:41:33 +0800245
246 return true;
247
248 ALOGV("%s: not support type %d usecase %d device %d",
249 __func__, usecase->type, usecase->id, usecase->devices);
250
251 return false;
252}
253
254// already hold lock
255static inline bool is_active()
256{
257 ma_stream_type_t i = 0;
258
259 for (i = 0; i < STREAM_MAX_TYPES; i++)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800260 if (ma_cur_state_table[i].active)
jasmine cha75fa6f02018-03-30 15:41:33 +0800261 return true;
262
263 return false;
264}
265
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800266static void ma_cal_init(struct ma_audio_cal_settings *ma_cal)
267{
268 ma_cal->version.major = AUDIO_CAL_SETTINGS_VERSION_MAJOR_DEFAULT;
269 ma_cal->version.minor = AUDIO_CAL_SETTINGS_VERSION_MINOR_DEFAULT;
270 ma_cal->common.app_type = APP_TYPE_DEFAULT;
271 ma_cal->common.device = DEVICE_DEFAULT;
272 ma_cal->effect_scope_flag = EFFECTIVE_SCOPE_ALL;
273}
274
jasmine cha75fa6f02018-03-30 15:41:33 +0800275static bool check_and_send_all_audio_cal(struct audio_device *adev, ma_cmd_t cmd)
276{
277 int i = 0;
278 bool ret = false;
jasmine cha75fa6f02018-03-30 15:41:33 +0800279 struct listnode *node;
280 struct audio_usecase *usecase;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800281 struct ma_audio_cal_settings ma_cal;
jasmine cha75fa6f02018-03-30 15:41:33 +0800282
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800283 ma_cal_init(&ma_cal);
jasmine cha75fa6f02018-03-30 15:41:33 +0800284
285 list_for_each(node, &adev->usecase_list) {
286 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +0530287 if (usecase->stream.out && valid_usecase(usecase)) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800288 ma_cal.common.app_type = usecase->stream.out->app_type_cfg.app_type;
289 ma_cal.common.device = usecase->stream.out->devices;
jasmine cha75fa6f02018-03-30 15:41:33 +0800290 ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800291 __func__, usecase->id, ma_cal.common.app_type,
292 ma_cal.common.device);
jasmine cha75fa6f02018-03-30 15:41:33 +0800293
294 switch (cmd) {
295 case MA_CMD_VOL:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800296 ret = ma_set_volume_table_l(&ma_cal, STREAM_MAX_TYPES,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800297 ma_cur_state_table);
jasmine cha75fa6f02018-03-30 15:41:33 +0800298 if (ret)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800299 ALOGV("ma_set_volume_table_l success");
jasmine cha75fa6f02018-03-30 15:41:33 +0800300 else
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800301 ALOGE("ma_set_volume_table_l returned with error.");
Jasmine Cha0ad09772019-02-25 20:09:34 +0800302 print_state_log();
jasmine cha75fa6f02018-03-30 15:41:33 +0800303 break;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800304
jasmine cha75fa6f02018-03-30 15:41:33 +0800305 case MA_CMD_SWAP_ENABLE:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800306 /* lr swap only enable for speaker path */
307 if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
308 ret = ma_set_lr_swap_l(&ma_cal, true);
309 if (ret)
310 ALOGV("ma_set_lr_swap_l enable returned with success.");
311 else
312 ALOGE("ma_set_lr_swap_l enable returned with error.");
313 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800314 break;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800315
jasmine cha75fa6f02018-03-30 15:41:33 +0800316 case MA_CMD_SWAP_DISABLE:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800317 ret = ma_set_lr_swap_l(&ma_cal, false);
jasmine cha75fa6f02018-03-30 15:41:33 +0800318 if (ret)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800319 ALOGV("ma_set_lr_swap_l disable returned with success.");
jasmine cha75fa6f02018-03-30 15:41:33 +0800320 else
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800321 ALOGE("ma_set_lr_swap_l disable returned with error.");
jasmine cha75fa6f02018-03-30 15:41:33 +0800322 break;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800323
justinwengbbffa622019-01-11 14:38:06 +0800324 case MA_CMD_ROTATE_ENABLE:
325 if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
326 ret = ma_set_orientation_l(&ma_cal, my_data->dispaly_orientation);
327 if (ret)
Jasmine Cha0ad09772019-02-25 20:09:34 +0800328 ALOGV("ma_set_orientation_l %d returned with success.",
329 my_data->dispaly_orientation);
justinwengbbffa622019-01-11 14:38:06 +0800330 else
Jasmine Cha0ad09772019-02-25 20:09:34 +0800331 ALOGE("ma_set_orientation_l %d returned with error.",
332 my_data->dispaly_orientation);
justinwengbbffa622019-01-11 14:38:06 +0800333 }
334 break;
335
336 case MA_CMD_ROTATE_DISABLE:
337 ret = ma_set_orientation_l(&ma_cal, 0);
338 if (ret)
339 ALOGV("ma_set_orientation_l 0 returned with success.");
340 else
341 ALOGE("ma_set_orientation_l 0 returned with error.");
342 break;
343
jasmine cha75fa6f02018-03-30 15:41:33 +0800344 default:
345 ALOGE("%s: unsupported cmd %d", __func__, cmd);
346 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800347 }
348 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800349
350 return ret;
351}
352
353static bool find_sup_dev(char *name)
354{
Weiyin Jiang0d985872019-06-13 15:47:21 +0800355 char *token, *saveptr = NULL;
jasmine cha75fa6f02018-03-30 15:41:33 +0800356 const char s[2] = ",";
357 bool ret = false;
358 char sup_devs[128];
359
360 // the rule of comforming suppored dev's name
361 // 1. Both string len are equal
362 // 2. Both string content are equal
363
364 strncpy(sup_devs, SUPPORT_DEV, sizeof(sup_devs));
Weiyin Jiang0d985872019-06-13 15:47:21 +0800365 token = strtok_r(sup_devs, s, &saveptr);
jasmine cha75fa6f02018-03-30 15:41:33 +0800366 while (token != NULL) {
367 if (strncmp(token, name, strlen(token)) == 0 &&
368 strlen(token) == strlen(name)) {
369 ALOGD("%s: support dev %s", __func__, token);
370 ret = true;
371 break;
372 }
Weiyin Jiang0d985872019-06-13 15:47:21 +0800373 token = strtok_r(NULL, s, &saveptr);
jasmine cha75fa6f02018-03-30 15:41:33 +0800374 }
375
376 return ret;
377}
378
379static void ma_set_swap_l(struct audio_device *adev, bool enable)
380{
jasmine cha75fa6f02018-03-30 15:41:33 +0800381 if (enable)
382 check_and_send_all_audio_cal(adev, MA_CMD_SWAP_ENABLE);
383 else
384 check_and_send_all_audio_cal(adev, MA_CMD_SWAP_DISABLE);
385}
386
justinwengbbffa622019-01-11 14:38:06 +0800387static void ma_set_rotation_l(struct audio_device *adev, int orientation)
388{
389 if (orientation != 0)
390 check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_ENABLE);
391 else
392 check_and_send_all_audio_cal(adev, MA_CMD_ROTATE_DISABLE);
393}
394
jasmine cha75fa6f02018-03-30 15:41:33 +0800395static void ma_support_usb(bool enable, int card)
396{
397 char path[128];
398 char id[32];
399 int ret = 0;
400 int32_t fd = -1;
401 char *idd;
Weiyin Jiang0d985872019-06-13 15:47:21 +0800402 char *saveptr = NULL;
jasmine cha75fa6f02018-03-30 15:41:33 +0800403
404 if (enable) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800405 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid", card);
jasmine cha75fa6f02018-03-30 15:41:33 +0800406 if (ret < 0) {
407 ALOGE("%s: failed on snprintf (%d) to path %s\n",
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800408 __func__, ret, path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800409 goto done;
410 }
411 fd = open(path, O_RDONLY);
412 if (fd < 0) {
413 ALOGE("%s: error failed to open id file %s error: %d\n",
414 __func__, path, errno);
415 goto done;
416 }
417 if (read(fd, id, sizeof(id)) < 0) {
418 ALOGE("%s: file read error", __func__);
419 goto done;
420 }
421 //replace '\n' to '\0'
Weiyin Jiang0d985872019-06-13 15:47:21 +0800422 idd = strtok_r(id, "\n", &saveptr);
jasmine cha75fa6f02018-03-30 15:41:33 +0800423
424 if (find_sup_dev(idd)) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800425 ALOGV("%s: support usbid is %s", __func__, id);
jasmine cha75fa6f02018-03-30 15:41:33 +0800426 g_supported_dev |= SUPPORTED_USB;
427 } else
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800428 ALOGV("%s: usbid %s isn't found from %s", __func__, id, SUPPORT_DEV);
jasmine cha75fa6f02018-03-30 15:41:33 +0800429 } else {
430 g_supported_dev &= ~SUPPORTED_USB;
431 }
432
433done:
434 if (fd >= 0) close(fd);
435}
436
437// adev_init lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700438void ma_init(void *platform, maxx_audio_init_config_t init_config)
jasmine cha75fa6f02018-03-30 15:41:33 +0800439{
440 ma_stream_type_t i = 0;
441 int ret = 0;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800442 char lib_path[128] = {0};
443 char mps_path[128] = {0};
444 char cnf_path[128] = {0};
445 struct snd_card_split *snd_split_handle = NULL;
Arun Mirpurid750ac52019-04-12 18:33:55 -0700446
447 fp_platform_set_parameters = init_config.fp_platform_set_parameters;
448 fp_audio_extn_get_snd_card_split = init_config.fp_audio_extn_get_snd_card_split;
449
450 snd_split_handle = fp_audio_extn_get_snd_card_split();
jasmine cha75fa6f02018-03-30 15:41:33 +0800451
452 if (platform == NULL) {
453 ALOGE("%s: platform is NULL", __func__);
454 goto error;
455 }
456
457 if (my_data) { free(my_data); }
458 my_data = calloc(1, sizeof(struct ma_platform_data));
459 if (my_data == NULL) {
460 ALOGE("%s: ma_cal alloct fail", __func__);
461 goto error;
462 }
463
464 pthread_mutex_init(&my_data->lock, NULL);
465
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800466 my_data->platform = platform;
jasmine cha75fa6f02018-03-30 15:41:33 +0800467 ret = snprintf(lib_path, sizeof(lib_path), "%s/%s", LIB_MA_PATH, LIB_MA_PARAM);
468 if (ret < 0) {
469 ALOGE("%s: snprintf failed for lib %s, ret %d", __func__, LIB_MA_PARAM, ret);
470 goto error;
471 }
472
473 my_data->waves_handle = dlopen(lib_path, RTLD_NOW);
474 if (my_data->waves_handle == NULL) {
Jasmine Cha0ad09772019-02-25 20:09:34 +0800475 ALOGE("%s: DLOPEN failed for %s, %s", __func__, LIB_MA_PARAM, dlerror());
jasmine cha75fa6f02018-03-30 15:41:33 +0800476 goto error;
477 } else {
478 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM);
479
480 my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800481 MA_QDSP_PARAM_INIT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800482 if (!my_data->ma_param_init) {
483 ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror());
484 goto error;
485 }
486
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800487 my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(
488 my_data->waves_handle, MA_QDSP_PARAM_DEINIT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800489 if (!my_data->ma_param_deinit) {
490 ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror());
491 goto error;
492 }
493
justinwengbbffa622019-01-11 14:38:06 +0800494 my_data->ma_is_feature_used = (ma_is_feature_used_t)dlsym(my_data->waves_handle,
495 MA_QDSP_IS_FEATURE_USED);
496 if (!my_data->ma_is_feature_used) {
497 ALOGV("%s: dlsym error %s for ma_is_feature_used", __func__, dlerror());
498 }
499
500 my_data->ma_set_orientation = (ma_set_orientation_t)dlsym(my_data->waves_handle,
501 MA_QDSP_SET_ORIENTATION);
502 if (!my_data->ma_set_orientation) {
503 ALOGV("%s: dlsym error %s for ma_set_orientation", __func__, dlerror());
504 }
505
jasmine cha75fa6f02018-03-30 15:41:33 +0800506 my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800507 MA_QDSP_SET_LR_SWAP);
jasmine cha75fa6f02018-03-30 15:41:33 +0800508 if (!my_data->ma_set_lr_swap) {
509 ALOGE("%s: dlsym error %s for ma_set_lr_swap", __func__, dlerror());
510 goto error;
511 }
512
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800513 my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(
514 my_data->waves_handle, MA_QDSP_SET_MODE);
jasmine cha75fa6f02018-03-30 15:41:33 +0800515 if (!my_data->ma_set_sound_mode) {
516 ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror());
517 goto error;
518 }
519
520 my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800521 MA_QDSP_SET_VOL);
jasmine cha75fa6f02018-03-30 15:41:33 +0800522 if (!my_data->ma_set_volume) {
523 ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror());
524 goto error;
525 }
526
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800527 my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(
528 my_data->waves_handle, MA_QDSP_SET_VOLT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800529 if (!my_data->ma_set_volume_table) {
530 ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror());
531 goto error;
532 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800533
534 my_data->ma_set_param = (ma_set_param_t)dlsym(
535 my_data->waves_handle, MA_QDSP_SET_PARAM);
536 if (!my_data->ma_set_param) {
537 ALOGE("%s: dlsym error %s for ma_set_param", __func__, dlerror());
538 goto error;
539 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800540 }
541
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800542 /* get preset table */
543 if (snd_split_handle == NULL) {
544 snprintf(mps_path, sizeof(mps_path), "%s/%s.mps",
545 PRESET_PATH, MPS_BASE_STRING);
546 } else {
547 snprintf(mps_path, sizeof(mps_path), "%s/%s_%s.mps",
548 PRESET_PATH, MPS_BASE_STRING, snd_split_handle->form_factor);
jasmine cha75fa6f02018-03-30 15:41:33 +0800549 }
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800550
551 /* get config files */
552 if (snd_split_handle == NULL) {
553 snprintf(cnf_path, sizeof(cnf_path), "%s/%s.ini",
554 PRESET_PATH, CONFIG_BASE_STRING);
555 } else {
556 snprintf(cnf_path, sizeof(cnf_path), "%s/%s_%s.ini",
557 PRESET_PATH, CONFIG_BASE_STRING, snd_split_handle->form_factor);
558 }
559
560 /* check file */
561 if (access(mps_path, R_OK) < 0) {
562 ALOGW("%s: file %s isn't existed.", __func__, mps_path);
563 goto error;
564 } else
565 ALOGD("%s: Loading mps file: %s", __func__, mps_path);
566
jasmine cha75fa6f02018-03-30 15:41:33 +0800567 /* TODO: check user preset table once the feature is enabled
568 if (access(USER_PRESET_PATH, F_OK) < 0 ){
569 ALOGW("%s: file %s isn't existed.", __func__, USER_PRESET_PATH);
570 goto error;
571 }
572 */
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800573
574 if (access(cnf_path, R_OK) < 0) {
575 ALOGW("%s: file %s isn't existed.", __func__, cnf_path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800576 goto error;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800577 } else
578 ALOGD("%s: Loading ini file: %s", __func__, cnf_path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800579
580 /* init ma parameter */
581 if (my_data->ma_param_init(&g_ma_audio_cal_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800582 mps_path,
583 USER_PRESET_PATH, /* unused */
584 cnf_path,
585 &set_audio_cal)) {
jasmine cha75fa6f02018-03-30 15:41:33 +0800586 if (!g_ma_audio_cal_handle) {
587 ALOGE("%s: ma parameters initialize failed", __func__);
588 my_data->ma_param_deinit(&g_ma_audio_cal_handle);
589 goto error;
590 }
591 ALOGD("%s: ma parameters initialize successful", __func__);
592 } else {
593 ALOGE("%s: ma parameters initialize failed", __func__);
594 goto error;
595 }
596
597 /* init volume table */
598 for (i = 0; i < STREAM_MAX_TYPES; i++) {
599 ma_cur_state_table[i].vol = 0.0;
600 ma_cur_state_table[i].active = false;
601 }
602
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800603 my_data->speaker_lr_swap = false;
justinwengbbffa622019-01-11 14:38:06 +0800604 my_data->orientation_used = false;
605 my_data->dispaly_orientation = 0;
606
607 if (g_ma_audio_cal_handle && my_data->ma_is_feature_used) {
Jasmine Cha0ad09772019-02-25 20:09:34 +0800608 my_data->orientation_used = my_data->ma_is_feature_used(
609 g_ma_audio_cal_handle, "SET_ORIENTATION");
justinwengbbffa622019-01-11 14:38:06 +0800610 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800611
jasmine cha75fa6f02018-03-30 15:41:33 +0800612 return;
613
614error:
615 if (my_data) { free(my_data); }
616 my_data = NULL;
617}
618
619//adev_init lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700620void ma_deinit()
jasmine cha75fa6f02018-03-30 15:41:33 +0800621{
622 if (my_data) {
623 /* deinit ma parameter */
624 if (my_data->ma_param_deinit &&
625 my_data->ma_param_deinit(&g_ma_audio_cal_handle))
626 ALOGD("%s: ma parameters uninitialize successful", __func__);
627 else
628 ALOGD("%s: ma parameters uninitialize failed", __func__);
629
630 pthread_mutex_destroy(&my_data->lock);
631 free(my_data);
632 my_data = NULL;
633 }
634}
635
636// adev_init and adev lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700637bool ma_set_state(struct audio_device *adev, int stream_type,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800638 float vol, bool active)
jasmine cha75fa6f02018-03-30 15:41:33 +0800639{
640 bool ret = false;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800641 struct ma_state pr_mstate;
jasmine cha75fa6f02018-03-30 15:41:33 +0800642
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800643 if (stream_type >= STREAM_MAX_TYPES ||
644 stream_type < STREAM_MIN_TYPES) {
645 ALOGE("%s: stream_type %d out of range.", __func__, stream_type);
646 return ret;
647 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800648
649 if (!my_data) {
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800650 ALOGV("%s: maxxaudio isn't initialized.", __func__);
jasmine cha75fa6f02018-03-30 15:41:33 +0800651 return ret;
652 }
653
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800654 ALOGV("%s: stream[%d] vol[%f] active[%s]",
655 __func__, stream_type, vol, active ? "true" : "false");
jasmine cha75fa6f02018-03-30 15:41:33 +0800656
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800657 pr_mstate.vol = ma_cur_state_table[(ma_stream_type_t)stream_type].vol;
658 pr_mstate.active = ma_cur_state_table[(ma_stream_type_t)stream_type].active;
659
660 // update condition: vol or active state changes
661 if (pr_mstate.vol != vol || pr_mstate.active != active) {
662
663 pthread_mutex_lock(&my_data->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800664
665 ma_cur_state_table[(ma_stream_type_t)stream_type].vol = vol;
666 ma_cur_state_table[(ma_stream_type_t)stream_type].active = active;
667
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800668 ret = check_and_send_all_audio_cal(adev, MA_CMD_VOL);
jasmine cha75fa6f02018-03-30 15:41:33 +0800669
670 pthread_mutex_unlock(&my_data->lock);
671 }
672
673 return ret;
674}
675
Arun Mirpurid750ac52019-04-12 18:33:55 -0700676void ma_set_device(struct audio_usecase *usecase)
jasmine cha75fa6f02018-03-30 15:41:33 +0800677{
678 int i = 0;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800679 struct ma_audio_cal_settings ma_cal;
jasmine cha75fa6f02018-03-30 15:41:33 +0800680
681 if (!my_data) {
682 ALOGV("%s: maxxaudio isn't initialized.", __func__);
683 return;
684 }
685
686 if (!valid_usecase(usecase)) {
687 ALOGV("%s: %d is not supported usecase", __func__, usecase->id);
688 return;
689 }
690
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800691 ma_cal_init(&ma_cal);
jasmine cha75fa6f02018-03-30 15:41:33 +0800692
693 /* update audio_cal and send it */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800694 ma_cal.common.app_type = usecase->stream.out->app_type_cfg.app_type;
695 ma_cal.common.device = usecase->stream.out->devices;
696 ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
697 __func__, usecase->id, ma_cal.common.app_type,
698 ma_cal.common.device);
jasmine cha75fa6f02018-03-30 15:41:33 +0800699
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800700 pthread_mutex_lock(&my_data->lock);
jasmine cha75fa6f02018-03-30 15:41:33 +0800701
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800702 if (is_active()) {
justinwengbbffa622019-01-11 14:38:06 +0800703
704 if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
705 if (my_data->orientation_used)
Jasmine Cha0ad09772019-02-25 20:09:34 +0800706 ma_set_rotation_l(usecase->stream.out->dev,
707 my_data->dispaly_orientation);
justinwengbbffa622019-01-11 14:38:06 +0800708 else
709 ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
710 } else {
711 if (my_data->orientation_used)
712 ma_set_rotation_l(usecase->stream.out->dev, 0);
713 else
714 ma_set_swap_l(usecase->stream.out->dev, false);
715 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800716
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800717 if (!ma_set_volume_table_l(&ma_cal,
718 STREAM_MAX_TYPES,
719 ma_cur_state_table))
720 ALOGE("ma_set_volume_table_l returned with error.");
721 else
722 ALOGV("ma_set_volume_table_l success");
Jasmine Cha0ad09772019-02-25 20:09:34 +0800723 print_state_log();
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800724
jasmine cha75fa6f02018-03-30 15:41:33 +0800725 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800726 pthread_mutex_unlock(&my_data->lock);
jasmine cha75fa6f02018-03-30 15:41:33 +0800727}
728
Arun Mirpurid750ac52019-04-12 18:33:55 -0700729void ma_set_parameters(struct audio_device *adev,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800730 struct str_parms *parms)
jasmine cha75fa6f02018-03-30 15:41:33 +0800731{
732 int ret;
jasmine cha75fa6f02018-03-30 15:41:33 +0800733 int val;
734 char value[128];
735
736 // do LR swap and usb recognition
737 ret = str_parms_get_int(parms, "rotation", &val);
738 if (ret >= 0) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800739 if (!my_data) {
740 ALOGV("%s: maxxaudio isn't initialized.", __func__);
741 return;
742 }
743
jasmine cha75fa6f02018-03-30 15:41:33 +0800744 switch (val) {
745 case 270:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800746 my_data->speaker_lr_swap = true;
jasmine cha75fa6f02018-03-30 15:41:33 +0800747 break;
748 case 0:
749 case 90:
750 case 180:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800751 my_data->speaker_lr_swap = false;
jasmine cha75fa6f02018-03-30 15:41:33 +0800752 break;
753 }
justinwengbbffa622019-01-11 14:38:06 +0800754 my_data->dispaly_orientation = val;
755
756 if (my_data->orientation_used)
757 ma_set_rotation_l(adev, my_data->dispaly_orientation);
758 else
759 ma_set_swap_l(adev, my_data->speaker_lr_swap);
jasmine cha75fa6f02018-03-30 15:41:33 +0800760 }
761
762 // check connect status
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800763 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
764 sizeof(value));
jasmine cha75fa6f02018-03-30 15:41:33 +0800765 if (ret >= 0) {
766 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
767 if (audio_is_usb_out_device(device)) {
768 ret = str_parms_get_str(parms, "card", value, sizeof(value));
769 if (ret >= 0) {
770 const int card = atoi(value);
771 ma_support_usb(true, card);
772 }
773 }
774 }
775
776 // check disconnect status
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800777 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
778 sizeof(value));
jasmine cha75fa6f02018-03-30 15:41:33 +0800779 if (ret >= 0) {
780 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
781 if (audio_is_usb_out_device(device)) {
782 ret = str_parms_get_str(parms, "card", value, sizeof(value));
783 if (ret >= 0) {
784 const int card = atoi(value);
785 ma_support_usb(false, card /*useless*/);
786 }
787 }
788 }
789}
790
Arun Mirpurid750ac52019-04-12 18:33:55 -0700791bool ma_supported_usb()
jasmine cha75fa6f02018-03-30 15:41:33 +0800792{
793 ALOGV("%s: current support 0x%x", __func__, g_supported_dev);
794 return (g_supported_dev & SUPPORTED_USB) ? true : false;
795}