hal: read HDMI sink capability for dynamic output profile

- update read_hdmi_sink_caps to support dynamic sample
  rate, channel, and format based on HDMI EDID information

Change-Id: I69b3f19cb1d81c3e51695adae4f2379cbb439dc8
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8980026..cc4f36b 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -400,19 +400,15 @@
 #endif
 
 #ifndef HDMI_PASSTHROUGH_ENABLED
-#define audio_extn_dolby_update_passt_formats(adev, out)                   (0)
 #define audio_extn_dolby_update_passt_stream_configuration(adev, out)      (0)
 #define audio_extn_dolby_is_passt_convert_supported(adev, out)             (0)
 #define audio_extn_dolby_is_passt_supported(adev, out)                     (0)
 #define audio_extn_dolby_is_passthrough_stream(flags)                      (0)
-#define audio_extn_dolby_set_hdmi_config(adev, out)                        (0)
 #define audio_extn_dolby_get_passt_buffer_size(info)                       (0)
 #define audio_extn_dolby_set_passt_volume(out, mute)                       (0)
 #define audio_extn_dolby_set_passt_latency(out, latency)                   (0)
 #define AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH  0x4000
 #else
-int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
-                                          struct stream_out *out);
 bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
                                                  struct stream_out *out);
 bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
@@ -420,8 +416,6 @@
 void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
                                                  struct stream_out *out);
 bool audio_extn_dolby_is_passthrough_stream(int flags);
-int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
-                                     struct stream_out *out);
 int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info);
 int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute);
 int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency);
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index 115057c..41494b1 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -408,22 +408,6 @@
 #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
 
 #ifdef HDMI_PASSTHROUGH_ENABLED
-int audio_extn_dolby_update_passt_formats(struct audio_device *adev,
-                                          struct stream_out *out) {
-    int32_t i = 0, ret = -ENOSYS;
-
-    if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) ||
-        platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) {
-        out->supported_formats[i++] = AUDIO_FORMAT_AC3;
-        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
-        /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */
-        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
-        ret = 0;
-    }
-    ALOGV("%s: ret = %d", __func__, ret);
-    return ret;
-}
-
 bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
                                                  struct stream_out *out) {
 
@@ -501,11 +485,6 @@
     return false;
 }
 
-int audio_extn_dolby_set_hdmi_config(struct audio_device *adev,
-                                                    struct stream_out *out) {
-    return platform_set_hdmi_config(out);
-}
-
 int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) {
     return platform_get_compress_passthrough_buffer_size(info);
 }
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index d10bc18..dff662a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -231,11 +231,12 @@
 
 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_QUAD),/* QUAD_BACK is same as QUAD */
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
 };
 
@@ -243,6 +244,23 @@
     STRING_TO_ENUM(AUDIO_FORMAT_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+    STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+    STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
+};
+
+//list of all supported sample rates by HDMI specification.
+static const int out_hdmi_sample_rates[] = {
+    32000, 44100, 48000, 88200, 96000, 176400, 192000,
+};
+
+static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
+    STRING_TO_ENUM(32000),
+    STRING_TO_ENUM(44100),
+    STRING_TO_ENUM(48000),
+    STRING_TO_ENUM(88200),
+    STRING_TO_ENUM(96000),
+    STRING_TO_ENUM(176400),
+    STRING_TO_ENUM(192000),
 };
 
 static struct audio_device *adev = NULL;
@@ -799,39 +817,81 @@
     }
 }
 
+static void reset_hdmi_sink_caps(struct stream_out *out) {
+    int i = 0;
+
+    for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
+        out->supported_channel_masks[i] = 0;
+    }
+    for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
+        out->supported_formats[i] = 0;
+    }
+    for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
+        out->supported_sample_rates[i] = 0;
+    }
+}
+
 /* must be called with hw device mutex locked */
-static int read_hdmi_channel_masks(struct stream_out *out)
+static int read_hdmi_sink_caps(struct stream_out *out)
 {
-    int ret = 0, i = 0;
+    int ret = 0, i = 0, j = 0;
     int channels = platform_edid_get_max_channels(out->dev->platform);
 
+    reset_hdmi_sink_caps(out);
+
     switch (channels) {
-        /*
-         * Do not handle stereo output in Multi-channel cases
-         * Stereo case is handled in normal playback path
-         */
-    case 6:
-        ALOGV("%s: HDMI supports Quad and 5.1", __func__);
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
-        break;
     case 8:
-        ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
-        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+        ALOGV("%s: HDMI supports 7.1 channels", __func__);
         out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
+    case 6:
+        ALOGV("%s: HDMI supports 5.1 channels", __func__);
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
+    case 2:
+        ALOGV("%s: HDMI supports 2 channels", __func__);
+        out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
         break;
     default:
-        ALOGE("HDMI does not support multi channel playback");
+        ALOGE("invalid/nonstandard channal count[%d]",channels);
         ret = -ENOSYS;
         break;
     }
+
+    // check channel format caps
+    i = 0;
+    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
+        ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
+        out->supported_formats[i++] = AUDIO_FORMAT_AC3;
+        //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
+        //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
+        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
+        out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
+    }
+
+    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
+        ALOGV(":%s HDMI supports DTS format", __func__);
+        out->supported_formats[i++] = AUDIO_FORMAT_DTS;
+    }
+
+    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
+        ALOGV(":%s HDMI supports DTS HD format", __func__);
+        out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
+    }
+
+
+    // check sample rate caps
+    i = 0;
+    for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
+        if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
+            ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
+            out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
+        }
+    }
+
     return ret;
 }
 
@@ -1653,7 +1713,7 @@
         ALOGV("Disable passthrough , reset mixer to pcm");
         /* NO_PASSTHROUGH */
         out->compr_config.codec->compr_passthr = 0;
-        audio_extn_dolby_set_hdmi_config(adev, out);
+        platform_set_hdmi_config(out);
         audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
     }
     /* Must be called after removing the usecase from list */
@@ -1732,7 +1792,7 @@
             } else
                 check_and_set_hdmi_channels(adev, out->config.channels);
         }
-        audio_extn_dolby_set_hdmi_config(adev, out);
+        platform_set_hdmi_config(out);
     }
     list_add_tail(&adev->usecase_list, &uc_info->list);
 
@@ -2234,6 +2294,31 @@
             free(str);
         str = str_parms_to_str(reply);
     }
+
+    ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
+    if (ret >= 0) {
+        value[0] = '\0';
+        i = 0;
+        first = true;
+        while (out->supported_sample_rates[i] != 0) {
+            for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
+                if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
+                    if (!first) {
+                        strlcat(value, "|", sizeof(value));
+                    }
+                    strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
+                    first = false;
+                    break;
+                }
+            }
+            i++;
+        }
+        str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
+        if (str)
+            free(str);
+        str = str_parms_to_str(reply);
+    }
+
     str_parms_destroy(query);
     str_parms_destroy(reply);
     ALOGV("%s: exit: returns - %s", __func__, str);
@@ -3009,8 +3094,8 @@
 
     out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
 
-    ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
-        stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
+    ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
+        stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
         devices, flags, &out->stream);
 
 
@@ -3037,6 +3122,23 @@
     out->non_blocking = 0;
     out->use_small_bufs = false;
 
+    if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
+        (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+        pthread_mutex_lock(&adev->lock);
+        ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
+        ret = read_hdmi_sink_caps(out);
+        pthread_mutex_unlock(&adev->lock);
+        if (ret != 0) {
+            if (ret == -ENOSYS) {
+                /* ignore and go with default */
+                ret = 0;
+            } else {
+                ALOGE("error reading hdmi sink caps");
+                goto error_open;
+            }
+        }
+    }
+
     /* Init use case and pcm_config */
     if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
         !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
@@ -3045,8 +3147,14 @@
         out->devices & AUDIO_DEVICE_OUT_PROXY)) {
 
         pthread_mutex_lock(&adev->lock);
-        if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
-            ret = read_hdmi_channel_masks(out);
+        if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+            /*
+            * Do not handle stereo output in Multi-channel cases
+            * Stereo case is handled in normal playback path
+            */
+            if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
+                ret = AUDIO_CHANNEL_OUT_STEREO;
+        }
 
         if (out->devices & AUDIO_DEVICE_OUT_PROXY)
             ret = audio_extn_read_afe_proxy_channel_masks(out);
@@ -3058,9 +3166,12 @@
             config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
         if (config->channel_mask == 0)
             config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+        if (config->format == 0)
+            config->format = AUDIO_FORMAT_PCM_16_BIT;
 
         out->channel_mask = config->channel_mask;
         out->sample_rate = config->sample_rate;
+        out->format = config->format;
         out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
         out->config = pcm_config_hdmi_multi;
         out->config.rate = config->sample_rate;
@@ -3085,15 +3196,11 @@
             goto error_open;
         }
 
-        if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
-            ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
-            ALOGV("read and update_pass through formats");
-            ret = audio_extn_dolby_update_passt_formats(adev, out);
-            if(ret != 0) {
-                goto error_open;
-            }
+        if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
             if(config->offload_info.format == 0)
                 config->offload_info.format = out->supported_formats[0];
+            if (config->offload_info.sample_rate == 0)
+                config->offload_info.sample_rate = out->supported_sample_rates[0];
         }
 
         if (!is_supported_format(config->offload_info.format) &&
@@ -3125,9 +3232,16 @@
         }
 
         if (out->usecase == USECASE_INVALID) {
-            ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
-            ret = -EEXIST;
-            goto error_open;
+            if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
+                    config->format == 0 && config->sample_rate == 0 &&
+                    config->channel_mask == 0) {
+                ALOGI("%s dummy open to query sink cap",__func__);
+                out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
+            } else {
+                ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
+                ret = -EEXIST;
+                goto error_open;
+            }
         }
 
         if (config->offload_info.channel_mask)
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index e13415d..942ad5e 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -67,8 +67,9 @@
 #define ACDB_DEV_TYPE_OUT 1
 #define ACDB_DEV_TYPE_IN 2
 
-#define MAX_SUPPORTED_CHANNEL_MASKS 8
-#define MAX_SUPPORTED_FORMATS 3
+#define MAX_SUPPORTED_CHANNEL_MASKS 14
+#define MAX_SUPPORTED_FORMATS 15
+#define MAX_SUPPORTED_SAMPLE_RATES 7
 #define DEFAULT_HDMI_OUT_CHANNELS   2
 
 #define SND_CARD_STATE_OFFLINE 0
@@ -199,6 +200,7 @@
     /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
     audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
     audio_format_t supported_formats[MAX_SUPPORTED_FORMATS+1];
+    uint32_t supported_sample_rates[MAX_SUPPORTED_SAMPLE_RATES+1];
     bool muted;
     uint64_t written; /* total frames written, not cleared when entering standby */
     audio_io_handle_t handle;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 17e496d..03e7c89 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -4298,12 +4298,23 @@
         ALOGV("%s:E_AC3", __func__);
         format = DOLBY_DIGITAL_PLUS;
         break;
+    case AUDIO_FORMAT_DTS:
+        ALOGV("%s:DTS", __func__);
+        format = DTS;
+        break;
+    case AUDIO_FORMAT_DTS_HD:
+        ALOGV("%s:DTS_HD", __func__);
+        format = DTS_HD;
+        break;
     case AUDIO_FORMAT_PCM_16_BIT:
     case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
     case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
-    default:
         ALOGV("%s:PCM", __func__);
-        format =  LPCM;
+        format = LPCM;
+        break;
+    default:
+        ALOGE("%s:invalid format:%d", __func__,format);
+        format =  -1;
         break;
     }
     return format;
@@ -4337,6 +4348,11 @@
     int i, ret;
     unsigned char format_id = platform_map_to_edid_format(format);
 
+    if (format_id <= 0) {
+        ALOGE("%s invalid edid format mappting for :%x" ,__func__, format);
+        return false;
+    }
+
     ret = platform_get_edid_info(platform);
     info = (edid_audio_info *)my_data->edid_info;
     if (ret == 0 && info != NULL) {
@@ -4347,17 +4363,45 @@
               *  & DOLBY_DIGITAL_PLUS
               */
             if (info->audio_blocks_array[i].format_id == format_id) {
-                ALOGV("%s:platform_is_edid_supported_format true %x",
+                ALOGV("%s:returns true %x",
                       __func__, format);
                 return true;
             }
         }
     }
-    ALOGV("%s:platform_is_edid_supported_format false %x",
+    ALOGV("%s:returns false %x",
            __func__, format);
     return false;
 }
 
+bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    edid_audio_info *info = NULL;
+    int num_audio_blocks;
+    int i, ret, count;
+
+    ret = platform_get_edid_info(platform);
+    info = (edid_audio_info *)my_data->edid_info;
+    if (ret == 0 && info != NULL) {
+        for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+             /*
+              * To check
+              *  is there any special for CONFIG_HDMI_PASSTHROUGH_CONVERT
+              *  & DOLBY_DIGITAL_PLUS
+              */
+            if (info->audio_blocks_array[i].sampling_freq == sample_rate) {
+                ALOGV("%s: returns true %d", __func__, sample_rate);
+                return true;
+            }
+        }
+    }
+    ALOGV("%s: returns false %d", __func__, sample_rate);
+
+    return false;
+}
+
 int platform_set_edid_channels_configuration(void *platform, int channels) {
 
     struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index e32a73d..9bcd388 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1152,6 +1152,12 @@
     return  false;
 }
 
+bool platform_is_edid_supported_sample_rate(void *platform __unused,
+                                    int sample_rate __unused)
+{
+    return false;
+}
+
 void platform_cache_edid(void * platform __unused)
 {
 
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 785a202..4c82175 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -4249,12 +4249,23 @@
         ALOGV("%s:E_AC3", __func__);
         format = DOLBY_DIGITAL_PLUS;
         break;
+    case AUDIO_FORMAT_DTS:
+        ALOGV("%s:DTS", __func__);
+        format = DTS;
+        break;
+    case AUDIO_FORMAT_DTS_HD:
+        ALOGV("%s:DTS_HD", __func__);
+        format = DTS_HD;
+        break;
     case AUDIO_FORMAT_PCM_16_BIT:
     case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
     case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
-    default:
         ALOGV("%s:PCM", __func__);
-        format =  LPCM;
+        format = LPCM;
+        break;
+    default:
+        ALOGE("%s:invalid format:%d", __func__,format);
+        format =  -1;
         break;
     }
     return format;
@@ -4288,6 +4299,11 @@
     int i, ret;
     unsigned char format_id = platform_map_to_edid_format(format);
 
+    if (format_id <= 0) {
+        ALOGE("%s invalid edid format mappting for :%x" ,__func__, format);
+        return false;
+    }
+
     ret = platform_get_edid_info(platform);
     info = (edid_audio_info *)my_data->edid_info;
     if (ret == 0 && info != NULL) {
@@ -4298,17 +4314,46 @@
               *  & DOLBY_DIGITAL_PLUS
               */
             if (info->audio_blocks_array[i].format_id == format_id) {
-                ALOGV("%s:platform_is_edid_supported_format true %x",
+                ALOGV("%s:returns true %x",
                       __func__, format);
                 return true;
             }
         }
     }
-    ALOGV("%s:platform_is_edid_supported_format false %x",
+    ALOGV("%s:returns false %x",
            __func__, format);
     return false;
 }
 
+bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    struct audio_device *adev = my_data->adev;
+    edid_audio_info *info = NULL;
+    int num_audio_blocks;
+    int i, ret, count;
+
+    ret = platform_get_edid_info(platform);
+    info = (edid_audio_info *)my_data->edid_info;
+    if (ret == 0 && info != NULL) {
+        for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+             /*
+              * To check
+              *  is there any special for CONFIG_HDMI_PASSTHROUGH_CONVERT
+              *  & DOLBY_DIGITAL_PLUS
+              */
+            if (info->audio_blocks_array[i].sampling_freq == sample_rate) {
+                ALOGV("%s: returns true %d", __func__, sample_rate);
+                return true;
+            }
+        }
+    }
+    ALOGV("%s: returns false %d", __func__, sample_rate);
+
+    return false;
+}
+
+
 int platform_set_edid_channels_configuration(void *platform, int channels) {
 
     struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index fb72e40..8a0b5a4 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -127,6 +127,7 @@
 int platform_set_edid_channels_configuration(void *platform, int channels);
 unsigned char platform_map_to_edid_format(int format);
 bool platform_is_edid_supported_format(void *platform, int format);
+bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate);
 void platform_cache_edid(void * platform);
 void platform_invalidate_edid(void * platform);
 int platform_set_hdmi_config(struct stream_out *out);