audio: Add ACDB INIT extension

- Add an audio extension for ACDB
- ACDB Init from AHAL and STHAL are routed via this extension

CRs-Fixed: 2028493
Change-Id: Ib63c8fa4bf1f89d4dbfce8b6584ac1d8271e5f38
diff --git a/hal/Android.mk b/hal/Android.mk
index 9a8d27c..93e4083 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -54,7 +54,8 @@
 	audio_hw.c \
 	voice.c \
 	platform_info.c \
-	$(AUDIO_PLATFORM)/platform.c
+	$(AUDIO_PLATFORM)/platform.c \
+        acdb.c
 
 LOCAL_SRC_FILES += audio_extn/audio_extn.c \
                    audio_extn/utils.c
diff --git a/hal/Makefile.am b/hal/Makefile.am
index cbce291..0edf504 100644
--- a/hal/Makefile.am
+++ b/hal/Makefile.am
@@ -11,7 +11,8 @@
             platform_info.c \
             ${TARGET_PLATFORM}/platform.c \
             audio_extn/audio_extn.c \
-            audio_extn/utils.c
+            audio_extn/utils.c \
+            acdb.c
 
 if HDMI_EDID
 AM_CFLAGS += -DHDMI_EDID
diff --git a/hal/acdb.c b/hal/acdb.c
new file mode 100644
index 0000000..cbb96bd
--- /dev/null
+++ b/hal/acdb.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audio_hw_acdb"
+//#define LOG_NDEBUG 0
+#define LOG_NDDEBUG 0
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/log.h>
+#include <cutils/list.h>
+#include "acdb.h"
+#include "platform_api.h"
+
+int acdb_init(int snd_card_num)
+{
+
+    int result = -1;
+    char *cvd_version = NULL;
+
+    char *snd_card_name = NULL;
+    struct mixer *mixer = NULL;
+    struct acdb_platform_data *my_data = NULL;
+
+    if(snd_card_num < 0) {
+        ALOGE("invalid sound card number");
+        return result;
+    }
+
+    mixer = mixer_open(snd_card_num);
+    if (!mixer) {
+        ALOGE("%s: Unable to open the mixer card: %d", __func__,
+               snd_card_num);
+        goto cleanup;
+    }
+
+    my_data = calloc(1, sizeof(struct acdb_platform_data));
+    if (!my_data) {
+        ALOGE("failed to allocate acdb platform data");
+        goto cleanup;
+    }
+
+    list_init(&my_data->acdb_meta_key_list);
+
+    /* Extract META KEY LIST INFO */
+    platform_info_init(PLATFORM_INFO_XML_PATH, my_data, ACDB_EXTN);
+
+    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
+    if (my_data->acdb_handle == NULL) {
+        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
+        goto cleanup;
+    }
+
+    ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
+
+    my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
+                                                     "acdb_loader_init_v3");
+    if (my_data->acdb_init_v3 == NULL)
+        ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
+
+    my_data->acdb_init_v2 = (acdb_init_v2_t)dlsym(my_data->acdb_handle,
+                                                     "acdb_loader_init_v2");
+    if (my_data->acdb_init_v2 == NULL)
+        ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
+
+    my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
+                                                 "acdb_loader_init_ACDB");
+    if (my_data->acdb_init == NULL && my_data->acdb_init_v2 == NULL
+                                                 && my_data->acdb_init_v3 == NULL) {
+        ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
+        goto cleanup;
+    }
+
+    /* Get CVD version */
+    cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
+    if (!cvd_version) {
+        ALOGE("%s: Failed to allocate cvd version", __func__);
+        goto cleanup;
+    } else {
+        struct mixer_ctl *ctl = NULL;
+        int count = 0;
+
+        ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL);
+        if (!ctl) {
+            ALOGE("%s: Could not get ctl for mixer cmd - %s",  __func__, CVD_VERSION_MIXER_CTL);
+            goto cleanup;
+        }
+        mixer_ctl_update(ctl);
+
+        count = mixer_ctl_get_num_values(ctl);
+        if (count > MAX_CVD_VERSION_STRING_SIZE)
+            count = MAX_CVD_VERSION_STRING_SIZE;
+
+        result = mixer_ctl_get_array(ctl, cvd_version, count);
+        if (result != 0) {
+            ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__);
+            goto cleanup;
+        }
+    }
+
+    /* Get Sound card name */
+    snd_card_name = strdup(mixer_get_name(mixer));
+    if (!snd_card_name) {
+        ALOGE("failed to allocate memory for snd_card_name");
+        result = -1;
+        goto cleanup;
+    }
+
+    int key = 0;
+    struct listnode *node = NULL;
+    struct meta_key_list *key_info = NULL;
+
+    if (my_data->acdb_init_v3) {
+        result = my_data->acdb_init_v3(snd_card_name, cvd_version,
+                                       &my_data->acdb_meta_key_list);
+    } else if (my_data->acdb_init_v2) {
+        node = list_head(&my_data->acdb_meta_key_list);
+        key_info = node_to_item(node, struct meta_key_list, list);
+        key = key_info->cal_info.nKey;
+        result = my_data->acdb_init_v2(snd_card_name, cvd_version, key);
+    } else {
+        result = my_data->acdb_init();
+    }
+
+cleanup:
+    if (NULL != my_data) {
+        if (my_data->acdb_handle)
+            dlclose(my_data->acdb_handle);
+
+        struct listnode *node;
+        struct meta_key_list *key_info;
+        list_for_each(node, &my_data->acdb_meta_key_list) {
+            key_info = node_to_item(node, struct meta_key_list, list);
+            free(key_info);
+        }
+        free(my_data);
+    }
+
+    if (mixer)
+        mixer_close(mixer);
+
+    if (cvd_version)
+        free(cvd_version);
+
+    if (snd_card_name)
+        free(snd_card_name);
+
+    return result;
+}
+
+int acdb_set_metainfo_key(void *platform, char *name, int key) {
+
+    struct meta_key_list *key_info = (struct meta_key_list *)
+                                        calloc(1, sizeof(struct meta_key_list));
+    struct acdb_platform_data *pdata = (struct acdb_platform_data *)platform;
+    if (!key_info) {
+        ALOGE("%s: Could not allocate memory for key %d", __func__, key);
+        return -ENOMEM;
+    }
+
+    key_info->cal_info.nKey = key;
+    strlcpy(key_info->name, name, sizeof(key_info->name));
+    list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);
+
+    ALOGD("%s: successfully added module %s and key %d to the list", __func__,
+               key_info->name, key_info->cal_info.nKey);
+
+    return 0;
+}
diff --git a/hal/acdb.h b/hal/acdb.h
new file mode 100644
index 0000000..44a51ed
--- /dev/null
+++ b/hal/acdb.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ACDB_H
+#define ACDB_H
+
+#include <linux/msm_audio_calibration.h>
+
+#define MAX_CVD_VERSION_STRING_SIZE 100
+#define LIB_ACDB_LOADER "libacdbloader.so"
+#define CVD_VERSION_MIXER_CTL "CVD Version"
+#define ACDB_METAINFO_KEY_MODULE_NAME_LEN 100
+
+#ifdef LINUX_ENABLED
+#define PLATFORM_INFO_XML_PATH "/etc/audio_platform_info.xml"
+#else
+#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
+#endif
+
+/* Audio calibration related functions */
+typedef void (*acdb_deallocate_t)();
+typedef int  (*acdb_init_t)();
+typedef int  (*acdb_init_v2_t)(const char *, char *, int);
+typedef int  (*acdb_init_v3_t)(const char *, char *, struct listnode *);
+typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
+typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);
+typedef void (*acdb_send_voice_cal_t)(int, int);
+typedef int (*acdb_reload_vocvoltable_t)(int);
+typedef int  (*acdb_get_default_app_type_t)(void);
+typedef int (*acdb_loader_get_calibration_t)(char *attr, int size, void *data);
+typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
+typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+typedef int (*acdb_send_common_top_t) (void);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
+typedef int (*acdb_reload_t) (char *, char *, char *, int);
+typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
+typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
+
+struct meta_key_list {
+    struct listnode list;
+    struct audio_cal_info_metainfo cal_info;
+    char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
+};
+
+struct acdb_platform_data {
+    /* Audio calibration related functions */
+    void                       *acdb_handle;
+    acdb_init_t                acdb_init;
+    acdb_init_v2_t             acdb_init_v2;
+    acdb_init_v3_t             acdb_init_v3;
+    struct listnode acdb_meta_key_list;
+};
+
+int acdb_init(int);
+
+int acdb_set_metainfo_key(void *platform, char *name, int key);
+#endif //ACDB_H
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index bdb039f..c2a9604 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -587,6 +587,8 @@
 void audio_extn_utils_update_stream_app_type_cfg_for_usecase(
                                   struct audio_device *adev,
                                   struct audio_usecase *usecase);
+int audio_extn_utils_get_snd_card_num();
+
 #ifdef DS2_DOLBY_DAP_ENABLED
 #define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
 #define SET_HW_INFO_FUNC "dap_hal_set_hw_info"
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index b8be7aa..13faf64 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -1936,3 +1936,66 @@
     return 0;
 }
 #endif
+
+#define MAX_SND_CARD 8
+#define RETRY_US 500000
+#define RETRY_NUMBER 10
+
+int audio_extn_utils_get_snd_card_num()
+{
+
+    void *hw_info = NULL;
+    struct mixer *mixer = NULL;
+    int retry_num = 0;
+    int snd_card_num = 0;
+    char* snd_card_name = NULL;
+
+    while (snd_card_num < MAX_SND_CARD) {
+        mixer = mixer_open(snd_card_num);
+
+        while (!mixer && retry_num < RETRY_NUMBER) {
+            usleep(RETRY_US);
+            mixer = mixer_open(snd_card_num);
+            retry_num++;
+        }
+
+        if (!mixer) {
+            ALOGE("%s: Unable to open the mixer card: %d", __func__,
+                   snd_card_num);
+            retry_num = 0;
+            snd_card_num++;
+            continue;
+        }
+
+        snd_card_name = strdup(mixer_get_name(mixer));
+        if (!snd_card_name) {
+            ALOGE("failed to allocate memory for snd_card_name\n");
+            mixer_close(mixer);
+            return -1;
+        }
+        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
+
+        hw_info = hw_info_init(snd_card_name);
+        if (hw_info) {
+            ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
+            break;
+        }
+        ALOGE("%s: Failed to init hardware info", __func__);
+        retry_num = 0;
+        snd_card_num++;
+        free(snd_card_name);
+        mixer_close(mixer);
+    }
+
+    mixer_close(mixer);
+    hw_info_deinit(hw_info);
+    if (snd_card_name)
+        free(snd_card_name);
+
+    if (snd_card_num >= MAX_SND_CARD) {
+        ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
+        return -1;
+    }
+
+    return snd_card_num;
+}
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 935bae3..ef1bba0 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -32,13 +32,13 @@
 #include <platform_api.h>
 #include "platform.h"
 #include "audio_extn.h"
+#include "acdb.h"
 #include "voice_extn.h"
 #include "edid.h"
 #include "sound/compress_params.h"
 #include "sound/msmcal-hwdep.h"
 #include <dirent.h>
 #include <linux/msm_audio.h>
-#include "linux/msm_audio_calibration.h"
 
 #define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100)
 #define MAX_MIXER_XML_PATH  100
@@ -132,11 +132,6 @@
 #define DEFAULT_APP_TYPE_RX_PATH  0x11130
 #define DEFAULT_APP_TYPE_TX_PATH 0x11132
 
-/* Retry for delay in FW loading*/
-#define RETRY_NUMBER 20
-#define RETRY_US 500000
-#define MAX_SND_CARD 8
-
 #define SAMPLE_RATE_8KHZ  8000
 #define SAMPLE_RATE_16KHZ 16000
 
@@ -217,24 +212,7 @@
     CAL_MODE_RTAC           = 0x4
 };
 
-/* Audio calibration related functions */
-typedef void (*acdb_deallocate_t)();
-typedef int  (*acdb_init_t)(const char *, char *, int);
-typedef int  (*acdb_init_v3_t)(const char *, char *, struct listnode *);
-typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
-typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);
-typedef void (*acdb_send_voice_cal_t)(int, int);
-typedef int (*acdb_reload_vocvoltable_t)(int);
-typedef int  (*acdb_get_default_app_type_t)(void);
-typedef int (*acdb_loader_get_calibration_t)(char *attr, int size, void *data);
 acdb_loader_get_calibration_t acdb_loader_get_calibration;
-typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
-typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
-typedef int (*acdb_send_common_top_t) (void);
-typedef int (*acdb_set_codec_data_t) (void *, char *);
-typedef int (*acdb_reload_t) (char *, char *, char *, int);
-typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
-typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
 
 typedef struct codec_backend_cfg {
     uint32_t sample_rate;
@@ -248,12 +226,6 @@
 static native_audio_prop na_props = {0, 0, NATIVE_AUDIO_MODE_INVALID};
 static bool supports_true_32_bit = false;
 
-struct meta_key_list {
-    struct listnode list;
-    struct audio_cal_info_metainfo cal_info;
-    char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
-};
-
 static int max_be_dai_names = 0;
 static const struct be_dai_name_struct *be_dai_name_table;
 
@@ -2061,7 +2033,7 @@
 {
     char value[PROPERTY_VALUE_MAX];
     struct platform_data *my_data = NULL;
-    int retry_num = 0, snd_card_num = 0;
+    int snd_card_num = 0;
     const char *snd_card_name;
     char mixer_xml_path[MAX_MIXER_XML_PATH],ffspEnable[PROPERTY_VALUE_MAX];
     const char *mixer_ctl_name = "Set HPX ActiveBe";
@@ -2070,6 +2042,25 @@
     int wsaCount =0;
     bool is_wsa_combo_supported = false;
 
+    snd_card_num = audio_extn_utils_get_snd_card_num();
+    if(snd_card_num < 0) {
+        ALOGE("%s: Unable to find correct sound card", __func__);
+        return NULL;
+    }
+
+    adev->snd_card = snd_card_num;
+    ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
+
+    adev->mixer = mixer_open(snd_card_num);
+    if (!adev->mixer) {
+        ALOGE("%s: Unable to open the mixer card: %d", __func__,
+               snd_card_num);
+        return NULL;
+    }
+
+    snd_card_name = mixer_get_name(adev->mixer);
+    ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
+
     my_data = calloc(1, sizeof(struct platform_data));
 
     if (!my_data) {
@@ -2077,62 +2068,31 @@
         return NULL;
     }
 
-    while (snd_card_num < MAX_SND_CARD) {
-        adev->mixer = mixer_open(snd_card_num);
-
-        while (!adev->mixer && retry_num < RETRY_NUMBER) {
-            usleep(RETRY_US);
-            adev->mixer = mixer_open(snd_card_num);
-            retry_num++;
-        }
-
-        if (!adev->mixer) {
-            ALOGE("%s: Unable to open the mixer card: %d", __func__,
-                   snd_card_num);
-            retry_num = 0;
-            snd_card_num++;
-            continue;
-        }
-
-        snd_card_name = mixer_get_name(adev->mixer);
-        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
-
-        my_data->hw_info = hw_info_init(snd_card_name);
-        if (!my_data->hw_info) {
-            ALOGE("%s: Failed to init hardware info", __func__);
-        } else {
-            query_platform(snd_card_name, mixer_xml_path);
-            ALOGD("%s: mixer path file is %s", __func__,
-                                    mixer_xml_path);
-            if (audio_extn_read_xml(adev, snd_card_num, mixer_xml_path,
-                                    MIXER_XML_PATH_AUXPCM) == -ENOSYS) {
-                adev->audio_route = audio_route_init(snd_card_num,
-                                                 mixer_xml_path);
-            }
-            if (!adev->audio_route) {
-                ALOGE("%s: Failed to init audio route controls, aborting.",
-                       __func__);
-                free(my_data);
-                mixer_close(adev->mixer);
-                return NULL;
-            }
-            adev->snd_card = snd_card_num;
-            update_codec_type(snd_card_name);
-            update_interface(snd_card_name);
-            ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
-            break;
-        }
-        retry_num = 0;
-        snd_card_num++;
-        mixer_close(adev->mixer);
-    }
-
-    if (snd_card_num >= MAX_SND_CARD) {
-        ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
+    my_data->hw_info = hw_info_init(snd_card_name);
+    if (!my_data->hw_info) {
+        ALOGE("%s: Failed to init hardware info", __func__);
         free(my_data);
         return NULL;
     }
 
+    query_platform(snd_card_name, mixer_xml_path);
+    ALOGD("%s: mixer path file is %s", __func__,
+                            mixer_xml_path);
+    if (audio_extn_read_xml(adev, snd_card_num, mixer_xml_path,
+                            MIXER_XML_PATH_AUXPCM) == -ENOSYS) {
+        adev->audio_route = audio_route_init(snd_card_num,
+                                         mixer_xml_path);
+    }
+    if (!adev->audio_route) {
+        ALOGE("%s: Failed to init audio route controls, aborting.",
+               __func__);
+        free(my_data);
+        mixer_close(adev->mixer);
+        return NULL;
+    }
+    update_codec_type(snd_card_name);
+    update_interface(snd_card_name);
+
     my_data->adev = adev;
     my_data->fluence_in_spkr_mode = false;
     my_data->fluence_in_voice_call = false;
@@ -2239,12 +2199,12 @@
 
     /* Initialize ACDB and PCM ID's */
     if (is_external_codec)
-        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
+        platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data, PLATFORM);
     else if (!strncmp(snd_card_name, "sdm660-snd-card-skush",
                sizeof("sdm660-snd-card-skush")))
-        platform_info_init(PLATFORM_INFO_XML_PATH_SKUSH, my_data);
+        platform_info_init(PLATFORM_INFO_XML_PATH_SKUSH, my_data, PLATFORM);
     else
-        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data, PLATFORM);
 
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
@@ -2347,7 +2307,15 @@
             goto acdb_init_fail;
         }
 
-        platform_acdb_init(my_data);
+        int result = acdb_init(adev->snd_card);
+        if (!result) {
+            my_data->is_acdb_initialized = true;
+            ALOGD("ACDB initialized");
+            audio_hwdep_send_cal(my_data);
+        } else {
+            my_data->is_acdb_initialized = false;
+            ALOGD("ACDB initialization failed");
+        }
     }
     audio_extn_pm_vote();
 
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 1d32409..013d681 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -38,11 +38,11 @@
 #include <platform_api.h>
 #include "platform.h"
 #include "audio_extn.h"
+#include "acdb.h"
 #include "voice_extn.h"
 #include "edid.h"
 #include "sound/compress_params.h"
 #include "sound/msmcal-hwdep.h"
-#include <linux/msm_audio_calibration.h>
 
 #define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100)
 #define MIXER_FILE_DELIMITER "_"
@@ -103,11 +103,6 @@
 #define DEFAULT_APP_TYPE_RX_PATH  0x11130
 #define DEFAULT_APP_TYPE_TX_PATH  0x11132
 
-/* Retry for delay in FW loading*/
-#define RETRY_NUMBER 10
-#define RETRY_US 500000
-#define MAX_SND_CARD 8
-
 #define SAMPLE_RATE_8KHZ  8000
 #define SAMPLE_RATE_16KHZ 16000
 
@@ -187,23 +182,7 @@
     CAL_MODE_RTAC           = 0x4
 };
 
-/* Audio calibration related functions */
-typedef void (*acdb_deallocate_t)();
-typedef int  (*acdb_init_t)(const char *, char *, int);
-typedef int  (*acdb_init_v3_t)(const char *, char *, struct listnode *);
-typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
-typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);
-typedef void (*acdb_send_voice_cal_t)(int, int);
-typedef int (*acdb_reload_vocvoltable_t)(int);
-typedef int  (*acdb_get_default_app_type_t)(void);
-typedef int (*acdb_loader_get_calibration_t)(char *attr, int size, void *data);
 acdb_loader_get_calibration_t acdb_loader_get_calibration;
-typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
-typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
-typedef int (*acdb_send_common_top_t) (void);
-typedef int (*acdb_set_codec_data_t) (void *, char *);
-typedef int (*acdb_reload_t) (char *, char *, char *, int);
-typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
 
 typedef struct codec_backend_cfg {
     uint32_t sample_rate;
@@ -216,13 +195,6 @@
 
 static native_audio_prop na_props = {0, 0, NATIVE_AUDIO_MODE_INVALID};
 static bool supports_true_32_bit = false;
-typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
-
-struct meta_key_list {
-    struct listnode list;
-    struct audio_cal_info_metainfo cal_info;
-    char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
-};
 
 static int max_be_dai_names = 0;
 static const struct be_dai_name_struct *be_dai_name_table;
@@ -1752,125 +1724,109 @@
     char baseband[PROPERTY_VALUE_MAX];
     char value[PROPERTY_VALUE_MAX];
     struct platform_data *my_data = NULL;
-    int retry_num = 0, snd_card_num = 0;
     char *snd_card_name = NULL, *snd_card_name_t = NULL;
     char *snd_internal_name = NULL;
     char *tmp = NULL;
     char mixer_xml_file[MIXER_PATH_MAX_LENGTH]= {0};
     int idx;
 
-    my_data = calloc(1, sizeof(struct platform_data));
+    adev->snd_card = audio_extn_utils_get_snd_card_num();
+    if (adev->snd_card < 0) {
+        ALOGE("%s: Unable to find correct sound card", __func__);
+        return NULL;
+    }
+    ALOGD("%s: Opened sound card:%d", __func__, adev->snd_card);
 
-    if (!my_data) {
-        ALOGE("failed to allocate platform data");
+    adev->mixer = mixer_open(adev->snd_card);
+    if (!adev->mixer) {
+        ALOGE("%s: Unable to open the mixer card: %d", __func__,
+               adev->snd_card);
         return NULL;
     }
 
-    while (snd_card_num < MAX_SND_CARD) {
-        adev->mixer = mixer_open(snd_card_num);
-
-        while (!adev->mixer && retry_num < RETRY_NUMBER) {
-            usleep(RETRY_US);
-            adev->mixer = mixer_open(snd_card_num);
-            retry_num++;
-        }
-
-        if (!adev->mixer) {
-            ALOGE("%s: Unable to open the mixer card: %d", __func__,
-                   snd_card_num);
-            retry_num = 0;
-            snd_card_num++;
-            continue;
-        }
-
-        snd_card_name = strdup(mixer_get_name(adev->mixer));
-        if (!snd_card_name) {
-            ALOGE("failed to allocate memory for snd_card_name\n");
-            free(my_data);
-            mixer_close(adev->mixer);
-            return NULL;
-        }
-        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
-
-        my_data->hw_info = hw_info_init(snd_card_name);
-        if (!my_data->hw_info) {
-            ALOGE("%s: Failed to init hardware info", __func__);
-        } else {
-            if (platform_is_i2s_ext_modem(snd_card_name, my_data)) {
-                ALOGD("%s: Call MIXER_XML_PATH_I2S", __func__);
-
-                adev->audio_route = audio_route_init(snd_card_num,
-                                                     MIXER_XML_PATH_I2S);
-            } else {
-                /* Get the codec internal name from the sound card name
-                 * and form the mixer paths file name dynamically. This
-                 * is generic way of picking any codec name based mixer
-                 * files in future with no code change. This code
-                 * assumes mixer files are formed with format as
-                 * mixer_paths_internalcodecname.xml
-
-                 * If this dynamically read mixer files fails to open then it
-                 * falls back to default mixer file i.e mixer_paths.xml. This is
-                 * done to preserve backward compatibility but not mandatory as
-                 * long as the mixer files are named as per above assumption.
-                */
-                snd_card_name_t = strdup(snd_card_name);
-                snd_internal_name = strtok_r(snd_card_name_t, "-", &tmp);
-
-                if (snd_internal_name != NULL)
-                    snd_internal_name = strtok_r(NULL, "-", &tmp);
-
-                if (snd_internal_name != NULL) {
-                    strlcpy(mixer_xml_file, MIXER_XML_BASE_STRING,
-                        MIXER_PATH_MAX_LENGTH);
-                    strlcat(mixer_xml_file, MIXER_FILE_DELIMITER,
-                        MIXER_PATH_MAX_LENGTH);
-                    strlcat(mixer_xml_file, snd_internal_name,
-                        MIXER_PATH_MAX_LENGTH);
-                    strlcat(mixer_xml_file, MIXER_FILE_EXT,
-                        MIXER_PATH_MAX_LENGTH);
-                } else {
-                    strlcpy(mixer_xml_file, MIXER_XML_DEFAULT_PATH,
-                        MIXER_PATH_MAX_LENGTH);
-                }
-
-                if (F_OK == access(mixer_xml_file, 0)) {
-                    ALOGD("%s: Loading mixer file: %s", __func__, mixer_xml_file);
-                    if (audio_extn_read_xml(adev, snd_card_num, mixer_xml_file,
-                                    MIXER_XML_PATH_AUXPCM) == -ENOSYS)
-                        adev->audio_route = audio_route_init(snd_card_num,
-                                                       mixer_xml_file);
-                } else {
-                    ALOGD("%s: Loading default mixer file", __func__);
-                    if(audio_extn_read_xml(adev, snd_card_num, MIXER_XML_DEFAULT_PATH,
-                                    MIXER_XML_PATH_AUXPCM) == -ENOSYS)
-                        adev->audio_route = audio_route_init(snd_card_num,
-                                                       MIXER_XML_DEFAULT_PATH);
-                }
-            }
-            if (!adev->audio_route) {
-                ALOGE("%s: Failed to init audio route controls, aborting.",
-                       __func__);
-                if (my_data)
-                    free(my_data);
-                if (snd_card_name)
-                    free(snd_card_name);
-                if (snd_card_name_t)
-                    free(snd_card_name_t);
-                mixer_close(adev->mixer);
-                return NULL;
-            }
-            adev->snd_card = snd_card_num;
-            ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
-            break;
-        }
-        retry_num = 0;
-        snd_card_num++;
+    snd_card_name = strdup(mixer_get_name(adev->mixer));
+    if (!snd_card_name) {
+        ALOGE("failed to allocate memory for snd_card_name\n");
         mixer_close(adev->mixer);
+        return NULL;
     }
 
-    if (snd_card_num >= MAX_SND_CARD) {
-        ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
+    my_data = calloc(1, sizeof(struct platform_data));
+    if (!my_data) {
+        ALOGE("failed to allocate platform data");
+        if (snd_card_name)
+            free(snd_card_name);
+        mixer_close(adev->mixer);
+        return NULL;
+    }
+
+    my_data->hw_info = hw_info_init(snd_card_name);
+    if (!my_data->hw_info) {
+        ALOGE("failed to init hw_info");
+        mixer_close(adev->mixer);
+        if (my_data)
+            free(my_data);
+
+        if (snd_card_name)
+            free(snd_card_name);
+        return NULL;
+    }
+
+    if (platform_is_i2s_ext_modem(snd_card_name, my_data)) {
+        ALOGD("%s: Call MIXER_XML_PATH_I2S", __func__);
+
+        adev->audio_route = audio_route_init(adev->snd_card,
+                                             MIXER_XML_PATH_I2S);
+    } else {
+        /* Get the codec internal name from the sound card name
+         * and form the mixer paths file name dynamically. This
+         * is generic way of picking any codec name based mixer
+         * files in future with no code change. This code
+         * assumes mixer files are formed with format as
+         * mixer_paths_internalcodecname.xml
+
+         * If this dynamically read mixer files fails to open then it
+         * falls back to default mixer file i.e mixer_paths.xml. This is
+         * done to preserve backward compatibility but not mandatory as
+         * long as the mixer files are named as per above assumption.
+        */
+        snd_card_name_t = strdup(snd_card_name);
+        snd_internal_name = strtok_r(snd_card_name_t, "-", &tmp);
+
+        if (snd_internal_name != NULL) {
+            snd_internal_name = strtok_r(NULL, "-", &tmp);
+        }
+        if (snd_internal_name != NULL) {
+            strlcpy(mixer_xml_file, MIXER_XML_BASE_STRING,
+                MIXER_PATH_MAX_LENGTH);
+            strlcat(mixer_xml_file, MIXER_FILE_DELIMITER,
+                MIXER_PATH_MAX_LENGTH);
+            strlcat(mixer_xml_file, snd_internal_name,
+                MIXER_PATH_MAX_LENGTH);
+            strlcat(mixer_xml_file, MIXER_FILE_EXT,
+                MIXER_PATH_MAX_LENGTH);
+        } else {
+            strlcpy(mixer_xml_file, MIXER_XML_DEFAULT_PATH,
+                MIXER_PATH_MAX_LENGTH);
+        }
+
+        if (F_OK == access(mixer_xml_file, 0)) {
+            ALOGD("%s: Loading mixer file: %s", __func__, mixer_xml_file);
+            if (audio_extn_read_xml(adev, adev->snd_card, mixer_xml_file,
+                            MIXER_XML_PATH_AUXPCM) == -ENOSYS)
+                adev->audio_route = audio_route_init(adev->snd_card,
+                                               mixer_xml_file);
+        } else {
+            ALOGD("%s: Loading default mixer file", __func__);
+            if (audio_extn_read_xml(adev, adev->snd_card, MIXER_XML_DEFAULT_PATH,
+                            MIXER_XML_PATH_AUXPCM) == -ENOSYS)
+                adev->audio_route = audio_route_init(adev->snd_card,
+                                               MIXER_XML_DEFAULT_PATH);
+        }
+    }
+    if (!adev->audio_route) {
+        ALOGE("%s: Failed to init audio route controls, aborting.",
+               __func__);
         if (my_data)
             free(my_data);
         if (snd_card_name)
@@ -1954,9 +1910,9 @@
 
     /* Initialize ACDB ID's */
     if (my_data->is_i2s_ext_modem)
-        platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
+        platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data, PLATFORM);
     else
-        platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+        platform_info_init(PLATFORM_INFO_XML_PATH, my_data, PLATFORM);
 
     my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
     my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
@@ -2059,7 +2015,16 @@
             ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files", __func__, dlerror());
             goto acdb_init_fail;
         }
-        platform_acdb_init(my_data);
+
+        int result = acdb_init(adev->snd_card);
+        if (!result) {
+            my_data->is_acdb_initialized = true;
+            ALOGD("ACDB initialized");
+            audio_hwdep_send_cal(my_data);
+        } else {
+            my_data->is_acdb_initialized = false;
+            ALOGD("ACDB initialization failed");
+        }
     }
 
     /* init keep-alive for compress passthru */
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 269aedc..1b6c1f1 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -31,7 +31,11 @@
 #define SAMPLE_RATE_11025 11025
 #define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
 #define MAX_VOLUME_CAL_STEPS 15
-#define ACDB_METAINFO_KEY_MODULE_NAME_LEN 100
+
+typedef enum {
+    PLATFORM,
+    ACDB_EXTN,
+} caller_t;
 
 struct amp_db_and_gain_table {
     float amp;
@@ -142,7 +146,7 @@
 int platform_get_snd_device_backend_index(snd_device_t device);
 
 /* From platform_info.c */
-int platform_info_init(const char *filename, void *);
+int platform_info_init(const char *filename, void *, caller_t);
 
 void platform_snd_card_update(void *platform, int snd_scard_state);
 
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 6b64261..61dfb5d 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -36,6 +36,7 @@
 #include <cutils/log.h>
 #include <cutils/str_parms.h>
 #include <audio_hw.h>
+#include "acdb.h"
 #include "platform_api.h"
 #include <platform.h>
 #include <math.h>
@@ -81,6 +82,7 @@
 static section_t section;
 
 struct platform_info {
+    caller_t          caller;
     void             *platform;
     struct str_parms *kvpairs;
 };
@@ -369,9 +371,21 @@
     }
 
     int key = atoi((char *)attr[3]);
-    if (platform_set_acdb_metainfo_key(my_data.platform, (char*)attr[1], key) < 0) {
-        ALOGE("%s: key %d was not set!", __func__, key);
-        goto done;
+    switch(my_data.caller) {
+        case ACDB_EXTN:
+                if(acdb_set_metainfo_key(my_data.platform, (char*)attr[1], key) < 0) {
+                    ALOGE("%s: key %d was not set!", __func__, key);
+                    goto done;
+                }
+                break;
+        case PLATFORM:
+                if(platform_set_acdb_metainfo_key(my_data.platform, (char*)attr[1], key) < 0) {
+                    ALOGE("%s: key %d was not set!", __func__, key);
+                    goto done;
+                }
+                break;
+        default:
+                ALOGE("%s: unknown caller!", __func__);
     }
 
 done:
@@ -381,58 +395,73 @@
 static void start_tag(void *userdata __unused, const XML_Char *tag_name,
                       const XML_Char **attr)
 {
-    if (strcmp(tag_name, "bit_width_configs") == 0) {
-        section = BITWIDTH;
-    } else if (strcmp(tag_name, "acdb_ids") == 0) {
-        section = ACDB;
-    } else if (strcmp(tag_name, "pcm_ids") == 0) {
-        section = PCM_ID;
-    } else if (strcmp(tag_name, "backend_names") == 0) {
-        section = BACKEND_NAME;
-    } else if (strcmp(tag_name, "config_params") == 0) {
-        section = CONFIG_PARAMS;
-    } else if (strcmp(tag_name, "interface_names") == 0) {
-        section = INTERFACE_NAME;
-    } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
-        section = GAIN_LEVEL_MAPPING;
-    } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
-        section = ACDB_METAINFO_KEY;
-    } else if (strcmp(tag_name, "device") == 0) {
-        if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
-            (section != INTERFACE_NAME)) {
-            ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface names");
-            return;
-        }
+    if (my_data.caller == ACDB_EXTN) {
+        if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
+            section = ACDB_METAINFO_KEY;
+        } else if (strcmp(tag_name, "param") == 0) {
+            if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) {
+                ALOGE("param tag only supported with CONFIG_PARAMS section");
+                return;
+            }
 
-        /* call into process function for the current section */
-        section_process_fn fn = section_table[section];
-        fn(attr);
-    } else if (strcmp(tag_name, "gain_level_map") == 0) {
-        if (section != GAIN_LEVEL_MAPPING) {
-            ALOGE("usecase tag only supported with GAIN_LEVEL_MAPPING section");
-            return;
+            section_process_fn fn = section_table[section];
+            fn(attr);
         }
+    } else if(my_data.caller == PLATFORM) {
+        if (strcmp(tag_name, "bit_width_configs") == 0) {
+            section = BITWIDTH;
+        } else if (strcmp(tag_name, "acdb_ids") == 0) {
+            section = ACDB;
+        } else if (strcmp(tag_name, "pcm_ids") == 0) {
+            section = PCM_ID;
+        } else if (strcmp(tag_name, "backend_names") == 0) {
+            section = BACKEND_NAME;
+        } else if (strcmp(tag_name, "config_params") == 0) {
+            section = CONFIG_PARAMS;
+        } else if (strcmp(tag_name, "interface_names") == 0) {
+            section = INTERFACE_NAME;
+        } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
+            section = GAIN_LEVEL_MAPPING;
+        } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
+            section = ACDB_METAINFO_KEY;
+        } else if (strcmp(tag_name, "device") == 0) {
+            if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
+                (section != INTERFACE_NAME)) {
+                ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface names");
+                return;
+            }
 
-        section_process_fn fn = section_table[GAIN_LEVEL_MAPPING];
-        fn(attr);
-    } else if (strcmp(tag_name, "usecase") == 0) {
-        if (section != PCM_ID) {
-            ALOGE("usecase tag only supported with PCM_ID section");
-            return;
+            /* call into process function for the current section */
+            section_process_fn fn = section_table[section];
+            fn(attr);
+        } else if (strcmp(tag_name, "gain_level_map") == 0) {
+            if (section != GAIN_LEVEL_MAPPING) {
+                ALOGE("usecase tag only supported with GAIN_LEVEL_MAPPING section");
+                return;
+            }
+
+            section_process_fn fn = section_table[GAIN_LEVEL_MAPPING];
+            fn(attr);
+        } else if (strcmp(tag_name, "usecase") == 0) {
+            if (section != PCM_ID) {
+                ALOGE("usecase tag only supported with PCM_ID section");
+                return;
+            }
+
+            section_process_fn fn = section_table[PCM_ID];
+            fn(attr);
+        } else if (strcmp(tag_name, "param") == 0) {
+            if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) {
+                ALOGE("param tag only supported with CONFIG_PARAMS section");
+                return;
+            }
+
+            section_process_fn fn = section_table[section];
+            fn(attr);
         }
-
-        section_process_fn fn = section_table[PCM_ID];
-        fn(attr);
-    } else if (strcmp(tag_name, "param") == 0) {
-        if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) {
-            ALOGE("param tag only supported with CONFIG_PARAMS section");
-            return;
-        }
-
-        section_process_fn fn = section_table[section];
-        fn(attr);
+    } else {
+            ALOGE("%s: unknown caller!", __func__);
     }
-
     return;
 }
 
@@ -448,7 +477,9 @@
         section = ROOT;
     } else if (strcmp(tag_name, "config_params") == 0) {
         section = ROOT;
-        platform_set_parameters(my_data.platform, my_data.kvpairs);
+        if (my_data.caller == PLATFORM) {
+            platform_set_parameters(my_data.platform, my_data.kvpairs);
+        }
     } else if (strcmp(tag_name, "interface_names") == 0) {
         section = ROOT;
     } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
@@ -458,7 +489,7 @@
     }
 }
 
-int platform_info_init(const char *filename, void *platform)
+int platform_info_init(const char *filename, void *platform, caller_t caller_type)
 {
     XML_Parser      parser;
     FILE            *file;
@@ -483,6 +514,7 @@
         goto err_close_file;
     }
 
+    my_data.caller = caller_type;
     my_data.platform = platform;
     my_data.kvpairs = str_parms_create();