blob: 3d51636f8cf187c562deba6b6addd5956a22761e [file] [log] [blame]
jasmine cha75fa6f02018-03-30 15:41:33 +08001/*
Arun Mirpurid750ac52019-04-12 18:33:55 -07002 * Copyright (C) 2018-2019 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{
355 char *token;
356 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));
365 token = strtok(sup_devs, s);
366 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 }
373 token = strtok(NULL, s);
374 }
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;
402
403 if (enable) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800404 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid", card);
jasmine cha75fa6f02018-03-30 15:41:33 +0800405 if (ret < 0) {
406 ALOGE("%s: failed on snprintf (%d) to path %s\n",
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800407 __func__, ret, path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800408 goto done;
409 }
410 fd = open(path, O_RDONLY);
411 if (fd < 0) {
412 ALOGE("%s: error failed to open id file %s error: %d\n",
413 __func__, path, errno);
414 goto done;
415 }
416 if (read(fd, id, sizeof(id)) < 0) {
417 ALOGE("%s: file read error", __func__);
418 goto done;
419 }
420 //replace '\n' to '\0'
421 idd = strtok(id, "\n");
422
423 if (find_sup_dev(idd)) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800424 ALOGV("%s: support usbid is %s", __func__, id);
jasmine cha75fa6f02018-03-30 15:41:33 +0800425 g_supported_dev |= SUPPORTED_USB;
426 } else
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800427 ALOGV("%s: usbid %s isn't found from %s", __func__, id, SUPPORT_DEV);
jasmine cha75fa6f02018-03-30 15:41:33 +0800428 } else {
429 g_supported_dev &= ~SUPPORTED_USB;
430 }
431
432done:
433 if (fd >= 0) close(fd);
434}
435
436// adev_init lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700437void ma_init(void *platform, maxx_audio_init_config_t init_config)
jasmine cha75fa6f02018-03-30 15:41:33 +0800438{
439 ma_stream_type_t i = 0;
440 int ret = 0;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800441 char lib_path[128] = {0};
442 char mps_path[128] = {0};
443 char cnf_path[128] = {0};
444 struct snd_card_split *snd_split_handle = NULL;
Arun Mirpurid750ac52019-04-12 18:33:55 -0700445
446 fp_platform_set_parameters = init_config.fp_platform_set_parameters;
447 fp_audio_extn_get_snd_card_split = init_config.fp_audio_extn_get_snd_card_split;
448
449 snd_split_handle = fp_audio_extn_get_snd_card_split();
jasmine cha75fa6f02018-03-30 15:41:33 +0800450
451 if (platform == NULL) {
452 ALOGE("%s: platform is NULL", __func__);
453 goto error;
454 }
455
456 if (my_data) { free(my_data); }
457 my_data = calloc(1, sizeof(struct ma_platform_data));
458 if (my_data == NULL) {
459 ALOGE("%s: ma_cal alloct fail", __func__);
460 goto error;
461 }
462
463 pthread_mutex_init(&my_data->lock, NULL);
464
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800465 my_data->platform = platform;
jasmine cha75fa6f02018-03-30 15:41:33 +0800466 ret = snprintf(lib_path, sizeof(lib_path), "%s/%s", LIB_MA_PATH, LIB_MA_PARAM);
467 if (ret < 0) {
468 ALOGE("%s: snprintf failed for lib %s, ret %d", __func__, LIB_MA_PARAM, ret);
469 goto error;
470 }
471
472 my_data->waves_handle = dlopen(lib_path, RTLD_NOW);
473 if (my_data->waves_handle == NULL) {
Jasmine Cha0ad09772019-02-25 20:09:34 +0800474 ALOGE("%s: DLOPEN failed for %s, %s", __func__, LIB_MA_PARAM, dlerror());
jasmine cha75fa6f02018-03-30 15:41:33 +0800475 goto error;
476 } else {
477 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM);
478
479 my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800480 MA_QDSP_PARAM_INIT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800481 if (!my_data->ma_param_init) {
482 ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror());
483 goto error;
484 }
485
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800486 my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(
487 my_data->waves_handle, MA_QDSP_PARAM_DEINIT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800488 if (!my_data->ma_param_deinit) {
489 ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror());
490 goto error;
491 }
492
justinwengbbffa622019-01-11 14:38:06 +0800493 my_data->ma_is_feature_used = (ma_is_feature_used_t)dlsym(my_data->waves_handle,
494 MA_QDSP_IS_FEATURE_USED);
495 if (!my_data->ma_is_feature_used) {
496 ALOGV("%s: dlsym error %s for ma_is_feature_used", __func__, dlerror());
497 }
498
499 my_data->ma_set_orientation = (ma_set_orientation_t)dlsym(my_data->waves_handle,
500 MA_QDSP_SET_ORIENTATION);
501 if (!my_data->ma_set_orientation) {
502 ALOGV("%s: dlsym error %s for ma_set_orientation", __func__, dlerror());
503 }
504
jasmine cha75fa6f02018-03-30 15:41:33 +0800505 my_data->ma_set_lr_swap = (ma_set_lr_swap_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800506 MA_QDSP_SET_LR_SWAP);
jasmine cha75fa6f02018-03-30 15:41:33 +0800507 if (!my_data->ma_set_lr_swap) {
508 ALOGE("%s: dlsym error %s for ma_set_lr_swap", __func__, dlerror());
509 goto error;
510 }
511
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800512 my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(
513 my_data->waves_handle, MA_QDSP_SET_MODE);
jasmine cha75fa6f02018-03-30 15:41:33 +0800514 if (!my_data->ma_set_sound_mode) {
515 ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror());
516 goto error;
517 }
518
519 my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800520 MA_QDSP_SET_VOL);
jasmine cha75fa6f02018-03-30 15:41:33 +0800521 if (!my_data->ma_set_volume) {
522 ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror());
523 goto error;
524 }
525
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800526 my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(
527 my_data->waves_handle, MA_QDSP_SET_VOLT);
jasmine cha75fa6f02018-03-30 15:41:33 +0800528 if (!my_data->ma_set_volume_table) {
529 ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror());
530 goto error;
531 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800532
533 my_data->ma_set_param = (ma_set_param_t)dlsym(
534 my_data->waves_handle, MA_QDSP_SET_PARAM);
535 if (!my_data->ma_set_param) {
536 ALOGE("%s: dlsym error %s for ma_set_param", __func__, dlerror());
537 goto error;
538 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800539 }
540
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800541 /* get preset table */
542 if (snd_split_handle == NULL) {
543 snprintf(mps_path, sizeof(mps_path), "%s/%s.mps",
544 PRESET_PATH, MPS_BASE_STRING);
545 } else {
546 snprintf(mps_path, sizeof(mps_path), "%s/%s_%s.mps",
547 PRESET_PATH, MPS_BASE_STRING, snd_split_handle->form_factor);
jasmine cha75fa6f02018-03-30 15:41:33 +0800548 }
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800549
550 /* get config files */
551 if (snd_split_handle == NULL) {
552 snprintf(cnf_path, sizeof(cnf_path), "%s/%s.ini",
553 PRESET_PATH, CONFIG_BASE_STRING);
554 } else {
555 snprintf(cnf_path, sizeof(cnf_path), "%s/%s_%s.ini",
556 PRESET_PATH, CONFIG_BASE_STRING, snd_split_handle->form_factor);
557 }
558
559 /* check file */
560 if (access(mps_path, R_OK) < 0) {
561 ALOGW("%s: file %s isn't existed.", __func__, mps_path);
562 goto error;
563 } else
564 ALOGD("%s: Loading mps file: %s", __func__, mps_path);
565
jasmine cha75fa6f02018-03-30 15:41:33 +0800566 /* TODO: check user preset table once the feature is enabled
567 if (access(USER_PRESET_PATH, F_OK) < 0 ){
568 ALOGW("%s: file %s isn't existed.", __func__, USER_PRESET_PATH);
569 goto error;
570 }
571 */
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800572
573 if (access(cnf_path, R_OK) < 0) {
574 ALOGW("%s: file %s isn't existed.", __func__, cnf_path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800575 goto error;
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800576 } else
577 ALOGD("%s: Loading ini file: %s", __func__, cnf_path);
jasmine cha75fa6f02018-03-30 15:41:33 +0800578
579 /* init ma parameter */
580 if (my_data->ma_param_init(&g_ma_audio_cal_handle,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800581 mps_path,
582 USER_PRESET_PATH, /* unused */
583 cnf_path,
584 &set_audio_cal)) {
jasmine cha75fa6f02018-03-30 15:41:33 +0800585 if (!g_ma_audio_cal_handle) {
586 ALOGE("%s: ma parameters initialize failed", __func__);
587 my_data->ma_param_deinit(&g_ma_audio_cal_handle);
588 goto error;
589 }
590 ALOGD("%s: ma parameters initialize successful", __func__);
591 } else {
592 ALOGE("%s: ma parameters initialize failed", __func__);
593 goto error;
594 }
595
596 /* init volume table */
597 for (i = 0; i < STREAM_MAX_TYPES; i++) {
598 ma_cur_state_table[i].vol = 0.0;
599 ma_cur_state_table[i].active = false;
600 }
601
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800602 my_data->speaker_lr_swap = false;
justinwengbbffa622019-01-11 14:38:06 +0800603 my_data->orientation_used = false;
604 my_data->dispaly_orientation = 0;
605
606 if (g_ma_audio_cal_handle && my_data->ma_is_feature_used) {
Jasmine Cha0ad09772019-02-25 20:09:34 +0800607 my_data->orientation_used = my_data->ma_is_feature_used(
608 g_ma_audio_cal_handle, "SET_ORIENTATION");
justinwengbbffa622019-01-11 14:38:06 +0800609 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800610
jasmine cha75fa6f02018-03-30 15:41:33 +0800611 return;
612
613error:
614 if (my_data) { free(my_data); }
615 my_data = NULL;
616}
617
618//adev_init lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700619void ma_deinit()
jasmine cha75fa6f02018-03-30 15:41:33 +0800620{
621 if (my_data) {
622 /* deinit ma parameter */
623 if (my_data->ma_param_deinit &&
624 my_data->ma_param_deinit(&g_ma_audio_cal_handle))
625 ALOGD("%s: ma parameters uninitialize successful", __func__);
626 else
627 ALOGD("%s: ma parameters uninitialize failed", __func__);
628
629 pthread_mutex_destroy(&my_data->lock);
630 free(my_data);
631 my_data = NULL;
632 }
633}
634
635// adev_init and adev lock held
Arun Mirpurid750ac52019-04-12 18:33:55 -0700636bool ma_set_state(struct audio_device *adev, int stream_type,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800637 float vol, bool active)
jasmine cha75fa6f02018-03-30 15:41:33 +0800638{
639 bool ret = false;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800640 struct ma_state pr_mstate;
jasmine cha75fa6f02018-03-30 15:41:33 +0800641
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800642 if (stream_type >= STREAM_MAX_TYPES ||
643 stream_type < STREAM_MIN_TYPES) {
644 ALOGE("%s: stream_type %d out of range.", __func__, stream_type);
645 return ret;
646 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800647
648 if (!my_data) {
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800649 ALOGV("%s: maxxaudio isn't initialized.", __func__);
jasmine cha75fa6f02018-03-30 15:41:33 +0800650 return ret;
651 }
652
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800653 ALOGV("%s: stream[%d] vol[%f] active[%s]",
654 __func__, stream_type, vol, active ? "true" : "false");
jasmine cha75fa6f02018-03-30 15:41:33 +0800655
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800656 pr_mstate.vol = ma_cur_state_table[(ma_stream_type_t)stream_type].vol;
657 pr_mstate.active = ma_cur_state_table[(ma_stream_type_t)stream_type].active;
658
659 // update condition: vol or active state changes
660 if (pr_mstate.vol != vol || pr_mstate.active != active) {
661
662 pthread_mutex_lock(&my_data->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800663
664 ma_cur_state_table[(ma_stream_type_t)stream_type].vol = vol;
665 ma_cur_state_table[(ma_stream_type_t)stream_type].active = active;
666
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800667 ret = check_and_send_all_audio_cal(adev, MA_CMD_VOL);
jasmine cha75fa6f02018-03-30 15:41:33 +0800668
669 pthread_mutex_unlock(&my_data->lock);
670 }
671
672 return ret;
673}
674
Arun Mirpurid750ac52019-04-12 18:33:55 -0700675void ma_set_device(struct audio_usecase *usecase)
jasmine cha75fa6f02018-03-30 15:41:33 +0800676{
677 int i = 0;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800678 struct ma_audio_cal_settings ma_cal;
jasmine cha75fa6f02018-03-30 15:41:33 +0800679
680 if (!my_data) {
681 ALOGV("%s: maxxaudio isn't initialized.", __func__);
682 return;
683 }
684
685 if (!valid_usecase(usecase)) {
686 ALOGV("%s: %d is not supported usecase", __func__, usecase->id);
687 return;
688 }
689
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800690 ma_cal_init(&ma_cal);
jasmine cha75fa6f02018-03-30 15:41:33 +0800691
692 /* update audio_cal and send it */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800693 ma_cal.common.app_type = usecase->stream.out->app_type_cfg.app_type;
694 ma_cal.common.device = usecase->stream.out->devices;
695 ALOGV("%s: send usecase(%d) app_type(%d) device(%d)",
696 __func__, usecase->id, ma_cal.common.app_type,
697 ma_cal.common.device);
jasmine cha75fa6f02018-03-30 15:41:33 +0800698
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800699 pthread_mutex_lock(&my_data->lock);
jasmine cha75fa6f02018-03-30 15:41:33 +0800700
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800701 if (is_active()) {
justinwengbbffa622019-01-11 14:38:06 +0800702
703 if (ma_cal.common.device & AUDIO_DEVICE_OUT_SPEAKER) {
704 if (my_data->orientation_used)
Jasmine Cha0ad09772019-02-25 20:09:34 +0800705 ma_set_rotation_l(usecase->stream.out->dev,
706 my_data->dispaly_orientation);
justinwengbbffa622019-01-11 14:38:06 +0800707 else
708 ma_set_swap_l(usecase->stream.out->dev, my_data->speaker_lr_swap);
709 } else {
710 if (my_data->orientation_used)
711 ma_set_rotation_l(usecase->stream.out->dev, 0);
712 else
713 ma_set_swap_l(usecase->stream.out->dev, false);
714 }
jasmine cha75fa6f02018-03-30 15:41:33 +0800715
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800716 if (!ma_set_volume_table_l(&ma_cal,
717 STREAM_MAX_TYPES,
718 ma_cur_state_table))
719 ALOGE("ma_set_volume_table_l returned with error.");
720 else
721 ALOGV("ma_set_volume_table_l success");
Jasmine Cha0ad09772019-02-25 20:09:34 +0800722 print_state_log();
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800723
jasmine cha75fa6f02018-03-30 15:41:33 +0800724 }
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800725 pthread_mutex_unlock(&my_data->lock);
jasmine cha75fa6f02018-03-30 15:41:33 +0800726}
727
Arun Mirpurid750ac52019-04-12 18:33:55 -0700728void ma_set_parameters(struct audio_device *adev,
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800729 struct str_parms *parms)
jasmine cha75fa6f02018-03-30 15:41:33 +0800730{
731 int ret;
jasmine cha75fa6f02018-03-30 15:41:33 +0800732 int val;
733 char value[128];
734
735 // do LR swap and usb recognition
736 ret = str_parms_get_int(parms, "rotation", &val);
737 if (ret >= 0) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800738 if (!my_data) {
739 ALOGV("%s: maxxaudio isn't initialized.", __func__);
740 return;
741 }
742
jasmine cha75fa6f02018-03-30 15:41:33 +0800743 switch (val) {
744 case 270:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800745 my_data->speaker_lr_swap = true;
jasmine cha75fa6f02018-03-30 15:41:33 +0800746 break;
747 case 0:
748 case 90:
749 case 180:
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800750 my_data->speaker_lr_swap = false;
jasmine cha75fa6f02018-03-30 15:41:33 +0800751 break;
752 }
justinwengbbffa622019-01-11 14:38:06 +0800753 my_data->dispaly_orientation = val;
754
755 if (my_data->orientation_used)
756 ma_set_rotation_l(adev, my_data->dispaly_orientation);
757 else
758 ma_set_swap_l(adev, my_data->speaker_lr_swap);
jasmine cha75fa6f02018-03-30 15:41:33 +0800759 }
760
761 // check connect status
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800762 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
763 sizeof(value));
jasmine cha75fa6f02018-03-30 15:41:33 +0800764 if (ret >= 0) {
765 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
766 if (audio_is_usb_out_device(device)) {
767 ret = str_parms_get_str(parms, "card", value, sizeof(value));
768 if (ret >= 0) {
769 const int card = atoi(value);
770 ma_support_usb(true, card);
771 }
772 }
773 }
774
775 // check disconnect status
Aalique Grahame5ce7fbe2019-01-28 12:08:13 -0800776 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
777 sizeof(value));
jasmine cha75fa6f02018-03-30 15:41:33 +0800778 if (ret >= 0) {
779 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
780 if (audio_is_usb_out_device(device)) {
781 ret = str_parms_get_str(parms, "card", value, sizeof(value));
782 if (ret >= 0) {
783 const int card = atoi(value);
784 ma_support_usb(false, card /*useless*/);
785 }
786 }
787 }
788}
789
Arun Mirpurid750ac52019-04-12 18:33:55 -0700790bool ma_supported_usb()
jasmine cha75fa6f02018-03-30 15:41:33 +0800791{
792 ALOGV("%s: current support 0x%x", __func__, g_supported_dev);
793 return (g_supported_dev & SUPPORTED_USB) ? true : false;
794}