mpq8092: Porting audio HAL changes

Porting audio HAL changes

Change-Id: I85e739ed231ee09ebf150da2ea3fd4f5d4aa3a24
diff --git a/hal_mpq/audio_bitstream_sm.c b/hal_mpq/audio_bitstream_sm.c
index 9f2564d..d2e4e6e 100644
--- a/hal_mpq/audio_bitstream_sm.c
+++ b/hal_mpq/audio_bitstream_sm.c
@@ -26,7 +26,7 @@
 #include <math.h>
 
 #define LOG_TAG "AudioBitstreamStateMachine"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
 #define LOG_NDDEBUG 0
 #include <utils/Log.h>
 
@@ -36,7 +36,6 @@
 #include <platform.h>
 // ----------------------------------------------------------------------------
 
-
 /*
 Initialize all input and output pointers
 Allocate twice the max buffer size of input and output for sufficient buffering
@@ -45,52 +44,62 @@
 {
     bstream->buffering_factor = buffering_factor;
     bstream->buffering_factor_cnt = 0;
+    bstream->inp_buf_size = SAMPLES_PER_CHANNEL *
+                        MAX_INPUT_CHANNELS_SUPPORTED*
+                        (bstream->buffering_factor+1);
+    bstream->inp_buf = (char *)malloc( bstream->inp_buf_size);
 
-    bstream->inp_buf=(char *)malloc(SAMPLES_PER_CHANNEL*
-                MAX_INPUT_CHANNELS_SUPPORTED*
-                (bstream->buffering_factor+1));
                                 // multiplied by 2 to convert to bytes
     if(bstream->inp_buf != NULL) {
         bstream->inp_buf_curr_ptr = bstream->inp_buf;
         bstream->inp_buf_write_ptr = bstream->inp_buf;
     } else {
         ALOGE("MS11 input buffer not allocated");
+        bstream->inp_buf_size = 0;
         return 0;
     }
 
-    bstream->enc_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*
-                MAX_INPUT_CHANNELS_SUPPORTED*
-                FACTOR_FOR_BUFFERING);
+    bstream->enc_out_buf_size = SAMPLES_PER_CHANNEL * MAX_INPUT_CHANNELS_SUPPORTED*
+                        FACTOR_FOR_BUFFERING;
+    bstream->enc_out_buf =(char *)malloc(bstream->enc_out_buf_size);
+
     if(bstream->enc_out_buf) {
         bstream->enc_out_buf_write_ptr = bstream->enc_out_buf;
     } else {
         ALOGE("MS11 Enc output buffer not allocated");
+        bstream->enc_out_buf_size = 0;
         return 0;
     }
-    bstream->pcm_2_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL*STEREO_CHANNELS *
-                    FACTOR_FOR_BUFFERING);
+    bstream->pcm_2_out_buf_size =  SAMPLES_PER_CHANNEL*STEREO_CHANNELS *
+                    FACTOR_FOR_BUFFERING;
+    bstream->pcm_2_out_buf =(char *)malloc(bstream->pcm_2_out_buf_size);
     if(bstream->pcm_2_out_buf) {
         bstream->pcm_2_out_buf_write_ptr = bstream->pcm_2_out_buf;
     } else {
         ALOGE("MS11 PCM2Ch output buffer not allocated");
+        bstream->pcm_2_out_buf_size = 0;
         return 0;
     }
-    bstream->pcm_mch_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
-                     MAX_OUTPUT_CHANNELS_SUPPORTED *
-                     FACTOR_FOR_BUFFERING);
+    bstream->pcm_mch_out_buf_size = SAMPLES_PER_CHANNEL * MAX_OUTPUT_CHANNELS_SUPPORTED *
+                     FACTOR_FOR_BUFFERING;
+
+    bstream->pcm_mch_out_buf =(char *)malloc(bstream->pcm_mch_out_buf_size);
     if(bstream->pcm_mch_out_buf) {
         bstream->pcm_mch_out_buf_write_ptr = bstream->pcm_mch_out_buf;
     } else {
         ALOGE("MS11 PCMMCh output buffer not allocated");
+        bstream->pcm_mch_out_buf_size = 0;
         return 0;
     }
-    bstream->passt_out_buf =(char *)malloc(SAMPLES_PER_CHANNEL *
+    bstream->passt_out_buf_size =SAMPLES_PER_CHANNEL *
                        MAX_INPUT_CHANNELS_SUPPORTED *
-                       FACTOR_FOR_BUFFERING);
+                       FACTOR_FOR_BUFFERING;
+    bstream->passt_out_buf =(char *)malloc(bstream->passt_out_buf_size);
     if(bstream->passt_out_buf) {
         bstream->passt_out_buf_write_ptr = bstream->passt_out_buf;
     } else {
         ALOGE("MS11 Enc output buffer not allocated");
+        bstream->passt_out_buf_size  = 0;
         return 0;
     }
     return 1;
@@ -159,9 +168,8 @@
                     struct audio_bitstream_sm *bstream,
                     char *buf_ptr, size_t bytes)
 {
-    int32_t bufLen = SAMPLES_PER_CHANNEL*MAX_INPUT_CHANNELS_SUPPORTED*(bstream->buffering_factor+1);
     // flush the input buffer if input is not consumed
-    if( (bstream->inp_buf_write_ptr+bytes) > (bstream->inp_buf+bufLen) ) {
+    if( (bstream->inp_buf_write_ptr+bytes) > (bstream->inp_buf+bstream->inp_buf_size) ) {
         ALOGE("Input bitstream is not consumed");
         return;
     }
@@ -226,6 +234,38 @@
     return bstream->inp_buf_write_ptr;
 }
 
+int audio_bitstream_set_input_buffer_ptr(
+                        struct audio_bitstream_sm *bstream, int bytes)
+{
+    if(((bstream->inp_buf_curr_ptr + bytes) <=
+                        (bstream->inp_buf + bstream->inp_buf_size)) &&
+        ((bstream->inp_buf_curr_ptr + bytes) >= bstream->inp_buf))
+
+        bstream->inp_buf_curr_ptr += bytes;
+     else {
+        ALOGE("Invalid input buffer size %d bytes", bytes);
+        return -EINVAL;
+     }
+
+    return 0;
+}
+
+int audio_bitstream_set_input_buffer_write_ptr(
+                        struct audio_bitstream_sm *bstream, int bytes)
+{
+    if(((bstream->inp_buf_write_ptr + bytes) <=
+                        (bstream->inp_buf + bstream->inp_buf_size)) &&
+        ((bstream->inp_buf_write_ptr + bytes) >= bstream->inp_buf))
+
+        bstream->inp_buf_write_ptr += bytes;
+     else {
+        ALOGE("Invalid input buffer size %d bytes", bytes);
+        return -EINVAL;
+     }
+
+    return 0;
+}
+
 /*
 Get the output buffer start pointer to start rendering the pcm sampled to driver
 */
diff --git a/hal_mpq/audio_hw.h b/hal_mpq/audio_hw.h
index e1319a5..7814d95 100644
--- a/hal_mpq/audio_hw.h
+++ b/hal_mpq/audio_hw.h
@@ -24,7 +24,7 @@
 #include <hardware/audio.h>
 #include <tinyalsa/asoundlib.h>
 #include <tinycompress/tinycompress.h>
-
+#include "sound/compress_params.h"
 #include <audio_route/audio_route.h>
 
 #define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
@@ -45,6 +45,7 @@
 #define DEFAULT_HDMI_OUT_CHANNELS   2
 
 typedef int snd_device_t;
+#include <platform.h>
 
 /* These are the supported use cases by the hardware.
  * Each usecase is mapped to a specific PCM device.
@@ -56,11 +57,11 @@
     USECASE_AUDIO_PLAYBACK_DEEP_BUFFER = 0,
     USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
     USECASE_AUDIO_PLAYBACK_MULTI_CH,
-    USECASE_AUDIO_PLAYBACK_OFFLOAD,
-
-    /* FM usecase */
     USECASE_AUDIO_PLAYBACK_FM,
-
+    USECASE_AUDIO_PLAYBACK_OFFLOAD,
+    USECASE_AUDIO_PLAYBACK_OFFLOAD1,
+    USECASE_AUDIO_PLAYBACK_OFFLOAD2,
+    USECASE_AUDIO_PLAYBACK_OFFLOAD3,
     /* Capture usecases */
     USECASE_AUDIO_RECORD,
     USECASE_AUDIO_RECORD_COMPRESS,
@@ -88,6 +89,28 @@
     AUDIO_USECASE_MAX
 } audio_usecase_t;
 
+typedef enum {
+    DEEP_BUFFER_PLAYBACK_STREAM = 0,
+    LOW_LATENCY_PLAYBACK_STREAM,
+    MCH_PCM_PLAYBACK_STREAM,
+    OFFLOAD_PLAYBACK_STREAM,
+    LOW_LATENCY_RECORD_STREAM,
+    RECORD_STREAM,
+    VOICE_CALL_STREAM
+} audio_usecase_stream_type_t;
+
+#define STRING_TO_ENUM(string) { #string, string }
+struct string_to_enum {
+    const char *name;
+    uint32_t value;
+};
+
+static const struct string_to_enum out_channels_name_to_enum_table[] = {
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 /*
@@ -118,14 +141,43 @@
     int data[];
 };
 
+struct alsa_handle {
+
+    struct listnode list;
+//Parameters of the stream
+    struct pcm *pcm;
+    struct pcm_config config;
+
+    struct compress *compr;
+    struct compr_config compr_config;
+
+    struct stream_out *out;
+
+    audio_usecase_t usecase;
+    int device_id;
+    unsigned int sample_rate;
+    audio_channel_mask_t channel_mask;
+    audio_format_t input_format;
+    audio_format_t output_format;
+    audio_devices_t devices;
+
+    route_format_t route_format;
+    int decoder_type;
+
+    bool cmd_pending ;
+};
+
 struct stream_out {
     struct audio_stream_out stream;
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
     pthread_cond_t  cond;
+    /* TODO remove this */
+    /*
     struct pcm_config config;
     struct compr_config compr_config;
     struct pcm *pcm;
     struct compress *compr;
+    */
     int standby;
     int pcm_device_id;
     unsigned int sample_rate;
@@ -154,6 +206,54 @@
     int send_new_metadata;
 
     struct audio_device *dev;
+
+    /*devices configuration */
+    int left_volume;
+    int right_volume;
+    audio_usecase_stream_type_t uc_strm_type;
+    int hdmi_format;
+    int spdif_format;
+    int* device_formats;   //TODO:Needs to come from AudioRutingManager
+    struct audio_config *config;
+
+    /* list of the session handles */
+    struct listnode session_list;
+
+    /* /MS11 instance */
+    int use_ms11_decoder;
+    void  *ms11_decoder;
+    struct compr_config compr_config;
+
+    int channels;
+
+    /* Buffering utility */
+    struct audio_bitstream_sm    *bitstrm;
+
+    int                 buffer_size;
+    int                 decoder_type;
+    bool                dec_conf_set;
+    uint32_t            min_bytes_req_to_dec;
+    bool                is_m11_file_mode;
+    void                *dec_conf_buf;
+    int32_t             dec_conf_bufLength;
+    bool                first_bitstrm_buf;
+
+    bool                open_dec_route;
+    int                 dec_format_devices;
+    bool                open_dec_mch_route;
+    int                 dec_mch_format_devices;
+    bool                open_passt_route;
+    int                 passt_format_devices;
+    bool                sw_open_trans_route;
+    int                 sw_trans_format_devices;
+    bool                hw_open_trans_route;
+    int                 hw_trans_format_devices;
+    bool                channel_status_set;
+    unsigned char       channel_status[24];
+    int                 route_audio_to_a2dp;
+    int                 is_ms11_file_playback_mode;
+    char *              write_temp_buf;
+    struct output_metadata  output_meta_data;
 };
 
 struct stream_in {
@@ -194,6 +294,7 @@
     snd_device_t out_snd_device;
     snd_device_t in_snd_device;
     union stream_ptr stream;
+    struct alsa_handle *handle;
 };
 
 struct audio_device {
@@ -225,6 +326,9 @@
     [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
     [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD1] = "compress-offload-playback1",
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
     [USECASE_AUDIO_RECORD] = "audio-record",
     [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
     [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
@@ -245,6 +349,7 @@
     [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
 };
 
+
 int adev_open_output_stream(struct audio_hw_device *dev,
                                    audio_io_handle_t handle,
                                    audio_devices_t devices,
diff --git a/hal_mpq/audio_stream_out.c b/hal_mpq/audio_stream_out.c
index 71eb2f1..5e9eb74 100644
--- a/hal_mpq/audio_stream_out.c
+++ b/hal_mpq/audio_stream_out.c
@@ -49,12 +49,24 @@
 #include <platform.h>
 
 #include "sound/compress_params.h"
+#include "audio_bitstream_sm.h"
+
+//TODO: enable sw_decode if required
+#define USE_SWDECODE 0
+
+#if USE_SWDECODE
+#include "SoftMS11.h"
+#endif
 
 #define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
 #define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
 /* ToDo: Check and update a proper value in msec */
 #define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define STRING_LENGTH_OF_INTEGER 12
+
+static int send_offload_cmd_l(struct stream_out* out, int command);
+static int get_snd_codec_id(audio_format_t format);
 
 struct pcm_config pcm_config_deep_buffer = {
     .channels = 2,
@@ -89,18 +101,1230 @@
     .avail_min = 0,
 };
 
-#define STRING_TO_ENUM(string) { #string, string }
+inline int nextMultiple(int n, int m) {
+    return ((n/m) + 1) * m;
+}
 
-struct string_to_enum {
-    const char *name;
-    uint32_t value;
-};
+/*******************************************************************************
+Description: check for MS11 supported formats
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int is_ms11_supported_fromats(int format)
+{
+    ALOGVV("is_ms11_supported_fromats");
+    int main_format = format & AUDIO_FORMAT_MAIN_MASK;
+    if(((main_format == AUDIO_FORMAT_AAC) ||
+        (main_format == AUDIO_FORMAT_HE_AAC_V1) ||
+        (main_format == AUDIO_FORMAT_HE_AAC_V2) ||
+        (main_format == AUDIO_FORMAT_AC3) ||
+        (main_format == AUDIO_FORMAT_AC3_PLUS) ||
+        (main_format == AUDIO_FORMAT_EAC3))) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+#endif
 
-static const struct string_to_enum out_channels_name_to_enum_table[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-};
+/*******************************************************************************
+Description: check if ac3 can played as pass through without MS11 decoder
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int can_ac3_passthrough_without_ms11(struct stream_out *out, int format)
+{
+    ALOGVV("can_ac3_passthrough_without_ms11");
+    int main_format = format & AUDIO_FORMAT_MAIN_MASK;
+    if(main_format == AUDIO_FORMAT_AC3) {
+        if(((out->hdmi_format == COMPRESSED) ||
+            (out->hdmi_format == AUTO_DEVICE_FORMAT) ||
+            (out->hdmi_format == COMPRESSED_CONVERT_EAC3_AC3) ||
+            (out->hdmi_format == COMPRESSED_CONVERT_ANY_AC3)) &&
+            ((out->spdif_format == COMPRESSED) ||
+             (out->spdif_format == AUTO_DEVICE_FORMAT) ||
+             (out->spdif_format == COMPRESSED_CONVERT_EAC3_AC3) ||
+             (out->spdif_format == COMPRESSED_CONVERT_ANY_AC3))) {
+                return 1;
+        }
+    }
+    return 0;
+}
+#endif
+
+/*******************************************************************************
+Description: get levels of buffering, interms of number of buffers
+*******************************************************************************/
+int get_buffering_factor(struct stream_out *out)
+{
+    ALOGVV("get_buffering_factor");
+    if((out->format == AUDIO_FORMAT_PCM_16_BIT) ||
+       (out->format == AUDIO_FORMAT_PCM_24_BIT))
+        return 1;
+    else
+        return NUM_OF_PERIODS;
+}
+
+/*******************************************************************************
+Description: get the buffer size based on format and device format type
+*******************************************************************************/
+void get_fragment_size_and_format(struct stream_out *out, int routeFormat, int *fragment_size,
+                                       int *fragment_count, int *format)
+{
+    ALOGV("get_fragment_size_and_format");
+
+    int frame_size = 0;
+    *format = out->format;
+    *fragment_count = NUM_OF_PERIODS;
+    switch(out->format) {
+    case AUDIO_FORMAT_PCM_16_BIT:
+        frame_size = PCM_16_BITS_PER_SAMPLE * out->channels;
+        /*TODO: do we need below calculation */
+        *fragment_size = nextMultiple(((frame_size * out->sample_rate * TIME_PER_BUFFER)/1000) + MIN_SIZE_FOR_METADATA , frame_size * 32);
+        break;
+    case AUDIO_FORMAT_PCM_24_BIT:
+        frame_size = PCM_24_BITS_PER_SAMPLE * out->channels;
+        *fragment_size = nextMultiple(((frame_size * out->sample_rate * TIME_PER_BUFFER)/1000) + MIN_SIZE_FOR_METADATA, frame_size * 32);
+        break;
+    case AUDIO_FORMAT_AAC:
+    case AUDIO_FORMAT_HE_AAC_V1:
+    case AUDIO_FORMAT_HE_AAC_V2:
+    case AUDIO_FORMAT_AAC_ADIF:
+    case AUDIO_FORMAT_AC3:
+    case AUDIO_FORMAT_AC3_DM:
+    case AUDIO_FORMAT_EAC3:
+    case AUDIO_FORMAT_EAC3_DM:
+        if(routeFormat == ROUTE_UNCOMPRESSED_MCH) {
+            frame_size = PCM_16_BITS_PER_SAMPLE * out->channels;
+            *fragment_size = nextMultiple(AC3_PERIOD_SIZE * out->channels + MIN_SIZE_FOR_METADATA, frame_size * 32);
+            *format = AUDIO_FORMAT_PCM_16_BIT;
+        } else if(routeFormat == ROUTE_UNCOMPRESSED) {
+            frame_size = PCM_16_BITS_PER_SAMPLE * 2;
+            *fragment_size = nextMultiple(AC3_PERIOD_SIZE * 2 + MIN_SIZE_FOR_METADATA, frame_size * 32);
+            *format = AUDIO_FORMAT_PCM_16_BIT;
+        } else {
+            *fragment_size = PERIOD_SIZE_COMPR;
+        }
+        break;
+    case AUDIO_FORMAT_DTS:
+    case AUDIO_FORMAT_DTS_LBR:
+    case AUDIO_FORMAT_MP3:
+    case AUDIO_FORMAT_WMA:
+    case AUDIO_FORMAT_WMA_PRO:
+    case AUDIO_FORMAT_MP2:
+        *fragment_size = PERIOD_SIZE_COMPR;
+        break;
+    default:
+        *fragment_size = PERIOD_SIZE_COMPR;
+        *format = out->format;
+    }
+
+    /*TODO: remove this if fragement count needs to be decided based on the format*/
+    *fragment_count = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+    fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+
+    ALOGV("fragment_size: %d, fragment_count: %d", *fragment_size, *fragment_count);
+    return;
+}
+
+/*******************************************************************************
+Description: buffer length updated to player
+*******************************************************************************/
+int get_buffer_length(struct stream_out *out)
+{
+    /* TODO: Do we need below */
+    ALOGV("get_buffer_length");
+    int buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+    switch(out->format) {
+    case AUDIO_FORMAT_PCM_16_BIT:
+        buffer_size = ((PCM_16_BITS_PER_SAMPLE * out->channels * out->sample_rate * TIME_PER_BUFFER)/1000);
+        break;
+    case AUDIO_FORMAT_PCM_24_BIT:
+        buffer_size = ((PCM_24_BITS_PER_SAMPLE * out->channels * out->sample_rate * TIME_PER_BUFFER)/1000);
+        break;
+    case AUDIO_FORMAT_AAC:
+    case AUDIO_FORMAT_HE_AAC_V1:
+    case AUDIO_FORMAT_HE_AAC_V2:
+    case AUDIO_FORMAT_AAC_ADIF:
+        buffer_size = AAC_BLOCK_PER_CHANNEL_MS11 * out->channels;
+        break;
+    case AUDIO_FORMAT_AC3:
+    case AUDIO_FORMAT_AC3_DM:
+    case AUDIO_FORMAT_EAC3:
+    case AUDIO_FORMAT_EAC3_DM:
+        buffer_size = AC3_BUFFER_SIZE;
+        break;
+    case AUDIO_FORMAT_DTS:
+    case AUDIO_FORMAT_DTS_LBR:
+    case AUDIO_FORMAT_MP3:
+    case AUDIO_FORMAT_WMA:
+    case AUDIO_FORMAT_WMA_PRO:
+    case AUDIO_FORMAT_MP2:
+        buffer_size = COMPR_INPUT_BUFFER_SIZE;
+        break;
+    default:
+        buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+    }
+
+    /*TODO: remove this if fragement count needs to be decided based on the format*/
+    buffer_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+    return buffer_size;
+}
+
+/* TODO: Uncomment this when enabling A2DP
+ TODO: add support for the 24 bit playback*/
+#if 0
+/*******************************************************************************
+Description: fix up devices for supporting A2DP playback
+*******************************************************************************/
+void fixUpDevicesForA2DPPlayback(struct stream_out *out)
+{
+    ALOGVV("fixUpDevicesForA2DPPlayback");
+    if(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
+        out->route_audio_to_a2dp = 1;
+        out->devices  &= ~AUDIO_DEVICE_OUT_ALL_A2DP;
+        //TODO: add spdif and proxy
+        //out->devices  &= ~AUDIO_DEVICE_OUT_SPDIF;
+        //out->devices |=  AudioSystem::DEVICE_OUT_PROXY;
+    }
+}
+#endif
+
+/*******************************************************************************
+Description: open temp buffer so that meta data mode can be updated properly
+*******************************************************************************/
+int  open_temp_buf_for_metadata(struct stream_out *out)
+{
+    ALOGV("%s", __func__);
+    if (out->write_temp_buf == NULL) {
+        /*Max Period size which is exposed by the compr driver
+        The value needs to be modified when the period size is modified*/
+        out->write_temp_buf = (char *) malloc(PLAYBACK_MAX_PERIOD_SIZE);
+        if (out->write_temp_buf == NULL) {
+            ALOGE("Memory allocation of temp buffer to write pcm to driver failed");
+            return -EINVAL;
+        }
+    }
+    return 0;
+}
+
+/*******************************************************************************
+Description: get index of handle based on device handle device
+*******************************************************************************/
+struct alsa_handle * get_handle_based_on_devices(struct stream_out *out, int handleDevices)
+{
+    ALOGVV("get_handle_based_on_devices");
+    struct listnode *node;
+    struct alsa_handle *handle = NULL;
+
+    list_for_each(node, &out->session_list) {
+            handle = node_to_item(node, struct alsa_handle, list);
+            if(handle->devices & handleDevices)
+                break;
+    }
+    return handle;
+}
+
+void reset_out_parameters(struct stream_out *out) {
+
+    out->hdmi_format = UNCOMPRESSED;
+    out->spdif_format = UNCOMPRESSED;
+    out->decoder_type = UNCOMPRESSED ;
+    out->dec_conf_set = false;
+    out->min_bytes_req_to_dec = 0;
+    out->is_m11_file_mode = false;
+    out->dec_conf_bufLength = 0;
+    out->first_bitstrm_buf = false;
+    out->open_dec_route = false;
+    out->dec_format_devices = AUDIO_DEVICE_NONE;
+    out->open_dec_mch_route = false;
+    out->dec_mch_format_devices =AUDIO_DEVICE_NONE;
+    out->open_passt_route = false;
+    out->passt_format_devices = AUDIO_DEVICE_NONE;
+    out->sw_open_trans_route = false;
+    out->sw_trans_format_devices = AUDIO_DEVICE_NONE;
+    out->hw_open_trans_route =false ;
+    out->hw_trans_format_devices = AUDIO_DEVICE_NONE;
+    out->channel_status_set = false;
+    out->route_audio_to_a2dp = false;
+    out->is_ms11_file_playback_mode = false;
+    out->write_temp_buf = NULL;
+    return;
+}
+
+struct alsa_handle *get_alsa_handle() {
+
+    struct alsa_handle *handle;
+        handle = (struct alsa_handle *)calloc(1, sizeof(struct alsa_handle));
+        if(handle == NULL) {
+            ALOGE("%s calloc failed for handle", __func__);
+        } else {
+            ALOGE("%s handle is 0x%x", __func__,(uint32_t)handle);
+        }
+
+        return handle;
+}
+
+void free_alsa_handle(struct alsa_handle *handle) {
+
+    if(handle == NULL) {
+        ALOGE("%s Invalid handle", __func__);
+    }
+    free(handle);
+
+    return;
+}
+
+
+struct alsa_handle *get_handle_by_route_format(struct stream_out *out,
+                            int route_format)
+{
+    struct listnode *node;
+    struct alsa_handle *handle = NULL;
+    ALOGV("%s",__func__);
+    list_for_each(node, &out->session_list)  {
+        handle = node_to_item(node, struct alsa_handle, list);
+        if(handle->route_format & route_format) {
+            ALOGV("%s found handle %x",__func__,(uint32_t)handle);
+            break;
+        }
+    }
+
+    return handle;
+}
+
+/*******************************************************************************
+Description: get the format index
+*******************************************************************************/
+int get_format_index(int format)
+{
+    ALOGVV("get_format_index");
+    int idx = 0,i;
+    for(i=0; i<NUM_SUPPORTED_CODECS; i++) {
+        if(format == format_index[i][0]) {
+            idx = format_index[i][1];
+            break;
+        }
+    }
+   return idx;
+}
+
+int get_compress_available_space(struct alsa_handle *handle)
+{
+   uint32_t ret;
+   size_t avail = 0;
+   struct timespec tstamp;
+   ret = compress_get_hpointer(handle->compr,&avail, &tstamp);
+   if(ret!=0) {
+       ALOGE("cannot get available space\n");
+    } else
+        ret = (int)avail;
+    return ret;
+}
+
+
+/*******************************************************************************
+Description: validate if the decoder requires configuration to be set as first
+             buffer
+*******************************************************************************/
+int is_decoder_config_required(struct stream_out *out)
+{
+    ALOGVV("is_decoder_config_required");
+    int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+    uint32_t i;
+    if(!out->is_ms11_file_playback_mode)
+        return 0;
+    for(i=0; i<sizeof(decodersRequireConfig)/sizeof(int); i++)
+        if(main_format == decodersRequireConfig[i])
+            return 1;
+    return 0;
+}
+
+/*******************************************************************************
+Description: query if input buffering mode require
+*******************************************************************************/
+int is_input_buffering_mode_reqd(struct stream_out *out)
+{
+    ALOGVV("is_input_buffering_mode_reqd");
+    if((out->decoder_type == SW_PASSTHROUGH) ||
+       (out->decoder_type == DSP_PASSTHROUGH))
+        return 1;
+    else
+        return 0;
+}
+
+
+
+/*******************************************************************************
+Description: update use case and routing flags
+*******************************************************************************/
+void update_decode_type_and_routing_states(struct stream_out *out)
+{
+    ALOGV("%s", __func__);
+
+    int format_index = get_format_index(out->format);
+    int decodeType, idx;
+
+    out->open_dec_route = false;
+    out->open_dec_mch_route = false;
+    out->open_passt_route = false;
+    out->sw_open_trans_route = false;
+    out->hw_open_trans_route = false;
+    out->dec_format_devices = out->devices;
+    out->dec_mch_format_devices = AUDIO_DEVICE_NONE;
+    out->passt_format_devices = AUDIO_DEVICE_NONE;
+    out->sw_trans_format_devices = AUDIO_DEVICE_NONE;
+    out->hw_trans_format_devices = AUDIO_DEVICE_NONE;
+    out->decoder_type = 0;
+
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+    if(is_ms11_supported_fromats(out->format))
+        out->use_ms11_decoder = true;
+#endif
+
+    ALOGV("format_index: %d devices %x", format_index,out->devices);
+    if(out->devices & AUDIO_DEVICE_OUT_SPDIF) {
+        decodeType = usecase_docode_hdmi_spdif[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index]
+            [out->spdif_format];
+        ALOGV("SPDIF: decoderType: %d", decodeType);
+        out->decoder_type = decodeType;
+        for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+            if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+                switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+                    case ROUTE_UNCOMPRESSED:
+                        ALOGVV("ROUTE_UNCOMPRESSED");
+                        ALOGVV("SPDIF opened with stereo decode");
+                        out->open_dec_route = true;
+                        break;
+                    case ROUTE_UNCOMPRESSED_MCH:
+                        ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+                        ALOGVV("SPDIF opened with multichannel decode");
+                        out->open_dec_mch_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+                        out->dec_mch_format_devices |= AUDIO_DEVICE_OUT_SPDIF;
+                        break;
+                    case ROUTE_COMPRESSED:
+                        ALOGVV("ROUTE_COMPRESSED");
+                        out->open_passt_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+                        out->passt_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+                        break;
+                    case ROUTE_DSP_TRANSCODED_COMPRESSED:
+                        ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+                        out->hw_open_trans_route = true;
+                        out->hw_trans_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+                        break;
+                    case ROUTE_SW_TRANSCODED_COMPRESSED:
+                        ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+                        out->sw_open_trans_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_SPDIF;
+                        out->sw_trans_format_devices = AUDIO_DEVICE_OUT_SPDIF;
+                        break;
+                    default:
+                        ALOGW("INVALID ROUTE for SPDIF, decoderType %d, routeFormat %d",
+                                decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+                        break;
+                }
+            }
+        }
+    }
+    if(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+        decodeType = usecase_docode_hdmi_spdif[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index]
+            [out->hdmi_format];
+        ALOGV("HDMI: decoderType: %d", decodeType);
+        out->decoder_type |= decodeType;
+        for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+            if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+                switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+                    case ROUTE_UNCOMPRESSED:
+                        ALOGVV("ROUTE_UNCOMPRESSED");
+                        ALOGVV("HDMI opened with stereo decode");
+                        out->open_dec_route = true;
+                        break;
+                    case ROUTE_UNCOMPRESSED_MCH:
+                        ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+                        ALOGVV("HDMI opened with multichannel decode");
+                        out->open_dec_mch_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        out->dec_mch_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        break;
+                    case ROUTE_COMPRESSED:
+                        ALOGVV("ROUTE_COMPRESSED");
+                        out->open_passt_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        out->passt_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        break;
+                    case ROUTE_DSP_TRANSCODED_COMPRESSED:
+                        ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+                        out->hw_open_trans_route = true;
+                        out->hw_trans_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        break;
+                    case ROUTE_SW_TRANSCODED_COMPRESSED:
+                        ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+                        out->sw_open_trans_route = true;
+                        out->dec_format_devices &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        out->sw_trans_format_devices |= AUDIO_DEVICE_OUT_AUX_DIGITAL;
+                        break;
+                    default:
+                        ALOGW("INVALID ROUTE for HDMI, decoderType %d, routeFormat %d",
+                                decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+                        break;
+                }
+            }
+        }
+    }
+    if(out->devices & ~(AUDIO_DEVICE_OUT_AUX_DIGITAL |
+                AUDIO_DEVICE_OUT_SPDIF)) {
+        decodeType = usecase_decode_format[NUM_STATES_FOR_EACH_DEVICE_FMT*format_index];
+        ALOGV("Other Devices: decoderType: %d", decodeType);
+        out->decoder_type |= decodeType;
+        for(idx=0; idx<NUM_DECODE_PATH; idx++) {
+            if(route_to_driver[idx][DECODER_TYPE_IDX] == decodeType) {
+                switch(route_to_driver[idx][ROUTE_FORMAT_IDX]) {
+                    case ROUTE_UNCOMPRESSED:
+                        ALOGVV("ROUTE_UNCOMPRESSED");
+                        ALOGVV("Other Devices opened with stereo decode");
+                        out->open_dec_route = true;
+                        break;
+                    case ROUTE_UNCOMPRESSED_MCH:
+                        ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+                        ALOGVV("Other Devices opened with multichannel decode");
+                        out->open_dec_mch_route = true;
+                        out->dec_format_devices &= ~(out->devices &
+                                ~(AUDIO_DEVICE_OUT_SPDIF |
+                                    AUDIO_DEVICE_OUT_AUX_DIGITAL));
+                        out->dec_mch_format_devices |= (out->devices &
+                                ~(AUDIO_DEVICE_OUT_SPDIF |
+                                    AUDIO_DEVICE_OUT_AUX_DIGITAL));
+                        break;
+                    default:
+                        ALOGW("INVALID ROUTE for Other Devices, decoderType %d, routeFormat %d",
+                                decodeType, route_to_driver[idx][ROUTE_FORMAT_IDX]);
+                        break;
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+Description: update handle states
+*******************************************************************************/
+int update_alsa_handle_state(struct stream_out *out)
+{
+    ALOGV("%s", __func__);
+
+    struct alsa_handle *handle = NULL;
+    struct listnode *node;
+
+    if(out->open_dec_route) {
+        if((handle = get_alsa_handle())== NULL)
+            goto error;
+        list_add_tail(&out->session_list, &handle->list);
+        handle->route_format = ROUTE_UNCOMPRESSED;
+        handle->devices = out->dec_format_devices;
+        handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+        handle->out = out;
+        handle->cmd_pending = false;
+        ALOGD("open_dec_route: routeformat: %d, devices: 0x%x: "
+                ,handle->route_format, handle->devices);
+    }
+    if(out->open_dec_mch_route) {
+        if((handle = get_alsa_handle())== NULL)
+            goto error;
+        list_add_tail(&out->session_list, &handle->list);
+        handle->route_format = ROUTE_UNCOMPRESSED_MCH;
+        handle->devices = out->dec_mch_format_devices;
+        handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+        handle->out = out;
+        handle->cmd_pending = false;
+        ALOGD("OpenMCHDecodeRoute: routeformat: %d, devices: 0x%x: "
+               ,handle->route_format, handle->devices);
+    }
+    if(out->open_passt_route) {
+        if((handle = get_alsa_handle())== NULL)
+            goto error;
+        list_add_tail(&out->session_list, &handle->list);
+        handle->route_format = ROUTE_COMPRESSED;
+        handle->devices = out->passt_format_devices;
+        handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+        handle->out = out;
+        handle->cmd_pending = false;
+        ALOGD("open_passt_route: routeformat: %d, devices: 0x%x: "
+               ,handle->route_format, handle->devices);
+    }
+    if(out->sw_open_trans_route) {
+        if((handle = get_alsa_handle())== NULL)
+            goto error;
+        handle->route_format = ROUTE_SW_TRANSCODED_COMPRESSED;
+        handle->devices = out->sw_trans_format_devices;
+        handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+        handle->out = out;
+        handle->cmd_pending = false;
+        ALOGD("OpenTranscodeRoute: routeformat: %d, devices: 0x%x: "
+               ,handle->route_format, handle->devices);
+    }
+    if(out->hw_open_trans_route) {
+        if((handle = get_alsa_handle())== NULL)
+            goto error;
+        handle->route_format = ROUTE_DSP_TRANSCODED_COMPRESSED;
+        handle->devices = out->hw_trans_format_devices;
+        handle->usecase = platform_get_usecase(USECASE_AUDIO_PLAYBACK_OFFLOAD);
+        handle->out = out;
+        handle->cmd_pending = false;
+        ALOGD("OpenTranscodeRoute: routeformat: %d, devices: 0x%x: "
+               ,handle->route_format, handle->devices);
+    }
+
+return 0;
+
+error:
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        free_alsa_handle(handle);
+    }
+
+    return -ENOMEM;
+}
+
+/*******************************************************************************
+Description: setup input path
+*******************************************************************************/
+int allocate_internal_buffers(struct stream_out *out)
+{
+    ALOGV("%s",__func__);
+    int ret = 0;
+    int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+
+    /*
+    setup the bitstream state machine
+    */
+    out->bitstrm = ( struct audio_bitstream_sm *)calloc(1,
+            sizeof(struct audio_bitstream_sm));
+    if(!audio_bitstream_init(out->bitstrm, get_buffering_factor(out))) {
+        ALOGE("%s Unable to allocate bitstream buffering for MS11",__func__);
+        free(out->bitstrm);
+        out->bitstrm  = NULL;
+        return -EINVAL;
+    }
+
+    if(is_input_buffering_mode_reqd(out))
+        audio_bitstream_start_input_buffering_mode(out->bitstrm);
+
+    /*
+       setup the buffering data required for decode to start
+       AAC_ADIF would require worst case frame size before decode starts
+       other decoder formats handles the partial data, hence threshold is zero.
+     */
+
+    if(main_format == AUDIO_FORMAT_AAC_ADIF)
+        out->min_bytes_req_to_dec = AAC_BLOCK_PER_CHANNEL_MS11*out->channels-1;
+    else
+        out->min_bytes_req_to_dec = 0;
+
+    ret = open_temp_buf_for_metadata(out);
+    if(ret < 0) {
+        free(out->bitstrm);
+        out->bitstrm  = NULL;
+    }
+    out->buffer_size = get_buffer_length(out);
+
+    return ret;
+}
+
+/*******************************************************************************
+Description: setup input path
+*******************************************************************************/
+int free_internal_buffers(struct stream_out *out)
+{
+    if(out->bitstrm) {
+        free(out->bitstrm);
+        out->bitstrm  = NULL;
+    }
+
+    if(out->write_temp_buf) {
+        free(out->write_temp_buf);
+        out->write_temp_buf = NULL;
+    }
+
+    if(out->dec_conf_buf) {
+        free(out->dec_conf_buf);
+        out->dec_conf_buf = NULL;
+    }
+    return 0;
+}
+
+/*******************************************************************************
+Description: open MS11 instance
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+static int open_ms11_instance(struct stream_out *out)
+{
+    ALOGV("openMS11Instance");
+    int32_t formatMS11;
+    int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+    out->ms11_decoder = get_soft_ms11();
+    if(!out->ms11_decoder) {
+        ALOGE("Could not resolve all symbols Required for MS11");
+        return -EINVAL;
+    }
+    /*
+    MS11 created
+    */
+    if(initialize_ms11_function_pointers(out->ms11_decoder) == false) {
+        ALOGE("Could not resolve all symbols Required for MS11");
+        free_soft_ms11(out->ms11_decoder);
+        return -EINVAL;
+    }
+    /*
+    update format
+    */
+    if((main_format == AUDIO_FORMAT_AC3) ||
+       (main_format == AUDIO_FORMAT_EAC3)) {
+        /*TODO: who wil setCOMPRESSED_CONVERT_AC3_ASSOC */
+        if (out->spdif_format == COMPRESSED_CONVERT_AC3_ASSOC)
+            formatMS11 = FORMAT_DOLBY_DIGITAL_PLUS_MAIN_ASSOC;
+        else
+            formatMS11 = FORMAT_DOLBY_DIGITAL_PLUS_MAIN;
+    } else
+        formatMS11 = FORMAT_DOLBY_PULSE_MAIN;
+    /*
+    set the use case to the MS11 decoder and open the stream for decoding
+    */
+    if(ms11_set_usecase_and_open_stream_with_mode(out->ms11_decoder,
+                                    formatMS11, out->channels, out->sample_rate,
+                                    out->is_m11_file_mode)) {
+        ALOGE("SetUseCaseAndOpen MS11 failed");
+        free_soft_ms11(out->ms11_decoder);
+        return EINVAL;
+    }
+    if(is_decoder_config_required(out) && out->dec_conf_buf && out->dec_conf_bufLength) {
+        if(ms11_set_aac_config(out->ms11_decoder, (unsigned char *)out->dec_conf_buf,
+                                out->dec_conf_bufLength) == true) {
+            out->dec_conf_set = true;
+        }
+    }
+
+    return 0;
+}
+#endif
+/*******************************************************************************
+Description: copy input to internal buffer
+*******************************************************************************/
+void copy_bitstream_internal_buffer(struct audio_bitstream_sm *bitstrm,
+                    char *buffer, size_t bytes)
+{
+    // copy bitstream to internal buffer
+    audio_bitstream_copy_to_internal_buffer(bitstrm, (char *)buffer, bytes);
+#ifdef DEBUG
+    dumpInputOutput(INPUT, buffer, bytes, 0);
+#endif
+}
+
+/*******************************************************************************
+Description: set decoder config
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int setDecodeConfig(struct stream_out *out, char *buffer, size_t bytes)
+{
+    ALOGV("%s ", __func__);
+
+    int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+    if(!out->dec_conf_set) {
+        if(main_format == AUDIO_FORMAT_AAC ||
+                  main_format == AUDIO_FORMAT_HE_AAC_V1 ||
+                  main_format == AUDIO_FORMAT_AAC_ADIF ||
+                  main_format == AUDIO_FORMAT_HE_AAC_V2) {
+            if(out->ms11_decoder != NULL) {
+                if(ms11_set_aac_config(out->ms11_decoder,(unsigned char *)buffer,
+                            bytes) == false) {
+                    ALOGE("AAC decoder config fail");
+                    return 0;
+                }
+            }
+        }
+
+        out->dec_conf_bufLength = bytes;
+        if(out->dec_conf_buf)
+            free(out->dec_conf_buf);
+
+        out->dec_conf_buf = malloc(out->dec_conf_bufLength);
+        memcpy(out->dec_conf_buf,
+                buffer,
+                out->dec_conf_bufLength);
+        out->dec_conf_set = true;
+    }
+    out->dec_conf_set = true;
+    return bytes;
+}
+#endif
+
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+int validate_sw_free_space(struct stream_out* out, int bytes_consumed_in_decode, int *pcm_2ch_len,
+        int *pcm_mch_len, int *passthru_len, int *transcode_len, bool *wait_for_write_done) {
+
+    struct alsa_handle *handle = NULL;
+    char    *bufPtr;
+    int copy_output_buffer_size;
+
+    *pcm_2ch_len = *pcm_mch_len = *passthru_len = *transcode_len = *wait_for_write_done = 0;
+
+    if(out->decoder_type & SW_DECODE) {
+        bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+                                                                PCM_2CH_OUT);
+        /*TODO: there is chance of illegale access if ms11 output exceeds bitstream
+            output buffer boudary */
+        copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->ms11_decoder,
+                                                            PCM_2CH_OUT,
+                                                            bufPtr);
+        handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);
+        if(handle == NULL) {
+           ALOGE("%s Invalid handle", __func__);
+           return -EINVAL;
+        }
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+            *wait_for_write_done = true;
+        }
+        *pcm_2ch_len = copy_output_buffer_size;
+
+    }
+    if(out->decoder_type & SW_DECODE_MCH) {
+        bufPtr=audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+                                                PCM_MCH_OUT);
+        copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->ms11_decoder,
+                                                PCM_MCH_OUT,
+                                                bufPtr);
+        handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED_MCH);
+        if(handle == NULL) {
+           ALOGE("%s Invalid handle", __func__);
+           return -EINVAL;
+        }
+
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+            *wait_for_write_done = true;
+        }
+        *pcm_mch_len = copy_output_buffer_size;
+    }
+    if(out->decoder_type & SW_PASSTHROUGH) {
+        bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT);
+        copy_output_buffer_size = bytes_consumed_in_decode;
+        memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm), copy_output_buffer_size);
+
+        handle = get_handle_by_route_format(out, ROUTE_COMPRESSED);
+        if(handle == NULL) {
+           ALOGE("%s Invalid handle", __func__);
+           return -EINVAL;
+        }
+
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+            *wait_for_write_done = true;
+        }
+        *passthru_len = copy_output_buffer_size;
+    }
+    if(out->decoder_type & SW_TRANSCODE) {
+        bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+                                                         TRANSCODE_OUT);
+        copy_output_buffer_size = ms11_copy_output_from_ms11buf(out->bitstrm,
+                                                         COMPRESSED_OUT,
+                                                         bufPtr);
+        handle = get_handle_by_route_format(out, ROUTE_SW_TRANSCODED_COMPRESSED);
+        if(handle == NULL) {
+           ALOGE("%s Invalid handle", __func__);
+           return -EINVAL;
+        }
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+            *wait_for_write_done = true;
+        }
+        *transcode_len = copy_output_buffer_size;
+    }
+    return 0;
+}
+#endif
+
+int validate_hw_free_space(struct stream_out *out, int bytes_consumed_in_decode, int *pcm_2ch_len,
+        int *pcm_mch_len, int *passthru_len, int *transcode_len, bool *wait_for_write_done) {
+
+    struct alsa_handle *handle = NULL;
+    char    *bufPtr;
+    int copy_output_buffer_size;
+    *pcm_2ch_len = *pcm_mch_len = *passthru_len = *transcode_len = *wait_for_write_done = 0;
+    if(out->decoder_type & DSP_DECODE) {
+        ALOGVV("DSP_DECODE");
+        bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm,
+                            PCM_MCH_OUT);
+        copy_output_buffer_size = bytes_consumed_in_decode;
+        memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm),
+                    copy_output_buffer_size);
+        ALOGVV("%s  bytes_consumed %d out bufPtr %x, pcm_mch_out_buf_size%d",
+                __func__,bytes_consumed_in_decode,bufPtr,
+                out->bitstrm->pcm_mch_out_buf_size);
+        handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);/*TODO: revisit */
+        if(handle == NULL) {
+            ALOGE("%s Invalid handle", __func__);
+            return -EINVAL;
+        }
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+            *wait_for_write_done = true;
+            /*reset input buffer pointer as flinger will resend the data back */
+            audio_bitstream_set_input_buffer_write_ptr(out->bitstrm,
+                        -copy_output_buffer_size);
+            *pcm_mch_len = copy_output_buffer_size;
+        }
+        else
+            *pcm_mch_len = copy_output_buffer_size;
+    }
+    if(out->decoder_type & DSP_PASSTHROUGH) {
+        ALOGVV("DSP_PASSTHROUGH");
+        bufPtr = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT);
+        copy_output_buffer_size = bytes_consumed_in_decode;
+        memcpy(bufPtr, audio_bitstream_get_input_buffer_ptr(out->bitstrm), copy_output_buffer_size);
+        handle = get_handle_by_route_format(out, ROUTE_COMPRESSED);
+        if(handle == NULL) {
+            ALOGE("%s Invalid handle", __func__);
+            return -EINVAL;
+        }
+        if(get_compress_available_space(handle) < copy_output_buffer_size) {
+            handle->cmd_pending = true;
+             *wait_for_write_done = true;
+            *passthru_len = copy_output_buffer_size;
+            /*reset input buffer pointer as flinger will resend the data back */
+            audio_bitstream_set_input_buffer_ptr(out->bitstrm, -copy_output_buffer_size);
+        }
+        else
+            *passthru_len = copy_output_buffer_size;
+    }
+    /*TODO: handle DSP Transcode usecase */
+    return 0;
+}
+
+int update_bitstrm_pointers(struct stream_out *out, int pcm_2ch_len,
+                                int pcm_mch_len, int passthru_len, int transcode_len) {
+
+    if(out->decoder_type & SW_DECODE) {
+            audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, PCM_2CH_OUT,
+                        pcm_2ch_len);
+
+    }
+    if(out->decoder_type & SW_DECODE_MCH || out->decoder_type & DSP_DECODE) {
+            audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, PCM_MCH_OUT, pcm_mch_len);
+    }
+    if(out->decoder_type & SW_PASSTHROUGH || out->decoder_type & DSP_PASSTHROUGH) {
+            audio_bitstream_set_output_buffer_write_ptr(out->bitstrm, COMPRESSED_OUT, passthru_len);
+    }
+    if(out->decoder_type & SW_TRANSCODE) {
+            audio_bitstream_set_output_buffer_write_ptr(out->bitstrm,
+                                TRANSCODE_OUT,
+                                 transcode_len);
+    }
+    return 0;
+}
+
+/*TODO correct it */
+static int configure_compr(struct stream_out *out,
+        struct alsa_handle *handle) {
+    handle->compr_config.codec = (struct snd_codec *)
+        calloc(1, sizeof(struct snd_codec));
+    handle->compr_config.codec->id =
+        get_snd_codec_id(out->format); /*TODO: correct this based on format*/
+    handle->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+    handle->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+    handle->compr_config.codec->sample_rate =
+        compress_get_alsa_rate(out->sample_rate);
+    handle->compr_config.codec->bit_rate = out->compr_config.codec->bit_rate;
+    handle->compr_config.codec->ch_in =
+        popcount(out->channel_mask);
+    handle->compr_config.codec->ch_out = handle->compr_config.codec->ch_in;
+    memcpy(&handle->compr_config.codec->options,
+                    &out->compr_config.codec->options,
+                     sizeof(union snd_codec_options));
+    return 0;
+}
+
+/*TODO: do we need to apply volume at the session open*/
+static int set_compress_volume(struct alsa_handle *handle, int left, int right)
+{
+
+    struct audio_device *adev = handle->out->dev;
+    struct mixer_ctl *ctl;
+    int volume[2];
+
+    char mixer_ctl_name[44]; // max length of name is 44 as defined
+    char device_id[STRING_LENGTH_OF_INTEGER+1];
+
+    memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
+    strlcpy(mixer_ctl_name, "Compress Playback Volume", sizeof(mixer_ctl_name));
+
+    memset(device_id, 0, sizeof(device_id));
+    snprintf(device_id, "%d", handle->device_id, sizeof(device_id));
+
+    strlcat(mixer_ctl_name, device_id, sizeof(mixer_ctl_name));
+
+    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);
+        return -EINVAL;
+    }
+    volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
+    volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
+    mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
+
+    return 0;
+
+}
+
+/*******************************************************************************
+Description: software decode handling
+*******************************************************************************/
+//TODO: enable sw_decode if required
+#if USE_SWDECODE
+static int sw_decode(struct stream_out *out,
+                                char *buffer,
+                                size_t bytes,
+                                size_t *bytes_consumed,
+                                bool *continueDecode)
+{
+    /* bytes pending to be decoded in current buffer*/
+    bool wait_for_write_done = false;
+    int bytes_pending_for_decode = 0;
+    /* bytes consumed in current write  buffer */
+    int total_bytes_consumed = 0;
+    size_t  copyBytesMS11 = 0;
+    size_t  bytes_consumed_in_decode = 0;
+    size_t  copy_output_buffer_size = 0;
+    uint32_t outSampleRate = out->sample_rate;
+    uint32_t outChannels = out->channels;
+    char * bufPtr;
+    int pcm_2ch_len, pcm_mch_len, passthru_len, transcode_len;
+    struct alsa_handle *handle = NULL;
+
+    ALOGVV("sw Decode");
+    // eos handling
+    if(bytes == 0) {
+        if(out->format == AUDIO_FORMAT_AAC_ADIF)
+            audio_bitstream_append_silence_internal_buffer(out->bitstrm,
+                                                  out->min_bytes_req_to_dec,0x0);
+        else
+            return false;
+    }
+    /*
+    check for sync word, if present then configure MS11 for fileplayback mode
+    OFF. This is specifically done to handle Widevine usecase, in which the
+    ADTS HEADER is not stripped off by the Widevine parser
+    */
+    if(out->first_bitstrm_buf == true) {
+        uint16_t uData = (*((char *)buffer) << 8) + *((char *)buffer + 1) ;
+        if(ADTS_HEADER_SYNC_RESULT == (uData & ADTS_HEADER_SYNC_MASK)) {
+            ALOGD("Sync word found hence configure MS11 in file_playback Mode OFF");
+            free_soft_ms11(out->ms11_decoder);
+            out->is_m11_file_mode = false;
+            open_ms11_instance(out);
+        }
+        out->first_bitstrm_buf = false;
+    }
+    //decode
+    if(out->decoder_type == SW_PASSTHROUGH) {
+        /*TODO: check if correct */
+        bytes_consumed_in_decode = audio_bitstream_get_size(out->bitstrm);
+    } else {
+        if(audio_bitstream_sufficient_buffer_to_decode(out->bitstrm,
+                                out->min_bytes_req_to_dec) == true) {
+            bufPtr = audio_bitstream_get_input_buffer_ptr(out->bitstrm);
+            copyBytesMS11 = audio_bitstream_get_size(out->bitstrm);
+            ms11_copy_bitstream_to_ms11_inpbuf(out->ms11_decoder, bufPtr,copyBytesMS11);
+            bytes_consumed_in_decode = ms11_stream_decode(out->ms11_decoder,
+                                            &outSampleRate, &outChannels);
+        }
+    }
+
+    if((out->sample_rate != outSampleRate) || (out->channels != outChannels)) {
+        ALOGD("Change in sample rate. New sample rate: %d", outSampleRate);
+        out->sample_rate = outSampleRate;
+        out->channels = outChannels;
+        handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED);
+        if(handle !=NULL) {
+            configure_compr(out, handle);
+            handle->compr = compress_open(SOUND_CARD, handle->device_id,
+                    COMPRESS_IN, &handle->compr_config);
+            if (handle->compr && !is_compress_ready(handle->compr)) {
+                ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+                compress_close(handle->compr);
+                handle->compr = NULL;
+            }
+            if (out->offload_callback)
+                compress_nonblock(handle->compr, out->non_blocking);
+
+            set_compress_volume(handle, out->left_volume, out->right_volume);
+        }
+
+        handle = get_handle_by_route_format(out, ROUTE_UNCOMPRESSED_MCH);
+        if(handle !=NULL) {
+            configure_compr(out, handle);
+            handle->compr = compress_open(SOUND_CARD, handle->device_id,
+                    COMPRESS_IN, &handle->compr_config);
+            if (handle->compr && !is_compress_ready(handle->compr)) {
+                ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+                compress_close(handle->compr);
+                handle->compr = NULL;
+            }
+            if (out->offload_callback)
+                compress_nonblock(handle->compr, out->non_blocking);
+            set_compress_volume(handle, out->left_volume, out->right_volume);
+            out->channel_status_set = false;
+        }
+    }
+
+
+    validate_sw_free_space(out, bytes_consumed_in_decode, &pcm_2ch_len, &pcm_mch_len,
+            &passthru_len, &transcode_len, &wait_for_write_done);
+
+    if(wait_for_write_done && out->non_blocking) {
+        send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+        *continueDecode = false;
+        *bytes_consumed = 0;
+        return 0;
+    } else {
+        update_bitstrm_pointers(out, pcm_2ch_len, pcm_mch_len,
+                passthru_len, transcode_len);
+        audio_bitstream_copy_residue_to_start(out->bitstrm, bytes_consumed_in_decode);
+        *bytes_consumed = bytes_consumed_in_decode;
+    }
+
+    copy_output_buffer_size = pcm_2ch_len + pcm_mch_len + passthru_len + transcode_len;
+    if(copy_output_buffer_size &&
+       audio_bitstream_sufficient_buffer_to_decode(out->bitstrm, out->min_bytes_req_to_dec) == true) {
+        *continueDecode = true;
+        return 0;
+    }
+    return 0;
+}
+#endif
+
+/*******************************************************************************
+Description: dsp decode handling
+*******************************************************************************/
+static bool dsp_decode(struct stream_out *out, char *buffer, size_t bytes,
+                      size_t *bytes_consumed, bool *continueDecode)
+{
+    char    *bufPtr;
+    size_t  bytes_consumed_in_decode = 0;
+
+    bool wait_for_write_done = false;
+    int pcm_2ch_len, pcm_mch_len, passthru_len, transcode_len;
+
+    ALOGVV("dsp_decode");
+    // decode
+    {
+        bytes_consumed_in_decode = audio_bitstream_get_size(out->bitstrm);
+    }
+    // handle change in sample rate
+    {
+    }
+    //TODO: check if the copy of the buffers can be avoided
+    /* can be removed as its not required for dsp decode usecase */
+    *continueDecode = false;
+    validate_hw_free_space(out, bytes_consumed_in_decode, &pcm_2ch_len, &pcm_mch_len,
+            &passthru_len, &transcode_len, &wait_for_write_done);
+
+    if(wait_for_write_done && out->non_blocking) {
+        send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+        *bytes_consumed = 0;
+        return 0;
+    } else {
+        update_bitstrm_pointers(out, pcm_2ch_len, pcm_mch_len,
+                passthru_len, transcode_len);
+        audio_bitstream_copy_residue_to_start(out->bitstrm, bytes_consumed_in_decode);
+        *bytes_consumed = bytes_consumed_in_decode;
+        ALOGV("%s bytes_consumed_in_decode =%d",__func__,bytes_consumed_in_decode);
+    }
+
+    return 0;
+}
+
+static bool decode(struct stream_out *out, char * buffer, size_t bytes,
+                    size_t *bytes_consumed, bool *continuedecode)
+{
+    ALOGV("decode");
+    bool    continueDecode = false;
+    int ret  = 0;
+
+    // TODO: enable software decode if required
+    /*if (out->use_ms11_decoder) {
+        ret = sw_decode(out, buffer, bytes,
+                                bytes_consumed, continuedecode);
+
+        // set channel status
+        // Set the channel status after first frame decode/transcode
+        //TODO: set the SPDIF channel status bits
+      if(out->channel_status_set == false)
+            setSpdifchannel_status(
+                    audio_bitstream_get_output_buffer_ptr(out->bitstrm, COMPRESSED_OUT),
+                    bytes, AUDIO_PARSER_CODEC_AC3);
+
+    } else */{
+        ret = dsp_decode(out, buffer, bytes,
+                                bytes_consumed, continuedecode);
+        // set channel status
+        // Set the channel status after first frame decode/transcode
+        //TODO: set the SPDIF channel status bits
+/*        if(out->channel_status_set == false)
+            setSpdifchannel_status(
+                    audio_bitstream_get_output_buffer_ptr(out->bitstrm, COMPRESSED_OUT),
+                    bytes, AUDIO_PARSER_CODEC_DTS);
+*/
+    }
+    return ret;
+}
+
+/*******************************************************************************
+Description: fixup sample rate and channel info based on format
+*******************************************************************************/
+void fixupSampleRateChannelModeMS11Formats(struct stream_out *out)
+{
+    ALOGV("fixupSampleRateChannelModeMS11Formats");
+    int main_format = out->format & AUDIO_FORMAT_MAIN_MASK;
+    int subFormat = out->format & AUDIO_FORMAT_SUB_MASK;
+/*
+NOTE: For AAC, the output of MS11 is 48000 for the sample rates greater than
+      24000. The samples rates <= 24000 will be at their native sample rate
+      For AC3, the PCM output is at its native sample rate if the decoding is
+      single decode usecase for MS11.
+*/
+    if(main_format == AUDIO_FORMAT_AAC ||
+       main_format == AUDIO_FORMAT_HE_AAC_V1 ||
+       main_format == AUDIO_FORMAT_HE_AAC_V2 ||
+       main_format == AUDIO_FORMAT_AAC_ADIF) {
+        out->sample_rate = out->sample_rate > 24000 ? 48000 : out->sample_rate;
+        out->channels       = 6;
+    } else if (main_format == AUDIO_FORMAT_AC3 ||
+               main_format == AUDIO_FORMAT_EAC3) {
+        /* transcode AC3/EAC3 44.1K to 48K AC3 for non dual-mono clips */
+        if (out->sample_rate == 44100 &&
+            (subFormat != AUDIO_FORMAT_DOLBY_SUB_DM) &&
+            (out->spdif_format == COMPRESSED ||
+             out->spdif_format == AUTO_DEVICE_FORMAT ||
+             out->spdif_format == COMPRESSED_CONVERT_EAC3_AC3) &&
+             (out->hdmi_format == UNCOMPRESSED ||
+              out->hdmi_format == UNCOMPRESSED_MCH)) {
+            out->sample_rate = 48000;
+            out->spdif_format = COMPRESSED_CONVERT_AC3_ASSOC;
+        } else if (out->sample_rate == 44100) {
+            out->spdif_format = UNCOMPRESSED;
+        }
+        out->channels   = 6;
+    }
+    ALOGD("ms11 format fixup: out->spdif_format %d, out->hdmi_format %d",
+                                     out->spdif_format, out->hdmi_format);
+}
 
 static bool is_supported_format(audio_format_t format)
 {
@@ -173,21 +1397,33 @@
 /* must be called iwth out->lock locked */
 static void stop_compressed_output_l(struct stream_out *out)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
+    bool is_compr_out = false;
+
+    ALOGV("%s", __func__);
     out->offload_state = OFFLOAD_STATE_IDLE;
     out->playback_started = 0;
     out->send_new_metadata = 1;
-    if (out->compr != NULL) {
-        compress_stop(out->compr);
-        while (out->offload_thread_blocked) {
-            pthread_cond_wait(&out->cond, &out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        if (handle->compr != NULL) {
+            compress_stop(handle->compr);
+            is_compr_out = true;
         }
     }
+    if (is_compr_out) {
+        while (out->offload_thread_blocked)
+            pthread_cond_wait(&out->cond, &out->lock);
+    }
 }
 
 static void *offload_thread_loop(void *context)
 {
     struct stream_out *out = (struct stream_out *) context;
     struct listnode *item;
+    struct listnode *node;
+    struct alsa_handle *handle;
 
     out->offload_state = OFFLOAD_STATE_IDLE;
     out->playback_started = 0;
@@ -217,15 +1453,15 @@
         cmd = node_to_item(item, struct offload_cmd, node);
         list_remove(item);
 
-        ALOGVV("%s STATE %d CMD %d out->compr %p",
-               __func__, out->offload_state, cmd->cmd, out->compr);
+        ALOGVV("%s STATE %d CMD %d",
+               __func__, out->offload_state, cmd->cmd);
 
         if (cmd->cmd == OFFLOAD_CMD_EXIT) {
             free(cmd);
             break;
         }
 
-        if (out->compr == NULL) {
+        if (list_empty(&out->session_list)) {
             ALOGE("%s: Compress handle is NULL", __func__);
             pthread_cond_signal(&out->cond);
             continue;
@@ -235,18 +1471,34 @@
         send_callback = false;
         switch(cmd->cmd) {
         case OFFLOAD_CMD_WAIT_FOR_BUFFER:
-            compress_wait(out->compr, -1);
+            list_for_each(node, &out->session_list) {
+                handle = node_to_item(node, struct alsa_handle, list);
+                if (handle->compr && handle->cmd_pending) {
+                    compress_wait(handle->compr, -1);
+                    handle->cmd_pending = false;
+                }
+            }
             send_callback = true;
             event = STREAM_CBK_EVENT_WRITE_READY;
             break;
         case OFFLOAD_CMD_PARTIAL_DRAIN:
-            compress_next_track(out->compr);
-            compress_partial_drain(out->compr);
+            list_for_each(node, &out->session_list) {
+                handle = node_to_item(node, struct alsa_handle, list);
+                if (handle->compr) {
+                    compress_next_track(handle->compr);
+                    compress_partial_drain(handle->compr);
+                }
+            }
             send_callback = true;
             event = STREAM_CBK_EVENT_DRAIN_READY;
             break;
         case OFFLOAD_CMD_DRAIN:
-            compress_drain(out->compr);
+            list_for_each(node, &out->session_list) {
+                handle = node_to_item(node, struct alsa_handle, list);
+                if (handle->compr) {
+                    compress_drain(handle->compr);
+                }
+            }
             send_callback = true;
             event = STREAM_CBK_EVENT_DRAIN_READY;
             break;
@@ -373,18 +1625,18 @@
     return 0;
 }
 
-static int stop_output_stream(struct stream_out *out)
+static int stop_output_stream(struct stream_out *out, struct alsa_handle *handle)
 {
     int i, ret = 0;
     struct audio_usecase *uc_info;
     struct audio_device *adev = out->dev;
 
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
-          out->usecase, use_case_table[out->usecase]);
-    uc_info = get_usecase_from_list(adev, out->usecase);
+          handle->usecase, use_case_table[handle->usecase]);
+    uc_info = get_usecase_from_list(adev, handle->usecase);
     if (uc_info == NULL) {
         ALOGE("%s: Could not find the usecase (%d) in the list",
-              __func__, out->usecase);
+              __func__, handle->usecase);
         return -EINVAL;
     }
 
@@ -409,63 +1661,66 @@
     return ret;
 }
 
-int start_output_stream(struct stream_out *out)
+int start_output_stream(struct stream_out *out, struct alsa_handle *handle)
 {
     int ret = 0;
     struct audio_usecase *uc_info;
     struct audio_device *adev = out->dev;
 
     ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
-          __func__, out->usecase, use_case_table[out->usecase], out->devices);
-    out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
-    if (out->pcm_device_id < 0) {
+          __func__, handle->usecase, use_case_table[handle->usecase], handle->devices);
+    handle->device_id = platform_get_pcm_device_id(handle->usecase, PCM_PLAYBACK);
+    if (handle->device_id < 0) {
         ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
-              __func__, out->pcm_device_id, out->usecase);
+              __func__, handle->device_id, handle->usecase);
         ret = -EINVAL;
         goto error_config;
     }
 
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
-    uc_info->id = out->usecase;
+    uc_info->id = handle->usecase;
+    uc_info->handle = handle;
     uc_info->type = PCM_PLAYBACK;
     uc_info->stream.out = out;
-    uc_info->devices = out->devices;
+    uc_info->devices = handle->devices;
     uc_info->in_snd_device = SND_DEVICE_NONE;
     uc_info->out_snd_device = SND_DEVICE_NONE;
 
     /* This must be called before adding this usecase to the list */
-    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
-        check_and_set_hdmi_channels(adev, out->config.channels);
+    //if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
+    //    check_and_set_hdmi_channels(adev, out->config.channels);
 
     list_add_tail(&adev->usecase_list, &uc_info->list);
 
-    select_devices(adev, out->usecase);
+    select_devices(adev, handle->usecase);
 
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
-          __func__, 0, out->pcm_device_id);
-    if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
-                               PCM_OUT | PCM_MONOTONIC, &out->config);
-        if (out->pcm && !pcm_is_ready(out->pcm)) {
-            ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
-            pcm_close(out->pcm);
-            out->pcm = NULL;
+          __func__, 0, handle->device_id);
+    if (out->uc_strm_type != OFFLOAD_PLAYBACK_STREAM) {
+        handle->compr = NULL;
+        handle->pcm = pcm_open(SOUND_CARD, handle->device_id,
+                               PCM_OUT | PCM_MONOTONIC, &handle->config);
+        if (handle->pcm && !pcm_is_ready(handle->pcm)) {
+            ALOGE("%s: %s", __func__, pcm_get_error(handle->pcm));
+            pcm_close(handle->pcm);
+            handle->pcm = NULL;
             ret = -EIO;
             goto error_open;
         }
     } else {
-        out->pcm = NULL;
-        out->compr = compress_open(SOUND_CARD, out->pcm_device_id,
-                                   COMPRESS_IN, &out->compr_config);
-        if (out->compr && !is_compress_ready(out->compr)) {
-            ALOGE("%s: %s", __func__, compress_get_error(out->compr));
-            compress_close(out->compr);
-            out->compr = NULL;
+        handle->pcm = NULL;
+        configure_compr(out, handle);
+        handle->compr = compress_open(SOUND_CARD, handle->device_id,
+                                   COMPRESS_IN, &handle->compr_config);
+        if (handle->compr && !is_compress_ready(handle->compr)) {
+            ALOGE("%s: %s", __func__, compress_get_error(handle->compr));
+            compress_close(handle->compr);
+            handle->compr = NULL;
             ret = -EIO;
             goto error_open;
         }
         if (out->offload_callback)
-            compress_nonblock(out->compr, out->non_blocking);
+            compress_nonblock(handle->compr, out->non_blocking);
 
         if (adev->visualizer_start_output != NULL)
             adev->visualizer_start_output(out->handle);
@@ -473,7 +1728,7 @@
     ALOGV("%s: exit", __func__);
     return 0;
 error_open:
-    stop_output_stream(out);
+    stop_output_stream(out, handle);
 error_config:
     return ret;
 }
@@ -494,10 +1749,12 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
 
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
+    /*if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
         return out->compr_config.fragment_size;
+    */
+    return (size_t)out->buffer_size;
 
-    return out->config.period_size * audio_stream_frame_size(stream);
+    //return out->config.period_size * audio_stream_frame_size(stream);
 }
 
 static uint32_t out_get_channels(const struct audio_stream *stream)
@@ -523,6 +1780,8 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
+    struct listnode *node;
+    struct alsa_handle *handle;
 
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
           out->usecase, use_case_table[out->usecase]);
@@ -538,21 +1797,21 @@
     pthread_mutex_lock(&adev->lock);
     if (!out->standby) {
         out->standby = true;
-        if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-            if (out->pcm) {
-                pcm_close(out->pcm);
-                out->pcm = NULL;
+        stop_compressed_output_l(out);
+        out->gapless_mdata.encoder_delay = 0;
+        out->gapless_mdata.encoder_padding = 0;
+
+        list_for_each(node, &out->session_list) {
+            handle = node_to_item(node, struct alsa_handle, list);
+            if (handle->compr != NULL) {
+                compress_close(handle->compr);
+                handle->compr = NULL;
+            } else if (handle->pcm) {
+                pcm_close(handle->pcm);
+                handle->pcm = NULL;
             }
-        } else {
-            stop_compressed_output_l(out);
-            out->gapless_mdata.encoder_delay = 0;
-            out->gapless_mdata.encoder_padding = 0;
-            if (out->compr != NULL) {
-                compress_close(out->compr);
-                out->compr = NULL;
-            }
+            stop_output_stream(out, handle);
         }
-        stop_output_stream(out);
     }
     pthread_mutex_unlock(&adev->lock);
     pthread_mutex_unlock(&out->lock);
@@ -608,8 +1867,7 @@
     int ret, val = 0;
     bool select_new_device = false;
 
-    ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
-          __func__, out->usecase, use_case_table[out->usecase], kvpairs);
+    ALOGD("%s: enter: kvpairs: %s", __func__, kvpairs);
     parms = str_parms_create_str(kvpairs);
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
     if (ret >= 0) {
@@ -653,12 +1911,63 @@
             if (!out->standby)
                 select_devices(adev, out->usecase);
         }
+//TODO:
+//Get the device and device format mapping from the RoutingManager.
+//Decide which streams need to be derouted and which need to opened/closed
+//Update the respective device in each of the handles
+#if 0
+        if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+
+            /* TODO get format form routing manager */
+            update_decode_type_and_routing_states(out);
+
+            if(is_input_buffering_mode_reqd(out))
+                audio_bitstream_start_input_buffering_mode(out->bitstrm);
+            else
+                audio_bitstream_stop_input_buffering_mode(out->bitstrm);
+            /*
+               For the runtime format change, close the device first to avoid any
+               concurrent PCM + Compressed sessions on the same device.
+             */
+             close_handles_for_device_switch(out);
+            if(!out->mopen_dec_route)
+                handleCloseForDeviceSwitch(ROUTE_UNCOMPRESSED);
+
+            if(!out->mopen_dec_mch_route)
+                handleCloseForDeviceSwitch(ROUTE_UNCOMPRESSED_MCH);
+
+            if(!out->mopen_passt_route)
+                handleCloseForDeviceSwitch(ROUTE_COMPRESSED);
+
+            if(!msw_open_trans_route)
+                handleCloseForDeviceSwitch(ROUTE_SW_TRANSCODED_COMPRESSED);
+
+            if(!mhw_open_trans_route)
+                handleCloseForDeviceSwitch(ROUTE_DSP_TRANSCODED_COMPRESSED);
+
+            if(out->mopen_dec_route)
+                handleSwitchAndOpenForDeviceSwitch(mdec_format_devices,
+                        ROUTE_UNCOMPRESSED);
+            if(out->mopen_dec_mch_route)
+                handleSwitchAndOpenForDeviceSwitch(mdec_mch_format_devices,
+                        ROUTE_UNCOMPRESSED_MCH);
+            if(out->mopen_passt_route)
+                handleSwitchAndOpenForDeviceSwitch(mpasst_format_devices,
+                        ROUTE_COMPRESSED);
+            if(out->msw_open_trans_route)
+                handleSwitchAndOpenForDeviceSwitch(msw_trans_format_devices,
+                        ROUTE_SW_TRANSCODED_COMPRESSED);
+            if(out->mhw_open_trans_route)
+                handleSwitchAndOpenForDeviceSwitch(mhw_trans_format_devices,
+                        ROUTE_DSP_TRANSCODED_COMPRESSED);
+        }
+#endif
 
         pthread_mutex_unlock(&adev->lock);
         pthread_mutex_unlock(&out->lock);
     }
 
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+    if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
         parse_compress_metadata(out, parms);
     }
 
@@ -707,42 +2016,206 @@
 static uint32_t out_get_latency(const struct audio_stream_out *stream)
 {
     struct stream_out *out = (struct stream_out *)stream;
+    struct listnode *item;
+    struct alsa_handle *handle;
 
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
+    //TODO: decide based on the clip properties
+    if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM)
         return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
 
-    return (out->config.period_count * out->config.period_size * 1000) /
-           (out->config.rate);
+    item = list_head(&out->session_list);
+    handle = node_to_item(item, struct alsa_handle, list);
+    if(!handle) {
+        ALOGE("%s: error pcm handle NULL", __func__);
+        return -EINVAL;
+    }
+
+    return (handle->config.period_count * handle->config.period_size * 1000) /
+        (handle->config.rate);
 }
 
 static int out_set_volume(struct audio_stream_out *stream, float left,
                           float right)
 {
     struct stream_out *out = (struct stream_out *)stream;
-    int volume[2];
+    struct listnode *node;
+    struct alsa_handle *handle;
+    struct audio_device *adev = out->dev;
+    int ret = -ENOSYS;
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        if (handle->pcm && (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH)){
+            /* only take left channel into account: the API is for stereo anyway */
+            out->muted = (left == 0.0f);
+            ret = 0;
+        } else if (handle->compr) {
 
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
-        /* only take left channel into account: the API is for stereo anyway */
-        out->muted = (left == 0.0f);
-        return 0;
-    } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        const char *mixer_ctl_name = "Compress Playback Volume";
-        struct audio_device *adev = out->dev;
-        struct mixer_ctl *ctl;
+            out->left_volume = left;
+            out->right_volume = right;
 
-        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);
-            return -EINVAL;
+            //ret = set_compress_volume(handle, left, right);
         }
-        volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
-        volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
-        mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
-        return 0;
+    }
+    pthread_mutex_unlock(&out->lock);
+
+    return ret;
+}
+
+static int write_data(struct stream_out *out, struct alsa_handle *handle,
+                   const void *buffer, int bytes) {
+
+    int ret = 0;
+    if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+        ALOGV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
+
+        ret = compress_write(handle->compr, buffer, bytes);
+        ALOGV("%s: writing buffer (%d bytes) to compress device returned %d",
+                    __func__, bytes, ret);
+        /* TODO:disnable this if ms12 */
+
+        if (ret >= 0 && ret < (ssize_t)bytes) {
+            send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
+        }
+        return ret;
+    } else {
+        if (handle->pcm) {
+            if (out->muted)
+                memset((void *)buffer, 0, bytes);
+            ALOGV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+            ret = pcm_write(handle->pcm, (void *)buffer, bytes);
+        }
     }
 
-    return -ENOSYS;
+    if (ret != 0) {
+        if ((handle && handle->pcm))
+            ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(handle->pcm));
+        out_standby(&out->stream.common);
+        usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
+                out_get_sample_rate(&out->stream.common));
+    }
+    return bytes;
+}
+
+/*******************************************************************************
+Description: render
+*******************************************************************************/
+size_t render_offload_data(struct stream_out *out, const void *buffer, size_t bytes)
+{
+    int ret =0;
+    uint32_t renderedPcmBytes = 0;
+    int      fragment_size;
+    uint32_t availableSize;
+    int bytes_to_write = bytes;
+    int renderType;
+    /*int metadataLength = sizeof(out->output_meta_data);*/
+    struct listnode *node;
+    struct alsa_handle *handle;
+
+    ALOGV("%s", __func__);
+
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        if (out->send_new_metadata) {
+            ALOGVV("send new gapless metadata");
+            compress_set_gapless_metadata(handle->compr, &out->gapless_mdata);
+        }
+
+        switch(handle->route_format) {
+        case ROUTE_UNCOMPRESSED:
+            ALOGVV("ROUTE_UNCOMPRESSED");
+            renderType = PCM_2CH_OUT;
+            break;
+        case ROUTE_UNCOMPRESSED_MCH:
+            ALOGVV("ROUTE_UNCOMPRESSED_MCH");
+            renderType = PCM_MCH_OUT;
+            break;
+        case ROUTE_COMPRESSED:
+            ALOGVV("ROUTE_COMPRESSED");
+            renderType = COMPRESSED_OUT;
+            break;
+        case ROUTE_SW_TRANSCODED_COMPRESSED:
+            ALOGVV("ROUTE_SW_TRANSCODED_COMPRESSED");
+            renderType = TRANSCODE_OUT;
+            break;
+        case ROUTE_DSP_TRANSCODED_COMPRESSED:
+            ALOGVV("ROUTE_DSP_TRANSCODED_COMPRESSED");
+            continue;
+        default:
+            continue;
+        };
+
+        fragment_size = handle->compr_config.fragment_size;
+        /*TODO handle timestamp case */
+#if USE_SWDECODE
+        while(audio_bitstream_sufficient_sample_to_render(out->bitstrm,
+                                                renderType, 1) == true) {
+            availableSize = audio_bitstream_get_output_buffer_write_ptr(out->bitstrm, renderType) -
+                audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType);
+            buffer = audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType);
+            bytes_to_write   = availableSize;
+
+            TODO: meta data is only neded for TS mode
+            out->output_meta_data.metadataLength = metadataLength;
+            out->output_meta_data.bufferLength = (availableSize >=
+                                             (fragment_size - metadataLength)) ?
+                                           fragment_size - metadataLength :
+                                           availableSize;
+            bytes_to_write = metadataLength +out->output_meta_data.bufferLength;
+            out->output_meta_data.timestamp = 0;
+            memcpy(out->write_temp_buf, &out->output_meta_data, metadataLength);
+            memcpy(out->write_temp_buf+metadataLength,
+                   audio_bitstream_get_output_buffer_ptr(out->bitstrm, renderType),
+                   out->output_meta_data.bufferLength);
+            ret = write_data(out, handle, out->write_temp_buf, bytes_to_write);
+#endif
+
+            ret = write_data(out, handle, buffer, bytes_to_write);
+            ALOGD("write_data returned with %d", ret);
+            if(ret < 0) {
+                ALOGE("write_data returned ret < 0");
+                return ret;
+            } else {
+                if (!out->playback_started) {
+                    compress_start(handle->compr);
+                }
+                /*TODO:Do we need this
+                if(renderType == ROUTE_UNCOMPRESSED ||
+                   (renderType == ROUTE_UNCOMPRESSED_MCH && !out->open_dec_route)) {
+                    mFrameCount++;
+                renderedPcmBytes += out->output_meta_data.bufferLength;
+                }*/
+                renderedPcmBytes += ret;
+#if USE_SWDECODE
+                 /*iTODO: enable for MS11
+                audio_bitstream_copy_residue_output_start(out->bitstrm, renderType,
+                        bytes_to_write);
+                TODO:what if ret<bytes_to_write*/
+#endif
+            }
+#if USE_SWDECODE
+        }
+#endif
+    }
+    out->playback_started = 1;
+    out->offload_state = OFFLOAD_STATE_PLAYING;
+    out->send_new_metadata = 0;
+    return renderedPcmBytes;
+}
+
+size_t render_pcm_data(struct stream_out *out, const void *buffer, size_t bytes)
+{
+    ALOGV("%s", __func__);
+    size_t ret = 0;
+    struct listnode *node;
+    struct alsa_handle *handle;
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        ALOGV("%s handle is 0x%x", __func__,(uint32_t)handle);
+        ret = write_data(out, handle, buffer, bytes);
+    }
+    return ret;
 }
 
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
@@ -751,21 +2224,66 @@
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
     ssize_t ret = 0;
+    struct listnode *node;
+    bool continueDecode;
+    struct alsa_handle *handle;
+    size_t bytes_consumed;
+    size_t total_bytes_consumed = 0;
+
+    ALOGV("%s bytes =%d", __func__, bytes);
 
     pthread_mutex_lock(&out->lock);
+
+//TODO: handle a2dp
+/*      if (mRouteAudioToA2dp &&
+                        mA2dpUseCase == AudioHardwareALSA::USECASE_NONE) {
+                a2dpRenderingControl(A2DP_RENDER_SETUP);
+        }
+*/
+   /* TODO: meta data comes in set_parameter it will be passed in compre_open
+      for all format exxce ms11 format
+     and  for ms11 it will be set sdecode fucntion while opneing ms11 instance
+     hence below piece of  code is no required*/
+   /*
+   if(!out->dec_conf_set && is_decoder_config_required(out)) {
+        if (setDecodeConfig(out, (char *)buffer, bytes))
+            ALOGD("decoder configuration set");
+    }
+    */
+
     if (out->standby) {
         out->standby = false;
-        pthread_mutex_lock(&adev->lock);
-            ret = start_output_stream(out);
-        pthread_mutex_unlock(&adev->lock);
-        /* ToDo: If use case is compress offload should return 0 */
-        if (ret != 0) {
-            out->standby = true;
-            goto exit;
+        list_for_each(node, &out->session_list) {
+            handle = node_to_item(node, struct alsa_handle, list);
+            pthread_mutex_lock(&adev->lock);
+            ret = start_output_stream(out, handle);
+            pthread_mutex_unlock(&adev->lock);
+            /* ToDo: If use case is compress offload should return 0 */
+            if (ret != 0) {
+                out->standby = true;
+                goto exit;
+            }
         }
     }
 
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+    if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
+#if USE_SWDECODE
+        //TODO: Enable for MS11
+        copy_bitstream_internal_buffer(out->bitstrm, (char *)buffer, bytes);
+        //DO check if timestamp mode handle partial buffer
+        do {
+
+            bytes_consumed = 0;
+            ret = decode(out, (char *)buffer, bytes, &bytes_consumed, &continueDecode);
+            if(ret < 0)
+                goto exit;
+            /*TODO: check for return size from write when ms11 is removed*/
+            render_offload_data(out, continueDecode);
+            total_bytes_consumed += bytes_consumed;
+
+        } while(continueDecode == true);
+#endif
+#if 0
         ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
         if (out->send_new_metadata) {
             ALOGVV("send new gapless metadata");
@@ -807,11 +2325,50 @@
                out_get_sample_rate(&out->stream.common));
     }
     return bytes;
+#endif
+        ret = render_offload_data(out, buffer, bytes);
+        total_bytes_consumed = ret;
+    } else {
+        ret = render_pcm_data(out, buffer, bytes);
+        total_bytes_consumed = ret;
+    }
+
+exit:
+    pthread_mutex_unlock(&out->lock);
+    ALOGV("total_bytes_consumed %d",total_bytes_consumed);
+    return total_bytes_consumed;
 }
 
 static int out_get_render_position(const struct audio_stream_out *stream,
                                    uint32_t *dsp_frames)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
+    struct stream_out *out = (struct stream_out *)stream;
+    struct audio_device *adev = out->dev;
+    *dsp_frames = 0;
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&out->lock);
+    if ((out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) && (dsp_frames != NULL)) {
+        list_for_each(node, &out->session_list) {
+            handle = node_to_item(node, struct alsa_handle, list);
+            if ((handle && handle->compr &&
+                        handle->route_format != ROUTE_DSP_TRANSCODED_COMPRESSED)){
+                compress_get_tstamp(handle->compr, (unsigned long *)dsp_frames,
+                        &out->sample_rate);
+                ALOGV("%s rendered frames %d sample_rate %d",
+                        __func__, *dsp_frames, out->sample_rate);
+            }
+            pthread_mutex_unlock(&out->lock);
+            return 0;
+        }
+    }
+    else {
+        pthread_mutex_unlock(&out->lock);
+        return -EINVAL;
+    }
+    return 0;
+#if 0
     struct stream_out *out = (struct stream_out *)stream;
     *dsp_frames = 0;
     if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
@@ -826,6 +2383,7 @@
         return 0;
     } else
         return -EINVAL;
+#endif
 }
 
 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
@@ -847,6 +2405,46 @@
 static int out_get_presentation_position(const struct audio_stream_out *stream,
                                    uint64_t *frames, struct timespec *timestamp)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
+    struct stream_out *out = (struct stream_out *)stream;
+    struct audio_device *adev = out->dev;
+    *frames = 0;
+    ALOGV("%s", __func__);
+    pthread_mutex_lock(&out->lock);
+    if ((frames != NULL)) {
+        list_for_each(node, &out->session_list) {
+            handle = node_to_item(node, struct alsa_handle, list);
+            if ((handle && handle->compr &&
+                        handle->route_format != ROUTE_DSP_TRANSCODED_COMPRESSED)){
+                compress_get_tstamp(handle->compr, (unsigned long *)frames,
+                        &out->sample_rate);
+            clock_gettime(CLOCK_MONOTONIC, timestamp);
+                ALOGV("%s rendered frames %d sample_rate %d",
+                        __func__, *frames, out->sample_rate);
+            }
+        else if (handle->pcm) {
+            size_t avail;
+            if (pcm_get_htimestamp(handle->pcm, &avail, timestamp) == 0) {
+                size_t kernel_buffer_size = handle->config.period_size * handle->config.period_count;
+                int64_t signed_frames = out->written - kernel_buffer_size + avail;
+                // This adjustment accounts for buffering after app processor.
+                // It is based on estimated DSP latency per use case, rather than exact.
+                signed_frames -=
+                    (platform_render_latency(handle->usecase) * out->sample_rate / 1000000LL);
+
+                // It would be unusual for this value to be negative, but check just in case ...
+                if (signed_frames >= 0) {
+                    *frames = signed_frames;
+                }
+            }
+        }
+
+        }
+    }
+        pthread_mutex_unlock(&out->lock);
+        return -EINVAL;
+#if 0
     struct stream_out *out = (struct stream_out *)stream;
     int ret = -1;
     unsigned long dsp_frames;
@@ -887,6 +2485,7 @@
     pthread_mutex_unlock(&out->lock);
 
     return ret;
+#endif
 }
 
 static int out_set_callback(struct audio_stream_out *stream,
@@ -904,64 +2503,84 @@
 
 static int out_pause(struct audio_stream_out* stream)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
     struct stream_out *out = (struct stream_out *)stream;
     int status = -ENOSYS;
     ALOGV("%s", __func__);
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        pthread_mutex_lock(&out->lock);
-        if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
-            status = compress_pause(out->compr);
+    pthread_mutex_lock(&out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        if (handle->compr != NULL && out->offload_state ==
+                OFFLOAD_STATE_PLAYING) {
+            status = compress_pause(handle->compr);
             out->offload_state = OFFLOAD_STATE_PAUSED;
         }
-        pthread_mutex_unlock(&out->lock);
     }
+    pthread_mutex_unlock(&out->lock);
     return status;
 }
 
 static int out_resume(struct audio_stream_out* stream)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
     struct stream_out *out = (struct stream_out *)stream;
     int status = -ENOSYS;
     ALOGV("%s", __func__);
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        status = 0;
-        pthread_mutex_lock(&out->lock);
-        if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
-            status = compress_resume(out->compr);
-            out->offload_state = OFFLOAD_STATE_PLAYING;
-        }
-        pthread_mutex_unlock(&out->lock);
+    pthread_mutex_lock(&out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+            status = 0;
+            if (handle->compr != NULL && out->offload_state ==
+                    OFFLOAD_STATE_PAUSED) {
+                status = compress_resume(handle->compr);
+                out->offload_state = OFFLOAD_STATE_PLAYING;
+            }
     }
+    pthread_mutex_unlock(&out->lock);
     return status;
 }
 
 static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
     struct stream_out *out = (struct stream_out *)stream;
     int status = -ENOSYS;
     ALOGV("%s", __func__);
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        pthread_mutex_lock(&out->lock);
-        if (type == AUDIO_DRAIN_EARLY_NOTIFY)
-            status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
-        else
-            status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
-        pthread_mutex_unlock(&out->lock);
+    pthread_mutex_lock(&out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        status = 0;
+        if (handle->compr != NULL) {
+            if (type == AUDIO_DRAIN_EARLY_NOTIFY)
+                status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
+            else
+                status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
+        }
     }
+    pthread_mutex_unlock(&out->lock);
     return status;
 }
 
 static int out_flush(struct audio_stream_out* stream)
 {
+    struct listnode *node;
+    struct alsa_handle *handle;
     struct stream_out *out = (struct stream_out *)stream;
+    int status = -ENOSYS;
     ALOGV("%s", __func__);
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
-        pthread_mutex_lock(&out->lock);
-        stop_compressed_output_l(out);
-        pthread_mutex_unlock(&out->lock);
-        return 0;
+    pthread_mutex_lock(&out->lock);
+    list_for_each(node, &out->session_list) {
+        handle = node_to_item(node, struct alsa_handle, list);
+        status = 0;
+        if (handle->compr != NULL) {
+            stop_compressed_output_l(out);
+        }
     }
-    return -ENOSYS;
+    pthread_mutex_unlock(&out->lock);
+    return status;
 }
 
 int adev_open_output_stream(struct audio_hw_device *dev,
@@ -973,7 +2592,9 @@
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
-    int i, ret;
+    struct alsa_handle *device_handle = NULL;
+    int i, ret, channels;
+    struct listnode *item;
 
     ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
           __func__, config->sample_rate, config->channel_mask, devices, flags);
@@ -982,7 +2603,9 @@
 
     if (devices == AUDIO_DEVICE_NONE)
         devices = AUDIO_DEVICE_OUT_SPEAKER;
+    list_init(&out->session_list);
 
+    reset_out_parameters(out);
     out->flags = flags;
     out->devices = devices;
     out->dev = adev;
@@ -990,109 +2613,13 @@
     out->sample_rate = config->sample_rate;
     out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
     out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
+    out->config = config;
     out->handle = handle;
 
+//*TODO: get hdmi/spdif format/channels from routing manager and intialize out->spdif_format & out->hdmi_format*/
     /* Init use case and pcm_config */
-    if (out->flags == AUDIO_OUTPUT_FLAG_DIRECT &&
-        out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
-        pthread_mutex_lock(&adev->lock);
-        ret = read_hdmi_channel_masks(out);
-        pthread_mutex_unlock(&adev->lock);
-        if (ret != 0)
-            goto error_open;
-
-        if (config->sample_rate == 0)
-            config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
-        if (config->channel_mask == 0)
-            config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
-
-        out->channel_mask = config->channel_mask;
-        out->sample_rate = config->sample_rate;
-        out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
-        out->config = pcm_config_hdmi_multi;
-        out->config.rate = config->sample_rate;
-        out->config.channels = popcount(out->channel_mask);
-        out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
-    } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-        if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
-            config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
-            ALOGE("%s: Unsupported Offload information", __func__);
-            ret = -EINVAL;
-            goto error_open;
-        }
-        if (!is_supported_format(config->offload_info.format)) {
-            ALOGE("%s: Unsupported audio format", __func__);
-            ret = -EINVAL;
-            goto error_open;
-        }
-
-        out->compr_config.codec = (struct snd_codec *)
-                                    calloc(1, sizeof(struct snd_codec));
-
-        out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
-        if (config->offload_info.channel_mask)
-            out->channel_mask = config->offload_info.channel_mask;
-        else if (config->channel_mask)
-            out->channel_mask = config->channel_mask;
-        out->format = config->offload_info.format;
-        out->sample_rate = config->offload_info.sample_rate;
-
-        out->stream.set_callback = out_set_callback;
-        out->stream.pause = out_pause;
-        out->stream.resume = out_resume;
-        out->stream.drain = out_drain;
-        out->stream.flush = out_flush;
-
-        out->compr_config.codec->id =
-                get_snd_codec_id(config->offload_info.format);
-        out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
-        out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
-        out->compr_config.codec->sample_rate =
-                    compress_get_alsa_rate(config->offload_info.sample_rate);
-        out->compr_config.codec->bit_rate =
-                    config->offload_info.bit_rate;
-        out->compr_config.codec->ch_in =
-                    popcount(config->channel_mask);
-        out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
-
-        if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
-            out->non_blocking = 1;
-
-        out->send_new_metadata = 1;
-        create_offload_callback_thread(out);
-        ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
-                __func__, config->offload_info.version,
-                config->offload_info.bit_rate);
-    } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
-        out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
-        out->config = pcm_config_low_latency;
-        out->sample_rate = out->config.rate;
-    } else {
-        out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
-        out->config = pcm_config_deep_buffer;
-        out->sample_rate = out->config.rate;
-    }
-
-    if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
-        if(adev->primary_output == NULL)
-            adev->primary_output = out;
-        else {
-            ALOGE("%s: Primary output is already opened", __func__);
-            ret = -EEXIST;
-            goto error_open;
-        }
-    }
-
-    /* Check if this usecase is already existing */
-    pthread_mutex_lock(&adev->lock);
-    if (get_usecase_from_list(adev, out->usecase) != NULL) {
-        ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
-        pthread_mutex_unlock(&adev->lock);
-        ret = -EEXIST;
-        goto error_open;
-    }
-    pthread_mutex_unlock(&adev->lock);
-
+    out->hdmi_format = UNCOMPRESSED;
+    out->spdif_format = UNCOMPRESSED;
     out->stream.common.get_sample_rate = out_get_sample_rate;
     out->stream.common.set_sample_rate = out_set_sample_rate;
     out->stream.common.get_buffer_size = out_get_buffer_size;
@@ -1119,6 +2646,138 @@
     pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
     pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
 
+    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
+        ALOGE("%s: Usecase is OFFLOAD", __func__);
+        if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
+            config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
+            ALOGE("%s: Unsupported Offload information", __func__);
+            ret = -EINVAL;
+            goto error_open;
+        }
+
+        if (!is_supported_format(config->offload_info.format)) {
+            ALOGE("%s: Unsupported audio format", __func__);
+            ret = -EINVAL;
+            goto error_open;
+        }
+        out->compr_config.codec = (struct snd_codec *)
+                calloc(1, sizeof(struct snd_codec));
+        //Session/clip config.
+        out->format = config->offload_info.format;
+        out->sample_rate = config->offload_info.sample_rate;
+        out->compr_config.codec->id =
+                get_snd_codec_id(config->offload_info.format);
+        out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+        out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
+        out->compr_config.codec->sample_rate =
+                    compress_get_alsa_rate(config->offload_info.sample_rate);
+        out->compr_config.codec->bit_rate =
+                    config->offload_info.bit_rate;
+        out->compr_config.codec->ch_in =
+                    popcount(config->channel_mask);
+        out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
+
+        if (config->offload_info.channel_mask)
+            out->channel_mask = config->offload_info.channel_mask;
+        else if (config->channel_mask)
+            out->channel_mask = config->channel_mask;
+        out->uc_strm_type = OFFLOAD_PLAYBACK_STREAM;
+
+        //Initialize the handles
+        /* ------------------------------------------------------------------------
+        Update use decoder type and routing flags and corresponding states
+        decoderType will cache the decode types such as decode/passthrough/transcode
+        and in s/w or dsp. Besides, the states to open decode/passthrough/transcode
+        handles with the corresponding devices and device formats are updated
+           -------------------------------------------------------------------------*/
+        update_decode_type_and_routing_states(out);
+
+        /* ------------------------------------------------------------------------
+        Update rxHandle states
+        Based on the states, we open the driver and store the handle at appropriate
+        index
+        -------------------------------------------------------------------------*/
+        update_alsa_handle_state(out);
+
+        /* ------------------------------------------------------------------------
+        setup routing
+        -------------------------------------------------------------------------*/
+        ret = allocate_internal_buffers(out);
+        if(ret < 0) {
+            ALOGE("%s:Error %d",__func__, ret);
+            goto error_handle;
+        }
+
+        //Callbacks
+        out->stream.set_callback = out_set_callback;
+        out->stream.pause = out_pause;
+        out->stream.resume = out_resume;
+        out->stream.drain = out_drain;
+        out->stream.flush = out_flush;
+
+        if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
+            out->non_blocking = 1;
+
+        out->send_new_metadata = 1;
+        create_offload_callback_thread(out);
+        ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
+                __func__, config->offload_info.version,
+                config->offload_info.bit_rate);
+    } else { //if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
+        ALOGE("%s: Usecase is DEEP_BUFFER", __func__);
+        if((device_handle = get_alsa_handle())== NULL)
+            goto error_handle;
+        list_add_tail(&out->session_list, &device_handle->list);
+        device_handle->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
+        device_handle->config = pcm_config_deep_buffer;
+        device_handle->out = out;
+        device_handle->cmd_pending = false;
+        out->sample_rate = device_handle->config.rate;
+        out->uc_strm_type = DEEP_BUFFER_PLAYBACK_STREAM;
+        out->buffer_size = device_handle->config.period_size *
+                            audio_stream_frame_size(&out->stream.common);
+    }/* else {
+        if((device_handle = get_alsa_handle())== NULL)
+            goto error_handle;
+        list_add_tail(&out->session_list, &device_handle->list);
+        device_handle->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
+        device_handle->config = pcm_config_low_latency;
+        device_handle->sample_rate = device_handle->config.rate;
+        device_handle->out = out;
+        device_handle->cmd_pending = false;
+        out->uc_strm_type  = LOW_LATENCY_PLAYBACK_STREAM;
+        out->buffer_size = device_handle->config.period_size *
+                            audio_stream_frame_size(&out->stream.common);
+    }*/
+
+    if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+        ALOGE("%s: Usecase is primary ", __func__);
+        if(adev->primary_output == NULL)
+            adev->primary_output = out;
+        else {
+            ALOGE("%s: Primary output is already opened", __func__);
+            ret = -EEXIST;
+            goto error_open;
+        }
+    }
+
+    /* Check if this usecase is already existing */
+    pthread_mutex_lock(&adev->lock);
+    if (out->uc_strm_type != OFFLOAD_PLAYBACK_STREAM) {
+        if (get_usecase_from_list(adev, device_handle->usecase) != NULL) {
+            ALOGE("%s: Usecase (%d) is already present", __func__,
+                        device_handle->usecase);
+            pthread_mutex_unlock(&adev->lock);
+            ret = -EEXIST;
+            goto error_open;
+        }
+    }
+    pthread_mutex_unlock(&adev->lock);
+
+
+    /* out->muted = false; by calloc() */
+
+
     config->format = out->stream.common.get_format(&out->stream.common);
     config->channel_mask = out->stream.common.get_channels(&out->stream.common);
     config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
@@ -1127,6 +2786,17 @@
     ALOGV("%s: exit", __func__);
     return 0;
 
+error_handle:
+    ret = -EINVAL;
+    ALOGE("%s: exit: error handle %d", __func__, ret);
+    while (!list_empty(&out->session_list)) {
+        item = list_head(&out->session_list);
+        list_remove(item);
+        device_handle  = node_to_item(item, struct alsa_handle, list);
+        platform_free_usecase(device_handle->usecase);
+        free_alsa_handle(device_handle);
+    }
+
 error_open:
     free(out);
     *stream_out = NULL;
@@ -1139,17 +2809,28 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
     struct audio_device *adev = out->dev;
-    int ret = 0;
+    struct listnode *item;
+    struct alsa_handle *handle;
 
-    ALOGV("%s: enter", __func__);
+    ALOGV("%s", __func__);
+
     out_standby(&stream->common);
-
-    if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+    if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
         destroy_offload_callback_thread(out);
 
-        if (out->compr_config.codec != NULL)
-            free(out->compr_config.codec);
+        while (!list_empty(&out->session_list)) {
+            item = list_head(&out->session_list);
+            list_remove(item);
+            handle  = node_to_item(item, struct alsa_handle, list);
+                if(handle->compr_config.codec != NULL)
+                    free(handle->compr_config.codec);
+            platform_free_usecase(handle->usecase);
+            free_alsa_handle(handle);
+        }
+        free(out->compr_config.codec);
     }
+
+    free_internal_buffers(out);
     pthread_cond_destroy(&out->cond);
     pthread_mutex_destroy(&out->lock);
     free(stream);
diff --git a/hal_mpq/mpq8092/platform.c b/hal_mpq/mpq8092/platform.c
index d7d67d5..3c1b4f7 100644
--- a/hal_mpq/mpq8092/platform.c
+++ b/hal_mpq/mpq8092/platform.c
@@ -91,20 +91,39 @@
     struct csd_data *csd;
 };
 
-static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
-    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
-                                            DEEP_BUFFER_PCM_DEVICE},
-    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
-                                           LOWLATENCY_PCM_DEVICE},
-    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
-                                        MULTIMEDIA2_PCM_DEVICE},
+static int pcm_device_table[AUDIO_USECASE_MAX][4] = {
+    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
+                                            DEEP_BUFFER_PCM_DEVICE,
+                                            DEEP_BUFFER_PCM_DEVICE, 0},
+    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
+                                           LOWLATENCY_PCM_DEVICE,
+                                           LOWLATENCY_PCM_DEVICE, 0},
+    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {USECASE_AUDIO_PLAYBACK_MULTI_CH,
+                                        MULTIMEDIA2_PCM_DEVICE,
+                                        MULTIMEDIA2_PCM_DEVICE, 0},
+    [USECASE_AUDIO_PLAYBACK_MULTI_CH] =    {USECASE_AUDIO_PLAYBACK_MULTI_CH,
+                                            MULTI_CHANNEL_PCM_DEVICE,
+                                            MULTI_CHANNEL_PCM_DEVICE, 0},
     [USECASE_AUDIO_PLAYBACK_OFFLOAD] =
-                     {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
-    [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
-    [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE},
-    [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
-                                          LOWLATENCY_PCM_DEVICE},
-    [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE,
+                     {USECASE_AUDIO_PLAYBACK_OFFLOAD, PLAYBACK_OFFLOAD_DEVICE1,
+                     PLAYBACK_OFFLOAD_DEVICE1, 0},
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD1] =    {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+                                            PLAYBACK_OFFLOAD_DEVICE2,
+                                            PLAYBACK_OFFLOAD_DEVICE2, 0},
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD2] =    {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+                                            PLAYBACK_OFFLOAD_DEVICE3,
+                                            PLAYBACK_OFFLOAD_DEVICE3, 0},
+    [USECASE_AUDIO_PLAYBACK_OFFLOAD3] =    {USECASE_AUDIO_PLAYBACK_OFFLOAD,
+                                            PLAYBACK_OFFLOAD_DEVICE4,
+                                            PLAYBACK_OFFLOAD_DEVICE4, 0},
+    [USECASE_AUDIO_RECORD] = {USECASE_AUDIO_RECORD, AUDIO_RECORD_PCM_DEVICE,
+                             AUDIO_RECORD_PCM_DEVICE, 0},
+    [USECASE_AUDIO_RECORD_COMPRESS] = {USECASE_AUDIO_RECORD_COMPRESS, COMPRESS_CAPTURE_DEVICE,
+                                       COMPRESS_CAPTURE_DEVICE, 0},
+    [USECASE_AUDIO_RECORD_LOW_LATENCY] = {USECASE_AUDIO_RECORD_LOW_LATENCY,
+                                          LOWLATENCY_PCM_DEVICE,
+                                          LOWLATENCY_PCM_DEVICE, 0},
+   /* [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {,
                                   MULTIMEDIA2_PCM_DEVICE},
     [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
     [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
@@ -124,6 +143,7 @@
                                       INCALL_MUSIC_UPLINK2_PCM_DEVICE},
     [USECASE_AUDIO_SPKR_CALIB_RX] = {SPKR_PROT_CALIB_RX_PCM_DEVICE, -1},
     [USECASE_AUDIO_SPKR_CALIB_TX] = {-1, SPKR_PROT_CALIB_TX_PCM_DEVICE},
+*/
 };
 
 /* Array to store sound devices */
@@ -593,12 +613,39 @@
 {
     int device_id;
     if (device_type == PCM_PLAYBACK)
-        device_id = pcm_device_table[usecase][0];
-    else
         device_id = pcm_device_table[usecase][1];
+    else
+        device_id = pcm_device_table[usecase][2];
     return device_id;
 }
 
+audio_usecase_t platform_get_usecase(
+        audio_usecase_stream_type_t uc_type)
+{
+    int i = 0;
+    for(i =0;i<AUDIO_USECASE_MAX; i++)
+        if((pcm_device_table[i][0] == (int)uc_type) &&
+                (pcm_device_table[i][3] == 0)) {
+            pcm_device_table[i][3] = 1;
+            break;
+        }
+
+    if(i == AUDIO_USECASE_MAX)
+        return -EINVAL;
+    else
+        return (audio_usecase_t)i;
+}
+
+int platform_free_usecase(audio_usecase_t uc_id)
+{
+    if(uc_id >= AUDIO_USECASE_MAX) {
+        ALOGV("%s: enter: invalid usecase(%d)", __func__, uc_id);
+        return -EINVAL;
+    }
+    pcm_device_table[uc_id][3] = 0;
+    return 0;
+}
+
 int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal_mpq/mpq8092/platform.h b/hal_mpq/mpq8092/platform.h
index 7559258..2a81df5 100644
--- a/hal_mpq/mpq8092/platform.h
+++ b/hal_mpq/mpq8092/platform.h
@@ -26,6 +26,7 @@
     FLUENCE_QUAD_MIC = 0x2,
 };
 
+#include <hardware/audio.h>
 /*
  * Below are the devices for which is back end is same, SLIMBUS_0_RX.
  * All these devices are handled by the internal HW codec. We can
@@ -34,6 +35,8 @@
 #define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \
     (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
      AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+/*TODO remove this once define in audio.h */
+#define AUDIO_DEVICE_OUT_SPDIF 0x4000
 
 /* Sound devices specific to the platform
  * The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
@@ -154,6 +157,16 @@
 #define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240
 #define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2
 
+/*******************************************************************************
+ADTS HEADER PARSING
+*******************************************************************************/
+//Required for ADTS Header Parsing
+#define ADTS_HEADER_SYNC_RESULT 0xfff0
+#define ADTS_HEADER_SYNC_MASK 0xfff6
+/*******************************************************************************
+HDMI and SPDIF Device Output format control
+*******************************************************************************/
+
 #define HDMI_MULTI_PERIOD_SIZE  336
 #define HDMI_MULTI_PERIOD_COUNT 8
 #define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6
@@ -174,8 +187,14 @@
 #define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
 #define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
 #define SPKR_PROT_CALIB_TX_PCM_DEVICE 22
-#define PLAYBACK_OFFLOAD_DEVICE 9
 #define COMPRESS_VOIP_CALL_PCM_DEVICE 3
+#define MULTI_CHANNEL_PCM_DEVICE 1
+#define VOICE_CALL_PCM_DEVICE 2
+//TODO: update the device number as per the dai links
+#define PLAYBACK_OFFLOAD_DEVICE1 2
+#define PLAYBACK_OFFLOAD_DEVICE2 3
+#define PLAYBACK_OFFLOAD_DEVICE3 4
+#define PLAYBACK_OFFLOAD_DEVICE4 19
 
 #define LOWLATENCY_PCM_DEVICE 15
 #define COMPRESS_CAPTURE_DEVICE 19
@@ -235,11 +254,48 @@
 void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
                              char *device_name);
 
-#define SAMPLES_PER_CHANNEL             1536*2
+/*******************************************************************************
+USECASES AND THE CORRESPONDING DEVICE FORMATS THAT WE SUPPORT IN HAL
+*******************************************************************************/
+/*
+In general max of 2 for pass through. Additional 1 for handling transcode
+as the existence of transcode is with a PCM handle followed by transcode handle
+So, a (AC3/EAC3) pass through + trancode require - 1 for pas through, 1 - pcm and
+1 - transcode
+*/
+#define NUM_DEVICES_SUPPORT_COMPR_DATA 2+1
+#define NUM_SUPPORTED_CODECS           16
+#define NUM_COLUMN_FOR_INDEXING        2
+#define NUM_STATES_FOR_EACH_DEVICE_FMT 3
+#define DECODER_TYPE_IDX               0
+#define ROUTE_FORMAT_IDX               1
+
+#define MIN_SIZE_FOR_METADATA    64
+#define NUM_OF_PERIODS           8
+/*Period size to be a multiple of chanels * bitwidth,
+So min period size = LCM (1,2...8) * 4*/
+#define PERIOD_SIZE_COMPR        3360
+#define MS11_INPUT_BUFFER_SIZE   1536
+/*Max Period size which is exposed by the compr driver
+The value needs to be modified when the period size is modified*/
+#define PLAYBACK_MAX_PERIOD_SIZE (160 * 1024)
+
+#define COMPR_INPUT_BUFFER_SIZE  (PERIOD_SIZE_COMPR - MIN_SIZE_FOR_METADATA)
+#define PCM_16_BITS_PER_SAMPLE   2
+#define PCM_24_BITS_PER_SAMPLE   3
+#define AC3_PERIOD_SIZE          1536 * PCM_16_BITS_PER_SAMPLE
+#define TIME_PER_BUFFER          40 //Time duration in ms
+#define SAMPLES_PER_CHANNEL             32*1024 //1536*2 /*TODO:correct it
 #define MAX_INPUT_CHANNELS_SUPPORTED    8
 #define FACTOR_FOR_BUFFERING            2
 #define STEREO_CHANNELS                 2
 #define MAX_OUTPUT_CHANNELS_SUPPORTED   8
+#define PCM_BLOCK_PER_CHANNEL_MS11      1536*2
+#define AAC_BLOCK_PER_CHANNEL_MS11      768
+#define NUMBER_BITS_IN_A_BYTE           8
+#define AC3_BUFFER_SIZE                 1920*2
+
+#define MAX_OUTPUT_CHANNELS_SUPPORTED   8
 
 #define PCM_2CH_OUT                 0
 #define PCM_MCH_OUT                 1
@@ -248,6 +304,333 @@
 #define TRANSCODE_OUT               3
 #define FACTOR_FOR_BUFFERING        2
 
+#define NUM_DEVICES_SUPPORT_COMPR_DATA 2+1
+#define NUM_SUPPORTED_CODECS           16
+#define NUM_COLUMN_FOR_INDEXING        2
+#define NUM_STATES_FOR_EACH_DEVICE_FMT 3
+#define DECODER_TYPE_IDX               0
+#define ROUTE_FORMAT_IDX               1
+#define NUM_OF_PERIODS                 8
+
+enum {
+    LPCM,
+    MULTI_CH_PCM,
+    COMPR,
+    TRANSCODE
+};
+
+
+/*
+List of indexes of the supported formats
+Redundant formats such as (AAC-LC, HEAAC) are removed from the indexes as they
+are treated with the AAC format
+*/
+enum {
+    PCM_IDX = 0,
+    AAC_IDX,
+    AC3_IDX,
+    EAC3_IDX,
+    DTS_IDX,
+    DTS_LBR_IDX,
+    MP3_IDX,
+    WMA_IDX,
+    WMA_PRO_IDX,
+    MP2_IDX,
+    ALL_FORMATS_IDX
+};
+/*
+List of pass through's supported in the current usecases
+*/
+enum {
+    NO_PASSTHROUGH = 0,
+    AC3_PASSTHR,
+    EAC3_PASSTHR,
+    DTS_PASSTHR
+};
+/*
+List of transcoder's supported in the current usecases
+*/
+enum {
+    NO_TRANSCODER = 0,
+    AC3_TRANSCODER,
+    DTS_TRANSCODER
+};
+/*
+Requested end device format by user/app through set parameters
+*/
+enum {
+    UNCOMPRESSED = 0,
+    COMPRESSED,
+    COMPRESSED_CONVERT_EAC3_AC3,
+    COMPRESSED_CONVERT_ANY_AC3,
+    COMPRESSED_CONVERT_ANY_DTS,
+    AUTO_DEVICE_FORMAT,
+    UNCOMPRESSED_MCH,  /* not to be exposed, internal use only */
+    COMPRESSED_CONVERT_AC3_ASSOC, /* not to be exposed, internal use only */
+    ALL_DEVICE_FORMATS
+};
+/*
+List of type of data routed on end device
+*/
+typedef enum {
+    ROUTE_NONE = 0x0,
+    ROUTE_UNCOMPRESSED = 0x1,
+    ROUTE_COMPRESSED = 0x2,
+    ROUTE_SW_TRANSCODED = 0x10,   //route sub-format, not to be used directly
+    ROUTE_DSP_TRANSCODED = 0x20,  //route sub-format, not to be used directly
+    ROUTE_MCH = 0x40,             //route sub-format, not to be used directly
+    ROUTE_UNCOMPRESSED_MCH = (ROUTE_UNCOMPRESSED | ROUTE_MCH),
+    ROUTE_SW_TRANSCODED_COMPRESSED = (ROUTE_COMPRESSED | ROUTE_SW_TRANSCODED),
+    ROUTE_DSP_TRANSCODED_COMPRESSED = (ROUTE_COMPRESSED | ROUTE_DSP_TRANSCODED)
+}route_format_t;
+/*
+List of end device formats
+*/
+enum {
+    FORMAT_INVALID = -1,
+    FORMAT_PCM,
+    FORMAT_COMPR
+};
+/*
+Below are the only different types of decode that we perform
+*/
+enum {
+    DSP_DECODE = 1,      // render uncompressed
+    DSP_PASSTHROUGH = 2, // render compressed
+    DSP_TRANSCODE = 4,   // render as compressed
+    SW_DECODE = 8,       // render as uncompressed
+    SW_DECODE_MCH = 16,   // render as uncompressed
+    SW_PASSTHROUGH = 32, // render compressed
+    SW_TRANSCODE = 64,    // render compressed
+    NUM_DECODE_PATH = 7
+};
+/*
+Modes of buffering that we can support
+As of now, we only support input buffering to an extent specified by usecase
+*/
+enum {
+    NO_BUFFERING_MODE = 0,
+    INPUT_BUFFERING_MODE,
+    OUTPUT_BUFFEING_MODE
+};
+/*
+playback controls
+*/
+enum {
+    PLAY = 1,
+    PAUSE = (1<<1),
+    RESUME = (1<<2),
+    SEEK = (1<<3),
+    EOS = (1<<4),
+    STOP = (1<<5),
+    STANDBY = (1<<6),
+    INIT = (1<<7),
+};
+/*
+Multiple instance of use case
+*/
+enum {
+    STEREO_DRIVER = 0,
+    MULTI_CHANNEL_DRIVER,
+    COMRPESSED_DRIVER,
+};
+/*
+Instance bits
+*/
+enum {
+    MULTI_CHANNEL_1_BIT = 1<<4,
+    MULTI_CHANNEL_2_BIT = 1<<5,
+    MULTI_CHANNEL_3_BIT = 1<<6,
+    COMPRESSED_1_BIT    = 1<<12,
+    COMPRESSED_2_BIT    = 1<<13,
+    COMPRESSED_3_BIT    = 1<<14,
+    COMPRESSED_4_BIT    = 1<<15,
+    COMPRESSED_5_BIT    = 1<<16,
+    COMPRESSED_6_BIT    = 1<<17
+};
+
+/*
+List of support formats configured from frameworks
+*/
+static const int supportedFormats[NUM_SUPPORTED_CODECS] = {
+    AUDIO_FORMAT_PCM_16_BIT,
+    AUDIO_FORMAT_PCM_24_BIT,
+    AUDIO_FORMAT_AAC,
+    AUDIO_FORMAT_HE_AAC_V1,
+    AUDIO_FORMAT_HE_AAC_V2,
+    AUDIO_FORMAT_AAC_ADIF,
+    AUDIO_FORMAT_AC3,
+    AUDIO_FORMAT_AC3_DM,
+    AUDIO_FORMAT_EAC3,
+    AUDIO_FORMAT_EAC3_DM,
+    AUDIO_FORMAT_DTS,
+    AUDIO_FORMAT_DTS_LBR,
+    AUDIO_FORMAT_MP3,
+    AUDIO_FORMAT_WMA,
+    AUDIO_FORMAT_WMA_PRO,
+    AUDIO_FORMAT_MP2
+};
+/*
+we can only have 6 types of decoder type stored with bit masks.
+*/
+static const int route_to_driver[NUM_DECODE_PATH][NUM_COLUMN_FOR_INDEXING] = {
+    {DSP_DECODE,      ROUTE_UNCOMPRESSED_MCH},
+    {DSP_PASSTHROUGH, ROUTE_COMPRESSED},
+    {DSP_TRANSCODE,   ROUTE_DSP_TRANSCODED_COMPRESSED},
+    {SW_DECODE,       ROUTE_UNCOMPRESSED},
+    {SW_DECODE_MCH,   ROUTE_UNCOMPRESSED_MCH},
+    {SW_PASSTHROUGH,  ROUTE_COMPRESSED},
+    {SW_TRANSCODE,    ROUTE_SW_TRANSCODED_COMPRESSED}
+};
+/*
+table to query index based on the format
+*/
+static const int format_index[NUM_SUPPORTED_CODECS][NUM_COLUMN_FOR_INDEXING] = {
+/*---------------------------------------------
+|    FORMAT                  | INDEX           |
+----------------------------------------------*/
+    {AUDIO_FORMAT_PCM_16_BIT,  PCM_IDX},
+    {AUDIO_FORMAT_PCM_24_BIT,  PCM_IDX},
+    {AUDIO_FORMAT_AAC,         AAC_IDX},
+    {AUDIO_FORMAT_HE_AAC_V1,   AAC_IDX},
+    {AUDIO_FORMAT_HE_AAC_V2,   AAC_IDX},
+    {AUDIO_FORMAT_AAC_ADIF,    AAC_IDX},
+    {AUDIO_FORMAT_AC3,         AC3_IDX},
+    {AUDIO_FORMAT_AC3_DM,      AC3_IDX},
+    {AUDIO_FORMAT_EAC3,        EAC3_IDX},
+    {AUDIO_FORMAT_EAC3_DM,     EAC3_IDX},
+    {AUDIO_FORMAT_DTS,         DTS_IDX},
+    {AUDIO_FORMAT_DTS_LBR,     DTS_LBR_IDX},
+    {AUDIO_FORMAT_MP3,         MP3_IDX},
+    {AUDIO_FORMAT_WMA,         WMA_IDX},
+    {AUDIO_FORMAT_WMA_PRO,     WMA_PRO_IDX},
+    {AUDIO_FORMAT_MP2,         MP2_IDX}
+};
+
+/*
+Table to query non HDMI and SPDIF devices and their states such as type of
+decode, type of data routed to end device and type of transcoding needed
+*/
+static const int usecase_decode_format[ALL_FORMATS_IDX*NUM_STATES_FOR_EACH_DEVICE_FMT] = {
+/*-----------------
+|    UNCOMPR      |
+-----------------*/
+/*      PCM    */
+    DSP_DECODE,   //PCM_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    SW_DECODE,    // AAC_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    SW_DECODE,    //AC3_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    SW_DECODE,    //EAC3_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,   //DTS_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,   //DTS_LBR_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,   //MP3_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,   //WMA_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,   //WMA_PRO_IDX
+    FORMAT_PCM,   //ROUTE_FORMAT
+    NO_TRANSCODER,//TRANSCODE_FORMAT
+/*      PCM    */
+    DSP_DECODE,  //MP2_IDX
+    FORMAT_PCM,  //ROUTE_FORMAT
+    NO_TRANSCODER//TRANSCODE_FORMAT
+};
+/*
+Table to query HDMI and SPDIF devices and their states such as type of
+decode, type of data routed to end device and type of transcoding needed
+*/
+static const int usecase_docode_hdmi_spdif[ALL_FORMATS_IDX*NUM_STATES_FOR_EACH_DEVICE_FMT]
+                                [ALL_DEVICE_FORMATS] = {
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------
+|   UNCOMPRESSED   |     COMPR      |  COMPR_CONV  | COMPR_CONV    |   COMPR_CONV              |      AUTO         | UNCOMPR_MCH    |      AC3_AC3      |
+|                  |                |   EAC3_AC3   |   ANY_AC3     |     ANY_DTS               |                   |                |                   |
+--------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*   PCM            PCM              PCM             PCM             PCM                         PCM               PCM                 PCM   */
+    {DSP_DECODE,    DSP_DECODE,      DSP_DECODE,     DSP_DECODE,     DSP_DECODE|DSP_TRANSCODE,   DSP_DECODE,       DSP_DECODE,         DSP_DECODE},     //PCM_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  NO_TRANSCODER,  DTS_TRANSCODER,             NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}, //TRANSCODE_FMT
+/*   PCM            PCM              PCM             AC3             PCM                         PCM               PCM                 PCM   */
+    {SW_DECODE,     SW_DECODE,       SW_DECODE,      SW_TRANSCODE,   DSP_DECODE,                 SW_DECODE,        SW_DECODE_MCH,      SW_DECODE},     //AAC_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_COMPR,   FORMAT_PCM,                 FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},     //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  AC3_TRANSCODER, NO_TRANSCODER,              NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}, //TRANSCODE_FMT
+/*   PCM            AC3              AC3             AC3             PCM                         AC3               PCM                 AC3   */
+    {SW_DECODE,     SW_PASSTHROUGH,  SW_PASSTHROUGH, SW_PASSTHROUGH, DSP_DECODE,                 SW_PASSTHROUGH,   SW_DECODE_MCH,      SW_TRANSCODE},     //AC3_IDX
+    {FORMAT_PCM,    FORMAT_COMPR,    FORMAT_COMPR,   FORMAT_COMPR,   FORMAT_PCM,                 FORMAT_COMPR,     FORMAT_PCM,         FORMAT_COMPR},     //ROUTE_FORMAT
+    {NO_TRANSCODER, AC3_PASSTHR,     AC3_PASSTHR,    AC3_PASSTHR,    NO_TRANSCODER,              AC3_PASSTHR,      NO_TRANSCODER,      AC3_TRANSCODER},  //TRANSCODE_FMT
+/*   PCM            EAC3             AC3             AC3             PCM                         EAC3              PCM                 PCM   */
+    {SW_DECODE,     SW_PASSTHROUGH,  SW_TRANSCODE,   SW_TRANSCODE,   DSP_DECODE,                 SW_PASSTHROUGH,   SW_DECODE_MCH,      SW_TRANSCODE},     //EAC3_IDX
+    {FORMAT_PCM,    FORMAT_COMPR,    FORMAT_COMPR,   FORMAT_COMPR,   FORMAT_PCM,                 FORMAT_COMPR,     FORMAT_PCM,         FORMAT_COMPR},     //ROUTE_FORMAT
+    {NO_TRANSCODER, EAC3_PASSTHR,    AC3_TRANSCODER, AC3_TRANSCODER, NO_TRANSCODER,              EAC3_PASSTHR,     NO_TRANSCODER,      AC3_TRANSCODER},  //TRANSCODE_FMT
+/*   PCM            DTS              PCM             PCM             DTS                         DTS               PCM                 PCM    */
+    {DSP_DECODE,    DSP_PASSTHROUGH, DSP_DECODE,     DSP_DECODE,     DSP_PASSTHROUGH,            DSP_PASSTHROUGH,  DSP_DECODE,         DSP_DECODE},//DTS_IDX
+    {FORMAT_PCM,    FORMAT_COMPR,    FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_COMPR,     FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, DTS_PASSTHR,     NO_TRANSCODER,  NO_TRANSCODER,  DTS_PASSTHR,                DTS_PASSTHR,      NO_TRANSCODER,      NO_TRANSCODER},    //TRANSCODE_FMT
+/*   PCM            DTS_LBR          PCM             PCM             DTS                         DTS               PCM                 PCM    */
+    {DSP_DECODE,    DSP_PASSTHROUGH, DSP_DECODE,     DSP_DECODE,     DSP_PASSTHROUGH,            DSP_PASSTHROUGH,  DSP_DECODE,         DSP_DECODE},//DTS_LBR_IDX
+    {FORMAT_PCM,    FORMAT_COMPR,    FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_COMPR,     FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, DTS_PASSTHR,     NO_TRANSCODER,  NO_TRANSCODER,  DTS_PASSTHR,                DTS_PASSTHR,      NO_TRANSCODER,      NO_TRANSCODER},    //TRANSCODE_FMT
+/*   PCM            PCM              PCM             PCM             DTS                         PCM               PCM                 PCM    */
+    {DSP_DECODE,    DSP_DECODE,      DSP_DECODE,     DSP_DECODE,     DSP_DECODE|DSP_TRANSCODE,   DSP_DECODE,       DSP_DECODE,         DSP_DECODE},  //MP3_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  NO_TRANSCODER,  DTS_TRANSCODER,             NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}, //TRANSCODE_FMT
+/*   PCM            PCM              PCM             PCM             DTS                         PCM               PCM                 PCM    */
+    {DSP_DECODE,    DSP_DECODE,      DSP_DECODE,     DSP_DECODE,     DSP_DECODE|DSP_TRANSCODE,   DSP_DECODE,       DSP_DECODE,         DSP_DECODE},  //WMA_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  NO_TRANSCODER,  DTS_TRANSCODER,             NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}, //TRANSCODE_FMT
+/*   PCM            PCM              PCM             PCM             DTS                         PCM               PCM                 PCM    */
+    {DSP_DECODE,    DSP_DECODE,      DSP_DECODE,     DSP_DECODE,     DSP_DECODE|DSP_TRANSCODE,   DSP_DECODE,       DSP_DECODE,         DSP_DECODE},  //WMA_PRO_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  NO_TRANSCODER,  DTS_TRANSCODER,             NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}, //TRANSCODE_FMT
+/*   PCM            PCM              PCM             PCM             DTS                         PCM               PCM                 PCM    */
+    {DSP_DECODE,    DSP_DECODE,      DSP_DECODE,     DSP_DECODE,     DSP_DECODE|DSP_TRANSCODE,   DSP_DECODE,       DSP_DECODE,         DSP_DECODE},  //MP2_IDX
+    {FORMAT_PCM,    FORMAT_PCM,      FORMAT_PCM,     FORMAT_PCM,     FORMAT_COMPR,               FORMAT_PCM,       FORMAT_PCM,         FORMAT_PCM},   //ROUTE_FORMAT
+    {NO_TRANSCODER, NO_TRANSCODER,   NO_TRANSCODER,  NO_TRANSCODER,  DTS_TRANSCODER,             NO_TRANSCODER,    NO_TRANSCODER,      NO_TRANSCODER}  //TRANSCODE_FMT
+};
+/*
+List of decoders which require config as part of first buffer
+*/
+static const int decodersRequireConfig[] = {
+    AUDIO_FORMAT_AAC,
+    AUDIO_FORMAT_HE_AAC_V1,
+    AUDIO_FORMAT_HE_AAC_V2,
+    AUDIO_FORMAT_AAC_ADIF,
+    AUDIO_FORMAT_WMA,
+    AUDIO_FORMAT_WMA_PRO
+};
+/*
+List of enum that are used in Broadcast.
+NOTE: Need to be removed once broadcast is moved with updated states as above
+*/
+enum {
+    INVALID_FORMAT               = -1,
+    PCM_FORMAT                   = 0,
+    COMPRESSED_FORMAT            = 1,
+    COMPRESSED_FORCED_PCM_FORMAT = 2,
+    COMPRESSED_PASSTHROUGH_FORMAT = 3
+};
+
+
 struct audio_bitstream_sm {
     int                buffering_factor;
     int                buffering_factor_cnt;
@@ -255,18 +638,33 @@
     char               *inp_buf;
     char               *inp_buf_curr_ptr;
     char               *inp_buf_write_ptr;
+    uint32_t           inp_buf_size;
 
     char               *enc_out_buf;
     char               *enc_out_buf_write_ptr;
+    uint32_t           enc_out_buf_size;
 
     char               *pcm_2_out_buf;
     char               *pcm_2_out_buf_write_ptr;
+    uint32_t           pcm_2_out_buf_size;
 
     char               *pcm_mch_out_buf;
     char               *pcm_mch_out_buf_write_ptr;
+    uint32_t           pcm_mch_out_buf_size;
 
     char               *passt_out_buf;
     char               *passt_out_buf_write_ptr;
+    uint32_t           passt_out_buf_size;
+};
+
+/*
+Meta data structure for handling compressed output
+*/
+struct output_metadata {
+    uint32_t            metadataLength;
+    uint32_t            bufferLength;
+    uint64_t            timestamp;
+    uint32_t            reserved[12];
 };
 
 #endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal_mpq/platform_api.h b/hal_mpq/platform_api.h
index 44ad790..955aa3b 100644
--- a/hal_mpq/platform_api.h
+++ b/hal_mpq/platform_api.h
@@ -51,5 +51,7 @@
 /* returns the latency for a usecase in Us */
 int64_t platform_render_latency(audio_usecase_t usecase);
 int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
+audio_usecase_t platform_get_usecase(audio_usecase_stream_type_t uc_type);
+int platform_free_usecase(audio_usecase_t uc_id);
 
 #endif // QCOM_AUDIO_PLATFORM_API_H