hal: add multizone input bus support for automotive

Add primary capture, front passenger capture and
rear seat capture support for multi-zone audio
support on automotive platform.

Change-Id: I36c9776381b4e08a237fd70efaa9c7475c3700a0
Signed-off-by: Huicheng Liu <huicliu@codeaurora.org>
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index c3c80a0..ee27bfa 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -6086,6 +6086,9 @@
 typedef int (*auto_hal_open_output_stream_t)(struct stream_out*);
 static auto_hal_open_output_stream_t auto_hal_open_output_stream;
 
+typedef int (*auto_hal_open_input_stream_t)(struct stream_in*);
+static auto_hal_open_input_stream_t auto_hal_open_input_stream;
+
 typedef bool (*auto_hal_is_bus_device_usecase_t)(audio_usecase_t);
 static auto_hal_is_bus_device_usecase_t auto_hal_is_bus_device_usecase;
 
@@ -6117,6 +6120,10 @@
                                 audio_usecase_t);
 static auto_hal_get_output_snd_device_t auto_hal_get_output_snd_device;
 
+typedef snd_device_t (*auto_hal_get_snd_device_for_car_audio_stream_t)(int
+                                car_audio_stream);
+static auto_hal_get_snd_device_for_car_audio_stream_t auto_hal_get_snd_device_for_car_audio_stream;
+
 int auto_hal_feature_init(bool is_feature_enabled)
 {
     ALOGD("%s: Called with feature %s", __func__,
@@ -6146,6 +6153,9 @@
             !(auto_hal_open_output_stream =
                  (auto_hal_open_output_stream_t)dlsym(
                             auto_hal_lib_handle, "auto_hal_open_output_stream")) ||
+            !(auto_hal_open_input_stream =
+                 (auto_hal_open_input_stream_t)dlsym(
+                            auto_hal_lib_handle, "auto_hal_open_input_stream")) ||
             !(auto_hal_is_bus_device_usecase =
                  (auto_hal_is_bus_device_usecase_t)dlsym(
                             auto_hal_lib_handle, "auto_hal_is_bus_device_usecase")) ||
@@ -6169,7 +6179,10 @@
                             auto_hal_lib_handle, "auto_hal_get_input_snd_device")) ||
             !(auto_hal_get_output_snd_device =
                  (auto_hal_get_output_snd_device_t)dlsym(
-                            auto_hal_lib_handle, "auto_hal_get_output_snd_device"))) {
+                            auto_hal_lib_handle, "auto_hal_get_output_snd_device")) ||
+            !(auto_hal_get_snd_device_for_car_audio_stream =
+                 (auto_hal_get_snd_device_for_car_audio_stream_t)dlsym(
+                            auto_hal_lib_handle, "auto_hal_get_snd_device_for_car_audio_stream"))) {
             ALOGE("%s: dlsym failed", __func__);
             goto feature_disabled;
         }
@@ -6189,6 +6202,7 @@
     auto_hal_release_audio_patch = NULL;
     auto_hal_get_car_audio_stream_from_address = NULL;
     auto_hal_open_output_stream = NULL;
+    auto_hal_open_input_stream = NULL;
     auto_hal_is_bus_device_usecase = NULL;
     auto_hal_get_audio_port = NULL;
     auto_hal_set_audio_port_config = NULL;
@@ -6197,6 +6211,7 @@
     auto_hal_stop_hfp_downlink = NULL;
     auto_hal_get_input_snd_device = NULL;
     auto_hal_get_output_snd_device = NULL;
+    auto_hal_get_snd_device_for_car_audio_stream = NULL;
 
     ALOGW(":: %s: ---- Feature AUTO_HAL is disabled ----", __func__);
     return -ENOSYS;
@@ -6267,6 +6282,12 @@
                             auto_hal_open_output_stream(out): -ENOSYS);
 }
 
+int audio_extn_auto_hal_open_input_stream(struct stream_in *in)
+{
+    return ((auto_hal_open_input_stream) ?
+                            auto_hal_open_input_stream(in): -ENOSYS);
+}
+
 bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id)
 {
     return ((auto_hal_is_bus_device_usecase) ?
@@ -6321,6 +6342,12 @@
     return ((auto_hal_get_output_snd_device) ?
                             auto_hal_get_output_snd_device(adev, uc_id): SND_DEVICE_NONE);
 }
+
+snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(int car_audio_stream)
+{
+    return ((auto_hal_get_snd_device_for_car_audio_stream) ?
+                            auto_hal_get_snd_device_for_car_audio_stream(car_audio_stream): SND_DEVICE_NONE);
+}
 // END: AUTO_HAL ===================================================================
 
 void audio_extn_feature_init()
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8820d01..047eba8 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1346,6 +1346,16 @@
 #ifndef AUDIO_OUTPUT_FLAG_REAR_SEAT
 #define AUDIO_OUTPUT_FLAG_REAR_SEAT 0x2000000
 #endif
+#ifndef AUDIO_INPUT_FLAG_PRIMARY
+#define AUDIO_INPUT_FLAG_PRIMARY 0x100000
+#endif
+#ifndef AUDIO_INPUT_FLAG_FRONT_PASSENGER
+#define AUDIO_INPUT_FLAG_FRONT_PASSENGER 0x200000
+#endif
+#ifndef AUDIO_INPUT_FLAG_REAR_SEAT
+#define AUDIO_INPUT_FLAG_REAR_SEAT 0x400000
+#endif
+
 int audio_extn_auto_hal_init(struct audio_device *adev);
 void audio_extn_auto_hal_deinit(void);
 int audio_extn_auto_hal_create_audio_patch(struct audio_hw_device *dev,
@@ -1358,6 +1368,7 @@
                                 audio_patch_handle_t handle);
 int audio_extn_auto_hal_get_car_audio_stream_from_address(const char *address);
 int audio_extn_auto_hal_open_output_stream(struct stream_out *out);
+int audio_extn_auto_hal_open_input_stream(struct stream_in *in);
 bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id);
 int audio_extn_auto_hal_get_audio_port(struct audio_hw_device *dev,
                                 struct audio_port *config);
@@ -1373,6 +1384,7 @@
                                 audio_usecase_t uc_id);
 snd_device_t audio_extn_auto_hal_get_output_snd_device(struct audio_device *adev,
                                 audio_usecase_t uc_id);
+snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(int car_audio_stream);
 
 typedef streams_input_ctxt_t* (*fp_in_get_stream_t)(struct audio_device*, audio_io_handle_t);
 typedef streams_output_ctxt_t* (*fp_out_get_stream_t)(struct audio_device*, audio_io_handle_t);
diff --git a/hal/audio_extn/auto_hal.c b/hal/audio_extn/auto_hal.c
index abddeb0..44c4ebf 100644
--- a/hal/audio_extn/auto_hal.c
+++ b/hal/audio_extn/auto_hal.c
@@ -309,6 +309,35 @@
     return (0x1 << bus_num);
 }
 
+int auto_hal_open_input_stream(struct stream_in *in)
+{
+    int ret = 0;
+
+    switch(in->car_audio_stream) {
+    case CAR_AUDIO_STREAM_IN_PRIMARY:
+        in->usecase = USECASE_AUDIO_RECORD_BUS;
+        if (in->flags == AUDIO_INPUT_FLAG_NONE)
+            in->flags |= AUDIO_INPUT_FLAG_PRIMARY;
+        break;
+    case CAR_AUDIO_STREAM_IN_FRONT_PASSENGER:
+        in->usecase = USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER;
+        if (in->flags == AUDIO_INPUT_FLAG_NONE)
+            in->flags |= AUDIO_INPUT_FLAG_FRONT_PASSENGER;
+        break;
+    case CAR_AUDIO_STREAM_IN_REAR_SEAT:
+        in->usecase = USECASE_AUDIO_RECORD_BUS_REAR_SEAT;
+        if (in->flags == AUDIO_INPUT_FLAG_NONE)
+            in->flags |= AUDIO_INPUT_FLAG_REAR_SEAT;
+        break;
+    default:
+        ALOGE("%s: Car audio stream 0x%x not supported", __func__,
+            in->car_audio_stream);
+        ret = -EINVAL;
+    }
+
+    return ret;
+}
+
 int auto_hal_open_output_stream(struct stream_out *out)
 {
     int ret = 0;
@@ -401,11 +430,11 @@
     return false;
 }
 
-snd_device_t auto_hal_get_snd_device_for_car_audio_stream(struct stream_out *out)
+snd_device_t auto_hal_get_snd_device_for_car_audio_stream(int car_audio_stream)
 {
     snd_device_t snd_device = SND_DEVICE_NONE;
 
-    switch(out->car_audio_stream) {
+    switch(car_audio_stream) {
     case CAR_AUDIO_STREAM_MEDIA:
         snd_device = SND_DEVICE_OUT_BUS_MEDIA;
         break;
@@ -424,9 +453,18 @@
     case CAR_AUDIO_STREAM_REAR_SEAT:
         snd_device = SND_DEVICE_OUT_BUS_RSE;
         break;
+    case CAR_AUDIO_STREAM_IN_PRIMARY:
+        snd_device = SND_DEVICE_IN_BUS;
+        break;
+    case CAR_AUDIO_STREAM_IN_FRONT_PASSENGER:
+        snd_device = SND_DEVICE_IN_BUS_PAX;
+        break;
+    case CAR_AUDIO_STREAM_IN_REAR_SEAT:
+        snd_device = SND_DEVICE_IN_BUS_RSE;
+        break;
     default:
-        ALOGE("%s: Unknown car audio stream (%x)",
-            __func__, out->car_audio_stream);
+        ALOGE("%s: Unknown car audio stream (%#x)",
+            __func__, car_audio_stream);
     }
     return snd_device;
 }
diff --git a/hal/audio_extn/auto_hal.h b/hal/audio_extn/auto_hal.h
index 15a65d2..c1b3250 100644
--- a/hal/audio_extn/auto_hal.h
+++ b/hal/audio_extn/auto_hal.h
@@ -66,4 +66,7 @@
     USECASE_AUDIO_PLAYBACK_PHONE,
     USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER,
     USECASE_AUDIO_PLAYBACK_REAR_SEAT,
+    USECASE_AUDIO_RECORD_BUS,
+    USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER,
+    USECASE_AUDIO_RECORD_BUS_REAR_SEAT,
 };
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 366fc85..4cd84b6 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -164,6 +164,9 @@
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_VOIP_TX),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_AV_SYNC),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_DIRECT),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_PRIMARY),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FRONT_PASSENGER),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_REAR_SEAT),
 };
 
 const struct string_to_enum s_format_name_to_enum_table[] = {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f441d3b..0b9842a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -422,6 +422,10 @@
     [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
     [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
     [USECASE_ICC_CALL] = "icc-call",
+
+    [USECASE_AUDIO_RECORD_BUS] = "audio-record",
+    [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
+    [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -2853,11 +2857,14 @@
                     if (!priority_in)
                         priority_in = usecase->stream.in;
                 }
-
-                in_snd_device = platform_get_input_snd_device(adev->platform,
-                                                              priority_in,
-                                                              &out_devices,
-                                                              usecase->type);
+                if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
+                    in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
+                }
+                else
+                    in_snd_device = platform_get_input_snd_device(adev->platform,
+                                                                  priority_in,
+                                                                  &out_devices,
+                                                                  usecase->type);
             }
         }
     }
@@ -9462,6 +9469,20 @@
 
     in->usecase = USECASE_AUDIO_RECORD;
 
+    /* validate bus device address */
+    if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
+        /* extract car audio stream index */
+        in->car_audio_stream =
+            audio_extn_auto_hal_get_car_audio_stream_from_address(address);
+        if (in->car_audio_stream < 0) {
+            ALOGE("%s: invalid car audio stream %x",
+                __func__, in->car_audio_stream);
+            ret = -EINVAL;
+            goto err_open;
+        }
+        ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
+    }
+
     if (in->source == AUDIO_SOURCE_FM_TUNER) {
         if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
             in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
@@ -9665,6 +9686,14 @@
                 }
             }
         }
+        if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
+           ret = audio_extn_auto_hal_open_input_stream(in);
+           if (ret) {
+               ALOGE("%s: Failed to open input stream for bus device", __func__);
+               ret = -EINVAL;
+               goto err_open;
+           }
+        }
     }
     if (audio_extn_ssr_get_stream() != in)
         in->config.channels = channel_count;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index da68656..838622e 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -244,6 +244,9 @@
     USECASE_AUDIO_PLAYBACK_PHONE,
     USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER,
     USECASE_AUDIO_PLAYBACK_REAR_SEAT,
+    USECASE_AUDIO_RECORD_BUS,
+    USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER,
+    USECASE_AUDIO_RECORD_BUS_REAR_SEAT,
 
     /*Audio FM Tuner usecase*/
     USECASE_AUDIO_FM_TUNER_EXT,
@@ -330,12 +333,15 @@
  */
 #define MAX_CAR_AUDIO_STREAMS    32
 enum {
-    CAR_AUDIO_STREAM_MEDIA            = 0x1,
-    CAR_AUDIO_STREAM_SYS_NOTIFICATION = 0x2,
-    CAR_AUDIO_STREAM_NAV_GUIDANCE     = 0x4,
-    CAR_AUDIO_STREAM_PHONE            = 0x8,
-    CAR_AUDIO_STREAM_FRONT_PASSENGER  = 0x100,
-    CAR_AUDIO_STREAM_REAR_SEAT        = 0x10000,
+    CAR_AUDIO_STREAM_MEDIA              = 0x1,
+    CAR_AUDIO_STREAM_SYS_NOTIFICATION   = 0x2,
+    CAR_AUDIO_STREAM_NAV_GUIDANCE       = 0x4,
+    CAR_AUDIO_STREAM_PHONE              = 0x8,
+    CAR_AUDIO_STREAM_IN_PRIMARY         = 0x10,
+    CAR_AUDIO_STREAM_FRONT_PASSENGER    = 0x100,
+    CAR_AUDIO_STREAM_IN_FRONT_PASSENGER = 0x200,
+    CAR_AUDIO_STREAM_REAR_SEAT          = 0x10000,
+    CAR_AUDIO_STREAM_IN_REAR_SEAT       = 0x20000,
 };
 
 struct stream_app_type_cfg {
@@ -464,7 +470,7 @@
     error_log_t *error_log;
     bool pspd_coeff_sent;
 
-    int car_audio_stream;
+    int car_audio_stream; /* handle for car_audio_stream */
 
     union {
         char *addr;
@@ -538,6 +544,8 @@
     error_log_t *error_log;
 
     simple_stats_t start_latency_ms;
+
+    int car_audio_stream; /* handle for car_audio_stream*/
 };
 
 typedef enum {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 526a88f..4ad343f 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -523,6 +523,10 @@
                                           REAR_SEAT_PCM_DEVICE},
     [USECASE_AUDIO_FM_TUNER_EXT] = {-1, -1},
     [USECASE_ICC_CALL] = {ICC_PCM_DEVICE, ICC_PCM_DEVICE},
+
+    [USECASE_AUDIO_RECORD_BUS] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = {FRONT_PASSENGER_PCM_DEVICE, FRONT_PASSENGER_PCM_DEVICE},
+    [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = {REAR_SEAT_PCM_DEVICE, REAR_SEAT_PCM_DEVICE},
 };
 
 /* Array to store sound devices */
@@ -778,6 +782,8 @@
     [SND_DEVICE_OUT_VOIP_HEADPHONES] = "voip-headphones",
     [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic",
     [SND_DEVICE_IN_BUS] = "bus-mic",
+    [SND_DEVICE_IN_BUS_PAX] = "bus-mic",
+    [SND_DEVICE_IN_BUS_RSE] = "bus-mic",
     [SND_DEVICE_IN_EC_REF_LOOPBACK] = "ec-ref-loopback",
     [SND_DEVICE_IN_HANDSET_DMIC_AND_EC_REF_LOOPBACK] = "handset-dmic-and-ec-ref-loopback",
     [SND_DEVICE_IN_HANDSET_QMIC_AND_EC_REF_LOOPBACK] = "handset-qmic-and-ec-ref-loopback",
@@ -1069,6 +1075,8 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 4,
     [SND_DEVICE_IN_VOICE_HEARING_AID] = 44,
     [SND_DEVICE_IN_BUS] = 11,
+    [SND_DEVICE_IN_BUS_PAX] = 11,
+    [SND_DEVICE_IN_BUS_RSE] = 11,
     [SND_DEVICE_IN_CALL_PROXY] = 33,
     [SND_DEVICE_IN_ICC] = 46,
 };
@@ -1322,6 +1330,8 @@
     /* For legacy xml file parsing */
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_BUS)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_BUS_PAX)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_BUS_RSE)},
     {TO_NAME_INDEX(SND_DEVICE_IN_EC_REF_LOOPBACK)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AND_EC_REF_LOOPBACK)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_QMIC_AND_EC_REF_LOOPBACK)},
@@ -1403,6 +1413,9 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_REAR_SEAT)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_BUS)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER)},
+    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_BUS_REAR_SEAT)},
 };
 
 static const struct name_to_index usecase_type_index[USECASE_TYPE_MAX] = {
@@ -2618,6 +2631,8 @@
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_HEARING_AID] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_BUS] = strdup("TERT_TDM_TX_0");
+    hw_interface_table[SND_DEVICE_IN_BUS_PAX] = strdup("QUAT_TDM_TX_0");
+    hw_interface_table[SND_DEVICE_IN_BUS_RSE] = strdup("QUIN_TDM_TX_0");
     hw_interface_table[SND_DEVICE_IN_CALL_PROXY] = strdup("CALL_PROXY_TX");
     hw_interface_table[SND_DEVICE_IN_ICC] = strdup("TERT_TDM_TX_0");
     hw_interface_table[SND_DEVICE_OUT_ICC] = strdup("TERT_TDM_RX_0");
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 52e5f20..4f9842f 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -353,6 +353,8 @@
     SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
     SND_DEVICE_IN_VOICE_HEARING_AID,
     SND_DEVICE_IN_BUS,
+    SND_DEVICE_IN_BUS_PAX,
+    SND_DEVICE_IN_BUS_RSE,
     SND_DEVICE_IN_EC_REF_LOOPBACK,
     SND_DEVICE_IN_HANDSET_DMIC_AND_EC_REF_LOOPBACK,
     SND_DEVICE_IN_HANDSET_QMIC_AND_EC_REF_LOOPBACK,