hal: separate transcode loopback usecase for Tx and Rx

- In transcode loopback usecase source device is fixed
  with HDMI device and backend is not configurable.
- Separate transcode loopback usecase for Rx and Tx
  to select the backend based on the source device.

Change-Id: Icbed33fe748ab5f9fc4ace3ada605ba25ad2c51c
Signed-off-by: Surendar Karka <skarka@codeaurora.org>
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 7753747..ebf41db 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -103,8 +103,10 @@
 typedef struct audio_loopback {
     struct audio_device *adev;
     patch_db_t patch_db;
-    audio_usecase_t uc_id;
-    usecase_type_t  uc_type;
+    audio_usecase_t uc_id_rx;
+    audio_usecase_t uc_id_tx;
+    usecase_type_t  uc_type_rx;
+    usecase_type_t  uc_type_tx;
     pthread_mutex_t lock;
 } audio_loopback_t;
 
@@ -257,7 +259,7 @@
 int32_t release_loopback_session(loopback_patch_t *active_loopback_patch)
 {
     int32_t ret = 0;
-    struct audio_usecase *uc_info;
+    struct audio_usecase *uc_info_rx, *uc_info_tx;
     struct audio_device *adev = audio_loopback_mod->adev;
     struct stream_inout *inout =  &active_loopback_patch->patch_stream;
     struct audio_port_config *source_patch_config = &active_loopback_patch->
@@ -265,7 +267,7 @@
     int32_t pcm_dev_asm_rx_id = platform_get_pcm_device_id(USECASE_AUDIO_TRANSCODE_LOOPBACK,
                                                            PCM_PLAYBACK);
 
-    /* 1. Close the PCM devices */
+    /* Close the PCM devices */
     if (active_loopback_patch->source_stream) {
         compress_close(active_loopback_patch->source_stream);
         active_loopback_patch->source_stream = NULL;
@@ -281,8 +283,26 @@
             __func__);
     }
 
-    uc_info = get_usecase_from_list(adev, audio_loopback_mod->uc_id);
-    if (uc_info == NULL) {
+    uc_info_tx = get_usecase_from_list(adev, audio_loopback_mod->uc_id_tx);
+    if (uc_info_tx == NULL) {
+        ALOGE("%s: Could not find the loopback usecase (%d) in the list",
+            __func__, active_loopback_patch->patch_handle_id);
+        return -EINVAL;
+    }
+
+    disable_audio_route(adev, uc_info_tx);
+
+    /* Disable tx device */
+    disable_snd_device(adev, uc_info_tx->in_snd_device);
+
+    /* Reset backend device to default state */
+    platform_invalidate_backend_config(adev->platform,uc_info_tx->in_snd_device);
+
+    list_remove(&uc_info_tx->list);
+    free(uc_info_tx);
+
+    uc_info_rx = get_usecase_from_list(adev, audio_loopback_mod->uc_id_rx);
+    if (uc_info_rx == NULL) {
         ALOGE("%s: Could not find the loopback usecase (%d) in the list",
             __func__, active_loopback_patch->patch_handle_id);
         return -EINVAL;
@@ -293,18 +313,14 @@
 
     active_loopback_patch->patch_state = PATCH_INACTIVE;
 
-    /* 2. Get and set stream specific mixer controls */
-    disable_audio_route(adev, uc_info);
+    /* Get and set stream specific mixer controls */
+    disable_audio_route(adev, uc_info_rx);
 
-    /* 3. Disable the rx and tx devices */
-    disable_snd_device(adev, uc_info->out_snd_device);
-    disable_snd_device(adev, uc_info->in_snd_device);
+    /* Disable the rx device */
+    disable_snd_device(adev, uc_info_rx->out_snd_device);
 
-    /* 4. Reset backend device to default state */
-    platform_invalidate_backend_config(adev->platform,uc_info->in_snd_device);
-
-    list_remove(&uc_info->list);
-    free(uc_info);
+    list_remove(&uc_info_rx->list);
+    free(uc_info_rx);
 
     adev->active_input = get_next_active_input(adev);
 
@@ -368,7 +384,7 @@
 int create_loopback_session(loopback_patch_t *active_loopback_patch)
 {
     int32_t ret = 0, bits_per_sample;
-    struct audio_usecase *uc_info;
+    struct audio_usecase *uc_info_rx, *uc_info_tx;
     int32_t pcm_dev_asm_rx_id, pcm_dev_asm_tx_id;
     char dummy_write_buf[64];
     struct audio_device *adev = audio_loopback_mod->adev;
@@ -385,21 +401,38 @@
 
     ALOGD("%s: Create loopback session begin", __func__);
 
-    uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+    uc_info_rx = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
 
-    if (!uc_info) {
+    if (!uc_info_rx) {
         ALOGE("%s: Failure to open loopback session", __func__);
         return -ENOMEM;
     }
 
-    uc_info->id = USECASE_AUDIO_TRANSCODE_LOOPBACK;
-    uc_info->type = audio_loopback_mod->uc_type;
-    uc_info->stream.inout = &active_loopback_patch->patch_stream;
-    uc_info->devices = active_loopback_patch->patch_stream.out_config.devices;
-    uc_info->in_snd_device = SND_DEVICE_NONE;
-    uc_info->out_snd_device = SND_DEVICE_NONE;
+    uc_info_tx = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
 
-    list_add_tail(&adev->usecase_list, &uc_info->list);
+    if (!uc_info_tx) {
+        free(uc_info_rx);
+        ALOGE("%s: Failure to open loopback session", __func__);
+        return -ENOMEM;
+    }
+
+    uc_info_rx->id = USECASE_AUDIO_TRANSCODE_LOOPBACK_RX;
+    uc_info_rx->type = audio_loopback_mod->uc_type_rx;
+    uc_info_rx->stream.inout = &active_loopback_patch->patch_stream;
+    uc_info_rx->devices = active_loopback_patch->patch_stream.out_config.devices;
+    uc_info_rx->in_snd_device = SND_DEVICE_NONE;
+    uc_info_rx->out_snd_device = SND_DEVICE_NONE;
+
+
+    uc_info_tx->id = USECASE_AUDIO_TRANSCODE_LOOPBACK_TX;
+    uc_info_tx->type = audio_loopback_mod->uc_type_tx;
+    uc_info_tx->stream.inout = &active_loopback_patch->patch_stream;
+    uc_info_tx->devices = active_loopback_patch->patch_stream.in_config.devices;
+    uc_info_tx->in_snd_device = SND_DEVICE_NONE;
+    uc_info_tx->out_snd_device = SND_DEVICE_NONE;
+
+    list_add_tail(&adev->usecase_list, &uc_info_rx->list);
+    list_add_tail(&adev->usecase_list, &uc_info_tx->list);
 
     loopback_source_stream.source = AUDIO_SOURCE_UNPROCESSED;
     loopback_source_stream.device = inout->in_config.devices;
@@ -408,23 +441,24 @@
     loopback_source_stream.sample_rate = inout->in_config.sample_rate;
     loopback_source_stream.format = inout->in_config.format;
 
-    memcpy(&loopback_source_stream.usecase, uc_info,
+    memcpy(&loopback_source_stream.usecase, uc_info_rx,
            sizeof(struct audio_usecase));
     adev->active_input = &loopback_source_stream;
-    select_devices(adev, uc_info->id);
+    select_devices(adev, uc_info_rx->id);
+    select_devices(adev, uc_info_tx->id);
 
-    pcm_dev_asm_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
-    pcm_dev_asm_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
+    pcm_dev_asm_rx_id = platform_get_pcm_device_id(uc_info_rx->id, PCM_PLAYBACK);
+    pcm_dev_asm_tx_id = platform_get_pcm_device_id(uc_info_tx->id, PCM_CAPTURE);
 
     if (pcm_dev_asm_rx_id < 0 || pcm_dev_asm_tx_id < 0 ) {
-        ALOGE("%s: Invalid PCM devices (asm: rx %d tx %d) for the usecase(%d)",
-            __func__, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id, uc_info->id);
+        ALOGE("%s: Invalid PCM devices (asm: rx %d tx %d) for the RX usecase(%d), TX usecase(%d)",
+            __func__, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id, uc_info_rx->id, uc_info_tx->id);
         ret = -EIO;
         goto exit;
     }
 
-    ALOGD("%s: LOOPBACK PCM devices (rx: %d tx: %d) usecase(%d)",
-        __func__, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id, uc_info->id);
+    ALOGD("%s: LOOPBACK PCM devices (rx: %d tx: %d) RX usecase(%d) TX usecase(%d)",
+        __func__, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id, uc_info_rx->id, uc_info_tx->id);
 
     /* setup a channel for client <--> adsp communication for stream events */
     inout->dev = adev;
@@ -442,7 +476,7 @@
     }
     if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format,false, true)) {
         ret = audio_extn_ip_hdlr_intf_init(&inout->ip_hdlr_handle, NULL, NULL, adev,
-                                           USECASE_AUDIO_TRANSCODE_LOOPBACK);
+                                           USECASE_AUDIO_TRANSCODE_LOOPBACK_RX);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d", __func__, ret);
             inout->ip_hdlr_handle = NULL;
@@ -537,7 +571,7 @@
     }
     if (inout->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_open(inout->ip_hdlr_handle, true, inout,
-                                           USECASE_AUDIO_TRANSCODE_LOOPBACK);
+                                           USECASE_AUDIO_TRANSCODE_LOOPBACK_RX);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
             goto exit;
@@ -878,8 +912,10 @@
 
     ret = init_patch_database(&audio_loopback_mod->patch_db);
 
-    audio_loopback_mod->uc_id = USECASE_AUDIO_TRANSCODE_LOOPBACK;
-    audio_loopback_mod->uc_type = TRANSCODE_LOOPBACK;
+    audio_loopback_mod->uc_id_rx = USECASE_AUDIO_TRANSCODE_LOOPBACK_RX;
+    audio_loopback_mod->uc_id_tx = USECASE_AUDIO_TRANSCODE_LOOPBACK_TX;
+    audio_loopback_mod->uc_type_rx = TRANSCODE_LOOPBACK_RX;
+    audio_loopback_mod->uc_type_tx = TRANSCODE_LOOPBACK_TX;
 
 loopback_done:
     if (ret != 0) {
diff --git a/hal/audio_extn/ip_hdlr_intf.c b/hal/audio_extn/ip_hdlr_intf.c
index ece7af3..649c99f 100755
--- a/hal/audio_extn/ip_hdlr_intf.c
+++ b/hal/audio_extn/ip_hdlr_intf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -164,7 +164,7 @@
         stream_info = node_to_item(node, struct ip_hdlr_stream, list);
         /* send the error if rtic failure notifcation is received */
         if ((stream_info->stream == aud_sess_handle) &&
-            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK)) {
+            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)) {
             struct stream_inout *inout = (struct stream_inout *)aud_sess_handle;
             usecase = stream_info->usecase;
             adev = inout->dev;
@@ -230,7 +230,7 @@
         stream_info = node_to_item(node, struct ip_hdlr_stream, list);
         /* send the error if rtic failure notifcation is received */
         if ((stream_info->stream == aud_sess_handle) &&
-            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK)) {
+            (stream_info->usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)) {
             struct stream_inout *inout = (struct stream_inout *)aud_sess_handle;
             pthread_mutex_lock(&inout->pre_lock);
             pthread_mutex_lock(&inout->lock);
@@ -288,7 +288,7 @@
     param->payload_length = sizeof(struct reg_event);
     param->payload = reg_ev;
 
-    if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK) {
+    if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) {
         inout = (struct stream_inout *)stream_handle;
         adsp_hdlr_stream_handle = inout->adsp_hdlr_stream_handle;
         dev = inout->dev;
@@ -408,7 +408,7 @@
     ALOGD("%s:[%d] handle = %p, usecase = %d",__func__, ip_hdlr->ref_cnt, handle, usecase);
 
     if (is_dsp_decode) {
-        if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK) {
+        if (usecase == USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) {
             struct stream_inout *inout = (struct stream_inout *)aud_sess_handle;
             adsp_hdlr_stream_handle = inout->adsp_hdlr_stream_handle;
         } else {
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 6aab347..63cecd9 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -851,7 +851,7 @@
                                                 &usecase->stream.in->app_type_cfg);
         ALOGV("%s Selected apptype: %d", __func__, usecase->stream.in->app_type_cfg.app_type);
         break;
-    case TRANSCODE_LOOPBACK :
+    case TRANSCODE_LOOPBACK_RX :
         audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
                                                 &adev->streams_output_cfg_list,
                                                 usecase->stream.inout->out_config.devices,
@@ -911,7 +911,7 @@
           platform_get_snd_device_name(split_snd_device));
 
     if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE &&
-        usecase->type != TRANSCODE_LOOPBACK) {
+        usecase->type != TRANSCODE_LOOPBACK_RX) {
         ALOGE("%s: not a playback/capture path, no need to cfg app type", __func__);
         rc = 0;
         goto exit_send_app_type_cfg;
@@ -921,7 +921,7 @@
         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
         (usecase->id != USECASE_AUDIO_PLAYBACK_VOIP) &&
-        (usecase->id != USECASE_AUDIO_TRANSCODE_LOOPBACK) &&
+        (usecase->id != USECASE_AUDIO_TRANSCODE_LOOPBACK_RX) &&
         (!is_interactive_usecase(usecase->id)) &&
         (!is_offload_usecase(usecase->id)) &&
         (usecase->type != PCM_CAPTURE)) {
@@ -937,7 +937,7 @@
             goto exit_send_app_type_cfg;
     }
 
-    if (usecase->type == PCM_PLAYBACK || usecase->type == TRANSCODE_LOOPBACK) {
+    if (usecase->type == PCM_PLAYBACK || usecase->type == TRANSCODE_LOOPBACK_RX) {
         pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "Audio Stream %d App Type Cfg", pcm_device_id);
@@ -1073,7 +1073,7 @@
            __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
     } else {
         app_type = platform_get_default_app_type_v2(adev->platform, usecase->type);
-        if(usecase->type == TRANSCODE_LOOPBACK) {
+        if(usecase->type == TRANSCODE_LOOPBACK_RX) {
             sample_rate = usecase->stream.inout->out_config.sample_rate;
             app_type = usecase->stream.inout->out_app_type_cfg.app_type;
         }
@@ -1103,7 +1103,7 @@
 
     switch (usecase->type) {
     case PCM_PLAYBACK:
-    case TRANSCODE_LOOPBACK:
+    case TRANSCODE_LOOPBACK_RX:
         ALOGD("%s: usecase->out_snd_device %s",
               __func__, platform_get_snd_device_name(usecase->out_snd_device));
         /* check for out combo device */
@@ -1446,7 +1446,7 @@
         platform_send_audio_calibration(adev->platform, usecase,
                          platform_get_default_app_type_v2(adev->platform, usecase->type),
                          48000);
-    } else if (type == TRANSCODE_LOOPBACK && usecase->stream.inout != NULL) {
+    } else if (type == TRANSCODE_LOOPBACK_RX && usecase->stream.inout != NULL) {
         int snd_device = usecase->out_snd_device;
         snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
                      platform_get_spkr_prot_snd_device(snd_device) : snd_device;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index cef64a7..f31991a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -337,7 +337,8 @@
     [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
 
     /* Transcode loopback cases */
-    [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
 
     [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
     [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
@@ -963,7 +964,7 @@
 
     ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
 
-    if (usecase->type == PCM_CAPTURE)
+    if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
         snd_device = usecase->in_snd_device;
     else
         snd_device = usecase->out_snd_device;
@@ -1001,7 +1002,7 @@
         return -EINVAL;
 
     ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
-    if (usecase->type == PCM_CAPTURE)
+    if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
         snd_device = usecase->in_snd_device;
     else
         snd_device = usecase->out_snd_device;
@@ -1257,7 +1258,7 @@
     snd_device_t d2 = new_snd_device;
 
     switch (uc->type) {
-        case TRANSCODE_LOOPBACK :
+        case TRANSCODE_LOOPBACK_RX :
             a1 = uc->stream.inout->out_config.devices;
             a2 = new_uc->stream.inout->out_config.devices;
             break;
@@ -1929,7 +1930,8 @@
     bool is_it_true_mode = false;
 
     if (usecase->type == PCM_CAPTURE ||
-        usecase->type == TRANSCODE_LOOPBACK) {
+        usecase->type == TRANSCODE_LOOPBACK_RX ||
+        usecase->type == TRANSCODE_LOOPBACK_TX) {
         return false;
     }
 
@@ -2043,7 +2045,7 @@
                                                         usecase->stream.out);
         in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
         usecase->devices = usecase->stream.out->devices;
-    } else if (usecase->type == TRANSCODE_LOOPBACK ) {
+    } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
         if (usecase->stream.inout == NULL) {
             ALOGE("%s: stream.inout is NULL", __func__);
             return -EINVAL;
@@ -2054,8 +2056,14 @@
         stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
         out_snd_device = platform_get_output_snd_device(adev->platform,
                                                         &stream_out);
+        usecase->devices = out_snd_device;
+    } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
+        if (usecase->stream.inout == NULL) {
+            ALOGE("%s: stream.inout is NULL", __func__);
+            return -EINVAL;
+        }
         in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
-        usecase->devices = (out_snd_device | in_snd_device);
+        usecase->devices = in_snd_device;
     } else {
         /*
          * If the voice call is active, use the sound devices of voice call usecase
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 8cb395f..ba8a99c 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -195,7 +195,8 @@
 
     USECASE_AUDIO_PLAYBACK_SILENCE,
 
-    USECASE_AUDIO_TRANSCODE_LOOPBACK,
+    USECASE_AUDIO_TRANSCODE_LOOPBACK_RX,
+    USECASE_AUDIO_TRANSCODE_LOOPBACK_TX,
 
     USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
     USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
@@ -404,7 +405,8 @@
     VOICE_CALL,
     VOIP_CALL,
     PCM_HFP_CALL,
-    TRANSCODE_LOOPBACK
+    TRANSCODE_LOOPBACK_RX,
+    TRANSCODE_LOOPBACK_TX
 } usecase_type_t;
 
 union stream_ptr {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 25ce892..d05c5ed 100755
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -384,7 +384,8 @@
     [USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
                                         AFE_PROXY_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
-    [USECASE_AUDIO_TRANSCODE_LOOPBACK] = {TRANSCODE_LOOPBACK_RX_DEV_ID, TRANSCODE_LOOPBACK_TX_DEV_ID},
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = {TRANSCODE_LOOPBACK_RX_DEV_ID, -1},
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = {-1, TRANSCODE_LOOPBACK_TX_DEV_ID},
     [USECASE_AUDIO_PLAYBACK_VOIP] = {AUDIO_PLAYBACK_VOIP_PCM_DEVICE, AUDIO_PLAYBACK_VOIP_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_VOIP] = {AUDIO_RECORD_VOIP_PCM_DEVICE, AUDIO_RECORD_VOIP_PCM_DEVICE},
 
@@ -929,6 +930,8 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_EC_REF_LOOPBACK)},
+    {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)},
+    {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_TX)},
 };
 
 #define NO_COLS 2
@@ -3515,7 +3518,7 @@
         snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
         snd_device = usecase->in_snd_device;
-    else if (usecase->type == TRANSCODE_LOOPBACK)
+    else if (usecase->type == TRANSCODE_LOOPBACK_RX)
         snd_device = usecase->out_snd_device;
 
     acdb_dev_id = acdb_device_table[platform_get_spkr_prot_snd_device(snd_device)];
@@ -6423,7 +6426,7 @@
 
     backend_idx = platform_get_backend_index(snd_device);
 
-    if (usecase->type == TRANSCODE_LOOPBACK) {
+    if (usecase->type == TRANSCODE_LOOPBACK_RX) {
         backend_cfg.bit_width = usecase->stream.inout->out_config.bit_width;
         backend_cfg.sample_rate = usecase->stream.inout->out_config.sample_rate;
         backend_cfg.format = usecase->stream.inout->out_config.format;
@@ -6584,7 +6587,7 @@
 
     backend_cfg.passthrough_enabled = false;
 
-    if (usecase->type == TRANSCODE_LOOPBACK) {
+    if (usecase->type == TRANSCODE_LOOPBACK_TX) {
         backend_cfg.bit_width = usecase->stream.inout->in_config.bit_width;
         backend_cfg.sample_rate = usecase->stream.inout->in_config.sample_rate;
         backend_cfg.format = usecase->stream.inout->in_config.format;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 313c067..2d6bcf1 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -368,7 +368,8 @@
     [USECASE_AUDIO_RECORD_AFE_PROXY] = {AFE_PROXY_PLAYBACK_PCM_DEVICE,
                                         AFE_PROXY_RECORD_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_SILENCE] = {MULTIMEDIA9_PCM_DEVICE, -1},
-    [USECASE_AUDIO_TRANSCODE_LOOPBACK] = {TRANSCODE_LOOPBACK_RX_DEV_ID, TRANSCODE_LOOPBACK_TX_DEV_ID},
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = {TRANSCODE_LOOPBACK_RX_DEV_ID, -1},
+    [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = {-1, TRANSCODE_LOOPBACK_TX_DEV_ID},
 
     [USECASE_AUDIO_PLAYBACK_VOIP] = {AUDIO_PLAYBACK_VOIP_PCM_DEVICE, AUDIO_PLAYBACK_VOIP_PCM_DEVICE},
     [USECASE_AUDIO_RECORD_VOIP] = {AUDIO_RECORD_VOIP_PCM_DEVICE, AUDIO_RECORD_VOIP_PCM_DEVICE},
@@ -910,6 +911,8 @@
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_RECORD_AFE_PROXY)},
     {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_SILENCE)},
+    {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_RX)},
+    {TO_NAME_INDEX(USECASE_AUDIO_TRANSCODE_LOOPBACK_TX)},
 };
 
 #define NO_COLS 2
@@ -3295,7 +3298,7 @@
         snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
     else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
         snd_device = usecase->in_snd_device;
-    else if (usecase->type == TRANSCODE_LOOPBACK)
+    else if (usecase->type == TRANSCODE_LOOPBACK_RX)
         snd_device = usecase->out_snd_device;
 
     acdb_dev_id = acdb_device_table[platform_get_spkr_prot_snd_device(snd_device)];
@@ -6366,7 +6369,7 @@
 
     backend_idx = platform_get_backend_index(snd_device);
 
-    if (usecase->type == TRANSCODE_LOOPBACK) {
+    if (usecase->type == TRANSCODE_LOOPBACK_RX) {
         backend_cfg.bit_width = usecase->stream.inout->out_config.bit_width;
         backend_cfg.sample_rate = usecase->stream.inout->out_config.sample_rate;
         backend_cfg.format = usecase->stream.inout->out_config.format;
@@ -6525,7 +6528,7 @@
 
     backend_cfg.passthrough_enabled = false;
 
-    if (usecase->type == TRANSCODE_LOOPBACK) {
+    if (usecase->type == TRANSCODE_LOOPBACK_TX) {
         backend_cfg.bit_width = usecase->stream.inout->in_config.bit_width;
         backend_cfg.sample_rate = usecase->stream.inout->in_config.sample_rate;
         backend_cfg.format = usecase->stream.inout->in_config.format;