hal: Add support for ULLPP for proaudio

Give option to use ULLPP for proaudio use cases.
This is achieved by sending the required mixer control
and sending the app type to the NOIRQ driver.

CRS-Fixed: 1099039
Change-Id: Iff762fb6dd56641ca83a6ec91178731f5ba779d0
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index ae90cb3..6a7a4cd 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -106,6 +106,8 @@
 /* Set or Query stream profile type */
 #define AUDIO_PARAMETER_STREAM_PROFILE "audio_stream_profile"
 
+#define AUDIO_PARAMETER_KEY_VR_AUDIO_MODE "vr_audio_mode_on"
+
 /* audio input flags for compress and timestamp mode.
  * check other input flags defined in audio.h for conflicts
  */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index b12ab8e..550fbdc 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -92,6 +92,7 @@
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
@@ -192,7 +193,7 @@
         flag_name = strtok_r(NULL, "|", &last_r);
     }
 
-    ALOGV("parse_flag_names: flag - %d", flag);
+    ALOGV("parse_flag_names: flag - %x", flag);
     io_flags.in_flags = (audio_input_flags_t)flag;
     io_flags.out_flags = (audio_output_flags_t)flag;
     return io_flags;
@@ -676,8 +677,8 @@
               __func__, sample_rate, bit_width);
     }
 
-    ALOGV("%s: flags: %x, format: %x sample_rate %d, profile %s",
-           __func__, flags, format, sample_rate, profile);
+    ALOGV("%s: flags: %x, format: %x sample_rate %d, profile %s, app_type %d",
+           __func__, flags, format, sample_rate, profile, app_type_cfg->app_type);
     list_for_each(node_i, streams_output_cfg_list) {
         s_info = node_to_item(node_i, struct streams_io_cfg, list);
         /* Along with flags do profile matching if set at either end.*/
@@ -725,6 +726,12 @@
     return native_usecase;
 }
 
+
+static inline bool audio_is_vr_mode_on(struct audio_device *(__attribute__((unused)) adev))
+{
+    return adev->vr_audio_mode_enabled;
+}
+
 void audio_extn_utils_update_stream_app_type_cfg_for_usecase(
                                     struct audio_device *adev,
                                     struct audio_usecase *usecase)
@@ -789,12 +796,21 @@
     if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
+        (usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
         (!is_offload_usecase(usecase->id)) &&
         (usecase->type != PCM_CAPTURE)) {
         ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
         rc = 0;
         goto exit_send_app_type_cfg;
     }
+
+    //if VR is active then only send the mixer control
+    if (usecase->id == USECASE_AUDIO_PLAYBACK_ULL && !audio_is_vr_mode_on(adev)) {
+            ALOGI("ULL doesnt need sending app type cfg, returning");
+            rc = 0;
+            goto exit_send_app_type_cfg;
+    }
+
     if (usecase->type == PCM_PLAYBACK) {
         pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9da81e6..6644b48 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2169,6 +2169,9 @@
     struct audio_usecase *uc_info;
     struct audio_device *adev = out->dev;
     int snd_card_status = get_snd_card_state(adev);
+    char mixer_ctl_name[128];
+    struct mixer_ctl *ctl = NULL;
+    char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
 
     if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
         ret = -EINVAL;
@@ -2249,6 +2252,28 @@
         } else
             flags |= PCM_MONOTONIC;
 
+        if ((adev->vr_audio_mode_enabled) &&
+            (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
+            snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+                    "PCM_Dev %d Topology", out->pcm_device_id);
+            ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+            if (!ctl) {
+                ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
+                      __func__, mixer_ctl_name);
+            } else {
+                //if success use ULLPP
+                ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
+                    __func__, mixer_ctl_name, out->pcm_device_id);
+                //There is a still a possibility that some sessions
+                // that request for FAST|RAW when 3D audio is active
+                //can go through ULLPP. Ideally we expects apps to
+                //listen to audio focus and stop concurrent playback
+                //Also, we will look for mode flag (voice_in_communication)
+                //before enabling the realtime flag.
+                mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
+            }
+        }
+
         while (1) {
             out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
                                flags, &out->config);
@@ -4245,8 +4270,8 @@
         }
     }
 
-    ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
-          __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
+    ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
+          __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
 
     /* TODO remove this hardcoding and check why width is zero*/
     if (out->bit_width == 0)
@@ -4277,6 +4302,7 @@
         ret = -EEXIST;
         goto error_open;
     }
+
     pthread_mutex_unlock(&adev->lock);
 
     out->stream.common.get_sample_rate = out_get_sample_rate;
@@ -4564,6 +4590,23 @@
             }
         }
     }
+
+    //handle vr audio setparam
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
+        value, sizeof(value));
+    if (ret >= 0) {
+        ALOGI("Setting vr mode to be %s", value);
+        if (!strncmp(value, "true", 4)) {
+            adev->vr_audio_mode_enabled = true;
+            ALOGI("Setting vr mode to true");
+        } else if (!strncmp(value, "false", 5)) {
+            adev->vr_audio_mode_enabled = false;
+            ALOGI("Setting vr mode to false");
+        } else {
+            ALOGI("wrong vr mode set");
+        }
+    }
+
     audio_extn_set_parameters(adev, parms);
 done:
     str_parms_destroy(parms);
@@ -4605,6 +4648,30 @@
         str_parms_add_int(reply, "SND_CARD_STATUS", val);
         goto exit;
     }
+    //handle vr audio getparam
+
+    ret = str_parms_get_str(query,
+        AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
+        value, sizeof(value));
+
+    if (ret >= 0) {
+        bool vr_audio_enabled = false;
+        pthread_mutex_lock(&adev->lock);
+        vr_audio_enabled = adev->vr_audio_mode_enabled;
+        pthread_mutex_unlock(&adev->lock);
+
+        ALOGI("getting vr mode to %d", vr_audio_enabled);
+
+        if (vr_audio_enabled) {
+            str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
+                "true");
+            goto exit;
+        } else {
+            str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
+                "false");
+            goto exit;
+        }
+    }
 
     pthread_mutex_lock(&adev->lock);
     audio_extn_get_parameters(adev, query, reply);
@@ -5193,6 +5260,9 @@
     }
 
     adev->bt_wb_speech_enabled = false;
+    //initialize this to false for now,
+    //this will be set to true through set param
+    adev->vr_audio_mode_enabled = false;
 
     audio_extn_ds2_enable(adev);
     *device = &adev->device.common;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index e99d546..abfba45 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -428,6 +428,7 @@
     bool native_playback_enabled;
     bool asrc_mode_enabled;
     qahwi_device_t qahwi_dev;
+    bool vr_audio_mode_enabled;
 };
 
 int select_devices(struct audio_device *adev,