hal: Add incall stereo capture

Add mixer control to pass channel config to kernel
to support incall stereo capture.

Bug: 79869195
Test: voice call regression

Change-Id: Ic2c9ebfc42cfc7a6e0d1a9facb4d2658f6c343cb
diff --git a/hal/Android.mk b/hal/Android.mk
index 9b1f4e6..cbee1d4 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -53,6 +53,7 @@
   LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="4"
   LOCAL_CFLAGS += -DKPI_OPTIMIZE_ENABLED
   LOCAL_CFLAGS += -DINCALL_MUSIC_ENABLED
+  LOCAL_CFLAGS += -DINCALL_STEREO_CAPTURE_ENABLED
   MULTIPLE_HW_VARIANTS_ENABLED := true
 endif
 endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 8a2562f..209cae9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -5006,6 +5006,18 @@
     in->capture_handle = handle;
     in->flags = flags;
 
+    ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
+    if (source == AUDIO_SOURCE_VOICE_UPLINK ||
+         source == AUDIO_SOURCE_VOICE_DOWNLINK) {
+        /* Force channel config requested to mono if incall
+           record is being requested for only uplink/downlink */
+        if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
+            config->channel_mask = AUDIO_CHANNEL_IN_MONO;
+            ret = -EINVAL;
+            goto err_open;
+        }
+    }
+
     if (is_usb_dev && may_use_hifi_record) {
         /* HiFi record selects an appropriate format, channel, rate combo
            depending on sink capabilities*/
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 5c528d7..61260b8 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -2146,6 +2146,13 @@
     return ret;
 }
 
+int platform_set_incall_recording_session_channels(void *platform __unused,
+                                             uint32_t channel_count __unused)
+{
+    return 0;
+}
+
+
 int platform_stop_incall_recording_usecase(void *platform __unused)
 {
     return 0;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 450e31c..567109e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -3259,6 +3259,35 @@
     return ret;
 }
 
+int platform_set_incall_recording_session_channels(void *platform,
+                                             uint32_t channel_count)
+{
+    int ret = 0;
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    const char *mixer_ctl_name = "Voc Rec Config";
+    int num_ctl_values;
+    int i;
+    struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+              __func__, mixer_ctl_name);
+        ret = -EINVAL;
+    } else {
+        num_ctl_values = mixer_ctl_get_num_values(ctl);
+        for (i = 0; i < num_ctl_values; i++) {
+            if (mixer_ctl_set_value(ctl, i, channel_count)) {
+                ALOGE("Error: invalid channel count: %x", channel_count);
+                ret = -EINVAL;
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
 int platform_stop_incall_recording_usecase(void *platform)
 {
     int ret = 0;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 5c7d81f..44305a1 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -104,6 +104,8 @@
 
 int platform_set_incall_recording_session_id(void *platform,
                                              uint32_t session_id, int rec_mode);
+int platform_set_incall_recording_session_channels(void *platform,
+                                                   uint32_t session_channels);
 int platform_stop_incall_recording_usecase(void *platform);
 int platform_start_incall_music_usecase(void *platform);
 int platform_stop_incall_music_usecase(void *platform);
diff --git a/hal/voice.c b/hal/voice.c
index f3b69b8..e6bf47f 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -309,6 +309,10 @@
         session_id = voice_get_active_session_id(adev);
         ret = platform_set_incall_recording_session_id(adev->platform,
                                                        session_id, rec_mode);
+#ifdef INCALL_STEREO_CAPTURE_ENABLED
+        ret = platform_set_incall_recording_session_channels(adev->platform,
+                                                        in->config.channels);
+#endif
         ALOGV("%s: Update usecase to %d",__func__, in->usecase);
     } else {
         ALOGV("%s: voice call not active", __func__);