audio: config audio backend for HDMI playback
-check EDID info for supported audio configuration,
and config audio backend for HDMI audio playback
with proper bitwidth and sample rate.
Change-Id: Iae65e00b0f4d2f74f303ef03610f8b3a098dc7aa
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index e679c64..d6e81b2 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3844,7 +3844,7 @@
val = atoi(value);
if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
ALOGV("invalidate cached edid");
- platform_invalidate_edid(adev->platform);
+ platform_invalidate_hdmi_config(adev->platform);
} else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
(val & AUDIO_DEVICE_IN_USB_DEVICE)) {
ret = str_parms_get_str(parms, "card", value, sizeof(value));
diff --git a/hal/edid.c b/hal/edid.c
index 06e1e05..8f183d0 100644
--- a/hal/edid.c
+++ b/hal/edid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2014 The Android Open Source Project
@@ -685,3 +685,44 @@
dump_edid_data(info);
return true;
}
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr)
+{
+ 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) {
+ ALOGV("%s: returns true for sample rate [%d]",
+ __func__, sr);
+ return true;
+ }
+ }
+ }
+ ALOGV("%s: returns false for sample rate [%d]",
+ __func__, sr);
+ return false;
+}
+
+bool edid_is_supported_bps(edid_audio_info* info, int bps)
+{
+ int i = 0;
+
+ if (bps == 16) {
+ //16 bit bps is always supported
+ //some oem may not update 16bit support in their edid info
+ return true;
+ }
+
+ 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) {
+ ALOGV("%s: returns true for bit width [%d]",
+ __func__, bps);
+ return true;
+ }
+ }
+ }
+ ALOGV("%s: returns false for bit width [%d]",
+ __func__, bps);
+ return false;
+}
diff --git a/hal/edid.h b/hal/edid.h
index 0d7fbe6..387b17e 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -97,4 +97,8 @@
#else
bool edid_get_sink_caps(edid_audio_info* info, char *edid_data);
#endif
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr);
+bool edid_is_supported_bps(edid_audio_info* info, int bps);
+
#endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index b18670e..2403c55 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1902,6 +1902,11 @@
my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
strdup("USB_AUDIO_RX SampleRate");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("HDMI_RX Bit Format");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("HDMI_RX SampleRate");
+
ret = audio_extn_utils_get_codec_version(snd_card_name,
my_data->adev->snd_card,
my_data->codec_version);
@@ -4135,6 +4140,7 @@
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
+ edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
backend_idx = platform_get_backend_index(snd_device);
@@ -4210,8 +4216,6 @@
}
}
-
-
/*
* hifi playback not supported on spkr devices, limit the Sample Rate
* to 48 khz.
@@ -4243,6 +4247,19 @@
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
+ if (backend_idx == HDMI_RX_BACKEND) {
+ //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 EDID info for supported bit widhth
+ if (!edid_is_supported_bps(edid_info,bit_width)) {
+ //reset to current sample rate
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ }
+ }
+
//check if mulitchannel clip needs to be down sampled to 48k
property_get("audio.playback.mch.downsample",value,"");
if (!strncmp("true", value, sizeof("true"))) {
@@ -4974,13 +4991,17 @@
platform_get_edid_info(platform);
}
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
{
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
+
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index b35e8e9..2b6a1d7 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1165,7 +1165,7 @@
}
-void platform_invalidate_edid(void * platform __unused)
+void platform_invalidate_hdmi_config(void * platform __unused)
{
}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 8922a4e..cd63143 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1738,6 +1738,10 @@
strdup("SLIM_6_RX Format");
my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_6_RX SampleRate");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("HDMI_RX Bit Format");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("HDMI_RX SampleRate");
my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
strdup("USB_AUDIO_RX Format");
@@ -4105,6 +4109,7 @@
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
+ edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
backend_idx = platform_get_backend_index(snd_device);
@@ -4211,8 +4216,21 @@
__func__, bit_width, sample_rate, channels);
}
+ if (backend_idx == HDMI_RX_BACKEND) {
+ //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 EDID info for supported bit widhth
+ if (!edid_is_supported_bps(edid_info,bit_width)) {
+ //reset to current sample rate
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ }
+ }
ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
__func__, backend_idx , bit_width, sample_rate);
+
// Force routing if the expected bitwdith or samplerate
// is not same as current backend comfiguration
if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
@@ -4917,13 +4935,18 @@
platform_get_edid_info(platform);
}
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
{
+ //reset HDMI EDID info
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
+
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index c6f3cb3..fc1c440 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -130,7 +130,6 @@
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);
void platform_invalidate_hdmi_config(void * platform);
int platform_set_hdmi_config(void *platform, uint32_t channel_count,
uint32_t sample_rate, bool enable_passthrough);