hal: edid: Update EDID parsing logic
Previously, the only sample rate that hal stored was the highest
supported sample rate. Hal would return false on Sample Rates(sr)
that were lower than the highest supported sr from the sink.
Streams were forced to be played at the highest sr that the
sink supported. A similar change was done in for bytes per
sample as well.
Change-Id: I41591958739562334d9409cffad4f55e1cc5e0bc
CRs-Fixed: 1084185
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 a42f984..9d13b94 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -4500,8 +4500,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
@@ -5275,24 +5279,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 d209359..0489fc9 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -4562,8 +4562,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
@@ -5347,24 +5351,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;
}