Merge "hal: edid: Update EDID parsing logic"
diff --git a/hal/edid.c b/hal/edid.c
index 8f183d0..e889530 100644
--- a/hal/edid.c
+++ b/hal/edid.c
@@ -86,57 +86,109 @@
     return format_str;
 }
 
-static int get_edid_sf(unsigned char byte)
+static bool is_supported_sr(unsigned char sr_byte, int sampling_rate )
+{
+    int result = 0;
+
+    ALOGV("%s: sr_byte: %d, sampling_freq: %d",__func__, sr_byte, sampling_rate);
+    switch (sampling_rate) {
+    case 192000:
+        result = (sr_byte & BIT(6));
+        break;
+    case 176400:
+        result = (sr_byte & BIT(5));
+        break;
+    case 96000:
+        result = (sr_byte & BIT(4));
+        break;
+    case 88200:
+        result = (sr_byte & BIT(3));
+        break;
+    case 48000:
+        result = (sr_byte & BIT(2));
+        break;
+    case 44100:
+        result = (sr_byte & BIT(1));
+        break;
+    case 32000:
+        result = (sr_byte & BIT(0));
+        break;
+     default:
+        break;
+    }
+
+    if (result)
+        return true;
+
+    return false;
+}
+
+static unsigned char get_edid_bps_byte(unsigned char byte,
+                        unsigned char format)
+{
+    if (format == 0) {
+        ALOGV("%s: not lpcm format, return 0",__func__);
+        return 0;
+    }
+    return byte;
+}
+
+static bool is_supported_bps(unsigned char bps_byte, int bps)
+{
+    int result = 0;
+
+    switch (bps) {
+    case 24:
+        ALOGV("24bit");
+        result = (bps_byte & BIT(2));
+        break;
+    case 20:
+        ALOGV("20bit");
+        result = (bps_byte & BIT(1));
+        break;
+    case 16:
+        ALOGV("16bit");
+        result = (bps_byte & BIT(0));
+        break;
+     default:
+        break;
+    }
+
+    if (result)
+        return true;
+
+    return false;
+}
+
+static int get_highest_edid_sf(unsigned char byte)
 {
     int nfreq = 0;
 
     if (byte & BIT(6)) {
-        ALOGV("192kHz");
+        ALOGV("Highest: 192kHz");
         nfreq = 192000;
     } else if (byte & BIT(5)) {
-        ALOGV("176kHz");
+        ALOGV("Highest: 176kHz");
         nfreq = 176000;
     } else if (byte & BIT(4)) {
-        ALOGV("96kHz");
+        ALOGV("Highest: 96kHz");
         nfreq = 96000;
     } else if (byte & BIT(3)) {
-        ALOGV("88.2kHz");
+        ALOGV("Highest: 88.2kHz");
         nfreq = 88200;
     } else if (byte & BIT(2)) {
-        ALOGV("48kHz");
+        ALOGV("Highest: 48kHz");
         nfreq = 48000;
     } else if (byte & BIT(1)) {
-        ALOGV("44.1kHz");
+        ALOGV("Highest: 44.1kHz");
         nfreq = 44100;
     } else if (byte & BIT(0)) {
-        ALOGV("32kHz");
+        ALOGV("Highest: 32kHz");
         nfreq = 32000;
     }
     return nfreq;
 }
 
-static int get_edid_bps(unsigned char byte,
-                        unsigned char format)
-{
-    int bits_per_sample = 0;
-    if (format == 1) {
-        if (byte & BIT(2)) {
-            ALOGV("24bit");
-            bits_per_sample = 24;
-        } else if (byte & BIT(1)) {
-            ALOGV("20bit");
-            bits_per_sample = 20;
-        } else if (byte & BIT(0)) {
-            ALOGV("16bit");
-            bits_per_sample = 16;
-        }
-    } else {
-        ALOGV("not lpcm format, return 0");
-        return 0;
-    }
-    return bits_per_sample;
-}
-
 static void update_channel_map(edid_audio_info* info)
 {
     /* HDMI Cable follows CEA standard so SAD is received in CEA
@@ -589,8 +641,8 @@
     for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
         ALOGV("%s:FormatId:%d rate:%d bps:%d channels:%d", __func__,
               info->audio_blocks_array[i].format_id,
-              info->audio_blocks_array[i].sampling_freq,
-              info->audio_blocks_array[i].bits_per_sample,
+              info->audio_blocks_array[i].sampling_freq_bitmask,
+              info->audio_blocks_array[i].bits_per_sample_bitmask,
               info->audio_blocks_array[i].channels);
     }
     ALOGV("%s:no of audio blocks:%d", __func__, info->audio_blocks);
@@ -670,16 +722,16 @@
         ALOGD("info->audio_blocks_array[i].format_id %s",
               edid_format_to_str(formats[i]));
 
-        ALOGV("Frequency Byte %d\n", frequency[i]);
-        info->audio_blocks_array[i].sampling_freq = get_edid_sf(frequency[i]);
-        ALOGV("info->audio_blocks_array[i].sampling_freq %d",
-              info->audio_blocks_array[i].sampling_freq);
+        ALOGV("Frequency Bitmask %d\n", frequency[i]);
+        info->audio_blocks_array[i].sampling_freq_bitmask = frequency[i];
+        ALOGV("info->audio_blocks_array[i].sampling_freq_bitmask %d",
+              info->audio_blocks_array[i].sampling_freq_bitmask);
 
-        ALOGV("BitsPerSample Byte %d\n", bitrate[i]);
-        info->audio_blocks_array[i].bits_per_sample =
-                   get_edid_bps(bitrate[i],formats[i]);
-        ALOGV("info->audio_blocks_array[i].bits_per_sample %d",
-              info->audio_blocks_array[i].bits_per_sample);
+        ALOGV("BitsPerSample Bitmask %d\n", bitrate[i]);
+        info->audio_blocks_array[i].bits_per_sample_bitmask =
+                   get_edid_bps_byte(bitrate[i],formats[i]);
+        ALOGV("info->audio_blocks_array[i].bits_per_sample_bitmask %d",
+              info->audio_blocks_array[i].bits_per_sample_bitmask);
     }
     dump_speaker_allocation(info);
     dump_edid_data(info);
@@ -691,7 +743,7 @@
     int i = 0;
     if (info != NULL && sr != 0) {
         for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
-            if (info->audio_blocks_array[i].sampling_freq == sr) {
+        if (is_supported_sr(info->audio_blocks_array[i].sampling_freq_bitmask , sr)) {
                 ALOGV("%s: returns true for sample rate [%d]",
                       __func__, sr);
                 return true;
@@ -715,7 +767,7 @@
 
     if (info != NULL && bps != 0) {
         for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
-            if (info->audio_blocks_array[i].bits_per_sample == bps) {
+            if (is_supported_bps(info->audio_blocks_array[i].bits_per_sample_bitmask, bps)) {
                 ALOGV("%s: returns true for bit width [%d]",
                       __func__, bps);
                 return true;
@@ -726,3 +778,24 @@
            __func__, bps);
     return false;
 }
+
+int edid_get_highest_supported_sr(edid_audio_info* info)
+{
+    int sr = 0;
+    int highest_sr = 0;
+    int i;
+
+    if (info != NULL) {
+        for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+          sr = get_highest_edid_sf(info->audio_blocks_array[i].sampling_freq_bitmask);
+          if (sr > highest_sr)
+            highest_sr = sr;
+        }
+    }
+    else
+        ALOGE("%s: info is NULL", __func__);
+
+    ALOGV("%s: returns [%d] for highest supported sr",
+        __func__, highest_sr);
+    return highest_sr;
+}
\ No newline at end of file
diff --git a/hal/edid.h b/hal/edid.h
index 387b17e..6a82103 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -79,8 +79,8 @@
 
 typedef struct edid_audio_block_info {
     edid_audio_format_id format_id;
-    int sampling_freq;
-    int bits_per_sample;
+    int sampling_freq_bitmask;
+    int bits_per_sample_bitmask;
     int channels;
 } edid_audio_block_info;
 
@@ -100,5 +100,6 @@
 
 bool edid_is_supported_sr(edid_audio_info* info, int sr);
 bool edid_is_supported_bps(edid_audio_info* info, int bps);
+int edid_get_highest_supported_sr(edid_audio_info* info);
 
 #endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8c79893..7433e3a 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -4503,8 +4503,12 @@
 
         //Check EDID info for supported samplerate
         if (!edid_is_supported_sr(edid_info,sample_rate)) {
-            //reset to current sample rate
-            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+            //check to see if current BE sample rate is supported by EDID
+            //else assign the highest sample rate supported by EDID
+            if (edid_is_supported_sr(edid_info,my_data->current_backend_cfg[backend_idx].sample_rate))
+                sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+            else
+                sample_rate = edid_get_highest_supported_sr(edid_info);
         }
 
         //Check EDID info for supported bit width
@@ -5301,24 +5305,13 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
-    int i, ret;
+    int ret = 0;
 
     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;
-            }
-        }
+        return edid_is_supported_sr(info, sample_rate);
     }
-    ALOGV("%s: returns false %d", __func__, sample_rate);
 
     return false;
 }
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 9907735..3551006 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -4565,8 +4565,12 @@
 
         //Check EDID info for supported samplerate
         if (!edid_is_supported_sr(edid_info,sample_rate)) {
-            //reset to current sample rate
-            sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+            //check to see if current BE sample rate is supported by EDID
+            //else assign the highest sample rate supported by EDID
+            if (edid_is_supported_sr(edid_info,my_data->current_backend_cfg[backend_idx].sample_rate))
+                sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+            else
+                sample_rate = edid_get_highest_supported_sr(edid_info);
         }
 
         //Check EDID info for supported bit width
@@ -5377,24 +5381,13 @@
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     edid_audio_info *info = NULL;
-    int i, ret;
+    int ret = 0;
 
     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;
-            }
-        }
+        return edid_is_supported_sr(info, sample_rate);
     }
-    ALOGV("%s: returns false %d", __func__, sample_rate);
 
     return false;
 }