Merge "hal: add a new key to query for decoder viability"
diff --git a/hal/Android.mk b/hal/Android.mk
index 6db1f98..72042d1 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -69,6 +69,10 @@
LOCAL_CFLAGS += -DANC_HEADSET_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_VBAT_MONITOR)),true)
+ LOCAL_CFLAGS += -DVBAT_MONITOR_ENABLED
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLUENCE)),true)
LOCAL_CFLAGS += -DFLUENCE_ENABLED
endif
@@ -227,10 +231,6 @@
LOCAL_SRC_FILES += audio_extn/source_track.c
endif
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUDIOSPHERE)),true)
- LOCAL_CFLAGS += -DAUDIOSPHERE_ENABLED
-endif
-
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
@@ -256,6 +256,14 @@
LOCAL_SRC_FILES += audio_extn/listen.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HDMI)),true)
+ LOCAL_CFLAGS += -DAUDIO_EXTERNAL_HDMI_ENABLED
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true)
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-parsers
+ LOCAL_SHARED_LIBRARIES += libaudioparsers
+endif
+endif
+
ifeq ($(strip $(BOARD_SUPPORTS_SOUND_TRIGGER)),true)
LOCAL_CFLAGS += -DSOUND_TRIGGER_ENABLED
LOCAL_CFLAGS += -DSOUND_TRIGGER_PLATFORM_NAME=$(TARGET_BOARD_PLATFORM)
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 96a7a19..1c5da54 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -72,6 +72,8 @@
#define AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
#define AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
+#define AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT "music_offload_vorbis_bitstream_fmt"
+
/* Query handle fm parameter*/
#define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 67d30ca..39ad4d1 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -62,6 +62,7 @@
bool custom_stereo_enabled;
uint32_t proxy_channel_num;
bool hpx_enabled;
+ bool vbat_enabled;
};
static struct audio_extn_module aextnmod = {
@@ -70,6 +71,7 @@
.custom_stereo_enabled = 0,
.proxy_channel_num = 2,
.hpx_enabled = 0,
+ .vbat_enabled = 0,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
@@ -79,8 +81,6 @@
/* Query offload playback instances count */
#define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
#define AUDIO_PARAMETER_HPX "HPX"
-#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE "asphere_enable"
-#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
#ifndef FM_ENABLED
#define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -216,6 +216,27 @@
}
#endif
+#ifdef VBAT_MONITOR_ENABLED
+bool audio_extn_is_vbat_enabled(void)
+{
+ ALOGD("%s: status: %d", __func__, aextnmod.vbat_enabled);
+ return (aextnmod.vbat_enabled ? true: false);
+}
+
+bool audio_extn_can_use_vbat(void)
+{
+ char prop_vbat_enabled[PROPERTY_VALUE_MAX] = "false";
+
+ property_get("persist.audio.vbat.enabled", prop_vbat_enabled, "0");
+ if (!strncmp("true", prop_vbat_enabled, 4)) {
+ aextnmod.vbat_enabled = 1;
+ }
+
+ ALOGD("%s: vbat.enabled property is set to %s", __func__, prop_vbat_enabled);
+ return (aextnmod.vbat_enabled ? true: false);
+}
+#endif
+
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
#else
@@ -535,103 +556,6 @@
return ret;
}
-#ifndef AUDIOSPHERE_ENABLED
-#define audio_extn_asphere_set_parameters(adev, parms) (0)
-#define audio_extn_asphere_get_parameters(adev, query, reply) (0)
-#else
-int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
- struct str_parms *parms)
-{
- int ret = 0, val[2];
- char value[32] = {0};
- int set_enable, set_strength;
- int enable = -1, strength = -1;
- struct mixer_ctl *ctl = NULL;
- const char *mixer_ctl_name = "MSM ASphere Set Param";
- char propValue[PROPERTY_VALUE_MAX] = {0};
- bool asphere_prop_enabled = false;
-
- if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
- if (!strncmp("true", propValue, 4))
- asphere_prop_enabled = true;
- }
-
- if (!asphere_prop_enabled) {
- ALOGV("%s: property not set!!! not doing anything", __func__);
- return ret;
- }
-
- set_enable = str_parms_get_str(parms,
- AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
- value, sizeof(value));
- if (set_enable > 0)
- enable = atoi(value);
-
- set_strength = str_parms_get_str(parms,
- AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
- value, sizeof(value));
- if (set_strength > 0)
- strength = atoi(value);
-
- if (set_enable >= 0 || set_strength >= 0) {
- ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: could not get ctl for mixer cmd - %s",
- __func__, mixer_ctl_name);
- return -EINVAL;
- }
- ALOGD("%s: set ctl \"%s:%d,%d\"",
- __func__, mixer_ctl_name, enable, strength);
- val[0] = enable;
- val[1] = strength;
- ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
- if (ret)
- ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
- __func__, mixer_ctl_name, enable, strength);
- }
- ALOGV("%s: exit ret %d", __func__, ret);
- return ret;
-}
-
-int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
- struct str_parms *query,
- struct str_parms *reply)
-{
- int ret = 0, val[2] = {-1, -1};
- char value[32] = {0};
- int get_enable, get_strength;
- struct mixer_ctl *ctl = NULL;
- const char *mixer_ctl_name = "MSM ASphere Set Param";
-
- get_enable = str_parms_get_str(query,
- AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
- value, sizeof(value));
- get_strength = str_parms_get_str(query,
- AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
- value, sizeof(value));
- if (get_enable > 0 || get_strength > 0) {
- ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: could not get ctl for mixer cmd - %s",
- __func__, mixer_ctl_name);
- return -EINVAL;
- }
- ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
- if (ret)
- ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
- __func__, mixer_ctl_name, val[0], val[1]);
- if (get_enable > 0)
- str_parms_add_int(reply,
- AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
- if (get_strength > 0)
- str_parms_add_int(reply,
- AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
- }
- ALOGV("%s: exit ret %d", __func__, ret);
- return ret;
-}
-#endif
-
void audio_extn_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
@@ -649,7 +573,8 @@
audio_extn_hpx_set_parameters(adev, parms);
audio_extn_pm_set_parameters(parms);
audio_extn_source_track_set_parameters(adev, parms);
- audio_extn_asphere_set_parameters(adev, parms);
+ if (adev->offload_effects_set_parameters != NULL)
+ adev->offload_effects_set_parameters(parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -663,7 +588,8 @@
audio_extn_dts_eagle_get_parameters(adev, query, reply);
audio_extn_hpx_get_parameters(query, reply);
audio_extn_source_track_get_parameters(adev, query, reply);
- audio_extn_asphere_get_parameters(adev, query, reply);
+ if (adev->offload_effects_get_parameters != NULL)
+ adev->offload_effects_get_parameters(query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
@@ -682,25 +608,23 @@
if (out->format == AUDIO_FORMAT_FLAC) {
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
if (ret >= 0) {
- out->gapless_mdata.min_blk_size =
out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
if (ret >= 0) {
- out->gapless_mdata.max_blk_size =
out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
out->compr_config.codec->options.flac_dec.min_blk_size,
@@ -713,63 +637,63 @@
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.frame_length = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.compatible_version = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.bit_depth = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.pb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.mb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.kb = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.num_channels = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.max_run = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.sample_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
" maxFrameBytes %d, avgBitRate %d, sampleRate %d",
@@ -785,52 +709,52 @@
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.compatible_version = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.compression_level = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.format_flags = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.total_frames = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.num_channels = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.sample_rate = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.ape.seek_table_present = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
" formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
@@ -849,49 +773,59 @@
}
else if (out->format == AUDIO_FORMAT_VORBIS) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT, value, sizeof(value));
+ if (ret >= 0) {
// transcoded bitstream mode
- out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
- out->send_new_metadata = 1;
+ out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = (atoi(value) > 0) ? 1 : 0;
+ out->is_compr_metadata_avail = true;
+ }
}
else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->format = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.avg_bit_rate = atoi(value);
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.super_block_align = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.channelmask = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
if (ret >= 0) {
out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
- out->send_new_metadata = 1;
+ out->is_compr_metadata_avail = true;
}
- ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ ALOGV("WMA params: fmt %x, bit rate %x, balgn %x, sr %d, chmsk %x"
+ " encop %x, op1 %x, op2 %x",
out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.avg_bit_rate,
out->compr_config.codec->options.wma.super_block_align,
out->compr_config.codec->options.wma.bits_per_sample,
out->compr_config.codec->options.wma.channelmask,
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 2bf19fc..3645cdb 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -103,7 +103,8 @@
#endif
#ifdef AUDIO_EXTN_FORMATS_ENABLED
-#define AUDIO_OUTPUT_BIT_WIDTH (config->offload_info.bit_width)
+#define AUDIO_OUTPUT_BIT_WIDTH ((config->offload_info.bit_width == 32) ? 24\
+ :config->offload_info.bit_width)
#else
#define AUDIO_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
#endif
@@ -127,6 +128,14 @@
bool audio_extn_should_use_handset_anc(int in_channels);
#endif
+#ifndef VBAT_MONITOR_ENABLED
+#define audio_extn_is_vbat_enabled() (0)
+#define audio_extn_can_use_vbat() (0)
+#else
+bool audio_extn_is_vbat_enabled(void);
+bool audio_extn_can_use_vbat(void);
+#endif
+
#ifndef FLUENCE_ENABLED
#define audio_extn_set_fluence_parameters(adev, parms) (0)
#define audio_extn_get_fluence_parameters(adev, query, reply) (0)
@@ -442,7 +451,8 @@
uint32_t sample_rate,
uint32_t bit_width,
struct stream_app_type_cfg *app_type_cfg);
-int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase);
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+ struct audio_usecase *usecase);
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
struct audio_usecase *usecase);
#ifdef DS2_DOLBY_DAP_ENABLED
@@ -500,4 +510,10 @@
void audio_extn_perf_lock_acquire(void);
void audio_extn_perf_lock_release(void);
#endif /* KPI_OPTIMIZE_ENABLED */
+
+#ifndef AUDIO_EXTERNAL_HDMI_ENABLED
+#define audio_utils_set_hdmi_channel_status(out, buffer, bytes) (0)
+#else
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes);
+#endif
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 78a7956..aab9f74 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -77,6 +77,7 @@
#define WAIT_TIME_SPKR_CALIB (60 * 1000 * 1000)
#define MIN_SPKR_IDLE_SEC (60 * 30)
+#define WAKEUP_MIN_IDLE_CHECK 30
/*Once calibration is started sleep for 1 sec to allow
the calibration to kick off*/
@@ -467,10 +468,16 @@
uc_info_rx->type = PCM_PLAYBACK;
uc_info_rx->in_snd_device = SND_DEVICE_NONE;
uc_info_rx->stream.out = adev->primary_output;
- uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED;
+ if (audio_extn_is_vbat_enabled())
+ uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT;
+ else
+ uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED;
disable_rx = true;
list_add_tail(&adev->usecase_list, &uc_info_rx->list);
- enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
+ if (audio_extn_is_vbat_enabled())
+ enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ else
+ enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
enable_audio_route(adev, uc_info_rx);
pcm_dev_rx_id = platform_get_pcm_device_id(uc_info_rx->id, PCM_PLAYBACK);
@@ -581,7 +588,7 @@
}
break;
} else if (status.status == -EAGAIN) {
- ALOGD("%s: spkr_prot_thread try again", __func__);
+ ALOGV("%s: spkr_prot_thread try again", __func__);
usleep(WAIT_FOR_GET_CALIB_STATUS);
} else {
ALOGE("%s: spkr_prot_thread get failed status %d",
@@ -629,7 +636,10 @@
}
if (disable_rx) {
list_remove(&uc_info_rx->list);
- disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
+ if (audio_extn_is_vbat_enabled())
+ disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ else
+ disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
disable_audio_route(adev, uc_info_rx);
}
if (disable_tx) {
@@ -758,18 +768,22 @@
if (is_speaker_in_use(&sec)) {
ALOGV("%s: WSA Speaker in use retry calibration", __func__);
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
} else {
+ ALOGD("%s: wsa speaker idle %ld,minimum time %ld", __func__, sec, min_idle_time);
if (sec < min_idle_time) {
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
- ALOGV("%s: wsa speaker idle %ld min time %ld", __func__, sec, min_idle_time);
goahead = true;
}
if (!list_empty(&adev->usecase_list)) {
ALOGD("%s: Usecase active re-try calibration", __func__);
- goahead = false;
+ pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
+ continue;
}
if (goahead) {
if (spk_1_tzn >= 0) {
@@ -801,15 +815,17 @@
if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
+ ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
/*Convert temp into q6 format*/
t0_spk_1 = (t0_spk_1 * (1 << 6));
- ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
} else {
ALOGV("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
__func__, i, NUM_ATTEMPTS);
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
}
@@ -841,15 +857,17 @@
if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
+ ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
/*Convert temp into q6 format*/
t0_spk_2 = (t0_spk_2 * (1 << 6));
- ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
} else {
ALOGV("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
__func__, i, NUM_ATTEMPTS);
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
}
@@ -883,19 +901,22 @@
if (is_speaker_in_use(&sec)) {
ALOGV("%s: Speaker in use retry calibration", __func__);
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
} else {
if (sec < min_idle_time) {
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
continue;
}
- ALOGD("%s: speaker idle %ld min time %ld", __func__, sec, min_idle_time);
goahead = true;
}
if (!list_empty(&adev->usecase_list)) {
ALOGD("%s: Usecase active re-try calibration", __func__);
goahead = false;
pthread_mutex_unlock(&adev->lock);
+ sleep(WAKEUP_MIN_IDLE_CHECK);
+ continue;
}
if (goahead) {
int status;
@@ -1075,6 +1096,12 @@
case SND_DEVICE_OUT_VOICE_SPEAKER:
acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED);
break;
+ case SND_DEVICE_OUT_SPEAKER_VBAT:
+ acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ break;
+ case SND_DEVICE_OUT_VOICE_SPEAKER_VBAT:
+ acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT);
+ break;
default:
acdb_id = -EINVAL;
break;
@@ -1092,6 +1119,10 @@
return SND_DEVICE_OUT_SPEAKER_PROTECTED;
case SND_DEVICE_OUT_VOICE_SPEAKER:
return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED;
+ case SND_DEVICE_OUT_SPEAKER_VBAT:
+ return SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT;
+ case SND_DEVICE_OUT_VOICE_SPEAKER_VBAT:
+ return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT;
default:
return snd_device;
}
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 24dee64..38dbb46 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -35,6 +35,12 @@
#include "audio_extn.h"
#include "voice.h"
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#ifdef HDMI_PASSTHROUGH_ENABLED
+#include "audio_parsers.h"
+#endif
+#endif
+
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
#define OUTPUTS_TAG "outputs"
@@ -52,6 +58,21 @@
#define BASE_TABLE_SIZE 64
#define MAX_BASEINDEX_LEN 256
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#define PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
+#define NON_LPCM (1<<1) /* 0 = audio, 1 = non-audio */
+#define SR_44100 (0<<0) /* 44.1kHz */
+#define SR_NOTID (1<<0) /* non indicated */
+#define SR_48000 (2<<0) /* 48kHz */
+#define SR_32000 (3<<0) /* 32kHz */
+#define SR_22050 (4<<0) /* 22.05kHz */
+#define SR_24000 (6<<0) /* 24kHz */
+#define SR_88200 (8<<0) /* 88.2kHz */
+#define SR_96000 (10<<0) /* 96kHz */
+#define SR_176400 (12<<0) /* 176.4kHz */
+#define SR_192000 (14<<0) /* 192kHz */
+
+#endif
struct string_to_enum {
const char *name;
uint32_t value;
@@ -504,14 +525,11 @@
app_type_cfg->bit_width = 16;
}
-#define GENERAL_RECORDING_APP_TYPE 0x11132
-int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+ struct audio_usecase *usecase)
{
char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
- struct stream_out *out;
- struct stream_in *in;
- struct audio_device *adev;
struct mixer_ctl *ctl;
int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -528,21 +546,16 @@
(usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
(!is_offload_usecase(usecase->id)) &&
(usecase->type != PCM_CAPTURE)) {
- ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id);
+ ALOGV("%s: a rx/tx path where app type cfg is not required %d", __func__, usecase->id);
rc = 0;
goto exit_send_app_type_cfg;
}
if (usecase->type == PCM_PLAYBACK) {
- out = usecase->stream.out;
- adev = out->dev;
snd_device = usecase->out_snd_device;
- pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
- }
- if (usecase->type == PCM_CAPTURE) {
- in = usecase->stream.in;
- adev = in->dev;
+ pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
+ } else if (usecase->type == PCM_CAPTURE) {
snd_device = usecase->in_snd_device;
- pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
+ pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
}
snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
@@ -564,7 +577,14 @@
goto exit_send_app_type_cfg;
}
- if (usecase->type == PCM_PLAYBACK) {
+ if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out == NULL)) {
+ sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
+ app_type_cfg[len++] = acdb_dev_id;
+ app_type_cfg[len++] = sample_rate;
+ ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, platform_get_default_app_type(adev->platform), acdb_dev_id, sample_rate);
+ } else if (usecase->type == PCM_PLAYBACK) {
if ((24 == usecase->stream.out->bit_width) &&
(usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -573,13 +593,13 @@
(usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
} else {
- sample_rate = out->app_type_cfg.sample_rate;
+ sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
}
- app_type_cfg[len++] = out->app_type_cfg.app_type;
+ app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
app_type_cfg[len++] = acdb_dev_id;
- if (((out->format == AUDIO_FORMAT_E_AC3) ||
- (out->format == AUDIO_FORMAT_E_AC3_JOC))
+ if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
+ (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
#ifdef HDMI_PASSTHROUGH_ENABLED
&& (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
#endif
@@ -588,10 +608,9 @@
else
app_type_cfg[len++] = sample_rate;
ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
- }
- else if (usecase->type == PCM_CAPTURE) {
- app_type_cfg[len++] = GENERAL_RECORDING_APP_TYPE;
+ __func__, usecase->stream.out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
+ } else if (usecase->type == PCM_CAPTURE) {
+ app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
app_type_cfg[len++] = acdb_dev_id;
app_type_cfg[len++] = sample_rate;
ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d",
@@ -767,3 +786,136 @@
outp[k] = '\0';
return k;
}
+
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+
+void get_default_compressed_channel_status(
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //compre out
+ channel_status[0] |= NON_LPCM;
+ // sample rate; fixed 48K for default/transcode
+ channel_status[3] |= SR_48000;
+}
+
+#ifdef HDMI_PASSTHROUGH_ENABLED
+int32_t get_compressed_channel_status(void *audio_stream_data,
+ uint32_t audio_frame_size,
+ unsigned char *channel_status,
+ enum audio_parser_code_type codec_type)
+ // codec_type - AUDIO_PARSER_CODEC_AC3
+ // - AUDIO_PARSER_CODEC_DTS
+{
+ unsigned char *stream;
+ int ret = 0;
+ stream = (unsigned char *)audio_stream_data;
+
+ if (audio_stream_data == NULL || audio_frame_size == 0) {
+ ALOGW("no buffer to get channel status, return default for compress");
+ get_default_compressed_channel_status(channel_status);
+ return ret;
+ }
+
+ memset(channel_status,0,24);
+ if(init_audio_parser(stream, audio_frame_size, codec_type) == -1)
+ {
+ ALOGE("init audio parser failed");
+ return -1;
+ }
+ ret = get_channel_status(channel_status, codec_type);
+ return ret;
+
+}
+
+#endif
+
+void get_lpcm_channel_status(uint32_t sampleRate,
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //LPCM OUT
+ channel_status[0] &= ~NON_LPCM;
+
+ switch (sampleRate) {
+ case 8000:
+ case 11025:
+ case 12000:
+ case 16000:
+ case 22050:
+ channel_status[3] |= SR_NOTID;
+ case 24000:
+ channel_status[3] |= SR_24000;
+ break;
+ case 32000:
+ channel_status[3] |= SR_32000;
+ break;
+ case 44100:
+ channel_status[3] |= SR_44100;
+ break;
+ case 48000:
+ channel_status[3] |= SR_48000;
+ break;
+ case 88200:
+ channel_status[3] |= SR_88200;
+ break;
+ case 96000:
+ channel_status[3] |= SR_96000;
+ break;
+ case 176400:
+ channel_status[3] |= SR_176400;
+ break;
+ case 192000:
+ channel_status[3] |= SR_192000;
+ break;
+ default:
+ ALOGV("Invalid sample_rate %u\n", sampleRate);
+ status = -1;
+ break;
+ }
+}
+
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes)
+{
+ unsigned char channel_status[24]={0};
+ struct snd_aes_iec958 iec958;
+ const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
+ struct mixer_ctl *ctl;
+ int i=0;
+#ifdef HDMI_PASSTHROUGH_ENABLED
+ if (audio_extn_is_dolby_format(out->format) &&
+ /*TODO:Extend code to support DTS passthrough*/
+ /*set compressed channel status bits*/
+ audio_extn_dolby_is_passthrough_stream(out->flags)){
+ get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
+ } else
+#endif
+ {
+ /*set channel status bit for LPCM*/
+ get_lpcm_channel_status(out->sample_rate, channel_status);
+ }
+
+ memcpy(iec958.status, channel_status,sizeof(iec958.status));
+ ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return;
+ }
+ if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
+ ALOGE("%s: Could not set channel status for ext HDMI ",
+ __func__);
+ return;
+ }
+
+}
+#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7c83168..b98d71b 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -165,7 +165,8 @@
const char * const use_case_table[AUDIO_USECASE_MAX] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
- [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
+ [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
+ [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
#ifdef MULTIPLE_OFFLOAD_ENABLED
[USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
@@ -453,10 +454,10 @@
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
audio_extn_utils_send_audio_calibration(adev, usecase);
- audio_extn_utils_send_app_type_cfg(usecase);
+ audio_extn_utils_send_app_type_cfg(adev, usecase);
strcpy(mixer_path, use_case_table[usecase->id]);
- platform_add_backend_name(mixer_path, snd_device);
- ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
+ platform_add_backend_name(mixer_path, snd_device, usecase);
+ ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
audio_route_apply_and_update_path(adev->audio_route, mixer_path);
ALOGV("%s: exit", __func__);
return 0;
@@ -477,8 +478,8 @@
else
snd_device = usecase->out_snd_device;
strcpy(mixer_path, use_case_table[usecase->id]);
- platform_add_backend_name(mixer_path, snd_device);
- ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
+ platform_add_backend_name(mixer_path, snd_device, usecase);
+ ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
audio_route_reset_and_update_path(adev->audio_route, mixer_path);
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
@@ -521,8 +522,10 @@
audio_extn_usb_start_capture(adev);
if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
- snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
- audio_extn_spkr_prot_is_enabled()) {
+ snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
+ snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
+ snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
+ audio_extn_spkr_prot_is_enabled()) {
if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
adev->snd_dev_ref_cnt[snd_device]--;
return -EINVAL;
@@ -534,8 +537,7 @@
return -EINVAL;
}
} else {
- ALOGV("%s: snd_device(%d: %s)", __func__,
- snd_device, device_name);
+ ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
/* due to the possibility of calibration overwrite between listen
and audio, notify listen hal before audio calibration is sent */
audio_extn_sound_trigger_update_device_status(snd_device,
@@ -579,8 +581,7 @@
}
if (adev->snd_dev_ref_cnt[snd_device] == 0) {
- ALOGV("%s: snd_device(%d: %s)", __func__,
- snd_device, device_name);
+ ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
/* exit usb play back thread */
if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
@@ -591,13 +592,18 @@
audio_extn_usb_stop_capture();
if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
- snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
- audio_extn_spkr_prot_is_enabled()) {
+ snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
+ snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
+ snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
+ audio_extn_spkr_prot_is_enabled()) {
audio_extn_spkr_prot_stop_processing(snd_device);
} else {
audio_route_reset_and_update_path(adev->audio_route, device_name);
}
+ if (snd_device == SND_DEVICE_OUT_HDMI)
+ adev->is_channel_status_set = false;
+
audio_extn_dev_arbi_release(snd_device);
audio_extn_sound_trigger_update_device_status(snd_device,
ST_EVENT_SND_DEVICE_FREE);
@@ -1155,9 +1161,20 @@
}
break;
}
+
+ ALOGV("%s: pcm_prepare", __func__);
+ ret = pcm_prepare(in->pcm);
+ if (ret < 0) {
+ ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+ pcm_close(in->pcm);
+ in->pcm = NULL;
+ goto error_open;
+ }
+
audio_extn_perf_lock_release();
- ALOGV("%s: exit", __func__);
+ ALOGD("%s: exit", __func__);
+
return ret;
error_open:
@@ -1166,11 +1183,30 @@
error_config:
adev->active_input = NULL;
+ /*
+ * sleep 50ms to allow sufficient time for kernel
+ * drivers to recover incases like SSR.
+ */
+ usleep(50000);
ALOGD("%s: exit: status(%d)", __func__, ret);
return ret;
}
+void lock_input_stream(struct stream_in *in)
+{
+ pthread_mutex_lock(&in->pre_lock);
+ pthread_mutex_lock(&in->lock);
+ pthread_mutex_unlock(&in->pre_lock);
+}
+
+void lock_output_stream(struct stream_out *out)
+{
+ pthread_mutex_lock(&out->pre_lock);
+ pthread_mutex_lock(&out->lock);
+ pthread_mutex_unlock(&out->pre_lock);
+}
+
/* must be called with out->lock locked */
static int send_offload_cmd_l(struct stream_out* out, int command)
{
@@ -1259,7 +1295,7 @@
prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
for (;;) {
struct offload_cmd *cmd = NULL;
stream_callback_event_t event;
@@ -1318,6 +1354,10 @@
ALOGE("%s: Next track returned error %d",__func__, ret);
if (ret != -ENETRESET) {
send_callback = true;
+ pthread_mutex_lock(&out->lock);
+ out->send_new_metadata = 1;
+ out->send_next_track_params = true;
+ pthread_mutex_unlock(&out->lock);
event = STREAM_CBK_EVENT_DRAIN_READY;
ALOGV("copl(%p):send drain callback, ret %d", out, ret);
} else
@@ -1334,10 +1374,10 @@
ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
break;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
- if (send_callback) {
+ if (send_callback && out->offload_callback) {
ALOGVV("%s: sending offload_callback event %d", __func__, event);
out->offload_callback(event, NULL, out->offload_cookie);
}
@@ -1366,7 +1406,7 @@
static int destroy_offload_callback_thread(struct stream_out *out)
{
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
@@ -1625,8 +1665,20 @@
}
break;
}
+
platform_set_stream_channel_map(adev->platform, out->channel_mask,
out->pcm_device_id);
+
+ ALOGV("%s: pcm_prepare", __func__);
+ if (pcm_is_ready(out->pcm)) {
+ ret = pcm_prepare(out->pcm);
+ if (ret < 0) {
+ ALOGE("%s: pcm_prepare returned %d", __func__, ret);
+ pcm_close(out->pcm);
+ out->pcm = NULL;
+ goto error_open;
+ }
+ }
} else {
platform_set_stream_channel_map(adev->platform, out->channel_mask,
out->pcm_device_id);
@@ -1641,6 +1693,9 @@
ret = -EIO;
goto error_open;
}
+ /* compress_open sends params of the track, so reset the flag here */
+ out->is_compr_metadata_avail = false;
+
if (out->offload_callback)
compress_nonblock(out->compr, out->non_blocking);
@@ -1669,11 +1724,18 @@
audio_extn_check_and_set_dts_hpx_state(adev);
}
}
- ALOGV("%s: exit", __func__);
+
+ ALOGD("%s: exit", __func__);
+
return 0;
error_open:
stop_output_stream(out);
error_config:
+ /*
+ * sleep 50ms to allow sufficient time for kernel
+ * drivers to recover incases like SSR.
+ */
+ usleep(50000);
return ret;
}
@@ -1803,8 +1865,11 @@
return 0;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (!out->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, out->handle);
+
pthread_mutex_lock(&adev->lock);
out->standby = true;
if (!is_offload_usecase(out->usecase)) {
@@ -1815,6 +1880,8 @@
} else {
ALOGD("copl(%p):standby", out);
stop_compressed_output_l(out);
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
out->gapless_mdata.encoder_delay = 0;
out->gapless_mdata.encoder_padding = 0;
if (out->compr != NULL) {
@@ -1840,7 +1907,6 @@
{
int ret = 0;
char value[32];
- bool is_meta_data_params = false;
if (!out || !parms) {
ALOGE("%s: return invalid ",__func__);
@@ -1849,31 +1915,15 @@
ret = audio_extn_parse_compress_metadata(out, parms);
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
- ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
- if(ret >= 0)
- is_meta_data_params = true;
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- is_meta_data_params = true;
out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- is_meta_data_params = true;
out->gapless_mdata.encoder_padding = atoi(value);
}
- if(!is_meta_data_params) {
- ALOGV("%s: Not gapless meta data params", __func__);
- return 0;
- }
- out->send_new_metadata = 1;
ALOGV("%s new encoder delay %u and padding %u", __func__,
out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
@@ -1904,7 +1954,7 @@
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
if (err >= 0) {
val = atoi(value);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
pthread_mutex_lock(&adev->lock);
/*
@@ -1968,7 +2018,7 @@
pthread_mutex_unlock(&adev->lock);
}
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
parse_compress_metadata(out, parms);
audio_extn_dts_create_state_notifier_node(out->usecase);
@@ -2124,7 +2174,7 @@
int snd_scard_state = get_snd_card_state(adev);
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
// increase written size during SSR to avoid mismatch
@@ -2157,6 +2207,13 @@
out->standby = true;
goto exit;
}
+ if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
+ adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
+ }
+
+ if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+ audio_utils_set_hdmi_channel_status(out, buffer, bytes);
+ adev->is_channel_status_set = true;
}
if (is_offload_usecase(out->usecase)) {
@@ -2165,6 +2222,12 @@
ALOGD("copl(%p):send new gapless metadata", out);
compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
out->send_new_metadata = 0;
+ if (out->send_next_track_params && out->is_compr_metadata_avail) {
+ ALOGD("copl(%p):send next track params in gapless", out);
+ compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
+ }
}
ret = compress_write(out->compr, buffer, bytes);
@@ -2197,15 +2260,24 @@
if (out->pcm) {
if (out->muted)
memset((void *)buffer, 0, bytes);
+
ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, out->handle);
+
if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
else
ret = pcm_write(out->pcm, (void *)buffer, bytes);
+
if (ret < 0)
ret = -errno;
else if (ret == 0)
out->written += bytes / (out->config.channels * sizeof(short));
+
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, out->handle);
}
}
@@ -2247,7 +2319,7 @@
*dsp_frames = 0;
if (is_offload_usecase(out->usecase)) {
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL) {
ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
&out->sample_rate);
@@ -2306,7 +2378,7 @@
int ret = -1;
unsigned long dsp_frames;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (is_offload_usecase(out->usecase)) {
if (out->compr != NULL) {
@@ -2358,7 +2430,7 @@
struct stream_out *out = (struct stream_out *)stream;
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_callback = callback;
out->offload_cookie = cookie;
pthread_mutex_unlock(&out->lock);
@@ -2372,7 +2444,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):pause compress driver", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2400,7 +2472,7 @@
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):resume compress driver", out);
status = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2425,7 +2497,7 @@
int status = -ENOSYS;
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (type == AUDIO_DRAIN_EARLY_NOTIFY)
status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
else
@@ -2441,7 +2513,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):calling compress flush", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
pthread_mutex_unlock(&out->lock);
ALOGD("copl(%p):out of compress flush", out);
@@ -2513,7 +2585,7 @@
return status;
}
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (!in->standby && in->is_st_session) {
ALOGD("%s: sound trigger pcm stop lab", __func__);
audio_extn_sound_trigger_stop_lab(in);
@@ -2521,6 +2593,9 @@
}
if (!in->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
+
pthread_mutex_lock(&adev->lock);
in->standby = true;
if (in->pcm) {
@@ -2555,7 +2630,7 @@
if (!parms)
goto error;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&adev->lock);
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
@@ -2639,7 +2714,7 @@
int i, ret = -1;
int snd_scard_state = get_snd_card_state(adev);
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (in->is_st_session) {
ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
@@ -2666,8 +2741,13 @@
goto exit;
}
in->standby = 0;
+ if (adev->adm_register_input_stream)
+ adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
}
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, in->capture_handle);
+
if (in->pcm) {
if (audio_extn_ssr_get_enabled() &&
audio_channel_count_from_in_mask(in->channel_mask) == 6)
@@ -2682,6 +2762,9 @@
ret = -errno;
}
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
+
/*
* Instead of writing zeroes here, we could trust the hardware
* to always provide zeroes when muted.
@@ -2731,7 +2814,7 @@
if (status != 0)
return status;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&in->dev->lock);
if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
in->enable_aec != enable &&
@@ -2799,6 +2882,7 @@
}
pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
if (devices == AUDIO_DEVICE_NONE)
@@ -2895,6 +2979,12 @@
} else {
ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
out->usecase = get_offload_usecase(adev);
+
+ out->stream.set_callback = out_set_callback;
+ out->stream.pause = out_pause;
+ out->stream.resume = out_resume;
+ out->stream.drain = out_drain;
+ out->stream.flush = out_flush;
}
if (config->offload_info.channel_mask)
out->channel_mask = config->offload_info.channel_mask;
@@ -2905,11 +2995,6 @@
format = out->format = config->offload_info.format;
out->sample_rate = config->offload_info.sample_rate;
- out->stream.set_callback = out_set_callback;
- out->stream.pause = out_pause;
- out->stream.resume = out_resume;
- out->stream.drain = out_drain;
- out->stream.flush = out_flush;
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
if (audio_extn_is_dolby_format(config->offload_info.format))
@@ -2974,6 +3059,8 @@
}
out->send_new_metadata = 1;
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
@@ -3014,6 +3101,10 @@
out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
out->config = pcm_config_afe_proxy_playback;
adev->voice_tx_output = out;
+ } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
+ out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
+ out->config = pcm_config_low_latency;
+ out->sample_rate = out->config.rate;
} else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
format = AUDIO_FORMAT_PCM_16_BIT;
out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
@@ -3390,6 +3481,7 @@
if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
voice_is_in_call(adev)) {
voice_stop_call(adev);
+ platform_set_gsm_mode(adev->platform, false);
adev->current_call_output = NULL;
}
}
@@ -3455,6 +3547,7 @@
devices, &in->stream, handle, source);
pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
@@ -3478,6 +3571,7 @@
in->standby = 1;
in->channel_mask = config->channel_mask;
in->capture_handle = handle;
+ in->flags = flags;
/* Update config params with the requested sample rate and channels */
in->usecase = USECASE_AUDIO_RECORD;
@@ -3620,10 +3714,13 @@
audio_route_free(adev->audio_route);
free(adev->snd_dev_ref_cnt);
platform_deinit(adev->platform);
+ if (adev->adm_deinit)
+ adev->adm_deinit(adev->adm_data);
free(device);
adev = NULL;
}
pthread_mutex_unlock(&adev_init_lock);
+
return 0;
}
@@ -3635,6 +3732,7 @@
{
switch (period_size) {
case 160:
+ case 192:
case 240:
case 320:
case 480:
@@ -3707,6 +3805,7 @@
list_init(&adev->usecase_list);
adev->cur_wfd_channels = 2;
adev->offload_usecases_state = 0;
+ adev->is_channel_status_set = false;
pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
@@ -3757,6 +3856,36 @@
adev->offload_effects_set_hpx_state =
(int (*)(bool))dlsym(adev->offload_effects_lib,
"offload_effects_bundle_set_hpx_state");
+ adev->offload_effects_get_parameters =
+ (void (*)(struct str_parms *, struct str_parms *))
+ dlsym(adev->offload_effects_lib,
+ "offload_effects_bundle_get_parameters");
+ adev->offload_effects_set_parameters =
+ (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
+ "offload_effects_bundle_set_parameters");
+ }
+ }
+
+ if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
+ adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
+ if (adev->adm_lib == NULL) {
+ ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
+ } else {
+ ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
+ adev->adm_init = (adm_init_t)
+ dlsym(adev->adm_lib, "adm_init");
+ adev->adm_deinit = (adm_deinit_t)
+ dlsym(adev->adm_lib, "adm_deinit");
+ adev->adm_register_input_stream = (adm_register_input_stream_t)
+ dlsym(adev->adm_lib, "adm_register_input_stream");
+ adev->adm_register_output_stream = (adm_register_output_stream_t)
+ dlsym(adev->adm_lib, "adm_register_output_stream");
+ adev->adm_deregister_stream = (adm_deregister_stream_t)
+ dlsym(adev->adm_lib, "adm_deregister_stream");
+ adev->adm_request_focus = (adm_request_focus_t)
+ dlsym(adev->adm_lib, "adm_request_focus");
+ adev->adm_abandon_focus = (adm_abandon_focus_t)
+ dlsym(adev->adm_lib, "adm_abandon_focus");
}
}
@@ -3790,6 +3919,9 @@
pthread_mutex_unlock(&adev_init_lock);
+ if (adev->adm_init)
+ adev->adm_data = adev->adm_init();
+
ALOGV("%s: exit", __func__);
return 0;
}
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index c2f37d4..dc0970f 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -50,6 +50,7 @@
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
+#define ADM_LIBRARY_PATH "/system/vendor/lib/libadm.so"
/* Flags used to initialize acdb_settings variable that goes to ACDB library */
#define NONE_FLAG 0x00000000
@@ -94,6 +95,7 @@
USECASE_AUDIO_PLAYBACK_OFFLOAD8,
USECASE_AUDIO_PLAYBACK_OFFLOAD9,
#endif
+ USECASE_AUDIO_PLAYBACK_ULL,
USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
@@ -182,6 +184,7 @@
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
pthread_cond_t cond;
struct pcm_config config;
struct compr_config compr_config;
@@ -216,6 +219,8 @@
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
+ bool send_next_track_params;
+ bool is_compr_metadata_avail;
unsigned int bit_width;
struct audio_device *dev;
@@ -224,6 +229,7 @@
struct stream_in {
struct audio_stream_in stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
struct pcm_config config;
struct pcm *pcm;
int standby;
@@ -236,6 +242,7 @@
bool enable_ns;
audio_format_t format;
audio_io_handle_t capture_handle;
+ audio_input_flags_t flags;
bool is_st_session;
bool is_st_session_active;
@@ -288,6 +295,14 @@
struct stream_app_type_cfg app_type_cfg;
};
+typedef void* (*adm_init_t)();
+typedef void (*adm_deinit_t)(void *);
+typedef void (*adm_register_output_stream_t)(void *, audio_io_handle_t, audio_output_flags_t);
+typedef void (*adm_register_input_stream_t)(void *, audio_io_handle_t, audio_input_flags_t);
+typedef void (*adm_deregister_stream_t)(void *, audio_io_handle_t);
+typedef void (*adm_request_focus_t)(void *, audio_io_handle_t);
+typedef void (*adm_abandon_focus_t)(void *, audio_io_handle_t);
+
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -314,6 +329,7 @@
int snd_card;
unsigned int cur_codec_backend_samplerate;
unsigned int cur_codec_backend_bit_width;
+ bool is_channel_status_set;
void *platform;
unsigned int offload_usecases_state;
void *visualizer_lib;
@@ -325,6 +341,20 @@
struct sound_card_status snd_card_status;
int (*offload_effects_set_hpx_state)(bool);
+
+ void *adm_data;
+ void *adm_lib;
+ adm_init_t adm_init;
+ adm_deinit_t adm_deinit;
+ adm_register_input_stream_t adm_register_input_stream;
+ adm_register_output_stream_t adm_register_output_stream;
+ adm_deregister_stream_t adm_deregister_stream;
+ adm_request_focus_t adm_request_focus;
+ adm_abandon_focus_t adm_abandon_focus;
+
+ void (*offload_effects_get_parameters)(struct str_parms *,
+ struct str_parms *);
+ void (*offload_effects_set_parameters)(struct str_parms *);
};
int select_devices(struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 293b1c6..b5f56c1 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -133,6 +133,7 @@
char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
[WCD9XXX_ANC_CAL] = "anc_cal",
[WCD9XXX_MBHC_CAL] = "mbhc_cal",
+ [WCD9XXX_VBAT_CAL] = "vbat_cal",
};
#define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
@@ -184,6 +185,7 @@
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
typedef int (*acdb_send_common_top_t) (void);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -216,6 +218,9 @@
bool ec_ref_enabled;
bool is_wsa_speaker;
bool is_acdb_initialized;
+ /* Vbat monitor related flags */
+ bool is_vbat_speaker;
+ bool gsm_mode_enabled;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -228,6 +233,7 @@
acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
acdb_get_default_app_type_t acdb_get_default_app_type;
acdb_send_common_top_t acdb_send_common_top;
+ acdb_set_codec_data_t acdb_set_codec_data;
#ifdef RECORD_PLAY_CONCURRENCY
bool rec_play_conc_set;
#endif
@@ -241,11 +247,17 @@
static bool is_external_codec = false;
static const int pcm_device_table_of_ext_codec[AUDIO_USECASE_MAX][2] = {
- [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC, QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC}
+ [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC, QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC},
+ [USECASE_VOICEMMODE1_CALL] = {VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC,
+ VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC},
+ [USECASE_VOICEMMODE2_CALL] = {VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC,
+ VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC},
};
/* List of use cases that has different PCM device ID's for internal and external codecs */
-static const int misc_usecase[AUDIO_USECASE_MAX] = { USECASE_QCHAT_CALL };
+static const int misc_usecase[AUDIO_USECASE_MAX] = {USECASE_QCHAT_CALL,
+ USECASE_VOICEMMODE1_CALL,
+ USECASE_VOICEMMODE2_CALL};
int pcm_device_table[AUDIO_USECASE_MAX][2] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
@@ -286,6 +298,10 @@
[USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
[USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
[USECASE_VOWLAN_CALL] = {VOWLAN_CALL_PCM_DEVICE, VOWLAN_CALL_PCM_DEVICE},
+ [USECASE_VOICEMMODE1_CALL] = {VOICEMMODE1_CALL_PCM_DEVICE,
+ VOICEMMODE1_CALL_PCM_DEVICE},
+ [USECASE_VOICEMMODE2_CALL] = {VOICEMMODE2_CALL_PCM_DEVICE,
+ VOICEMMODE2_CALL_PCM_DEVICE},
[USECASE_COMPRESS_VOIP_CALL] = {COMPRESS_VOIP_CALL_PCM_DEVICE, COMPRESS_VOIP_CALL_PCM_DEVICE},
[USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
AUDIO_RECORD_PCM_DEVICE},
@@ -320,6 +336,7 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = "speaker-ext-1",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
[SND_DEVICE_OUT_SPEAKER_WSA] = "wsa-speaker",
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = "vbat-speaker",
[SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
[SND_DEVICE_OUT_HEADPHONES] = "headphones",
[SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
@@ -329,6 +346,7 @@
[SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
[SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = "wsa-voice-speaker",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = "vbat-voice-speaker",
[SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
@@ -350,6 +368,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = "speaker-protected-vbat",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = "voice-speaker-protected-vbat",
#ifdef RECORD_PLAY_CONCURRENCY
[SND_DEVICE_OUT_VOIP_HANDSET] = "voip-handset",
[SND_DEVICE_OUT_VOIP_SPEAKER] = "voip-speaker",
@@ -425,6 +445,7 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 14,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 14,
[SND_DEVICE_OUT_SPEAKER_WSA] = 135,
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = 135,
[SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
[SND_DEVICE_OUT_HEADPHONES] = 10,
[SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
@@ -434,6 +455,7 @@
[SND_DEVICE_OUT_VOICE_HANDSET] = 7,
[SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = 135,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = 135,
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
@@ -455,6 +477,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = 103,
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = 124,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = 101,
#ifdef RECORD_PLAY_CONCURRENCY
[SND_DEVICE_OUT_VOIP_HANDSET] = 133,
[SND_DEVICE_OUT_VOIP_SPEAKER] = 132,
@@ -532,6 +556,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
@@ -541,6 +566,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_WSA)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
@@ -562,6 +588,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT)},
#ifdef RECORD_PLAY_CONCURRENCY
{TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_SPEAKER)},
@@ -649,6 +677,8 @@
{TO_NAME_INDEX(USECASE_VOLTE_CALL)},
{TO_NAME_INDEX(USECASE_QCHAT_CALL)},
{TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
+ {TO_NAME_INDEX(USECASE_VOICEMMODE1_CALL)},
+ {TO_NAME_INDEX(USECASE_VOICEMMODE2_CALL)},
{TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
{TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
{TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
@@ -735,7 +765,7 @@
if (!strncmp(snd_card_name, "msm8939-tapan-snd-card",
sizeof("msm8939-tapan-snd-card")) ||
!strncmp(snd_card_name, "msm8939-tapan9302-snd-card",
- sizeof("msm8939-tapan9302-snd-card"))||
+ sizeof("msm8939-tapan9302-snd-card")) ||
!strncmp(snd_card_name, "msm8939-tomtom9330-snd-card",
sizeof("msm8939-tomtom9330-snd-card")) ||
!strncmp(snd_card_name, "msm8952-tomtom-snd-card",
@@ -866,7 +896,7 @@
msm_be_id_array_len =
sizeof(msm_device_to_be_id_external_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
} else if (!strncmp(snd_card_name, "msm8952-snd-card-mtp",
- sizeof("msm8952-snd-card-mtpmsm8952-snd-card-mtp"))) {
+ sizeof("msm8952-snd-card-mtp"))) {
strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
sizeof(MIXER_XML_PATH_MTP));
msm_device_to_be_id = msm_device_to_be_id_internal_codec;
@@ -898,6 +928,24 @@
}
}
+void platform_set_gsm_mode(void *platform, bool enable)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ if (my_data->gsm_mode_enabled) {
+ my_data->gsm_mode_enabled = false;
+ ALOGV("%s: disabling gsm mode", __func__);
+ audio_route_reset_and_update_path(adev->audio_route, "gsm-mode");
+ }
+
+ if (enable) {
+ my_data->gsm_mode_enabled = true;
+ ALOGD("%s: enabling gsm mode", __func__);
+ audio_route_apply_and_update_path(adev->audio_route, "gsm-mode");
+ }
+}
+
void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)adev->platform;
@@ -908,20 +956,27 @@
if (strcmp(my_data->ec_ref_mixer_path, "")) {
ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
- audio_route_reset_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
+ audio_route_reset_and_update_path(adev->audio_route,
+ my_data->ec_ref_mixer_path);
}
if (enable) {
- strlcpy(my_data->ec_ref_mixer_path, "echo-reference", sizeof(my_data->ec_ref_mixer_path));
snd_device = platform_get_output_snd_device(adev->platform, &out);
+
/*
* If native audio device reference count > 0, then apply codec EC otherwise
- * fallback to headphones if so or default
+ * fallback to Speakers with VBat if enabled or default
*/
if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
- platform_add_backend_name(my_data->ec_ref_mixer_path, SND_DEVICE_OUT_HEADPHONES_44_1);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference headphones-44.1",
+ sizeof(my_data->ec_ref_mixer_path));
+ else if ((snd_device == SND_DEVICE_OUT_SPEAKER_VBAT) ||
+ (snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT))
+ strlcpy(my_data->ec_ref_mixer_path, "vbat-speaker echo-reference",
+ sizeof(my_data->ec_ref_mixer_path));
else
- platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
+ sizeof(my_data->ec_ref_mixer_path));
ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
audio_route_apply_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
@@ -1103,6 +1158,7 @@
backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+ backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("vbat-voice-speaker");
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1158,7 +1214,38 @@
void *buff;
};
-static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static int send_vbat_adc_data_to_acdb(struct platform_data *plat_data, char *cal_type)
+{
+ int ret = 0;
+ struct mixer_ctl *ctl;
+ uint16_t vbat_adc_data[2];
+ struct platform_data *my_data = plat_data;
+ struct audio_device *adev = my_data->adev;
+
+ const char *mixer_ctl_name = "Vbat ADC data";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer ctl name - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ vbat_adc_data[0] = mixer_ctl_get_value(ctl, 0);
+ vbat_adc_data[1] = mixer_ctl_get_value(ctl, 1);
+
+ ALOGD("%s: Vbat ADC output values: Dcp1: %d , Dcp2: %d",
+ __func__, vbat_adc_data[0], vbat_adc_data[1]);
+
+ ret = my_data->acdb_set_codec_data(&vbat_adc_data[0], cal_type);
+
+done:
+ return ret;
+}
+
+static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration,
+ struct platform_data *plat_data, int fd)
{
int ret = 0, type;
@@ -1170,6 +1257,12 @@
if (type == WCD9XXX_MAD_CAL)
continue;
+ if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+ ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
+ if (ret < 0)
+ ALOGE("%s error in sending vbat adc data to acdb", __func__);
+ }
+
calib.get_size = 1;
ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
&calib);
@@ -1223,7 +1316,7 @@
dlerror());
return;
}
- if (send_codec_cal(acdb_loader_get_calibration, fd) < 0)
+ if (send_codec_cal(acdb_loader_get_calibration, plat_data, fd) < 0)
ALOGE("%s: Could not send anc cal", __FUNCTION__);
}
@@ -1410,6 +1503,12 @@
acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 131;
}
+ /* Check if Vbat speaker enabled property is set, this should be done before acdb init */
+ bool ret = false;
+ ret = audio_extn_can_use_vbat();
+ if (ret)
+ my_data->is_vbat_speaker = true;
+
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1466,6 +1565,14 @@
ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
+ my_data->acdb_handle,
+ "acdb_loader_set_codec_data");
+ if (!my_data->acdb_set_codec_data)
+ ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+ __func__, LIB_ACDB_LOADER);
+
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
if (my_data->acdb_init == NULL) {
@@ -1517,7 +1624,6 @@
audio_extn_dap_hal_init(adev->snd_card);
audio_extn_dolby_set_license(adev);
- audio_hwdep_send_cal(my_data);
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -1542,6 +1648,26 @@
my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_5_RX SampleRate");
+
+ if (platform_get_native_support()) {
+
+ if (!strncmp(snd_card_name, "msm8976-tasha-snd-card",
+ sizeof("msm8976-tasha-snd-card")) ||
+ !strncmp(snd_card_name, "msm8976-tashalite-snd-card",
+ sizeof("msm8976-tashalite-snd-card"))) {
+ /* do nothing */
+ }
+ else {
+ platform_set_native_support(false);
+ }
+ }
+
+ ALOGD("native: native audio: %s for sound card %s",
+ (platform_get_native_support() ? "enabled" : "disabled"),
+ snd_card_name);
+
+
+
my_data->edid_info = NULL;
return my_data;
}
@@ -1625,13 +1751,20 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase)
{
if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
return;
}
+ if((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ !(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
+ ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
+ return;
+ }
+
const char * suffix = backend_table[snd_device];
if (suffix != NULL) {
@@ -1824,7 +1957,7 @@
{
na_props.platform_na_prop_enabled = na_props.ui_na_prop_enabled
= codec_support;
- ALOGD("%s: na_props.platform_na_prop_enabled: %d", __func__,
+ ALOGV("%s: na_props.platform_na_prop_enabled: %d", __func__,
na_props.platform_na_prop_enabled);
return 0;
}
@@ -1995,10 +2128,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2055,10 +2192,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2320,7 +2461,9 @@
else
snd_device = SND_DEVICE_OUT_BT_SCO;
} else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
- if (my_data->is_wsa_speaker)
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WSA;
else
snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
@@ -2381,7 +2524,9 @@
snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
else
{
- if (my_data->is_wsa_speaker)
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
snd_device = SND_DEVICE_OUT_SPEAKER_WSA;
else
snd_device = SND_DEVICE_OUT_SPEAKER;
@@ -3433,6 +3578,8 @@
* USECASE_VOLTE_CALL:
* USECASE_QCHAT_CALL:
* USECASE_VOWLAN_CALL:
+ * USECASE_VOICEMMODE1_CALL:
+ * USECASE_VOICEMMODE2_CALL:
* USECASE_COMPRESS_VOIP_CALL:
* USECASE_AUDIO_RECORD_FM_VIRTUAL:
* USECASE_INCALL_REC_UPLINK:
@@ -3495,6 +3642,8 @@
* USECASE_VOLTE_CALL:
* USECASE_QCHAT_CALL:
* USECASE_VOWLAN_CALL:
+ * USECASE_VOICEMMODE1_CALL:
+ * USECASE_VOICEMMODE2_CALL:
* USECASE_COMPRESS_VOIP_CALL:
* USECASE_AUDIO_RECORD_FM_VIRTUAL:
* USECASE_INCALL_REC_UPLINK:
@@ -4041,15 +4190,12 @@
}
edid_data[0] = count;
memcpy(&edid_data[1], block, count);
-
-#ifdef AUDIO_FEATURE_ENABLED_HDMI_EDID
if (!edid_get_sink_caps(info, edid_data)) {
ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
goto fail;
}
my_data->edid_valid = true;
return 0;
-#endif
fail:
if (my_data->edid_info) {
free(my_data->edid_info);
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9710147..a5b97ac 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -72,6 +72,7 @@
SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
SND_DEVICE_OUT_SPEAKER_REVERSE,
SND_DEVICE_OUT_SPEAKER_WSA,
+ SND_DEVICE_OUT_SPEAKER_VBAT,
SND_DEVICE_OUT_HEADPHONES,
SND_DEVICE_OUT_HEADPHONES_44_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
@@ -80,6 +81,7 @@
SND_DEVICE_OUT_VOICE_HANDSET,
SND_DEVICE_OUT_VOICE_SPEAKER,
SND_DEVICE_OUT_VOICE_SPEAKER_WSA,
+ SND_DEVICE_OUT_VOICE_SPEAKER_VBAT,
SND_DEVICE_OUT_VOICE_HEADPHONES,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
@@ -101,6 +103,8 @@
SND_DEVICE_OUT_ANC_HANDSET,
SND_DEVICE_OUT_SPEAKER_PROTECTED,
SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+ SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
+ SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
#ifdef RECORD_PLAY_CONCURRENCY
SND_DEVICE_OUT_VOIP_HANDSET,
SND_DEVICE_OUT_VOIP_SPEAKER,
@@ -260,6 +264,12 @@
#define QCHAT_CALL_PCM_DEVICE_OF_EXT_CODEC 28
#define VOWLAN_CALL_PCM_DEVICE 16
+#define VOICEMMODE1_CALL_PCM_DEVICE 26
+#define VOICEMMODE2_CALL_PCM_DEVICE 27
+
+#define VOICEMMODE1_CALL_PCM_DEVICE_OF_EXT_CODEC 29
+#define VOICEMMODE2_CALL_PCM_DEVICE_OF_EXT_CODEC 30
+
#define AFE_PROXY_PLAYBACK_PCM_DEVICE 7
#define AFE_PROXY_RECORD_PCM_DEVICE 8
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 6d2d478..b72cae9 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -373,7 +373,8 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase)
{
if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index aba47fd..723bf5b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -130,6 +130,7 @@
char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
[WCD9XXX_ANC_CAL] = "anc_cal",
[WCD9XXX_MBHC_CAL] = "mbhc_cal",
+ [WCD9XXX_VBAT_CAL] = "vbat_cal",
};
#define AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED "is_hw_dec_session_allowed"
@@ -186,6 +187,7 @@
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
typedef int (*acdb_send_common_top_t) (void);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -218,6 +220,9 @@
bool ec_ref_enabled;
bool is_i2s_ext_modem;
bool is_acdb_initialized;
+ /* Vbat monitor related flags */
+ bool is_vbat_speaker;
+ bool gsm_mode_enabled;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -230,6 +235,7 @@
acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
acdb_get_default_app_type_t acdb_get_default_app_type;
acdb_send_common_top_t acdb_send_common_top;
+ acdb_set_codec_data_t acdb_set_codec_data;
void *hw_info;
acdb_send_gain_dep_cal_t acdb_send_gain_dep_cal;
@@ -245,8 +251,10 @@
DEEP_BUFFER_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
+ MULTIMEDIA3_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE,
- MULTIMEDIA2_PCM_DEVICE},
+ MULTIMEDIA2_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_OFFLOAD] =
{PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE},
#ifdef MULTIPLE_OFFLOAD_ENABLED
@@ -324,6 +332,7 @@
[SND_DEVICE_OUT_SPEAKER] = "speaker",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = "speaker-ext-1",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = "speaker-vbat",
[SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
[SND_DEVICE_OUT_HEADPHONES] = "headphones",
[SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
@@ -332,6 +341,7 @@
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = "speaker-and-headphones-ext-2",
[SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
[SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = "voice-speaker-vbat",
[SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
@@ -353,6 +363,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = "speaker-protected-vbat",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = "voice-speaker-protected-vbat",
/* Capture sound devices */
[SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -422,6 +434,7 @@
[SND_DEVICE_OUT_SPEAKER] = 14,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 130,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = 14,
[SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
[SND_DEVICE_OUT_HEADPHONES] = 10,
[SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
@@ -430,6 +443,7 @@
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
[SND_DEVICE_OUT_VOICE_HANDSET] = 7,
[SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = 14,
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
@@ -451,6 +465,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = 103,
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = 124,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = 101,
[SND_DEVICE_IN_HANDSET_MIC] = 4,
[SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = 4,
@@ -522,6 +538,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
@@ -530,6 +547,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
@@ -550,6 +568,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_EXTERNAL)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)},
@@ -610,6 +630,7 @@
static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
#ifdef MULTIPLE_OFFLOAD_ENABLED
@@ -780,7 +801,26 @@
return ret_val;
}
-void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
+void platform_set_gsm_mode(void *platform, bool enable)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ if (my_data->gsm_mode_enabled) {
+ my_data->gsm_mode_enabled = false;
+ ALOGV("%s: disabling gsm mode", __func__);
+ audio_route_reset_and_update_path(adev->audio_route, "gsm-mode");
+ }
+
+ if (enable) {
+ my_data->gsm_mode_enabled = true;
+ ALOGD("%s: enabling gsm mode", __func__);
+ audio_route_apply_and_update_path(adev->audio_route, "gsm-mode");
+ }
+}
+
+void platform_set_echo_reference(struct audio_device *adev, bool enable,
+ audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)adev->platform;
snd_device_t snd_device = SND_DEVICE_NONE;
@@ -790,20 +830,27 @@
if (strcmp(my_data->ec_ref_mixer_path, "")) {
ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
- audio_route_reset_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
+ audio_route_reset_and_update_path(adev->audio_route,
+ my_data->ec_ref_mixer_path);
}
if (enable) {
- strlcpy(my_data->ec_ref_mixer_path, "echo-reference", sizeof(my_data->ec_ref_mixer_path));
snd_device = platform_get_output_snd_device(adev->platform, &out);
+
/*
* If native audio device reference count > 0, then apply codec EC otherwise
- * fallback to headphones if so or default
+ * fallback to Speakers with VBat if enabled or default
*/
if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
- platform_add_backend_name(my_data->ec_ref_mixer_path, SND_DEVICE_OUT_HEADPHONES_44_1);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference headphones-44.1",
+ sizeof(my_data->ec_ref_mixer_path));
+ else if ((snd_device == SND_DEVICE_OUT_SPEAKER_VBAT) ||
+ (snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT))
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference speaker-vbat",
+ sizeof(my_data->ec_ref_mixer_path));
else
- platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
+ sizeof(my_data->ec_ref_mixer_path));
ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
audio_route_apply_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
@@ -1011,6 +1058,7 @@
backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
backend_table[SND_DEVICE_OUT_HEADPHONES] = strdup("headphones");
backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+ backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("voice-speaker-vbat");
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1066,7 +1114,38 @@
void *buff;
};
-static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static int send_vbat_adc_data_to_acdb(struct platform_data *plat_data, char *cal_type)
+{
+ int ret = 0;
+ struct mixer_ctl *ctl;
+ uint16_t vbat_adc_data[2];
+ struct platform_data *my_data = plat_data;
+ struct audio_device *adev = my_data->adev;
+
+ const char *mixer_ctl_name = "Vbat ADC data";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer ctl name - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ vbat_adc_data[0] = mixer_ctl_get_value(ctl, 0);
+ vbat_adc_data[1] = mixer_ctl_get_value(ctl, 1);
+
+ ALOGD("%s: Vbat ADC output values: Dcp1: %d , Dcp2: %d",
+ __func__, vbat_adc_data[0], vbat_adc_data[1]);
+
+ ret = my_data->acdb_set_codec_data(&vbat_adc_data[0], cal_type);
+
+done:
+ return ret;
+}
+
+static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration,
+ struct platform_data *plat_data, int fd)
{
int type;
@@ -1080,6 +1159,13 @@
continue;
ret = 0;
+
+ if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+ ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
+ if (ret < 0)
+ ALOGE("%s error in sending vbat adc data to acdb", __func__);
+ }
+
calib.get_size = 1;
ret = acdb_loader_get_calibration(cal_name_info[type],
sizeof(struct param_data),
@@ -1140,7 +1226,7 @@
return;
}
- send_codec_cal(acdb_loader_get_calibration, fd);
+ send_codec_cal(acdb_loader_get_calibration, plat_data, fd);
}
static int platform_acdb_init(void *platform)
@@ -1180,7 +1266,7 @@
char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
- int retry_num = 0, snd_card_num = 0, key = 0, ret = 0;
+ int retry_num = 0, snd_card_num = 0, key = 0;
const char *snd_card_name;
char *cvd_version = NULL;
char *snd_internal_name = NULL;
@@ -1212,7 +1298,12 @@
continue;
}
- snd_card_name = mixer_get_name(adev->mixer);
+ snd_card_name = strdup(mixer_get_name(adev->mixer));
+ if (!snd_card_name) {
+ ALOGE("failed to allocate memory for snd_card_name\n");
+ free(my_data);
+ return NULL;
+ }
ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
my_data->hw_info = hw_info_init(snd_card_name);
@@ -1274,6 +1365,7 @@
ALOGE("%s: Failed to init audio route controls, aborting.",
__func__);
free(my_data);
+ free(snd_card_name);
return NULL;
}
adev->snd_card = snd_card_num;
@@ -1287,6 +1379,7 @@
if (snd_card_num >= MAX_SND_CARD) {
ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
free(my_data);
+ free(snd_card_name);
return NULL;
}
@@ -1340,6 +1433,12 @@
}
}
+ /* Check if Vbat speaker enabled property is set, this should be done before acdb init */
+ bool ret = false;
+ ret = audio_extn_can_use_vbat();
+ if (ret)
+ my_data->is_vbat_speaker = true;
+
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1402,6 +1501,14 @@
ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
+ my_data->acdb_handle,
+ "acdb_loader_set_codec_data");
+ if (!my_data->acdb_set_codec_data)
+ ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+ __func__, LIB_ACDB_LOADER);
+
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
if (my_data->acdb_init == NULL) {
@@ -1448,7 +1555,6 @@
audio_extn_spkr_prot_init(adev);
audio_extn_dolby_set_license(adev);
- audio_hwdep_send_cal(my_data);
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -1472,6 +1578,7 @@
strdup("SLIM_5_RX SampleRate");
my_data->edid_info = NULL;
+ free(snd_card_name);
return my_data;
}
@@ -1554,13 +1661,20 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase)
{
if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
return;
}
+ if((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ !(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
+ ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
+ return;
+ }
+
const char * suffix = backend_table[snd_device];
if (suffix != NULL) {
@@ -1914,10 +2028,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -1974,10 +2092,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2236,7 +2358,10 @@
else
snd_device = SND_DEVICE_OUT_BT_SCO;
} else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
- snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
+ else
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
snd_device = SND_DEVICE_OUT_USB_HEADSET;
@@ -2275,6 +2400,8 @@
snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_2;
else if (adev->speaker_lr_swap)
snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
+ else if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
else
snd_device = SND_DEVICE_OUT_SPEAKER;
} else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index b8f8cee..54406b6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -69,6 +69,7 @@
SND_DEVICE_OUT_SPEAKER_EXTERNAL_1,
SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
SND_DEVICE_OUT_SPEAKER_REVERSE,
+ SND_DEVICE_OUT_SPEAKER_VBAT,
SND_DEVICE_OUT_HEADPHONES,
SND_DEVICE_OUT_HEADPHONES_44_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
@@ -76,6 +77,7 @@
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
SND_DEVICE_OUT_VOICE_HANDSET,
SND_DEVICE_OUT_VOICE_SPEAKER,
+ SND_DEVICE_OUT_VOICE_SPEAKER_VBAT,
SND_DEVICE_OUT_VOICE_HEADPHONES,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
@@ -97,6 +99,8 @@
SND_DEVICE_OUT_ANC_HANDSET,
SND_DEVICE_OUT_SPEAKER_PROTECTED,
SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+ SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
+ SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
SND_DEVICE_OUT_END,
/*
@@ -217,6 +221,7 @@
#define DEEP_BUFFER_PCM_DEVICE 0
#define AUDIO_RECORD_PCM_DEVICE 0
#define MULTIMEDIA2_PCM_DEVICE 1
+#define MULTIMEDIA3_PCM_DEVICE 4
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 516f2d7..3ab5191 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -29,7 +29,8 @@
const char *platform_get_snd_device_name(snd_device_t snd_device);
int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
char *device_name);
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device);
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase);
bool platform_send_gain_dep_cal(void *platform, int level);
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
int platform_get_snd_device_index(char *snd_device_index_name);
@@ -119,4 +120,5 @@
int platform_set_device_params(struct stream_out *out, int param, int value);
int platform_set_audio_device_interface(const char * device_name, const char *intf_name,
const char * codec_type);
+void platform_set_gsm_mode(void *platform, bool enable);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 960b46e..3cf370d 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -42,6 +42,7 @@
#define AUDIO_PARAMETER_KEY_DEVICE_MUTE "device_mute"
#define AUDIO_PARAMETER_KEY_DIRECTION "direction"
#define AUDIO_PARAMETER_KEY_IN_CALL "in_call"
+#define AUDIO_PARAMETER_KEY_CALL_TYPE "call_type"
#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
@@ -515,6 +516,20 @@
}
}
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CALL_TYPE, str_value,
+ sizeof(str_value));
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_TYPE);
+ ALOGD("%s: call type is %s",__func__,str_value);
+
+ /* Expected call types are CDMA/GSM/WCDMA/LTE/TDSDMA/WLAN/UNKNOWN */
+ if (!strncmp("GSM", str_value, sizeof("GSM"))) {
+ platform_set_gsm_mode(adev->platform, true);
+ } else {
+ platform_set_gsm_mode(adev->platform, false);
+ }
+ }
+
done:
ALOGV("%s: exit with code(%d)", __func__, ret);
free(kv_pairs);
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index d5a362a..52ed11d 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -51,6 +51,14 @@
LOCAL_CFLAGS += -DAAC_ADTS_OFFLOAD_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_SPK)),true)
+ LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
+ LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
+endif
+
LOCAL_MODULE := libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index f105e15..9fd6838 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -122,6 +122,15 @@
// handle output device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
}
@@ -129,6 +138,20 @@
// register new device as available
index = mAvailableOutputDevices.add(devDesc);
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ if (mHdmiAudioDisabled || !mHdmiAudioEvent) {
+ mAvailableOutputDevices.remove(devDesc);
+ ALOGW("HDMI sink not connected, do not route audio to HDMI out");
+ return INVALID_OPERATION;
+ }
+ }
+#endif
if (index >= 0) {
sp<HwModule> module = mHwModules.getModuleForDevice(device);
if (module == 0) {
@@ -164,6 +187,15 @@
// handle output device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
if (index < 0) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device not connected: %x", device);
return INVALID_OPERATION;
}
@@ -177,7 +209,15 @@
// remove device from available output devices
mAvailableOutputDevices.remove(devDesc);
-
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, "hdmi_spkr", 9)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
// Propagate device availability to Engine
@@ -524,9 +564,8 @@
(isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION)
&& (!isStrategyActive(mPrimaryOutput,STRATEGY_MEDIA)))) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
- } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)||
- (isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION_RESPECTFUL)
- && (!isStrategyActive(mPrimaryOutput, STRATEGY_MEDIA)))) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL) ||
+ isStrategyActive(mPrimaryOutput,STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
@@ -547,6 +586,7 @@
{
ALOGV("setPhoneState() state %d", state);
// store previous phone state for management of sonification strategy below
+ audio_devices_t newDevice = AUDIO_DEVICE_NONE;
int oldState = mEngine->getPhoneState();
if (mEngine->setPhoneState(state) != NO_ERROR) {
@@ -564,8 +604,7 @@
if (stream == AUDIO_STREAM_PATCH) {
continue;
}
-
- handleIncallSonification((audio_stream_type_t)stream, false, true, curOutput);
+ handleIncallSonification((audio_stream_type_t)stream, false, true, curOutput);
}
}
@@ -837,7 +876,14 @@
setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
}
}
-
+ //update device for all non-primary outputs
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ audio_io_handle_t output = mOutputs.keyAt(i);
+ if (output != mPrimaryOutput->mIoHandle) {
+ newDevice = getNewOutputDevice(mOutputs.valueFor(output), false /*fromCache*/);
+ setOutputDevice(mOutputs.valueFor(output), newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ }
+ }
// if entering in call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
if (isStateInCall(state)) {
@@ -848,7 +894,7 @@
if (stream == AUDIO_STREAM_PATCH) {
continue;
}
- handleIncallSonification((audio_stream_type_t)stream, true, true, curOutput);
+ handleIncallSonification((audio_stream_type_t)stream, true, true, curOutput);
}
}
}
@@ -861,6 +907,53 @@
mLimitRingtoneVolume = false;
}
}
+
+void AudioPolicyManagerCustom::setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config)
+{
+ ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
+
+ if (mEngine->setForceUse(usage, config) != NO_ERROR) {
+ ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
+ return;
+ }
+ bool forceVolumeReeval = (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_DOCK) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_SYSTEM);
+
+ // check for device and output changes triggered by new force usage
+ checkA2dpSuspend();
+ checkOutputForAllStrategies();
+ updateDevicesAndOutputs();
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+ audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
+ updateCallRouting(newDevice);
+ }
+ // Use reverse loop to make sure any low latency usecases (generally tones)
+ // are not routed before non LL usecases (generally music).
+ // We can safely assume that LL output would always have lower index,
+ // and use this work-around to avoid routing of output with music stream
+ // from the context of short lived LL output.
+ // Note: in case output's share backend(HAL sharing is implicit) all outputs
+ // gets routing update while processing first output itself.
+ for (size_t i = mOutputs.size(); i > 0; i--) {
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i-1);
+ audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/);
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || outputDesc != mPrimaryOutput) {
+ setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ }
+ if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
+ applyStreamVolumes(outputDesc, newDevice, 0, true);
+ }
+ }
+
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
+ if (activeInput != 0) {
+ setInputDevice(activeInput, getNewInputDevice(activeInput));
+ }
+
+}
+
status_t AudioPolicyManagerCustom::stopSource(sp<SwAudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate)
@@ -869,10 +962,10 @@
handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
// handle special case for sonification while in call
- if (isInCall()) {
+ if (isInCall() && (outputDesc->mRefCount[stream] == 1)) {
if (outputDesc->isDuplicated()) {
- handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
- handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
+ handleIncallSonification(stream, false, false, outputDesc->mOutput1->mIoHandle);
+ handleIncallSonification(stream, false, false, outputDesc->mOutput2->mIoHandle);
}
handleIncallSonification(stream, false, false, outputDesc->mIoHandle);
}
@@ -884,6 +977,7 @@
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->mRefCount[stream] == 0 || forceDeviceUpdate) {
outputDesc->mStopTime[stream] = systemTime();
+ audio_devices_t prevDevice = outputDesc->device();
audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
// the track stop() command is received and at that time the audio track buffer can
@@ -901,10 +995,17 @@
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
(newDevice != desc->device())) {
- setOutputDevice(desc,
- getNewOutputDevice(desc, false /*fromCache*/),
+ audio_devices_t dev = getNewOutputDevice(mOutputs.valueFor(curOutput), false /*fromCache*/);
+ uint32_t delayMs;
+ if (dev == prevDevice) {
+ delayMs = 0;
+ } else {
+ delayMs = outputDesc->mLatency*2;
+ }
+ setOutputDevice(desc,
+ dev,
true,
- outputDesc->latency()*2);
+ delayMs);
}
}
// update the outputs if stopping one with a stream that can affect notification routing
@@ -1361,6 +1462,7 @@
}
#endif
+#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
/*
* WFD audio routes back to target speaker when starting a ringtone playback.
* This is because primary output is reused for ringtone, so output device is
@@ -1380,6 +1482,8 @@
else //route every thing else to ULL path
flags = AUDIO_OUTPUT_FLAG_FAST;
}
+#endif
+
// open a direct output if required by specified parameters
// force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
@@ -1720,7 +1824,7 @@
// Move tracks associated to this strategy from previous output to new output
for (int i = AUDIO_STREAM_SYSTEM; i < (int)AUDIO_STREAM_CNT; i++) {
// Do not call invalidate for ENFORCED_AUDIBLE (otherwise pops are seen for camcorder)
- if ((i != AUDIO_STREAM_ENFORCED_AUDIBLE && (i != AUDIO_STREAM_PATCH)) {
+ if ((i != AUDIO_STREAM_ENFORCED_AUDIBLE && (i != AUDIO_STREAM_PATCH))) {
ALOGD("Invalidate on releaseInput for stream :: %d ", i);
//FIXME see fixme on name change
mpClientInterface->invalidateStream((audio_stream_type_t)i);
@@ -1818,8 +1922,42 @@
}
AudioPolicyManagerCustom::AudioPolicyManagerCustom(AudioPolicyClientInterface *clientInterface)
- : AudioPolicyManager(clientInterface)
+ : AudioPolicyManager(clientInterface),
+ mHdmiAudioDisabled(false),
+ mHdmiAudioEvent(false),
+ mPrevPhoneState(0)
{
+ char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
+ bool prop_ssr_enabled = false;
+
+ if (property_get("ro.qc.sdk.audio.ssr", ssr_enabled, NULL)) {
+ prop_ssr_enabled = atoi(ssr_enabled) || !strncmp("true", ssr_enabled, 4);
+ }
+
+ for (size_t i = 0; i < mHwModules.size(); i++) {
+ ALOGV("Hw module %d", i);
+ for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
+ const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
+ ALOGV("Input profile ", j);
+ for (size_t k = 0; k < inProfile->mChannelMasks.size(); k++) {
+ audio_channel_mask_t channelMask =
+ inProfile->mChannelMasks.itemAt(k);
+ ALOGV("Channel Mask %x size %d", channelMask,
+ inProfile->mChannelMasks.size());
+ if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
+ if (!prop_ssr_enabled) {
+ ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
+ " input profile as SSR(surround sound record)"
+ " is not supported on this chipset variant");
+ inProfile->mChannelMasks.removeItemsAt(k, 1);
+ ALOGV("Channel Mask size now %d",
+ inProfile->mChannelMasks.size());
+ }
+ }
+ }
+ }
+ }
+
#ifdef RECORD_PLAY_CONCURRENCY
mIsInputRequestOnProgress = false;
#endif
@@ -1829,31 +1967,4 @@
mFallBackflag = getFallBackPath();
#endif
}
-audio_devices_t AudioPolicyManagerCustom::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
-{
- audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
- audio_devices_t device = AUDIO_DEVICE_NONE;
- switch (strategy) {
- case STRATEGY_SONIFICATION:
- case STRATEGY_ENFORCED_AUDIBLE:
- case STRATEGY_ACCESSIBILITY:
- case STRATEGY_REROUTING:
- case STRATEGY_MEDIA:
- if (strategy != STRATEGY_SONIFICATION){
- // no sonification on WFD sink
- device |= availableOutputDeviceTypes & AUDIO_DEVICE_OUT_PROXY;
- if (device != AUDIO_DEVICE_NONE) {
- ALOGV("Found proxy for strategy %d", strategy);
- return device;
- }
- }
- break;
- default:
- ALOGV("getDeviceForStrategy() unknown strategy: %d", strategy);
- break;
- }
- device = AudioPolicyManager::getDeviceForStrategy(strategy, fromCache);
- return device;
-}
-
}
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index b5a4461..dfaad65 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -36,7 +36,7 @@
#define AUDIO_FORMAT_AAC_ADTS 0x1E000000UL
#endif
-#ifndef AFE_PROXY_ENABLED
+#ifndef AUDIO_EXTN_AFE_PROXY_ENABLED
#define AUDIO_DEVICE_OUT_PROXY 0x1000000
#endif
// ----------------------------------------------------------------------------
@@ -54,7 +54,8 @@
const char *device_address,
const char *device_name);
virtual void setPhoneState(audio_mode_t state);
-
+ virtual void setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config);
virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
@@ -74,7 +75,6 @@
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session);
- virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache);
protected:
status_t checkAndSetVolume(audio_stream_type_t stream,
@@ -101,9 +101,9 @@
status_t stopSource(sp<SwAudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate);
- // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON 313
- // returns 0 if no mute/unmute event happened, the largest latency of the device where 314
- // the mute/unmute happened 315
+ // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
+ // returns 0 if no mute/unmute event happened, the largest latency of the device where
+ // the mute/unmute happened
uint32_t handleEventForBeacon(int){return 0;}
uint32_t setBeaconMute(bool){return 0;}
#ifdef VOICE_CONCURRENCY
@@ -119,14 +119,9 @@
//parameter indicates if HDMI plug in/out detected
bool mHdmiAudioEvent;
private:
- static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
- int indexInUi);
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
- static bool isVirtualInputDevice(audio_devices_t device);
- static bool deviceDistinguishesOnAddress(audio_devices_t device);
- uint32_t nextUniqueId();
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevice(
audio_devices_t device,
@@ -156,8 +151,6 @@
// Used for record + playback concurrency
bool mIsInputRequestOnProgress;
#endif
-
-
};
};
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 192320a..929991c 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -21,6 +21,11 @@
LOCAL_SRC_FILES += hw_accelerator.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUDIOSPHERE)),true)
+ LOCAL_CFLAGS += -DAUDIOSPHERE_ENABLED
+ LOCAL_SRC_FILES += asphere.c
+endif
+
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_DTS_EAGLE)),true)
diff --git a/post_proc/asphere.c b/post_proc/asphere.c
new file mode 100644
index 0000000..bbf1056
--- /dev/null
+++ b/post_proc/asphere.c
@@ -0,0 +1,301 @@
+/* Copyright (c) 2015, 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "audio_pp_asphere"
+/*#define LOG_NDEBUG 0*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <cutils/log.h>
+#include <cutils/list.h>
+#include <cutils/str_parms.h>
+#include <cutils/properties.h>
+#include <hardware/audio_effect.h>
+#include "bundle.h"
+#include "equalizer.h"
+#include "bass_boost.h"
+#include "virtualizer.h"
+#include "reverb.h"
+#include "asphere.h"
+
+#define ASPHERE_MIXER_NAME "MSM ASphere Set Param"
+
+#define AUDIO_PARAMETER_KEY_ASPHERE_STATUS "asphere_status"
+#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE "asphere_enable"
+#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
+
+#define AUDIO_ASPHERE_EVENT_NODE "/data/misc/audio_pp/event_node"
+
+enum {
+ ASPHERE_ACTIVE = 0,
+ ASPHERE_SUSPENDED,
+ ASPHERE_ERROR
+};
+
+struct asphere_module {
+ bool enabled;
+ int status;
+ int strength;
+ pthread_mutex_t lock;
+ int init_status;
+};
+
+static struct asphere_module asphere;
+pthread_once_t asphere_once = PTHREAD_ONCE_INIT;
+
+static int asphere_create_app_notification_node(void)
+{
+ int fd;
+ if ((fd = open(AUDIO_ASPHERE_EVENT_NODE, O_CREAT|O_TRUNC|O_WRONLY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+ ALOGE("creating notification node failed %d", errno);
+ return -EINVAL;
+ }
+ chmod(AUDIO_ASPHERE_EVENT_NODE, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
+ close(fd);
+ ALOGD("%s: successfully created notification node %s",
+ __func__, AUDIO_ASPHERE_EVENT_NODE);
+ return 0;
+}
+
+static int asphere_notify_app(void)
+{
+ int fd;
+ if ((fd = open(AUDIO_ASPHERE_EVENT_NODE, O_TRUNC|O_WRONLY)) < 0) {
+ ALOGE("opening notification node failed %d", errno);
+ return -EINVAL;
+ }
+ close(fd);
+ ALOGD("%s: successfully opened notification node", __func__);
+ return 0;
+}
+
+static int asphere_get_values_from_mixer(void)
+{
+ int ret = 0, val[2] = {-1, -1};
+ struct mixer_ctl *ctl = NULL;
+ struct mixer *mixer = mixer_open(MIXER_CARD);
+ if (mixer)
+ ctl = mixer_get_ctl_by_name(mixer, ASPHERE_MIXER_NAME);
+ if (!ctl) {
+ ALOGE("%s: could not get ctl for mixer cmd - %s",
+ __func__, ASPHERE_MIXER_NAME);
+ return -EINVAL;
+ }
+ ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
+ if (!ret) {
+ asphere.enabled = (val[0] == 0) ? false : true;
+ asphere.strength = val[1];
+ }
+ ALOGD("%s: returned %d, enabled:%d, strength:%d",
+ __func__, ret, val[0], val[1]);
+
+ return ret;
+}
+
+static int asphere_set_values_to_mixer(void)
+{
+ int ret = 0, val[2] = {-1, -1};
+ struct mixer_ctl *ctl = NULL;
+ struct mixer *mixer = mixer_open(MIXER_CARD);
+ if (mixer)
+ ctl = mixer_get_ctl_by_name(mixer, ASPHERE_MIXER_NAME);
+ if (!ctl) {
+ ALOGE("%s: could not get ctl for mixer cmd - %s",
+ __func__, ASPHERE_MIXER_NAME);
+ return -EINVAL;
+ }
+ val[0] = ((asphere.status == ASPHERE_ACTIVE) && asphere.enabled) ? 1 : 0;
+ val[1] = asphere.strength;
+
+ ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
+ ALOGD("%s: returned %d, enabled:%d, strength:%d",
+ __func__, ret, val[0], val[1]);
+
+ return ret;
+}
+
+static void asphere_init_once() {
+ ALOGD("%s", __func__);
+ pthread_mutex_init(&asphere.lock, NULL);
+ asphere.init_status = 1;
+ asphere_get_values_from_mixer();
+ asphere_create_app_notification_node();
+}
+
+static int asphere_init() {
+ pthread_once(&asphere_once, asphere_init_once);
+ return asphere.init_status;
+}
+
+void asphere_set_parameters(struct str_parms *parms)
+{
+ int ret = 0;
+ bool enable = false;
+ int strength = -1;
+ char value[32] = {0};
+ char propValue[PROPERTY_VALUE_MAX] = {0};
+ bool set_enable = false, set_strength = false;
+
+ if (!property_get("audio.pp.asphere.enabled", propValue, "false") ||
+ (strncmp("true", propValue, 4) != 0)) {
+ ALOGV("%s: property not set!!! not doing anything", __func__);
+ return;
+ }
+ if (asphere_init() != 1) {
+ ALOGW("%s: init check failed!!!", __func__);
+ return;
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+ value, sizeof(value));
+ if (ret > 0) {
+ enable = (atoi(value) == 1) ? true : false;
+ set_enable = true;
+ }
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+ value, sizeof(value));
+ if (ret > 0) {
+ strength = atoi(value);
+ if (strength >= 0 && strength <= 1000)
+ set_strength = true;
+ }
+
+ if (set_enable || set_strength) {
+ pthread_mutex_lock(&asphere.lock);
+ asphere.enabled = set_enable ? enable : asphere.enabled;
+ asphere.strength = set_strength ? strength : asphere.strength;
+ ret = asphere_set_values_to_mixer();
+ pthread_mutex_unlock(&asphere.lock);
+ ALOGV("%s: exit ret %d", __func__, ret);
+ }
+}
+
+void asphere_get_parameters(struct str_parms *query,
+ struct str_parms *reply)
+{
+ char value[32] = {0};
+ char propValue[PROPERTY_VALUE_MAX] = {0};
+ int get_status, get_enable, get_strength, ret;
+
+ if (!property_get("audio.pp.asphere.enabled", propValue, "false") ||
+ (strncmp("true", propValue, 4) != 0)) {
+ ALOGV("%s: property not set!!! not doing anything", __func__);
+ return;
+ }
+ if (asphere_init() != 1) {
+ ALOGW("%s: init check failed!!!", __func__);
+ return;
+ }
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ASPHERE_STATUS,
+ value, sizeof(value));
+ if (ret >= 0) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_ASPHERE_STATUS,
+ asphere.status);
+ }
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+ value, sizeof(value));
+ if (ret >= 0) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
+ asphere.enabled ? 1 : 0);
+ }
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+ value, sizeof(value));
+ if (ret >= 0) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
+ asphere.strength);
+ }
+}
+
+static bool effect_needs_asphere_concurrency_handling(effect_context_t *context)
+{
+ if (memcmp(&context->desc->type,
+ &equalizer_descriptor.type, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&context->desc->type,
+ &bassboost_descriptor.type, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&context->desc->type,
+ &virtualizer_descriptor.type, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&context->desc->type,
+ &ins_preset_reverb_descriptor.type, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&context->desc->type,
+ &ins_env_reverb_descriptor.type, sizeof(effect_uuid_t)) == 0)
+ return true;
+
+ return false;
+}
+
+void handle_asphere_on_effect_enabled(bool enable,
+ effect_context_t *context,
+ struct listnode *created_effects)
+{
+ struct listnode *node;
+ char propValue[PROPERTY_VALUE_MAX] = {0};
+
+ ALOGV("%s: effect %0x", __func__, context->desc->type.timeLow);
+ if (!property_get("audio.pp.asphere.enabled", propValue, "false") ||
+ (strncmp("true", propValue, 4) != 0)) {
+ ALOGV("%s: property not set!!! not doing anything", __func__);
+ return;
+ }
+ if (asphere_init() != 1) {
+ ALOGW("%s: init check failed!!!", __func__);
+ return;
+ }
+
+ if (!effect_needs_asphere_concurrency_handling(context)) {
+ ALOGV("%s: effect %0x, do not need concurrency handling",
+ __func__, context->desc->type.timeLow);
+ return;
+ }
+
+ list_for_each(node, created_effects) {
+ effect_context_t *fx_ctxt = node_to_item(node,
+ effect_context_t,
+ effects_list_node);
+ if (fx_ctxt != NULL &&
+ effect_needs_asphere_concurrency_handling(fx_ctxt) == true &&
+ fx_ctxt != context && effect_is_active(fx_ctxt) == true) {
+ ALOGV("%s: found another effect %0x, skip processing %0x", __func__,
+ fx_ctxt->desc->type.timeLow, context->desc->type.timeLow);
+ return;
+ }
+ }
+ pthread_mutex_lock(&asphere.lock);
+ asphere.status = enable ? ASPHERE_SUSPENDED : ASPHERE_ACTIVE;
+ asphere_set_values_to_mixer();
+ asphere_notify_app();
+ pthread_mutex_unlock(&asphere.lock);
+}
diff --git a/post_proc/asphere.h b/post_proc/asphere.h
new file mode 100644
index 0000000..d0e6830
--- /dev/null
+++ b/post_proc/asphere.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2015, 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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef OFFLOAD_ASPHERE_H_
+#define OFFLOAD_ASPHERE_H_
+
+#include <cutils/str_parms.h>
+#include <cutils/list.h>
+#include "bundle.h"
+
+#ifdef AUDIOSPHERE_ENABLED
+void asphere_get_parameters(struct str_parms *query,
+ struct str_parms *reply);
+void asphere_set_parameters(struct str_parms *reply);
+void handle_asphere_on_effect_enabled(bool enable,
+ effect_context_t *context,
+ struct listnode *created_effects);
+#else
+#define asphere_get_parameters(query, reply) (0)
+#define asphere_set_parameters(parms) (0)
+#define handle_asphere_on_effect_enabled(enable, context, created_effects) (0)
+#endif /* AUDIOSPHERE_ENABLED */
+
+#endif /* OFFLOAD_ASPHERE_H_ */
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index 6f1bdfa..1449eb4 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -51,6 +51,7 @@
#include "bass_boost.h"
#include "virtualizer.h"
#include "reverb.h"
+#include "asphere.h"
#ifdef DTS_EAGLE
#include "effect_util.h"
@@ -456,6 +457,24 @@
}
/*
+ * Effect Bundle Set and get param operations.
+ * currently only handles audio sphere scenario,
+ * but the interface itself can be utilized for any effect.
+ */
+__attribute__ ((visibility ("default")))
+void offload_effects_bundle_get_parameters(struct str_parms *query,
+ struct str_parms *reply)
+{
+ asphere_get_parameters(query, reply);
+}
+
+__attribute__ ((visibility ("default")))
+void offload_effects_bundle_set_parameters(struct str_parms *parms)
+{
+ asphere_set_parameters(parms);
+}
+
+/*
* Effect operations
*/
int set_config(effect_context_t *context, effect_config_t *config)
@@ -811,6 +830,7 @@
status = -ENOSYS;
goto exit;
}
+ handle_asphere_on_effect_enabled(true, context, &created_effects_list);
context->state = EFFECT_STATE_ACTIVE;
if (context->ops.enable)
context->ops.enable(context);
@@ -825,6 +845,7 @@
status = -ENOSYS;
goto exit;
}
+ handle_asphere_on_effect_enabled(false, context, &created_effects_list);
context->state = EFFECT_STATE_INITIALIZED;
if (context->ops.disable)
context->ops.disable(context);
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 51f8803..d4f418a 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -344,7 +344,7 @@
if (in_buffer->raw != out_buffer->raw) {
memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
} else {
- ALOGW("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
+ ALOGV("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
__func__);
}
@@ -681,6 +681,11 @@
bool recompute_flag = false;
int active_stream_count = 0;
ALOGV("%s context %p", __func__, handle);
+ if (recv_contex == NULL || recv_contex->desc == NULL) {
+ ALOGE("%s: Got invalid handle while release, DO NOTHING ", __func__);
+ return status;
+ }
+
pthread_mutex_lock(&vol_listner_init_lock);
// check if the handle/context provided is valid
@@ -690,13 +695,14 @@
&& (context->session_id == recv_contex->session_id)
&& (context->stream_type == recv_contex->stream_type)) {
ALOGV("--- Found something to remove ---");
- list_remove(&context->effect_list_node);
PRINT_STREAM_TYPE(context->stream_type);
if (context->dev_id && AUDIO_DEVICE_OUT_SPEAKER) {
recompute_flag = true;
}
+ list_remove(&context->effect_list_node);
free(context);
status = 0;
+ break;
} else {
++active_stream_count;
}
diff --git a/visualizer/offload_visualizer.c b/visualizer/offload_visualizer.c
index d363b77..b2f0952 100644
--- a/visualizer/offload_visualizer.c
+++ b/visualizer/offload_visualizer.c
@@ -300,20 +300,40 @@
return false;
}
-int configure_proxy_capture(struct mixer *mixer, int value) {
- const char *proxy_ctl_name = "AFE_PCM_RX Audio Mixer MultiMedia4";
+int set_control(const char* name, struct mixer *mixer, int value) {
struct mixer_ctl *ctl;
+ ctl = mixer_get_ctl_by_name(mixer, name);
+ if (ctl == NULL) {
+ ALOGW("%s: could not get %s ctl", __func__, name);
+ return -EINVAL;
+ }
+ if (mixer_ctl_set_value(ctl, 0, value) != 0) {
+ ALOGW("%s: error setting value %d on %s ", __func__, value, name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int configure_proxy_capture(struct mixer *mixer, int value) {
+ int retval = 0;
+
if (value && acdb_send_audio_cal)
acdb_send_audio_cal(AFE_PROXY_ACDB_ID, ACDB_DEV_TYPE_OUT);
- ctl = mixer_get_ctl_by_name(mixer, proxy_ctl_name);
- if (ctl == NULL) {
- ALOGW("%s: could not get %s ctl", __func__, proxy_ctl_name);
- return -EINVAL;
- }
- if (mixer_ctl_set_value(ctl, 0, value) != 0)
- ALOGW("%s: error setting value %d on %s ", __func__, value, proxy_ctl_name);
+ retval = set_control("AFE_PCM_RX Audio Mixer MultiMedia4", mixer, value);
+
+ if (retval != 0)
+ return retval;
+
+ // Extending visualizer to capture for compress2 path as well.
+ // for extending it to multiple offload either this needs to be extended
+ // or need to find better solution to enable only active offload sessions
+
+ retval = set_control("AFE_PCM_RX Audio Mixer MultiMedia7", mixer, value);
+ if (retval != 0)
+ return retval;
return 0;
}