hal: Fix mute issue for unsupported sample rate in passthru mode
-Mute is observed when passthrough session is opened with
unsupported sampling rate
-Return error when stream sampling rate is not supported
by the sink during compress passthrough playback
-Add correct condiiton check for convert usecases
Change-Id: Iea236f5076617a583b7882741b76468294fac013
CRs-fixed: 2096943
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index c30f982..117d270 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -465,12 +465,10 @@
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
-bool audio_extn_is_dolby_format(audio_format_t format);
int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev,
struct stream_out *out,
audio_format_t format);
#else
-#define audio_extn_is_dolby_format(format) (0)
#define audio_extn_dolby_get_snd_codec_id(adev, out, format) (0)
#endif
@@ -518,6 +516,7 @@
#define audio_extn_passthru_get_channel_count(out) (0)
#define audio_extn_passthru_update_dts_stream_configuration(out, buffer, bytes) (-ENOSYS)
#define audio_extn_passthru_is_direct_passthrough(out) (0)
+#define audio_extn_passthru_is_supported_backend_edid_cfg(adev, out) (0)
#else
bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
struct stream_out *out);
@@ -545,6 +544,8 @@
int audio_extn_passthru_update_dts_stream_configuration(struct stream_out *out,
const void *buffer, size_t bytes);
bool audio_extn_passthru_is_direct_passthrough(struct stream_out *out);
+bool audio_extn_passthru_is_supported_backend_edid_cfg(struct audio_device *adev,
+ struct stream_out *out);
#endif
#ifndef HFP_ENABLED
@@ -621,6 +622,7 @@
struct audio_usecase *usecase);
int audio_extn_utils_get_snd_card_num();
bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags);
+bool audio_extn_utils_is_dolby_format(audio_format_t format);
#ifdef DS2_DOLBY_DAP_ENABLED
#define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index bc7aa5c..fda9a1a 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -362,19 +362,6 @@
}
#endif /* DS1_DOLBY_DDP_ENABLED */
-#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
-bool audio_extn_is_dolby_format(audio_format_t format)
-{
- if (format == AUDIO_FORMAT_AC3 ||
- format == AUDIO_FORMAT_E_AC3 ||
- format == AUDIO_FORMAT_E_AC3_JOC)
- return true;
- else
- return false;
-}
-#endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
-
-
#ifdef DS1_DOLBY_DAP_ENABLED
void audio_extn_dolby_set_endpoint(struct audio_device *adev)
{
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index 701084a..8acffda 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -348,11 +348,13 @@
switch (out->format) {
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_E_AC3_JOC:
- case AUDIO_FORMAT_DTS_HD:
if (!platform_is_edid_supported_format(adev->platform,
- out->format)) {
- ALOGD("%s:PASSTHROUGH_CONVERT supported", __func__);
- convert = true;
+ out->format)) {
+ if (platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_AC3)) {
+ ALOGD("%s:PASSTHROUGH_CONVERT supported", __func__);
+ convert = true;
+ }
}
break;
default:
@@ -449,7 +451,7 @@
out->format)) {
ALOGV("%s : return true",__func__);
return true;
- } else if (audio_extn_is_dolby_format(out->format) &&
+ } else if (audio_extn_utils_is_dolby_format(out->format) &&
platform_is_edid_supported_format(out->dev->platform,
AUDIO_FORMAT_AC3)){
//return true for EAC3/EAC3_JOC formats
@@ -504,3 +506,44 @@
{
return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
}
+
+bool audio_extn_passthru_is_supported_backend_edid_cfg(struct audio_device *adev,
+ struct stream_out *out)
+{
+ struct audio_backend_cfg backend_cfg;
+ snd_device_t out_snd_device = SND_DEVICE_NONE;
+ int max_edid_channels = platform_edid_get_max_channels(out->dev->platform);
+
+ out_snd_device = platform_get_output_snd_device(adev->platform, out);
+
+ if (platform_get_codec_backend_cfg(adev, out_snd_device, &backend_cfg)) {
+ ALOGE("%s: ERROR: Unable to get current backend config!!!", __func__);
+ return false;
+ }
+
+ ALOGV("%s:becf: afe: bitwidth %d, samplerate %d channels %d format %d"
+ ", device (%s)", __func__, backend_cfg.bit_width,
+ backend_cfg.sample_rate, backend_cfg.channels, backend_cfg.format,
+ platform_get_snd_device_name(out_snd_device));
+
+ /* Check if the channels are supported */
+ if (max_edid_channels < backend_cfg.channels) {
+
+ ALOGE("%s: ERROR: Unsupported channels in passthru mode!!!"
+ " max_edid_channels - %d backend_channels - %d",
+ __func__, max_edid_channels, backend_cfg.channels);
+ return false;
+ }
+
+ /* Check if the sample rate supported */
+ if (!platform_is_edid_supported_sample_rate(adev->platform,
+ backend_cfg.sample_rate)) {
+
+ ALOGE("%s: ERROR: Unsupported sample rate in passthru mode!!!"
+ " backend_samplerate - %d",
+ __func__, backend_cfg.sample_rate);
+ return false;
+ }
+
+ return true;
+}
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 8ee5948..c1cc9ee 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -1676,7 +1676,7 @@
struct mixer_ctl *ctl;
ALOGV("%s: buffer %s bytes %zd", __func__, buffer, bytes);
#ifdef HDMI_PASSTHROUGH_ENABLED
- if (audio_extn_is_dolby_format(out->format) &&
+ if (audio_extn_utils_is_dolby_format(out->format) &&
/*TODO:Extend code to support DTS passthrough*/
/*set compressed channel status bits*/
audio_extn_passthru_is_passthrough_stream(out)){
@@ -2351,3 +2351,15 @@
exit:
return ret;
}
+
+bool audio_extn_utils_is_dolby_format(audio_format_t format)
+{
+ if (format == AUDIO_FORMAT_AC3 ||
+ format == AUDIO_FORMAT_E_AC3 ||
+ format == AUDIO_FORMAT_E_AC3_JOC)
+ return true;
+ else
+ return false;
+}
+
+
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 4b698b8..a7d36c6 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2781,7 +2781,7 @@
out->playback_started);
#ifdef DS1_DOLBY_DDP_ENABLED
- if (audio_extn_is_dolby_format(out->format))
+ if (audio_extn_utils_is_dolby_format(out->format))
audio_extn_dolby_send_ddp_endp_params(adev);
#endif
if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
@@ -3762,6 +3762,13 @@
audio_extn_passthru_is_passthrough_stream(out)) {
audio_extn_passthru_update_stream_configuration(adev, out,
buffer, bytes);
+ if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
+ !out->is_iec61937_info_available) {
+
+ if (!audio_extn_passthru_is_passthrough_stream(out)) {
+ out->is_iec61937_info_available = true;
+ } else if (audio_extn_passthru_is_enabled()) {
+ audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
out->is_iec61937_info_available = true;
if((out->format == AUDIO_FORMAT_DTS) ||
@@ -3773,7 +3780,7 @@
out->is_iec61937_info_available = false;
ALOGD("iec61937 transmission info not yet updated retry");
}
- } else {
+ } else if (!out->standby) {
/* if stream has started and after that there is
* stream config change (iec transmission config)
* then trigger select_device to update backend configuration.
@@ -3781,6 +3788,10 @@
out->stream_config_changed = true;
pthread_mutex_lock(&adev->lock);
select_devices(adev, out->usecase);
+ if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
+ ret = -EINVAL;
+ goto exit;
+ }
pthread_mutex_unlock(&adev->lock);
out->stream_config_changed = false;
out->is_iec61937_info_available = true;
@@ -3795,6 +3806,7 @@
goto exit;
}
}
+ }
}
if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
@@ -3826,6 +3838,13 @@
audio_hw_send_gain_dep_calibration(last_known_cal_step);
last_known_cal_step = -1;
}
+
+ if ((out->is_iec61937_info_available == true) &&
+ (audio_extn_passthru_is_passthrough_stream(out))&&
+ (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
+ ret = -EINVAL;
+ goto exit;
+ }
}
if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
@@ -5197,7 +5216,7 @@
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
- if (audio_extn_is_dolby_format(config->offload_info.format)) {
+ if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
audio_extn_dolby_send_ddp_endp_params(adev);
audio_extn_dolby_set_dmid(adev);
}
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index d000a7d..3e7b69c 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5564,6 +5564,33 @@
}
/*
+ * Get the backend configuration for current snd device
+ */
+int platform_get_codec_backend_cfg(struct audio_device* adev,
+ snd_device_t snd_device,
+ struct audio_backend_cfg *backend_cfg)
+{
+ int backend_idx = platform_get_backend_index(snd_device);
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ backend_cfg->bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ backend_cfg->sample_rate =
+ my_data->current_backend_cfg[backend_idx].sample_rate;
+ backend_cfg->channels =
+ my_data->current_backend_cfg[backend_idx].channels;
+ backend_cfg->format =
+ my_data->current_backend_cfg[backend_idx].format;
+
+ ALOGV("%s:becf: afe: bitwidth %d, samplerate %d channels %d format %d"
+ ", backend_idx %d device (%s)", __func__, backend_cfg->bit_width,
+ backend_cfg->sample_rate, backend_cfg->channels, backend_cfg->format,
+ backend_idx, platform_get_snd_device_name(snd_device));
+
+ return 0;
+}
+
+
+/*
*Validate the selected bit_width, sample_rate and channels using the edid
*of the connected sink device.
*/
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index dfe39a3..61ef223 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -5439,6 +5439,32 @@
}
/*
+ * Get the backend configuration for current snd device
+ */
+int platform_get_codec_backend_cfg(struct audio_device* adev,
+ snd_device_t snd_device,
+ struct audio_backend_cfg *backend_cfg)
+{
+ int backend_idx = platform_get_backend_index(snd_device);
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ backend_cfg->bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ backend_cfg->sample_rate =
+ my_data->current_backend_cfg[backend_idx].sample_rate;
+ backend_cfg->channels =
+ my_data->current_backend_cfg[backend_idx].channels;
+ backend_cfg->format =
+ my_data->current_backend_cfg[backend_idx].format;
+
+ ALOGV("%s:becf: afe: bitwidth %d, samplerate %d channels %d format %d"
+ ", backend_idx %d device (%s)", __func__, backend_cfg->bit_width,
+ backend_cfg->sample_rate, backend_cfg->channels, backend_cfg->format,
+ backend_idx, platform_get_snd_device_name(snd_device));
+
+ return 0;
+}
+
+/*
*Validate the selected bit_width, sample_rate and channels using the edid
*of the connected sink device.
*/