hal: support car audio stream for bus devices

Add support for car audio streams and usecases
including media, system notification, navigation
guidance and phone.
The car audio streams are routed to bus devices
with assigned address, which is defined in audio
policy configuration. This enables dynamic mixing
and routing done by Android car framework from
application to AudioFlinger and audio HAL.

Change-Id: I583fc7b5f2e8850b064a3cde5f93693b16c47841
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index b3297ed..dd75d20 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1216,6 +1216,10 @@
 #define audio_extn_auto_hal_create_audio_patch(dev, num_sources,\
     sources, num_sinks, sinks, handle) (0)
 #define audio_extn_auto_hal_release_audio_patch(dev, handle) (0)
+#define audio_extn_auto_hal_get_car_audio_stream_from_address(address) (-1)
+#define audio_extn_auto_hal_open_output_stream(out) (0)
+#define audio_extn_auto_hal_is_bus_device_usecase(uc_id) (0)
+#define audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) (0)
 #else
 int32_t audio_extn_auto_hal_init(struct audio_device *adev);
 void audio_extn_auto_hal_deinit(void);
@@ -1229,6 +1233,10 @@
                                 audio_patch_handle_t *handle);
 int audio_extn_auto_hal_release_audio_patch(struct audio_hw_device *dev,
                                 audio_patch_handle_t handle);
+int32_t audio_extn_auto_hal_get_car_audio_stream_from_address(const char *address);
+int32_t audio_extn_auto_hal_open_output_stream(struct stream_out *out);
+bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id);
+snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(struct stream_out *out);
 #endif
 
 bool audio_extn_edid_is_supported_sr(edid_audio_info* info, int sr);
diff --git a/hal/audio_extn/auto_hal.c b/hal/audio_extn/auto_hal.c
index c70dc17..d09225c 100644
--- a/hal/audio_extn/auto_hal.c
+++ b/hal/audio_extn/auto_hal.c
@@ -60,6 +60,16 @@
 /* Auto hal module struct */
 static struct auto_hal_module *auto_hal = NULL;
 
+extern struct pcm_config pcm_config_deep_buffer;
+extern struct pcm_config pcm_config_low_latency;
+
+static const audio_usecase_t bus_device_usecases[] = {
+    USECASE_AUDIO_PLAYBACK_MEDIA,
+    USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION,
+    USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE,
+    USECASE_AUDIO_PLAYBACK_PHONE,
+};
+
 /* Note: Due to ADP H/W design, SoC TERT/SEC TDM CLK and FSYNC lines are
  * both connected with CODEC and a single master is needed to provide
  * consistent CLK and FSYNC to slaves, hence configuring SoC TERT TDM as
@@ -310,6 +320,118 @@
     return ret;
 }
 
+int32_t audio_extn_auto_hal_get_car_audio_stream_from_address(const char *address)
+{
+    int32_t bus_num = -1;
+    char *str = NULL;
+    char *last_r = NULL;
+    char local_address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+
+    /* bus device with null address error out */
+    if (address == NULL) {
+        ALOGE("%s: null address for car stream", __func__);
+        return -1;
+    }
+
+    /* strtok will modify the original string. make a copy first */
+    strlcpy(local_address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+
+    /* extract bus number from address */
+    str = strtok_r(local_address, "BUS_",&last_r);
+    if (str != NULL)
+        bus_num = (int32_t)strtol(str, (char **)NULL, 10);
+
+    /* validate bus number */
+    if ((bus_num < 0) || (bus_num >= MAX_CAR_AUDIO_STREAMS)) {
+        ALOGE("%s: invalid bus number %d", __func__, bus_num);
+        return -1;
+    }
+
+    return (0x1 << bus_num);
+}
+
+int32_t audio_extn_auto_hal_open_output_stream(struct stream_out *out)
+{
+    int ret = 0;
+    unsigned int channels = audio_channel_count_from_out_mask(out->channel_mask);
+
+    switch(out->car_audio_stream) {
+    case CAR_AUDIO_STREAM_MEDIA:
+        /* media bus stream shares pcm device with deep-buffer */
+        out->usecase = USECASE_AUDIO_PLAYBACK_MEDIA;
+        out->config = pcm_config_deep_buffer;
+        out->config.period_size = get_output_period_size(out->sample_rate, out->format,
+                                        channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
+        if (out->config.period_size <= 0) {
+            ALOGE("Invalid configuration period size is not valid");
+            ret = -EINVAL;
+            goto error;
+        }
+        break;
+    case CAR_AUDIO_STREAM_SYS_NOTIFICATION:
+        /* sys notification bus stream shares pcm device with low-latency */
+        out->usecase = USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION;
+        out->config = pcm_config_low_latency;
+        break;
+    case CAR_AUDIO_STREAM_NAV_GUIDANCE:
+        out->usecase = USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE;
+        out->config = pcm_config_deep_buffer;
+        out->config.period_size = get_output_period_size(out->sample_rate, out->format,
+                                        channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
+        if (out->config.period_size <= 0) {
+            ALOGE("Invalid configuration period size is not valid");
+            ret = -EINVAL;
+            goto error;
+        }
+        break;
+    case CAR_AUDIO_STREAM_PHONE:
+        out->usecase = USECASE_AUDIO_PLAYBACK_PHONE;
+        out->config = pcm_config_low_latency;
+        break;
+    default:
+        ALOGE("%s: Car audio stream %x not supported", __func__,
+            out->car_audio_stream);
+        ret = -EINVAL;
+        goto error;
+    }
+
+error:
+    return ret;
+}
+
+bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id)
+{
+    unsigned int i;
+    for (i = 0; i < sizeof(bus_device_usecases)/sizeof(bus_device_usecases[0]); i++) {
+        if (uc_id == bus_device_usecases[i])
+            return true;
+    }
+    return false;
+}
+
+snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(struct stream_out *out)
+{
+    snd_device_t snd_device = SND_DEVICE_NONE;
+
+    switch(out->car_audio_stream) {
+    case CAR_AUDIO_STREAM_MEDIA:
+        snd_device = SND_DEVICE_OUT_BUS_MEDIA;
+        break;
+    case CAR_AUDIO_STREAM_SYS_NOTIFICATION:
+        snd_device = SND_DEVICE_OUT_BUS_SYS;
+        break;
+    case CAR_AUDIO_STREAM_NAV_GUIDANCE:
+        snd_device = SND_DEVICE_OUT_BUS_NAV;
+        break;
+    case CAR_AUDIO_STREAM_PHONE:
+        snd_device = SND_DEVICE_OUT_BUS_PHN;
+        break;
+    default:
+        ALOGE("%s: Unknown car audio stream (%x)",
+            __func__, out->car_audio_stream);
+    }
+    return snd_device;
+}
 int32_t audio_extn_auto_hal_init(struct audio_device *adev)
 {
     int32_t ret = 0;
diff --git a/hal/audio_extn/ext_hw_plugin.c b/hal/audio_extn/ext_hw_plugin.c
index 45ba1d7..6b4a718 100644
--- a/hal/audio_extn/ext_hw_plugin.c
+++ b/hal/audio_extn/ext_hw_plugin.c
@@ -265,6 +265,8 @@
     case USECASE_AUDIO_PLAYBACK_OFFLOAD8:
     case USECASE_AUDIO_PLAYBACK_OFFLOAD9:
     case USECASE_AUDIO_PLAYBACK_ULL:
+    case USECASE_AUDIO_PLAYBACK_MEDIA:
+    case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION:
         *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_PLAYBACK;
         break;
     case USECASE_AUDIO_RECORD:
@@ -281,6 +283,12 @@
     case USECASE_VOICEMMODE1_CALL:
         *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_CS_VOICE_CALL;
         break;
+    case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE:
+        *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DRIVER_SIDE_PLAYBACK;
+        break;
+    case USECASE_AUDIO_PLAYBACK_PHONE:
+        *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_PHONE_PLAYBACK;
+        break;
     default:
         ret = -EINVAL;
     }
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 09921af..9abddb9 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -1060,7 +1060,8 @@
         (usecase->id != USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) &&
         (!is_interactive_usecase(usecase->id)) &&
         (!is_offload_usecase(usecase->id)) &&
-        (usecase->type != PCM_CAPTURE)) {
+        (usecase->type != PCM_CAPTURE) &&
+        (!audio_extn_auto_hal_is_bus_device_usecase(usecase->id))) {
         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;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9691ce8..b2c23fe 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -399,7 +399,12 @@
 
     [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
 
-    [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
+    [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
+
+    [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
+    [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
+    [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
+    [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
 };
 
 static const audio_usecase_t offload_usecases[] = {
@@ -3805,10 +3810,10 @@
                                   is_low_latency);
 }
 
-static size_t get_output_period_size(uint32_t sample_rate,
-                                    audio_format_t format,
-                                    int channel_count,
-                                    int duration /*in millisecs*/)
+size_t get_output_period_size(uint32_t sample_rate,
+                            audio_format_t format,
+                            int channel_count,
+                            int duration /*in millisecs*/)
 {
     size_t size = 0;
     uint32_t bytes_per_sample = audio_bytes_per_sample(format);
@@ -6816,7 +6821,7 @@
                             audio_output_flags_t flags,
                             struct audio_config *config,
                             struct audio_stream_out **stream_out,
-                            const char *address __unused)
+                            const char *address)
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
@@ -6847,8 +6852,8 @@
     out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
 
     ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
-        stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
-        devices, flags, &out->stream);
+        stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
+        devices, flags, &out->stream, address);
 
 
     if (!out) {
@@ -6971,6 +6976,23 @@
         out->config.format = pcm_format_from_audio_format(out->format);
     }
 
+    /* validate bus device address */
+    if (out->devices & AUDIO_DEVICE_OUT_BUS) {
+        /* extract car audio stream index */
+        out->car_audio_stream =
+            audio_extn_auto_hal_get_car_audio_stream_from_address(address);
+        if (out->car_audio_stream < 0) {
+            ALOGE("%s: invalid car audio stream %x",
+                __func__, out->car_audio_stream);
+            ret = -EINVAL;
+            goto error_open;
+        }
+        /* save car audio stream and address for bus device */
+        strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+        ALOGV("%s: address %s, car_audio_stream %x",
+            __func__, out->address, out->car_audio_stream);
+    }
+
     /* Check for VOIP usecase */
     if (is_voip_rx) {
         if (!voice_extn_is_compress_voip_supported()) {
@@ -7442,6 +7464,13 @@
                 adev->haptics_config.channels = 1;
             } else
                 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
+        } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
+            ret = audio_extn_auto_hal_open_output_stream(out);
+            if (ret) {
+                ALOGE("%s: Failed to open output stream for bus device", __func__);
+                ret = -EINVAL;
+                goto error_open;
+            }
         } else {
             /* primary path is the default path selected if no other outputs are available/suitable */
             out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 9a93ed7..12312cc 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -222,6 +222,12 @@
 
     USECASE_AUDIO_A2DP_ABR_FEEDBACK,
 
+    /* car streams usecases */
+    USECASE_AUDIO_PLAYBACK_MEDIA,
+    USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION,
+    USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE,
+    USECASE_AUDIO_PLAYBACK_PHONE,
+
     AUDIO_USECASE_MAX
 };
 
@@ -290,6 +296,21 @@
     RENDER_MODE_AUDIO_STC_MASTER,
 } render_mode_t;
 
+#ifdef AUDIO_EXTN_AUTO_HAL_ENABLED
+/* This defines the physical car streams supported in audio HAL,
+ * limited by the available frontend PCM driver.
+ * Max number of physical streams supported is currently 8 and is
+ * represented by stream bit flag as indicated in vehicle HAL interface.
+ */
+#define MAX_CAR_AUDIO_STREAMS    8
+enum {
+    CAR_AUDIO_STREAM_MEDIA            = 0x1,
+    CAR_AUDIO_STREAM_SYS_NOTIFICATION = 0x2,
+    CAR_AUDIO_STREAM_NAV_GUIDANCE     = 0x4,
+    CAR_AUDIO_STREAM_PHONE            = 0x8,
+};
+#endif
+
 struct stream_app_type_cfg {
     int sample_rate;
     uint32_t bit_width;
@@ -407,6 +428,9 @@
 
     error_log_t *error_log;
     bool pspd_coeff_sent;
+
+    char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+    int car_audio_stream;
 };
 
 struct stream_in {
@@ -694,6 +718,11 @@
 streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
                                   audio_io_handle_t output);
 
+size_t get_output_period_size(uint32_t sample_rate,
+                            audio_format_t format,
+                            int channel_count,
+                            int duration /*in millisecs*/);
+
 #define LITERAL_TO_STRING(x) #x
 #define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\
             __FILE__ ":" LITERAL_TO_STRING(__LINE__)\
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 7fd2019..01d75e4 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -469,6 +469,15 @@
     [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] =
                      {PLAYBACK_INTERACTIVE_STRM_DEVICE8, PLAYBACK_INTERACTIVE_STRM_DEVICE8},
     [USECASE_AUDIO_EC_REF_LOOPBACK] = {-1, -1}, /* pcm id updated from platform info file */
+    [USECASE_AUDIO_PLAYBACK_MEDIA] = {MEDIA_PCM_DEVICE,
+                                      MEDIA_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = {SYS_NOTIFICATION_PCM_DEVICE,
+                                                 SYS_NOTIFICATION_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = {NAV_GUIDANCE_PCM_DEVICE,
+                                             NAV_GUIDANCE_PCM_DEVICE},
+    [USECASE_AUDIO_PLAYBACK_PHONE] = {PHONE_PCM_DEVICE,
+                                      PHONE_PCM_DEVICE},
+
 };
 
 /* Array to store sound devices */
@@ -565,6 +574,10 @@
     [SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_WB] = "wsa-speaker-and-bt-sco-wb",
     [SND_DEVICE_OUT_SPEAKER_WSA_AND_BT_SCO_SWB] = "wsa-speaker-and-bt-sco-wb",
     [SND_DEVICE_OUT_VOICE_HEARING_AID] = "hearing-aid",
+    [SND_DEVICE_OUT_BUS_MEDIA] = "bus-speaker",
+    [SND_DEVICE_OUT_BUS_SYS] = "bus-speaker",
+    [SND_DEVICE_OUT_BUS_NAV] = "bus-speaker",
+    [SND_DEVICE_OUT_BUS_PHN] = "bus-speaker",
 
     /* Capture sound devices */
     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -697,6 +710,7 @@
     [SND_DEVICE_OUT_VOIP_SPEAKER] = "voip-speaker",
     [SND_DEVICE_OUT_VOIP_HEADPHONES] = "voip-headphones",
     [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic",
+    [SND_DEVICE_IN_BUS] = "bus-mic",
 };
 
 // Platform specific backend bit width table
@@ -819,6 +833,10 @@
     [SND_DEVICE_OUT_SPEAKER_PROTECTED_RAS] = 134,
     [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT_RAS] = 134,
     [SND_DEVICE_OUT_VOICE_HEARING_AID] = 45,
+    [SND_DEVICE_OUT_BUS_MEDIA] = 78,
+    [SND_DEVICE_OUT_BUS_SYS] = 78,
+    [SND_DEVICE_OUT_BUS_NAV] = 14,
+    [SND_DEVICE_OUT_BUS_PHN] = 94,
     [SND_DEVICE_IN_HANDSET_MIC] = 4,
     [SND_DEVICE_IN_HANDSET_MIC_SB] = 163,
     [SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = 4,
@@ -946,6 +964,7 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = 4,
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 4,
     [SND_DEVICE_IN_VOICE_HEARING_AID] = 44,
+    [SND_DEVICE_IN_BUS] = 11,
 };
 
 struct name_to_index {
@@ -1042,6 +1061,10 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_SPEAKER)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_HEADPHONES)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEARING_AID)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_BUS_MEDIA)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_BUS_SYS)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_BUS_NAV)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_BUS_PHN)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_SB)},
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_EXTERNAL)},
@@ -1171,6 +1194,7 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)},
     /* For legacy xml file parsing */
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_BUS)},
 };
 
 static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -1232,7 +1256,10 @@
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_VOIP)},
     {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)},
     {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_TX)},
-
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MEDIA)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE)},
+    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_PHONE)},
 };
 
 static const struct name_to_index usecase_type_index[USECASE_TYPE_MAX] = {
@@ -2151,6 +2178,10 @@
        Need snd_device to route voice call and use specific acdb tuning.
        Also, BT_RX is a virtual port to indicate bluetooth hearing aid. */
     hw_interface_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("BT_RX"),
+    hw_interface_table[SND_DEVICE_OUT_BUS_MEDIA] = strdup("TERT_TDM_RX_0");
+    hw_interface_table[SND_DEVICE_OUT_BUS_SYS] = strdup("TERT_TDM_RX_0");
+    hw_interface_table[SND_DEVICE_OUT_BUS_NAV] = strdup("TERT_TDM_RX_1");
+    hw_interface_table[SND_DEVICE_OUT_BUS_PHN] = strdup("TERT_TDM_RX_2");
     hw_interface_table[SND_DEVICE_IN_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_SB] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = strdup("SLIMBUS_0_TX");
@@ -2277,6 +2308,7 @@
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX");
     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");
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
 
      /*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -5797,6 +5829,8 @@
         ALOGD("%s: setting sink capability(%d) for Proxy", __func__, channel_count);
         snd_device = SND_DEVICE_OUT_AFE_PROXY;
         audio_extn_set_afe_proxy_channel_mixer(adev, channel_count, snd_device);
+    } else if (devices & AUDIO_DEVICE_OUT_BUS) {
+        snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out);
     } else {
         ALOGE("%s: Unknown device(s) %#x", __func__, devices);
     }
@@ -7633,9 +7667,13 @@
 {
     switch (usecase) {
         case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
+        case USECASE_AUDIO_PLAYBACK_MEDIA:
+        case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE:
             return DEEP_BUFFER_PLATFORM_DELAY;
         case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
         case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
+        case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION:
+        case USECASE_AUDIO_PLAYBACK_PHONE:
             return LOW_LATENCY_PLATFORM_DELAY;
         case USECASE_AUDIO_PLAYBACK_OFFLOAD:
         case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index fba1077..7da728c 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -175,6 +175,10 @@
     SND_DEVICE_OUT_VOICE_SPEAKER_STEREO_AND_VOICE_ANC_HEADSET,
     SND_DEVICE_OUT_VOICE_SPEAKER_STEREO_AND_VOICE_ANC_FB_HEADSET,
     SND_DEVICE_OUT_VOICE_HEARING_AID,
+    SND_DEVICE_OUT_BUS_MEDIA,
+    SND_DEVICE_OUT_BUS_SYS,
+    SND_DEVICE_OUT_BUS_NAV,
+    SND_DEVICE_OUT_BUS_PHN,
     SND_DEVICE_OUT_END,
 
     /*
@@ -311,6 +315,7 @@
     SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE,
     SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
     SND_DEVICE_IN_VOICE_HEARING_AID,
+    SND_DEVICE_IN_BUS,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -625,6 +630,11 @@
 #define PLAYBACK_INTERACTIVE_STRM_DEVICE7 48
 #define PLAYBACK_INTERACTIVE_STRM_DEVICE8 49
 
+#define MEDIA_PCM_DEVICE DEEP_BUFFER_PCM_DEVICE
+#define SYS_NOTIFICATION_PCM_DEVICE 9
+#define NAV_GUIDANCE_PCM_DEVICE MULTIMEDIA2_PCM_DEVICE
+#define PHONE_PCM_DEVICE 12
+
 #ifdef PLATFORM_APQ8084
 #define FM_RX_VOLUME "Quat MI2S FM RX Volume"
 #elif PLATFORM_MSM8994