hal: add support to override volume gain to step mapping table

- if customer mapping is added in platform info file, use that
- in absence of customer table use default mapping

CRs-Fixed: 1089771
Change-Id: I4bf8bcf1913f16ad6298ff1f3fa5dd649c889b2a
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 4ccb89c..8e12dd6 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -38,6 +38,7 @@
 #include <audio_hw.h>
 #include "platform_api.h"
 #include <platform.h>
+#include <math.h>
 
 #define BUF_SIZE                    1024
 
@@ -49,6 +50,7 @@
     BACKEND_NAME,
     INTERFACE_NAME,
     CONFIG_PARAMS,
+    GAIN_LEVEL_MAPPING,
 } section_t;
 
 typedef void (* section_process_fn)(const XML_Char **attr);
@@ -60,6 +62,7 @@
 static void process_interface_name(const XML_Char **attr);
 static void process_config_params(const XML_Char **attr);
 static void process_root(const XML_Char **attr);
+static void process_gain_db_to_level_map(const XML_Char **attr);
 
 static section_process_fn section_table[] = {
     [ROOT] = process_root,
@@ -69,6 +72,7 @@
     [BACKEND_NAME] = process_backend_name,
     [INTERFACE_NAME] = process_interface_name,
     [CONFIG_PARAMS] = process_config_params,
+    [GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map,
 };
 
 static section_t section;
@@ -206,6 +210,30 @@
     return;
 }
 
+static void process_gain_db_to_level_map(const XML_Char **attr)
+{
+    struct amp_db_and_gain_table tbl_entry;
+
+    if ((strcmp(attr[0], "db") != 0) ||
+        (strcmp(attr[2], "level") != 0)) {
+        ALOGE("%s: invalid attribute passed  %s %sexpected amp db level",
+               __func__, attr[0], attr[2]);
+        goto done;
+    }
+
+    tbl_entry.db = atof(attr[1]);
+    tbl_entry.amp = exp(tbl_entry.db * 0.115129f);
+    tbl_entry.level = atoi(attr[3]);
+
+    ALOGV("%s: amp [%f]  db [%f] level [%d]", __func__,
+           tbl_entry.amp, tbl_entry.db, tbl_entry.level);
+    platform_add_gain_level_mapping(&tbl_entry);
+
+done:
+    return;
+}
+
+
 static void process_acdb_id(const XML_Char **attr)
 {
     int index;
@@ -337,6 +365,8 @@
         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, "device") == 0) {
         if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
             (section != INTERFACE_NAME)) {
@@ -347,6 +377,14 @@
         /* 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");
@@ -383,6 +421,8 @@
         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) {
+        section = ROOT;
     }
 }