Merge "hal:Audio: Add support for SBC8084"
diff --git a/hal/Android.mk b/hal/Android.mk
index d78d13b..6522bec 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -41,6 +41,10 @@
LOCAL_CFLAGS += -DANC_HEADSET_ENABLED
endif
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FLUENCE)),true)
+ LOCAL_CFLAGS += -DFLUENCE_ENABLED
+endif
+
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PROXY_DEVICE)),true)
LOCAL_CFLAGS += -DAFE_PROXY_ENABLED
endif
@@ -59,6 +63,10 @@
LOCAL_SRC_FILES += audio_extn/hfp.c
endif
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_CUSTOMSTEREO)),true)
+ LOCAL_CFLAGS += -DCUSTOM_STEREO_ENABLED
+endif
+
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_SSR)),true)
LOCAL_CFLAGS += -DSSR_ENABLED
LOCAL_SRC_FILES += audio_extn/ssr.c
@@ -122,7 +130,8 @@
libtinycompress \
libaudioroute \
libdl \
- libexpat
+ libexpat \
+ libmdmdetect
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
@@ -132,7 +141,8 @@
$(call include-path-for, audio-effects) \
$(LOCAL_PATH)/$(AUDIO_PLATFORM) \
$(LOCAL_PATH)/audio_extn \
- $(LOCAL_PATH)/voice_extn
+ $(LOCAL_PATH)/voice_extn \
+ $(TARGET_OUT_HEADERS)/libmdmdetect/inc
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_LISTEN)),true)
LOCAL_CFLAGS += -DAUDIO_LISTEN_ENABLED
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index ad487b1..d0caccb 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -28,6 +28,8 @@
#include "audio_hw.h"
#include "audio_extn.h"
+#include "platform.h"
+#include "platform_api.h"
#define MAX_SLEEP_RETRY 100
#define WIFI_INIT_WAIT_SLEEP 50
@@ -35,18 +37,22 @@
struct audio_extn_module {
bool anc_enabled;
bool aanc_enabled;
+ bool custom_stereo_enabled;
uint32_t proxy_channel_num;
};
static struct audio_extn_module aextnmod = {
.anc_enabled = 0,
.aanc_enabled = 0,
+ .custom_stereo_enabled = 0,
.proxy_channel_num = 2,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
#define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap"
#define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy"
+#define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono"
+
#ifndef FM_ENABLED
#define audio_extn_fm_set_parameters(adev, parms) (0)
#else
@@ -60,6 +66,45 @@
struct str_parms *parms);
#endif
+#ifndef CUSTOM_STEREO_ENABLED
+#define audio_extn_customstereo_set_parameters(adev, parms) (0)
+#else
+void audio_extn_customstereo_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int ret = 0;
+ char value[32]={0};
+ bool custom_stereo_state = false;
+ const char *mixer_ctl_name = "Set Custom Stereo OnOff";
+ struct mixer_ctl *ctl;
+
+ ALOGV("%s", __func__);
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_CUSTOM_STEREO, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (!strncmp("true", value, sizeof("true")) || atoi(value))
+ custom_stereo_state = true;
+
+ if (custom_stereo_state == aextnmod.custom_stereo_enabled)
+ return;
+
+ 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;
+ }
+ if (mixer_ctl_set_value(ctl, 0, custom_stereo_state) < 0) {
+ ALOGE("%s: Could not set custom stereo state %d",
+ __func__, custom_stereo_state);
+ return;
+ }
+ aextnmod.custom_stereo_enabled = custom_stereo_state;
+ ALOGV("%s: Setting custom stereo state success", __func__);
+ }
+}
+#endif /* CUSTOM_STEREO_ENABLED */
+
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
#else
@@ -130,8 +175,62 @@
}
#endif /* ANC_HEADSET_ENABLED */
+#ifndef FLUENCE_ENABLED
+#define audio_extn_set_fluence_parameters(adev, parms) (0)
+#define audio_extn_get_fluence_parameters(adev, query, reply) (0)
+#else
+void audio_extn_set_fluence_parameters(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int ret = 0, err;
+ char value[32];
+ struct listnode *node;
+ struct audio_usecase *usecase;
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FLUENCE,
+ value, sizeof(value));
+ ALOGV_IF(err >= 0, "%s: Set Fluence Type to %s", __func__, value);
+ if (err >= 0) {
+ ret = platform_set_fluence_type(adev->platform, value);
+ if (ret != 0) {
+ ALOGE("platform_set_fluence_type returned error: %d", ret);
+ } else {
+ /*
+ *If the fluence is manually set/reset, devices
+ *need to get updated for all the usecases
+ *i.e. audio and voice.
+ */
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ select_devices(adev, usecase->id);
+ }
+ }
+ }
+}
+
+int audio_extn_get_fluence_parameters(struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply)
+{
+ int ret = 0, err;
+ char value[256] = {0};
+
+ err = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE, value,
+ sizeof(value));
+ if (err >= 0) {
+ ret = platform_get_fluence_type(adev->platform, value, sizeof(value));
+ if (ret >= 0) {
+ ALOGV("%s: Fluence Type is %s", __func__, value);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE, value);
+ } else
+ goto done;
+ }
+done:
+ return ret;
+}
+#endif /* FLUENCE_ENABLED */
+
#ifndef AFE_PROXY_ENABLED
-#define audio_extn_set_afe_proxy_parameters(parms) (0)
+#define audio_extn_set_afe_proxy_parameters(adev, parms) (0)
#define audio_extn_get_afe_proxy_parameters(query, reply) (0)
#else
/* Front left channel. */
@@ -168,6 +267,10 @@
ALOGV("%s channel_count:%d",__func__, channel_count);
switch (channel_count) {
+ case 2:
+ set_values[0] = PCM_CHANNEL_FL;
+ set_values[1] = PCM_CHANNEL_FR;
+ break;
case 6:
set_values[0] = PCM_CHANNEL_FL;
set_values[1] = PCM_CHANNEL_FR;
@@ -205,7 +308,8 @@
return ret;
}
-int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev)
+int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev,
+ int channel_count)
{
int32_t ret = 0;
const char *channel_cnt_str = NULL;
@@ -216,9 +320,8 @@
/* use the existing channel count set by hardware params to
configure the back end for stereo as usb/a2dp would be
stereo by default */
- ALOGD("%s: channels = %d", __func__,
- aextnmod.proxy_channel_num);
- switch (aextnmod.proxy_channel_num) {
+ ALOGD("%s: channels = %d", __func__, channel_count);
+ switch (channel_count) {
case 8: channel_cnt_str = "Eight"; break;
case 7: channel_cnt_str = "Seven"; break;
case 6: channel_cnt_str = "Six"; break;
@@ -228,7 +331,7 @@
default: channel_cnt_str = "Two"; break;
}
- if(aextnmod.proxy_channel_num >= 2 && aextnmod.proxy_channel_num < 8) {
+ if(channel_count >= 2 && channel_count <= 8) {
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
ALOGE("%s: could not get ctl for mixer cmd - %s",
@@ -238,16 +341,19 @@
}
mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
- if (aextnmod.proxy_channel_num == 6 ||
- aextnmod.proxy_channel_num == 8)
- ret = afe_proxy_set_channel_mapping(adev,
- aextnmod.proxy_channel_num);
+ if (channel_count == 6 || channel_count == 8 || channel_count == 2) {
+ ret = afe_proxy_set_channel_mapping(adev, channel_count);
+ } else {
+ ALOGE("%s: set unsupported channel count(%d)", __func__, channel_count);
+ ret = -EINVAL;
+ }
ALOGD("%s: exit", __func__);
return ret;
}
-void audio_extn_set_afe_proxy_parameters(struct str_parms *parms)
+void audio_extn_set_afe_proxy_parameters(struct audio_device *adev,
+ struct str_parms *parms)
{
int ret, val;
char value[32]={0};
@@ -257,6 +363,7 @@
if (ret >= 0) {
val = atoi(value);
aextnmod.proxy_channel_num = val;
+ adev->cur_wfd_channels = val;
ALOGD("%s: channel capability set to: %d", __func__,
aextnmod.proxy_channel_num);
}
@@ -309,17 +416,25 @@
}
return ret;
}
+
+int32_t audio_extn_get_afe_proxy_channel_count()
+{
+ return aextnmod.proxy_channel_num;
+}
+
#endif /* AFE_PROXY_ENABLED */
void audio_extn_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
audio_extn_set_anc_parameters(adev, parms);
- audio_extn_set_afe_proxy_parameters(parms);
+ audio_extn_set_fluence_parameters(adev, parms);
+ audio_extn_set_afe_proxy_parameters(adev, parms);
audio_extn_fm_set_parameters(adev, parms);
audio_extn_listen_set_parameters(adev, parms);
audio_extn_hfp_set_parameters(adev, parms);
audio_extn_ddp_set_parameters(adev, parms);
+ audio_extn_customstereo_set_parameters(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -328,6 +443,7 @@
{
char *kv_pairs = NULL;
audio_extn_get_afe_proxy_parameters(query, reply);
+ audio_extn_get_fluence_parameters(adev, query, reply);
kv_pairs = str_parms_to_str(reply);
ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index fb428db..c7b0c0b 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -39,12 +39,26 @@
bool audio_extn_should_use_handset_anc(int in_channels);
#endif
-#ifndef AFE_PROXY_ENABLED
-#define audio_extn_set_afe_proxy_channel_mixer(adev) (0)
-#define audio_extn_read_afe_proxy_channel_masks(out) (0)
+#ifndef FLUENCE_ENABLED
+#define audio_extn_set_fluence_parameters(adev, parms) (0)
+#define audio_extn_get_fluence_parameters(adev, query, reply) (0)
#else
-int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev);
+void audio_extn_set_fluence_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+int audio_extn_get_fluence_parameters(struct audio_device *adev,
+ struct str_parms *query, struct str_parms *reply);
+#endif
+
+#ifndef AFE_PROXY_ENABLED
+#define audio_extn_set_afe_proxy_channel_mixer(adev,channel_count) (0)
+#define audio_extn_read_afe_proxy_channel_masks(out) (0)
+#define audio_extn_get_afe_proxy_channel_count() (0)
+#else
+int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev,
+ int channel_count);
int32_t audio_extn_read_afe_proxy_channel_masks(struct stream_out *out);
+int32_t audio_extn_get_afe_proxy_channel_count();
+
#endif
#ifndef USB_HEADSET_ENABLED
@@ -162,7 +176,7 @@
#endif
#ifndef DS1_DOLBY_DDP_ENABLED
-#define audio_extn_dolby_set_endpoint() (0)
+#define audio_extn_dolby_set_endpoint(adev) (0)
#else
void audio_extn_dolby_set_endpoint(struct audio_device *adev);
#endif
@@ -170,7 +184,7 @@
#ifndef DS1_DOLBY_DDP_ENABLED
#define audio_extn_ddp_set_parameters(adev, parms) (0)
#define audio_extn_is_dolby_format(format) (0)
-#define audio_extn_dolby_get_snd_codec_id(format) (0)
+#define audio_extn_dolby_get_snd_codec_id(adev, out, format) (0)
#define audio_extn_dolby_send_ddp_endp_params(adev) (0)
#else
bool audio_extn_is_dolby_format(audio_format_t format);
@@ -184,8 +198,10 @@
#ifndef HFP_ENABLED
#define audio_extn_hfp_is_active(adev) (0)
+#define audio_extn_hfp_get_usecase() (0)
#else
bool audio_extn_hfp_is_active(struct audio_device *adev);
+audio_usecase_t audio_extn_hfp_get_usecase();
#endif
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index bcc7381..99fa2b7 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -64,7 +64,7 @@
/* DS1-DDP Endp Params */
#define DDP_ENDP_NUM_PARAMS 17
-#define DDP_ENDP_NUM_DEVICES 22
+#define DDP_ENDP_NUM_DEVICES 23
static int ddp_endp_params_id[DDP_ENDP_NUM_PARAMS] = {
PARAM_ID_MAX_OUTPUT_CHANNELS, PARAM_ID_CTL_RUNNING_MODE,
PARAM_ID_CTL_ERROR_CONCEAL, PARAM_ID_CTL_ERROR_MAX_RPTS,
@@ -147,7 +147,10 @@
{8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
{AUDIO_DEVICE_OUT_PROXY, 2,
- {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
+ {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
+ {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
+ {AUDIO_DEVICE_OUT_PROXY, 6,
+ {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
};
@@ -264,9 +267,16 @@
(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
((usecase->stream.out->format == AUDIO_FORMAT_AC3) ||
(usecase->stream.out->format == AUDIO_FORMAT_EAC3))) {
+ /*
+ * Use wfd /hdmi sink channel cap for dolby params if device is wfd
+ * or hdmi. Otherwise use stereo configuration
+ */
+ int channel_cap = usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
+ adev->cur_hdmi_channels :
+ usecase->devices & AUDIO_DEVICE_OUT_PROXY ?
+ adev->cur_wfd_channels : 2;
send_ddp_endp_params_stream(usecase->stream.out, usecase->devices,
- usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
- adev->cur_hdmi_channels : 2, false /* set cache */);
+ channel_cap, false /* set cache */);
}
}
}
@@ -334,7 +344,9 @@
update_ddp_endp_table(ddp_dev, dev_ch_cap,
PARAM_ID_OUT_CTL_STEREO_MODE, val);
}
-
+ /* TODO: Do we need device channel caps here?
+ * We dont have that information as this is from dolby modules
+ */
send_ddp_endp_params(adev, ddp_dev, dev_ch_cap);
}
@@ -343,13 +355,20 @@
audio_format_t format)
{
int id = 0;
+ /*
+ * Use wfd /hdmi sink channel cap for dolby params if device is wfd
+ * or hdmi. Otherwise use stereo configuration
+ */
+ int channel_cap = out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
+ adev->cur_hdmi_channels :
+ out->devices & AUDIO_DEVICE_OUT_PROXY ?
+ adev->cur_wfd_channels : 2;
switch (format) {
case AUDIO_FORMAT_AC3:
id = SND_AUDIOCODEC_AC3;
send_ddp_endp_params_stream(out, out->devices,
- out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
- adev->cur_hdmi_channels : 2, true /* set_cache */);
+ channel_cap, true /* set_cache */);
#ifndef DS1_DOLBY_DAP_ENABLED
audio_extn_dolby_set_dmid(adev);
#endif
@@ -357,8 +376,7 @@
case AUDIO_FORMAT_EAC3:
id = SND_AUDIOCODEC_EAC3;
send_ddp_endp_params_stream(out, out->devices,
- out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
- adev->cur_hdmi_channels : 2, true /* set_cache */);
+ channel_cap, true /* set_cache */);
#ifndef DS1_DOLBY_DAP_ENABLED
audio_extn_dolby_set_dmid(adev);
#endif
@@ -430,8 +448,7 @@
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if ((usecase->type == PCM_PLAYBACK) &&
- (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY))
+ if (usecase->type == PCM_PLAYBACK)
send = true;
}
if (!send)
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index 2d6e1e0..c480490 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -220,7 +220,7 @@
bool audio_extn_hfp_is_active(struct audio_device *adev)
{
struct audio_usecase *hfp_usecase = NULL;
- hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
+ hfp_usecase = get_usecase_from_list(adev, hfpmod.ucid);
if (hfp_usecase != NULL)
return true;
@@ -228,6 +228,11 @@
return false;
}
+audio_usecase_t audio_extn_hfp_get_usecase()
+{
+ return hfpmod.ucid;
+}
+
void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
{
int ret;
diff --git a/hal/audio_extn/listen.c b/hal/audio_extn/listen.c
index 4a1980b..91bb04f 100644
--- a/hal/audio_extn/listen.c
+++ b/hal/audio_extn/listen.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -64,6 +64,7 @@
typedef void (*destroy_listen_hw_t)();
typedef int (*open_listen_session_t)(struct audio_hw_device *,
+ struct listen_open_params*,
struct listen_session**);
typedef int (*close_listen_session_t)(struct audio_hw_device *dev,
@@ -119,7 +120,6 @@
void audio_extn_listen_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
-
ALOGV("%s: enter", __func__);
if (listen_dev) {
char *kv_pairs = str_parms_to_str(parms);
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 5ec7eba..6c0eec0 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -633,7 +633,11 @@
ret = -EINVAL;
}
}
+
exit:
+ /* Clear VI feedback cal and replace with handset MIC */
+ platform_send_audio_calibration(adev->platform,
+ SND_DEVICE_IN_HANDSET_MIC);
if (ret) {
if (handle.pcm_tx)
pcm_close(handle.pcm_tx);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 88e3cad..699c3b7 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -152,7 +152,7 @@
file_size = st.st_size;
- read_buf = (char *)calloc(1, USB_BUFF_SIZE);
+ read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
err = read(fd, read_buf, USB_BUFF_SIZE);
str_start = strstr(read_buf, type);
if (str_start == NULL) {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index e0eb307..4787ab3 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -53,16 +53,14 @@
#include "voice_extn.h"
#include "sound/compress_params.h"
+#include "sound/asound.h"
-#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
-#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
-#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
-#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+
#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
struct pcm_config pcm_config_deep_buffer = {
@@ -121,6 +119,7 @@
[USECASE_VOICE2_CALL] = "voice2-call",
[USECASE_VOLTE_CALL] = "volte-call",
[USECASE_QCHAT_CALL] = "qchat-call",
+ [USECASE_VOWLAN_CALL] = "vowlan-call",
[USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
[USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
[USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
@@ -155,35 +154,6 @@
static int set_voice_volume_l(struct audio_device *adev, float volume);
-/* Read offload buffer size from a property.
- * If value is not power of 2 round it to
- * power of 2.
- */
-static uint32_t get_offload_buffer_size(audio_offload_info_t* info)
-{
- char value[PROPERTY_VALUE_MAX] = {0};
- uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
- if((property_get("audio.offload.buffer.size.kb", value, "")) &&
- atoi(value)) {
- fragment_size = atoi(value) * 1024;
- //ring buffer size needs to be 4k aligned.
- CHECK(!(fragment_size * COMPRESS_OFFLOAD_NUM_FRAGMENTS % 4096));
- }
-
- if (info != NULL && info->has_video && info->is_streaming) {
- fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
- ALOGV("%s: offload fragment size reduced for AV streaming to %d",
- __func__, out->compr_config.fragment_size);
- }
-
- if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
- fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
- else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
- fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
- ALOGVV("%s: fragment_size %d", __func__, fragment_size);
- return fragment_size;
-}
-
static int check_and_set_gapless_mode(struct audio_device *adev) {
@@ -214,8 +184,10 @@
static bool is_supported_format(audio_format_t format)
{
if (format == AUDIO_FORMAT_MP3 ||
- format == AUDIO_FORMAT_AAC)
- return true;
+ format == AUDIO_FORMAT_AAC ||
+ format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
+ format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ return true;
return false;
}
@@ -231,6 +203,10 @@
case AUDIO_FORMAT_AAC:
id = SND_AUDIOCODEC_AAC;
break;
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
+ id = SND_AUDIOCODEC_PCM;
+ break;
default:
ALOGE("%s: Unsupported audio format :%x", __func__, format);
}
@@ -575,21 +551,6 @@
return ret;
}
-static void update_devices_for_all_voice_usecases(struct audio_device *adev)
-{
- struct listnode *node;
- struct audio_usecase *usecase;
-
- list_for_each(node, &adev->usecase_list) {
- usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == VOICE_CALL) {
- ALOGV("%s: updating device for usecase:%s", __func__,
- use_case_table[usecase->id]);
- select_devices(adev, usecase->id);
- }
- }
-}
-
static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
{
struct audio_usecase *usecase;
@@ -627,6 +588,7 @@
struct audio_usecase *vc_usecase = NULL;
struct audio_usecase *voip_usecase = NULL;
struct audio_usecase *hfp_usecase = NULL;
+ audio_usecase_t hfp_ucid;
struct listnode *node;
int status = 0;
@@ -666,7 +628,8 @@
out_snd_device = voip_usecase->out_snd_device;
}
} else if (audio_extn_hfp_is_active(adev)) {
- hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
+ hfp_ucid = audio_extn_hfp_get_usecase();
+ hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
in_snd_device = hfp_usecase->in_snd_device;
out_snd_device = hfp_usecase->out_snd_device;
@@ -945,24 +908,30 @@
send_callback = false;
switch(cmd->cmd) {
case OFFLOAD_CMD_WAIT_FOR_BUFFER:
+ ALOGD("copl(%x):calling compress_wait", (unsigned int)out);
compress_wait(out->compr, -1);
+ ALOGD("copl(%x):out of compress_wait", (unsigned int)out);
send_callback = true;
event = STREAM_CBK_EVENT_WRITE_READY;
break;
case OFFLOAD_CMD_PARTIAL_DRAIN:
ret = compress_next_track(out->compr);
- if(ret == 0)
+ if(ret == 0) {
+ ALOGD("copl(%x):calling compress_partial_drain", (unsigned int)out);
compress_partial_drain(out->compr);
+ ALOGD("copl(%x):out of compress_partial_drain", (unsigned int)out);
+ }
else if(ret == -ETIMEDOUT)
compress_drain(out->compr);
else
ALOGE("%s: Next track returned error %d",__func__, ret);
-
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
break;
case OFFLOAD_CMD_DRAIN:
+ ALOGD("copl(%x):calling compress_drain", (unsigned int)out);
compress_drain(out->compr);
+ ALOGD("copl(%x):calling compress_drain", (unsigned int)out);
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
break;
@@ -1037,6 +1006,12 @@
"no change in HDMI channels", __func__);
ret = false;
break;
+ } else if (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD &&
+ popcount(usecase->stream.out->channel_mask) > 2) {
+ ALOGD("%s: multi-channel(%x) compress offload playback is active, "
+ "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
+ ret = false;
+ break;
}
}
}
@@ -1134,7 +1109,7 @@
struct audio_usecase *uc_info;
struct audio_device *adev = out->dev;
- ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
+ ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
__func__, out->usecase, use_case_table[out->usecase], out->devices);
out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
if (out->pcm_device_id < 0) {
@@ -1336,6 +1311,7 @@
out->pcm = NULL;
}
} else {
+ ALOGD("copl(%x):standby", (unsigned int)out);
stop_compressed_output_l(out);
out->gapless_mdata.encoder_delay = 0;
out->gapless_mdata.encoder_padding = 0;
@@ -1476,7 +1452,7 @@
} else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
voice_is_in_call(adev) &&
(out == adev->primary_output)) {
- update_devices_for_all_voice_usecases(adev);
+ voice_update_devices_for_all_voice_usecases(adev);
}
}
@@ -1619,9 +1595,9 @@
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
+ ALOGD("copl(%x): writing buffer (%d bytes) to compress device", (unsigned int)out, bytes);
if (out->send_new_metadata) {
- ALOGVV("send new gapless metadata");
+ ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
out->send_new_metadata = 0;
}
@@ -1629,6 +1605,7 @@
ret = compress_write(out->compr, buffer, bytes);
ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
if (ret >= 0 && ret < (ssize_t)bytes) {
+ ALOGD("No space available in compress driver, post msg to cb thread");
send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
}
if (!out->playback_started) {
@@ -1761,6 +1738,7 @@
int status = -ENOSYS;
ALOGV("%s", __func__);
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ ALOGD("copl(%x):pause compress driver", (unsigned int)out);
pthread_mutex_lock(&out->lock);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
status = compress_pause(out->compr);
@@ -1777,6 +1755,7 @@
int status = -ENOSYS;
ALOGV("%s", __func__);
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ ALOGD("copl(%x):resume compress driver", (unsigned int)out);
status = 0;
pthread_mutex_lock(&out->lock);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
@@ -1809,9 +1788,11 @@
struct stream_out *out = (struct stream_out *)stream;
ALOGV("%s", __func__);
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ ALOGD("copl(%x):calling compress flush", (unsigned int)out);
pthread_mutex_lock(&out->lock);
stop_compressed_output_l(out);
pthread_mutex_unlock(&out->lock);
+ ALOGD("copl(%x):out of compress flush", (unsigned int)out);
return 0;
}
return -ENOSYS;
@@ -1923,11 +1904,10 @@
(voice_extn_compress_voip_is_format_supported(in->format)) &&
(in->config.rate == 8000 || in->config.rate == 16000) &&
(popcount(in->channel_mask) == 1)) {
- ret = voice_extn_compress_voip_open_input_stream(in);
- if (ret != 0) {
+ err = voice_extn_compress_voip_open_input_stream(in);
+ if (err != 0) {
ALOGE("%s: Compress voip input cannot be opened, error:%d",
- __func__, ret);
- goto done;
+ __func__, err);
}
}
}
@@ -2151,6 +2131,9 @@
goto error_open;
}
} else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
+ ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
+ __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
+
if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
ALOGE("%s: Unsupported Offload information", __func__);
@@ -2170,8 +2153,10 @@
out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
if (config->offload_info.channel_mask)
out->channel_mask = config->offload_info.channel_mask;
- else if (config->channel_mask)
+ else if (config->channel_mask) {
out->channel_mask = config->channel_mask;
+ config->offload_info.channel_mask = config->channel_mask;
+ }
out->format = config->offload_info.format;
out->sample_rate = config->offload_info.sample_rate;
@@ -2188,7 +2173,13 @@
else
out->compr_config.codec->id =
get_snd_codec_id(config->offload_info.format);
- out->compr_config.fragment_size = get_offload_buffer_size(&config->offload_info);
+ if (audio_is_offload_pcm(config->offload_info.format)) {
+ out->compr_config.fragment_size =
+ platform_get_pcm_offload_buffer_size(&config->offload_info);
+ } else {
+ out->compr_config.fragment_size =
+ platform_get_compress_offload_buffer_size(&config->offload_info);
+ }
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
out->compr_config.codec->sample_rate =
compress_get_alsa_rate(config->offload_info.sample_rate);
@@ -2199,6 +2190,11 @@
out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
+ if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
+ else if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
+
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
out->non_blocking = 1;
@@ -2685,6 +2681,7 @@
adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
voice_init(adev);
list_init(&adev->usecase_list);
+ adev->cur_wfd_channels = 2;
/* Loads platform specific libraries dynamically */
adev->platform = platform_init(adev);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 205977b..e1172ef 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -32,13 +32,15 @@
#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
/* Flags used to initialize acdb_settings variable that goes to ACDB library */
-#define DMIC_FLAG 0x00000002
-#define QMIC_FLAG 0x00000004
-#define TTY_MODE_OFF 0x00000010
-#define TTY_MODE_FULL 0x00000020
-#define TTY_MODE_VCO 0x00000040
-#define TTY_MODE_HCO 0x00000080
-#define TTY_MODE_CLEAR 0xFFFFFF0F
+#define NONE_FLAG 0x00000000
+#define DMIC_FLAG 0x00000002
+#define QMIC_FLAG 0x00000004
+#define TTY_MODE_OFF 0x00000010
+#define TTY_MODE_FULL 0x00000020
+#define TTY_MODE_VCO 0x00000040
+#define TTY_MODE_HCO 0x00000080
+#define TTY_MODE_CLEAR 0xFFFFFF0F
+#define FLUENCE_MODE_CLEAR 0xFFFFFFF0
#define ACDB_DEV_TYPE_OUT 1
#define ACDB_DEV_TYPE_IN 2
@@ -80,6 +82,7 @@
USECASE_VOICE2_CALL,
USECASE_VOLTE_CALL,
USECASE_QCHAT_CALL,
+ USECASE_VOWLAN_CALL,
USECASE_COMPRESS_VOIP_CALL,
USECASE_INCALL_REC_UPLINK,
@@ -223,6 +226,7 @@
bool speaker_lr_swap;
struct voice voice;
unsigned int cur_hdmi_channels;
+ unsigned int cur_wfd_channels;
int snd_card;
void *platform;
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index 63506f9..7b955ba 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -123,28 +123,22 @@
SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
};
-static void update_hardware_info_8916(struct hardware_info *hw_info, const char *snd_card_name)
+static void update_hardware_info_8x16(struct hardware_info *hw_info, const char *snd_card_name)
{
- if (!strcmp(snd_card_name, "msm8916-snd-card")) {
+ if (!strcmp(snd_card_name, "msm8x16-snd-card")) {
strlcpy(hw_info->type, "", sizeof(hw_info->type));
- strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name));
+ strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
hw_info->snd_devices = NULL;
hw_info->num_snd_devices = 0;
strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
- } else if (!strcmp(snd_card_name, "msm8916-skuab-snd-card")) {
- strlcpy(hw_info->type, "skuab", sizeof(hw_info->type));
- strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name));
- hw_info->snd_devices = (snd_device_t *)helicon_skuab_variant_devices;
- hw_info->num_snd_devices = ARRAY_SIZE(helicon_skuab_variant_devices);
- strlcpy(hw_info->dev_extn, "-skuab", sizeof(hw_info->dev_extn));
- } else if (!strcmp(snd_card_name, "msm8916-skuaa-snd-card")) {
- strlcpy(hw_info->type, " skuaa", sizeof(hw_info->type));
- strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name));
+ } else if (!strcmp(snd_card_name, "msm8x16-skuh-snd-card")) {
+ strlcpy(hw_info->type, "skuh", sizeof(hw_info->type));
+ strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
hw_info->snd_devices = NULL;
hw_info->num_snd_devices = 0;
strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
} else {
- ALOGW("%s: Not an 8916 device", __func__);
+ ALOGW("%s: Not an 8x16 device", __func__);
}
}
@@ -154,9 +148,9 @@
hw_info = malloc(sizeof(struct hardware_info));
- if(strstr(snd_card_name, "msm8916")) {
- ALOGV("8916 - variant soundcard");
- update_hardware_info_8916(hw_info, snd_card_name);
+ if(strstr(snd_card_name, "msm8x16")) {
+ ALOGV("8x16 - variant soundcard");
+ update_hardware_info_8x16(hw_info, snd_card_name);
} else {
ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
free(hw_info);
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index afdc237..8cb2599 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -34,9 +34,26 @@
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
+#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
+#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
+#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+/* Used in calculating fragment size for pcm offload */
+#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 2000 /* 2 secs */
+#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 100 /* 100 millisecs */
+
+/* MAX PCM fragment size cannot be increased further due
+ * to flinger's cblk size of 1mb,and it has to be a multiple of
+ * 24 - lcm of channels supported by DSP
+ */
+#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+
+#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
/*
* This file will have a maximum of 38 bytes:
*
@@ -51,7 +68,7 @@
#define EDID_FORMAT_LPCM 1
/* Retry for delay in FW loading*/
-#define RETRY_NUMBER 10
+#define RETRY_NUMBER 20
#define RETRY_US 500000
#define MAX_SND_CARD 8
@@ -76,7 +93,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
-typedef int (*acdb_init_t)();
+typedef int (*acdb_init_t)(char *);
typedef void (*acdb_send_audio_cal_t)(int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -88,6 +105,7 @@
bool fluence_in_voice_rec;
bool fluence_in_audio_rec;
int fluence_type;
+ char fluence_cap[PROPERTY_VALUE_MAX];
int btsco_sample_rate;
bool slowtalk;
/* Audio calibration related functions */
@@ -416,6 +434,13 @@
__func__, dlerror());
goto error;
}
+ csd->enable_device_config = (enable_device_config_t)dlsym(csd->csd_client,
+ "csd_client_enable_device_config");
+ if (csd->enable_device_config == NULL) {
+ ALOGE("%s: dlsym error %s for csd_client_enable_device_config",
+ __func__, dlerror());
+ goto error;
+ }
csd->enable_device = (enable_device_t)dlsym(csd->csd_client,
"csd_client_enable_device");
if (csd->enable_device == NULL) {
@@ -581,10 +606,10 @@
my_data->fluence_in_audio_rec = false;
my_data->fluence_type = FLUENCE_NONE;
- property_get("ro.qc.sdk.audio.fluencetype", value, "");
- if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
+ property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
+ if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
my_data->fluence_type = FLUENCE_QUAD_MIC | FLUENCE_DUAL_MIC;
- } else if (!strncmp("fluence", value, sizeof("fluence"))) {
+ } else if (!strncmp("fluence", my_data->fluence_cap, sizeof("fluence"))) {
my_data->fluence_type = FLUENCE_DUAL_MIC;
} else {
my_data->fluence_type = FLUENCE_NONE;
@@ -643,15 +668,15 @@
__func__, LIB_ACDB_LOADER);
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
- "acdb_loader_init_ACDB");
+ "acdb_loader_init_v2");
if (my_data->acdb_init == NULL)
- ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
+ ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
else
- my_data->acdb_init();
+ my_data->acdb_init(snd_card_name);
}
/* Initialize ACDB ID's */
- platform_info_init();
+ platform_info_init(PLATFORM_INFO_XML_PATH);
/* init usb */
audio_extn_usb_init(adev);
@@ -763,6 +788,63 @@
return ret;
}
+int platform_set_fluence_type(void *platform, char *value)
+{
+ int ret = 0;
+ int fluence_type = FLUENCE_NONE;
+ int fluence_flag = NONE_FLAG;
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ ALOGV("%s: fluence type:%d", __func__, my_data->fluence_type);
+
+ /* only dual mic turn on and off is supported as of now through setparameters */
+ if (!strncmp(AUDIO_PARAMETER_VALUE_DUALMIC,value, sizeof(AUDIO_PARAMETER_VALUE_DUALMIC))) {
+ if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro")) ||
+ !strncmp("fluence", my_data->fluence_cap, sizeof("fluence"))) {
+ ALOGV("fluence dualmic feature enabled \n");
+ fluence_type = FLUENCE_DUAL_MIC;
+ fluence_flag = DMIC_FLAG;
+ } else {
+ ALOGE("%s: Failed to set DUALMIC", __func__);
+ ret = -1;
+ goto done;
+ }
+ } else if (!strncmp(AUDIO_PARAMETER_KEY_NO_FLUENCE, value, sizeof(AUDIO_PARAMETER_KEY_NO_FLUENCE))) {
+ ALOGV("fluence disabled");
+ fluence_type = FLUENCE_NONE;
+ } else {
+ ALOGE("Invalid fluence value : %s",value);
+ ret = -1;
+ goto done;
+ }
+
+ if (fluence_type != my_data->fluence_type) {
+ ALOGV("%s: Updating fluence_type to :%d", __func__, fluence_type);
+ my_data->fluence_type = fluence_type;
+ adev->acdb_settings = (adev->acdb_settings & FLUENCE_MODE_CLEAR) | fluence_flag;
+ }
+done:
+ return ret;
+}
+
+int platform_get_fluence_type(void *platform, char *value, uint32_t len)
+{
+ int ret = 0;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (my_data->fluence_type == FLUENCE_QUAD_MIC) {
+ strlcpy(value, "quadmic", len);
+ } else if (my_data->fluence_type == FLUENCE_DUAL_MIC) {
+ strlcpy(value, "dualmic", len);
+ } else if (my_data->fluence_type == FLUENCE_NONE) {
+ strlcpy(value, "none", len);
+ } else
+ ret = -1;
+
+ return ret;
+}
+
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
int ret = 0;
@@ -819,6 +901,32 @@
}
return ret;
}
+int platform_switch_voice_call_enable_device_config(void *platform,
+ snd_device_t out_snd_device,
+ snd_device_t in_snd_device)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ int acdb_rx_id, acdb_tx_id;
+ int ret = 0;
+
+ acdb_rx_id = acdb_device_table[out_snd_device];
+ acdb_tx_id = acdb_device_table[in_snd_device];
+
+ if (my_data->csd != NULL) {
+ if (acdb_rx_id > 0 && acdb_tx_id > 0) {
+ ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
+ if (ret < 0) {
+ ALOGE("%s: csd_enable_device_config, failed, error %d",
+ __func__, ret);
+ }
+ } else {
+ ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
+ acdb_rx_id, acdb_tx_id);
+ }
+ }
+ return ret;
+}
+
int platform_switch_voice_call_device_post(void *platform,
snd_device_t out_snd_device,
@@ -897,6 +1005,10 @@
}
return ret;
}
+int platform_get_sample_rate(void *platform, uint32_t *rate)
+{
+ return 0;
+}
int platform_set_voice_volume(void *platform, int volume)
{
@@ -963,6 +1075,44 @@
return ret;
}
+int platform_set_device_mute(void *platform, bool state, char *dir)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ struct mixer_ctl *ctl;
+ char *mixer_ctl_name = NULL;
+ int ret = 0;
+ uint32_t set_values[ ] = {0,
+ ALL_SESSION_VSID,
+ 0};
+ if(dir == NULL) {
+ ALOGE("%s: Invalid direction:%s", __func__, dir);
+ return -EINVAL;
+ }
+
+ if (!strncmp("rx", dir, sizeof("rx"))) {
+ mixer_ctl_name = "Voice Rx Device Mute";
+ } else if (!strncmp("tx", dir, sizeof("tx"))) {
+ mixer_ctl_name = "Voice Tx Device Mute";
+ } else {
+ return -EINVAL;
+ }
+
+ set_values[0] = state;
+ 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;
+ }
+
+ ALOGV("%s: Setting device mute state: %d, mixer ctrl:%s",
+ __func__,state, mixer_ctl_name);
+ mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+ return ret;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -1087,14 +1237,17 @@
snd_device = SND_DEVICE_OUT_HDMI ;
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
+ ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
+ audio_extn_set_afe_proxy_channel_mixer(adev, 2);
snd_device = SND_DEVICE_OUT_USB_HEADSET;
} else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
} else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
snd_device = SND_DEVICE_OUT_HANDSET;
} else if (devices & AUDIO_DEVICE_OUT_PROXY) {
- ALOGD("%s: setting sink capability for Proxy", __func__);
- audio_extn_set_afe_proxy_channel_mixer(adev);
+ channel_count = audio_extn_get_afe_proxy_channel_count();
+ ALOGD("%s: setting sink capability(%d) for Proxy", __func__, channel_count);
+ audio_extn_set_afe_proxy_channel_mixer(adev, channel_count);
snd_device = SND_DEVICE_OUT_AFE_PROXY;
} else {
ALOGE("%s: Unknown device(s) %#x", __func__, devices);
@@ -1613,23 +1766,7 @@
char *str = NULL;
char value[256] = {0};
int ret;
- int fluence_type;
- ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
- value, sizeof(value));
- if (ret >= 0) {
- if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
- strlcpy(value, "fluencepro", sizeof(value));
- } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- strlcpy(value, "fluence", sizeof(value));
- } else {
- strlcpy(value, "none", sizeof(value));
- }
-
- str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
- }
-
- memset(value, 0, sizeof(value));
ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
value, sizeof(value));
if (ret >= 0) {
@@ -1683,3 +1820,69 @@
else
return false;
}
+
+/* Read offload buffer size from a property.
+ * If value is not power of 2 round it to
+ * power of 2.
+ */
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
+{
+ char value[PROPERTY_VALUE_MAX] = {0};
+ uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ if((property_get("audio.offload.buffer.size.kb", value, "")) &&
+ atoi(value)) {
+ fragment_size = atoi(value) * 1024;
+ }
+
+ if (info != NULL && info->has_video && info->is_streaming) {
+ fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
+ ALOGV("%s: offload fragment size reduced for AV streaming to %d",
+ __func__, out->compr_config.fragment_size);
+ }
+
+ fragment_size = ALIGN( fragment_size, 1024);
+
+ if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
+uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
+{
+ uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ uint32_t bits_per_sample = 16;
+
+ if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
+ bits_per_sample = 32;
+ }
+
+ if (!info->has_video) {
+ fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+
+ } else if (info->has_video && info->is_streaming) {
+ fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING
+ * info->sample_rate
+ * bits_per_sample
+ * popcount(info->channel_mask))/1000;
+
+ } else if (info->has_video) {
+ fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV
+ * info->sample_rate
+ * bits_per_sample
+ * popcount(info->channel_mask))/1000;
+ }
+
+ fragment_size = ALIGN( fragment_size, 1024);
+
+ if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+
+ ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 378d578..cad5198 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -193,6 +193,7 @@
typedef int (*init_t)();
typedef int (*deinit_t)();
typedef int (*disable_device_t)();
+typedef int (*enable_device_config_t)(int, int);
typedef int (*enable_device_t)(int, int, uint32_t);
typedef int (*volume_t)(uint32_t, int);
typedef int (*mic_mute_t)(uint32_t, int);
@@ -209,6 +210,7 @@
init_t init;
deinit_t deinit;
disable_device_t disable_device;
+ enable_device_config_t enable_device_config;
enable_device_t enable_device;
volume_t volume;
mic_mute_t mic_mute;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index c1ba595..ed1a781 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -561,6 +561,12 @@
return ret;
}
+int platform_set_device_mute(void *platform, bool state, char *dir)
+{
+ LOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index e0b1dde..f43a3b0 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -126,22 +126,36 @@
SND_DEVICE_OUT_SPEAKER,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+ SND_DEVICE_OUT_VOICE_SPEAKER,
};
static void update_hardware_info_8084(struct hardware_info *hw_info, const char *snd_card_name)
{
- if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card")) {
+ if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card") ||
+ !strncmp(snd_card_name, "apq8084-taiko-i2s-mtp-snd-card",
+ sizeof("apq8084-taiko-i2s-mtp-snd-card")) ||
+ !strncmp(snd_card_name, "apq8084-tomtom-mtp-snd-card",
+ sizeof("apq8084-tomtom-mtp-snd-card"))) {
strlcpy(hw_info->type, "mtp", sizeof(hw_info->type));
strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name));
hw_info->snd_devices = NULL;
hw_info->num_snd_devices = 0;
strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
- } else if (!strcmp(snd_card_name, "apq8084-taiko-cdp-snd-card")) {
+ } else if ((!strcmp(snd_card_name, "apq8084-taiko-cdp-snd-card")) ||
+ !strncmp(snd_card_name, "apq8084-tomtom-cdp-snd-card",
+ sizeof("apq8084-tomtom-cdp-snd-card"))) {
strlcpy(hw_info->type, " cdp", sizeof(hw_info->type));
strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name));
hw_info->snd_devices = (snd_device_t *)taiko_apq8084_CDP_variant_devices;
hw_info->num_snd_devices = ARRAY_SIZE(taiko_apq8084_CDP_variant_devices);
strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn));
+ } else if (!strncmp(snd_card_name, "apq8084-taiko-i2s-cdp-snd-card",
+ sizeof("apq8084-taiko-i2s-cdp-snd-card"))) {
+ strlcpy(hw_info->type, " cdp", sizeof(hw_info->type));
+ strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name));
+ hw_info->snd_devices = NULL;
+ hw_info->num_snd_devices = 0;
+ strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
} else if (!strcmp(snd_card_name, "apq8084-taiko-liquid-snd-card")) {
strlcpy(hw_info->type , " liquid", sizeof(hw_info->type));
strlcpy(hw_info->name, "apq8084", sizeof(hw_info->type));
@@ -257,6 +271,8 @@
struct hardware_info *hw_info;
hw_info = malloc(sizeof(struct hardware_info));
+ hw_info->snd_devices = NULL;
+ hw_info->num_snd_devices = 0;
if(strstr(snd_card_name, "msm8974") ||
strstr(snd_card_name, "apq8074")) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index fb14330..0491d10 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -31,12 +31,36 @@
#include "platform.h"
#include "audio_extn.h"
#include "voice_extn.h"
+#include "sound/compress_params.h"
+#include "mdm_detect.h"
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
+#define MIXER_XML_PATH_I2S "/system/etc/mixer_paths_i2s.xml"
+
+#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
+#define PLATFORM_INFO_XML_PATH_I2S "/system/etc/audio_platform_info_i2s.xml"
+
#define LIB_ACDB_LOADER "libacdbloader.so"
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
+#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
+#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+
+/* Used in calculating fragment size for pcm offload */
+#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 2000 /* 2 secs */
+#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 100 /* 100 millisecs */
+
+/* MAX PCM fragment size cannot be increased further due
+ * to flinger's cblk size of 1mb,and it has to be a multiple of
+ * 24 - lcm of channels supported by DSP
+ */
+#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+
+#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
/*
* This file will have a maximum of 38 bytes:
*
@@ -88,8 +112,11 @@
bool fluence_in_voice_rec;
bool fluence_in_audio_rec;
int fluence_type;
+ int fluence_mode;
+ char fluence_cap[PROPERTY_VALUE_MAX];
int btsco_sample_rate;
bool slowtalk;
+ bool is_i2s_ext_modem;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -125,6 +152,7 @@
[USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
[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_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},
@@ -219,6 +247,11 @@
[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = "handset-stereo-dmic-ef",
[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = "speaker-stereo-dmic-ef",
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = "vi-feedback",
+ [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = "voice-speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = "speaker-dmic-broadside",
};
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -292,6 +325,11 @@
[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = 34,
[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = 35,
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = 102,
+ [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = 12,
+ [SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = 12,
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = 119,
+ [SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = 121,
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = 120,
};
struct snd_device_index {
@@ -370,6 +408,11 @@
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_STEREO_DMIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_STEREO_DMIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)},
};
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
@@ -391,7 +434,7 @@
return 0;
}
-static struct csd_data *open_csd_client()
+static struct csd_data *open_csd_client(bool i2s_ext_modem)
{
struct csd_data *csd = calloc(1, sizeof(struct csd_data));
@@ -493,6 +536,16 @@
__func__, dlerror());
goto error;
}
+
+ csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client,
+ "csd_client_get_sample_rate");
+ if (csd->get_sample_rate == NULL) {
+ ALOGE("%s: dlsym error %s for csd_client_get_sample_rate",
+ __func__, dlerror());
+
+ goto error;
+ }
+
csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init");
if (csd->init == NULL) {
@@ -500,7 +553,7 @@
__func__, dlerror());
goto error;
} else {
- csd->init();
+ csd->init(i2s_ext_modem);
}
}
return csd;
@@ -521,10 +574,44 @@
}
}
+static void platform_csd_init(struct platform_data *plat_data)
+{
+ struct dev_info mdm_detect_info;
+ int ret = 0;
+
+ /* Call ESOC API to get the number of modems.
+ * If the number of modems is not zero, load CSD Client specific
+ * symbols. Voice call is handled by MDM and apps processor talks to
+ * MDM through CSD Client
+ */
+ ret = get_system_info(&mdm_detect_info);
+ if (ret > 0) {
+ ALOGE("%s: Failed to get system info, ret %d", __func__, ret);
+ }
+ ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
+
+ if (mdm_detect_info.num_modems > 0)
+ plat_data->csd = open_csd_client(plat_data->is_i2s_ext_modem);
+}
+
+static bool platform_is_i2s_ext_modem(const char *snd_card_name,
+ struct platform_data *plat_data)
+{
+ plat_data->is_i2s_ext_modem = false;
+
+ if (!strncmp(snd_card_name, "apq8084-taiko-i2s-mtp-snd-card",
+ sizeof("apq8084-taiko-i2s-mtp-snd-card")) ||
+ !strncmp(snd_card_name, "apq8084-taiko-i2s-cdp-snd-card",
+ sizeof("apq8084-taiko-i2s-cdp-snd-card"))) {
+ plat_data->is_i2s_ext_modem = true;
+ }
+ ALOGV("%s, is_i2s_ext_modem:%d",__func__, plat_data->is_i2s_ext_modem);
+
+ return plat_data->is_i2s_ext_modem;
+}
+
void *platform_init(struct audio_device *adev)
{
- char platform[PROPERTY_VALUE_MAX];
- char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
int retry_num = 0, snd_card_num = 0;
@@ -556,10 +643,16 @@
if (!my_data->hw_info) {
ALOGE("%s: Failed to init hardware info", __func__);
} else {
- if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH,
- MIXER_XML_PATH_AUXPCM) == -ENOSYS)
+ if (platform_is_i2s_ext_modem(snd_card_name, my_data)) {
+ ALOGD("%s: Call MIXER_XML_PATH_I2S", __func__);
+
+ adev->audio_route = audio_route_init(snd_card_num,
+ MIXER_XML_PATH_I2S);
+ } else if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH,
+ MIXER_XML_PATH_AUXPCM) == -ENOSYS) {
adev->audio_route = audio_route_init(snd_card_num,
MIXER_XML_PATH);
+ }
if (!adev->audio_route) {
ALOGE("%s: Failed to init audio route controls, aborting.",
__func__);
@@ -587,11 +680,12 @@
my_data->fluence_in_voice_rec = false;
my_data->fluence_in_audio_rec = false;
my_data->fluence_type = FLUENCE_NONE;
+ my_data->fluence_mode = FLUENCE_ENDFIRE;
- property_get("ro.qc.sdk.audio.fluencetype", value, "");
- if (!strncmp("fluencepro", value, sizeof("fluencepro"))) {
+ property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
+ if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
my_data->fluence_type = FLUENCE_QUAD_MIC | FLUENCE_DUAL_MIC;
- } else if (!strncmp("fluence", value, sizeof("fluence"))) {
+ } else if (!strncmp("fluence", my_data->fluence_cap, sizeof("fluence"))) {
my_data->fluence_type = FLUENCE_DUAL_MIC;
} else {
my_data->fluence_type = FLUENCE_NONE;
@@ -617,6 +711,11 @@
if (!strncmp("true", value, sizeof("true"))) {
my_data->fluence_in_spkr_mode = true;
}
+
+ property_get("persist.audio.fluence.mode",value,"");
+ if (!strncmp("broadside", value, sizeof("broadside"))) {
+ my_data->fluence_mode = FLUENCE_BROADSIDE;
+ }
}
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
@@ -658,18 +757,13 @@
}
/* Initialize ACDB ID's */
- platform_info_init();
+ if (my_data->is_i2s_ext_modem)
+ platform_info_init(PLATFORM_INFO_XML_PATH_I2S);
+ else
+ platform_info_init(PLATFORM_INFO_XML_PATH);
- /* If platform is apq8084 and baseband is MDM, load CSD Client specific
- * symbols. Voice call is handled by MDM and apps processor talks to
- * MDM through CSD Client
- */
- property_get("ro.board.platform", platform, "");
- property_get("ro.baseband", baseband, "");
- if (!strncmp("apq8084", platform, sizeof("apq8084")) &&
- !strncmp("mdm", baseband, sizeof("mdm"))) {
- my_data->csd = open_csd_client();
- }
+ /* load csd client */
+ platform_csd_init(my_data);
/* init usb */
audio_extn_usb_init(adev);
@@ -781,6 +875,63 @@
return ret;
}
+int platform_set_fluence_type(void *platform, char *value)
+{
+ int ret = 0;
+ int fluence_type = FLUENCE_NONE;
+ int fluence_flag = NONE_FLAG;
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ ALOGV("%s: fluence type:%d", __func__, my_data->fluence_type);
+
+ /* only dual mic turn on and off is supported as of now through setparameters */
+ if (!strncmp(AUDIO_PARAMETER_VALUE_DUALMIC,value, sizeof(AUDIO_PARAMETER_VALUE_DUALMIC))) {
+ if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro")) ||
+ !strncmp("fluence", my_data->fluence_cap, sizeof("fluence"))) {
+ ALOGV("fluence dualmic feature enabled \n");
+ fluence_type = FLUENCE_DUAL_MIC;
+ fluence_flag = DMIC_FLAG;
+ } else {
+ ALOGE("%s: Failed to set DUALMIC", __func__);
+ ret = -1;
+ goto done;
+ }
+ } else if (!strncmp(AUDIO_PARAMETER_KEY_NO_FLUENCE, value, sizeof(AUDIO_PARAMETER_KEY_NO_FLUENCE))) {
+ ALOGV("fluence disabled");
+ fluence_type = FLUENCE_NONE;
+ } else {
+ ALOGE("Invalid fluence value : %s",value);
+ ret = -1;
+ goto done;
+ }
+
+ if (fluence_type != my_data->fluence_type) {
+ ALOGV("%s: Updating fluence_type to :%d", __func__, fluence_type);
+ my_data->fluence_type = fluence_type;
+ adev->acdb_settings = (adev->acdb_settings & FLUENCE_MODE_CLEAR) | fluence_flag;
+ }
+done:
+ return ret;
+}
+
+int platform_get_fluence_type(void *platform, char *value, uint32_t len)
+{
+ int ret = 0;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (my_data->fluence_type == FLUENCE_QUAD_MIC) {
+ strlcpy(value, "quadmic", len);
+ } else if (my_data->fluence_type == FLUENCE_DUAL_MIC) {
+ strlcpy(value, "dualmic", len);
+ } else if (my_data->fluence_type == FLUENCE_NONE) {
+ strlcpy(value, "none", len);
+ } else
+ ret = -1;
+
+ return ret;
+}
+
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
int ret = 0;
@@ -942,6 +1093,20 @@
return ret;
}
+int platform_get_sample_rate(void *platform, uint32_t *rate)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ int ret = 0;
+
+ if ((my_data->csd != NULL) && my_data->is_i2s_ext_modem) {
+ ret = my_data->csd->get_sample_rate(rate);
+ if (ret < 0) {
+ ALOGE("%s: csd_get_sample_rate error %d\n", __func__, ret);
+ }
+ }
+ return ret;
+}
+
int platform_set_voice_volume(void *platform, int volume)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -969,7 +1134,8 @@
mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
if (my_data->csd != NULL) {
- ret = my_data->csd->volume(ALL_SESSION_VSID, volume);
+ ret = my_data->csd->volume(ALL_SESSION_VSID, volume,
+ DEFAULT_VOLUME_RAMP_DURATION_MS);
if (ret < 0) {
ALOGE("%s: csd_volume error %d", __func__, ret);
}
@@ -986,7 +1152,7 @@
int ret = 0;
uint32_t set_values[ ] = {0,
ALL_SESSION_VSID,
- DEFAULT_VOLUME_RAMP_DURATION_MS};
+ DEFAULT_MUTE_RAMP_DURATION_MS};
set_values[0] = state;
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
@@ -999,7 +1165,8 @@
mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
if (my_data->csd != NULL) {
- ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state);
+ ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state,
+ DEFAULT_MUTE_RAMP_DURATION_MS);
if (ret < 0) {
ALOGE("%s: csd_mic_mute error %d", __func__, ret);
}
@@ -1007,6 +1174,44 @@
return ret;
}
+int platform_set_device_mute(void *platform, bool state, char *dir)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ struct mixer_ctl *ctl;
+ char *mixer_ctl_name = NULL;
+ int ret = 0;
+ uint32_t set_values[ ] = {0,
+ ALL_SESSION_VSID,
+ 0};
+ if(dir == NULL) {
+ ALOGE("%s: Invalid direction:%s", __func__, dir);
+ return -EINVAL;
+ }
+
+ if (!strncmp("rx", dir, sizeof("rx"))) {
+ mixer_ctl_name = "Voice Rx Device Mute";
+ } else if (!strncmp("tx", dir, sizeof("tx"))) {
+ mixer_ctl_name = "Voice Tx Device Mute";
+ } else {
+ return -EINVAL;
+ }
+
+ set_values[0] = state;
+ 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;
+ }
+
+ ALOGV("%s: Setting device mute state: %d, mixer ctrl:%s",
+ __func__,state, mixer_ctl_name);
+ mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+
+ return ret;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -1131,14 +1336,17 @@
snd_device = SND_DEVICE_OUT_HDMI ;
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
+ ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
+ audio_extn_set_afe_proxy_channel_mixer(adev, 2);
snd_device = SND_DEVICE_OUT_USB_HEADSET;
} else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
} else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
snd_device = SND_DEVICE_OUT_HANDSET;
} else if (devices & AUDIO_DEVICE_OUT_PROXY) {
- ALOGD("%s: setting sink capability for Proxy", __func__);
- audio_extn_set_afe_proxy_channel_mixer(adev);
+ channel_count = audio_extn_get_afe_proxy_channel_count();
+ ALOGD("%s: setting sink capability(%d) for Proxy", __func__, channel_count);
+ audio_extn_set_afe_proxy_channel_mixer(adev, channel_count);
snd_device = SND_DEVICE_OUT_AFE_PROXY;
} else {
ALOGE("%s: Unknown device(s) %#x", __func__, devices);
@@ -1218,7 +1426,10 @@
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
} else {
adev->acdb_settings |= DMIC_FLAG;
- snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
}
} else {
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
@@ -1253,7 +1464,10 @@
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
my_data->fluence_in_spkr_mode) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
@@ -1269,8 +1483,12 @@
set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_aec) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
+ my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
@@ -1286,8 +1504,12 @@
set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_ns) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
+ my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
@@ -1308,8 +1530,10 @@
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
channel_count == 1 ) {
if(my_data->fluence_type & FLUENCE_DUAL_MIC &&
- my_data->fluence_in_audio_rec)
+ my_data->fluence_in_audio_rec) {
snd_device = SND_DEVICE_IN_HANDSET_DMIC;
+ set_echo_reference(adev->mixer, EC_REF_RX);
+ }
}
} else if (source == AUDIO_SOURCE_FM_RX ||
source == AUDIO_SOURCE_FM_RX_A2DP) {
@@ -1660,24 +1884,8 @@
char *str = NULL;
char value[256] = {0};
int ret;
- int fluence_type;
char *kv_pairs = NULL;
- ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE,
- value, sizeof(value));
- if (ret >= 0) {
- if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
- strlcpy(value, "fluencepro", sizeof(value));
- } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- strlcpy(value, "fluence", sizeof(value));
- } else {
- strlcpy(value, "none", sizeof(value));
- }
-
- str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value);
- }
-
- memset(value, 0, sizeof(value));
ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
value, sizeof(value));
if (ret >= 0) {
@@ -1699,7 +1907,7 @@
kv_pairs = str_parms_to_str(reply);
ALOGV_IF(kv_pairs != NULL, "%s: exit: returns - %s", __func__, kv_pairs);
- free(reply);
+ free(kv_pairs);
}
/* Delay in Us */
@@ -1733,3 +1941,69 @@
else
return false;
}
+
+/* Read offload buffer size from a property.
+ * If value is not power of 2 round it to
+ * power of 2.
+ */
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
+{
+ char value[PROPERTY_VALUE_MAX] = {0};
+ uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ if((property_get("audio.offload.buffer.size.kb", value, "")) &&
+ atoi(value)) {
+ fragment_size = atoi(value) * 1024;
+ }
+
+ if (info != NULL && info->has_video && info->is_streaming) {
+ fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
+ ALOGV("%s: offload fragment size reduced for AV streaming to %d",
+ __func__, fragment_size);
+ }
+
+ fragment_size = ALIGN( fragment_size, 1024);
+
+ if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
+uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
+{
+ uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ uint32_t bits_per_sample = 16;
+
+ if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
+ bits_per_sample = 32;
+ }
+
+ if (!info->has_video) {
+ fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+
+ } else if (info->has_video && info->is_streaming) {
+ fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING
+ * info->sample_rate
+ * bits_per_sample
+ * popcount(info->channel_mask))/1000;
+
+ } else if (info->has_video) {
+ fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV
+ * info->sample_rate
+ * bits_per_sample
+ * popcount(info->channel_mask))/1000;
+ }
+
+ fragment_size = ALIGN( fragment_size, 1024);
+
+ if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+
+ ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9749be4..63d6fc6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -26,6 +26,11 @@
FLUENCE_QUAD_MIC = 0x2,
};
+enum {
+ FLUENCE_ENDFIRE = 0x1,
+ FLUENCE_BROADSIDE = 0x2,
+};
+
/*
* Below are the devices for which is back end is same, SLIMBUS_0_RX.
* All these devices are handled by the internal HW codec. We can
@@ -120,6 +125,11 @@
SND_DEVICE_IN_HANDSET_STEREO_DMIC,
SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
SND_DEVICE_IN_CAPTURE_VI_FEEDBACK,
+ SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -129,7 +139,7 @@
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
#define ALL_SESSION_VSID 0xFFFFFFFF
-#define DEFAULT_MUTE_RAMP_DURATION 500
+#define DEFAULT_MUTE_RAMP_DURATION_MS 20
#define DEFAULT_VOLUME_RAMP_DURATION_MS 20
#define MIXER_PATH_MAX_LENGTH 100
@@ -168,11 +178,19 @@
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
#define HFP_PCM_RX 5
-#define HFP_SCO_RX 23
-#define HFP_ASM_RX_TX 24
#define INCALL_MUSIC_UPLINK_PCM_DEVICE 1
+
+#ifdef PLATFORM_MSM8610
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 14
+#elif PLATFORM_MSM8x26
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
+#elif PLATFORM_MSM8974
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 35
+#else
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE -1
+#endif
+
#define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
#define SPKR_PROT_CALIB_TX_PCM_DEVICE 25
#define PLAYBACK_OFFLOAD_DEVICE 9
@@ -196,32 +214,44 @@
#define VOICE2_CALL_PCM_DEVICE 14
#define VOLTE_CALL_PCM_DEVICE 17
#define QCHAT_CALL_PCM_DEVICE 18
+#define VOWLAN_CALL_PCM_DEVICE 30
#elif PLATFORM_APQ8084
#define VOICE_CALL_PCM_DEVICE 20
-#define VOICE2_CALL_PCM_DEVICE 13
+#define VOICE2_CALL_PCM_DEVICE 28
#define VOLTE_CALL_PCM_DEVICE 21
#define QCHAT_CALL_PCM_DEVICE 06
+#define VOWLAN_CALL_PCM_DEVICE -1
#elif PLATFORM_MSM8610
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 13
#define VOLTE_CALL_PCM_DEVICE 15
#define QCHAT_CALL_PCM_DEVICE 14
+#define VOWLAN_CALL_PCM_DEVICE -1
#else
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 22
#define VOLTE_CALL_PCM_DEVICE 14
#define QCHAT_CALL_PCM_DEVICE 20
+#define VOWLAN_CALL_PCM_DEVICE -1
+#endif
+
+#ifdef PLATFORM_MSM8x26
+#define HFP_SCO_RX 28
+#define HFP_ASM_RX_TX 29
+#else
+#define HFP_SCO_RX 23
+#define HFP_ASM_RX_TX 24
#endif
#define LIB_CSD_CLIENT "libcsd-client.so"
/* CSD-CLIENT related functions */
-typedef int (*init_t)();
+typedef int (*init_t)(bool);
typedef int (*deinit_t)();
typedef int (*disable_device_t)();
typedef int (*enable_device_config_t)(int, int);
typedef int (*enable_device_t)(int, int, uint32_t);
-typedef int (*volume_t)(uint32_t, int);
-typedef int (*mic_mute_t)(uint32_t, int);
+typedef int (*volume_t)(uint32_t, int, uint16_t);
+typedef int (*mic_mute_t)(uint32_t, int, uint16_t);
typedef int (*slow_talk_t)(uint32_t, uint8_t);
typedef int (*start_voice_t)(uint32_t);
typedef int (*stop_voice_t)(uint32_t);
@@ -229,6 +259,7 @@
typedef int (*stop_playback_t)(uint32_t);
typedef int (*start_record_t)(uint32_t, int);
typedef int (*stop_record_t)(uint32_t);
+typedef int (*get_sample_rate_t)(uint32_t *);
/* CSD Client structure */
struct csd_data {
void *csd_client;
@@ -246,6 +277,7 @@
stop_playback_t stop_playback;
start_record_t start_record;
stop_record_t stop_record;
+ get_sample_rate_t get_sample_rate;
};
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 2c12ea6..bf6bdcb 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -28,6 +28,8 @@
void platform_add_backend_name(char *mixer_path, snd_device_t snd_device);
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
int platform_get_snd_device_index(char *snd_device_index_name);
+int platform_set_fluence_type(void *platform, char *value);
+int platform_get_fluence_type(void *platform, char *value, uint32_t len);
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
int platform_switch_voice_call_device_pre(void *platform);
@@ -44,6 +46,8 @@
int platform_stop_voice_call(void *platform, uint32_t vsid);
int platform_set_voice_volume(void *platform, int volume);
int platform_set_mic_mute(void *platform, bool state);
+int platform_get_sample_rate(void *platform, uint32_t *rate);
+int platform_set_device_mute(void *platform, bool state, char *dir);
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
int platform_set_hdmi_channels(void *platform, int channel_count);
@@ -63,6 +67,10 @@
bool platform_listen_update_status(snd_device_t snd_device);
/* From platform_info_parser.c */
-int platform_info_init(void);
+int platform_info_init(const char *filename);
+
+struct audio_offload_info_t;
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
+uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 8f56107..85a05eb 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -38,7 +38,6 @@
#include "platform_api.h"
#include <platform.h>
-#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
#define BUF_SIZE 1024
static void process_device(const XML_Char **attr)
@@ -52,20 +51,20 @@
index = platform_get_snd_device_index((char *)attr[1]);
if (index < 0) {
- ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH);
+ ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
+ __func__, attr[1]);
goto done;
}
if (strcmp(attr[2], "acdb_id") != 0) {
- ALOGE("%s: Device %s in %s has no acdb_id, no ACDB ID set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH);
+ ALOGE("%s: Device %s in platform info xml has no acdb_id, no ACDB ID set!",
+ __func__, attr[1]);
goto done;
}
if(platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
- ALOGE("%s: Device %s in %s, ACDB ID %d was not set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH, atoi((char *)attr[3]));
+ ALOGE("%s: Device %s in platform info xml ACDB ID %d was not set!",
+ __func__, attr[1], atoi((char *)attr[3]));
goto done;
}
@@ -91,7 +90,7 @@
}
-int platform_info_init(void)
+int platform_info_init(const char *filename)
{
XML_Parser parser;
FILE *file;
@@ -99,10 +98,10 @@
int bytes_read;
void *buf;
- file = fopen(PLATFORM_INFO_XML_PATH, "r");
+ file = fopen(filename, "r");
if (!file) {
ALOGD("%s: Failed to open %s, using defaults.",
- __func__, PLATFORM_INFO_XML_PATH);
+ __func__, filename);
ret = -ENODEV;
goto done;
}
@@ -134,7 +133,7 @@
if (XML_ParseBuffer(parser, bytes_read,
bytes_read == 0) == XML_STATUS_ERROR) {
ALOGE("%s: XML_ParseBuffer failed, for %s",
- __func__, PLATFORM_INFO_XML_PATH);
+ __func__, filename);
ret = -EINVAL;
goto err_free_parser;
}
diff --git a/hal/voice.c b/hal/voice.c
index 28d44db..ac067a3 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -106,6 +106,7 @@
int i, ret = 0;
struct audio_usecase *uc_info;
int pcm_dev_rx_id, pcm_dev_tx_id;
+ uint32_t sample_rate = 8000;
struct voice_session *session = NULL;
struct pcm_config voice_config = pcm_config_voice_call;
@@ -133,6 +134,13 @@
ret = -EIO;
goto error_start_voice;
}
+ ret = platform_get_sample_rate(adev->platform, &sample_rate);
+ if (ret < 0) {
+ ALOGE("platform_get_sample_rate error %d\n", ret);
+ } else {
+ voice_config.rate = sample_rate;
+ }
+ ALOGD("voice_config.rate %d\n", voice_config.rate);
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
__func__, adev->snd_card, pcm_dev_rx_id);
@@ -397,8 +405,7 @@
adev->voice.tty_mode = tty_mode;
adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
if (voice_is_in_call(adev))
- //todo: what about voice2, volte and qchat usecases?
- select_devices(adev, USECASE_VOICE_CALL);
+ voice_update_devices_for_all_voice_usecases(adev);
}
}
@@ -438,4 +445,19 @@
voice_extn_init(adev);
}
+void voice_update_devices_for_all_voice_usecases(struct audio_device *adev)
+{
+ struct listnode *node;
+ struct audio_usecase *usecase;
+
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == VOICE_CALL) {
+ ALOGV("%s: updating device for usecase:%s", __func__,
+ use_case_table[usecase->id]);
+ select_devices(adev, usecase->id);
+ }
+ }
+}
+
diff --git a/hal/voice.h b/hal/voice.h
index a7733b1..d160569 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -24,7 +24,7 @@
#define VOICE_SESS_IDX (BASE_SESS_IDX)
#ifdef MULTI_VOICE_SESSION_ENABLED
-#define MAX_VOICE_SESSIONS 4
+#define MAX_VOICE_SESSIONS 5
#else
#define MAX_VOICE_SESSIONS 1
#endif
@@ -86,4 +86,5 @@
struct stream_out *out);
int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
struct stream_in *in);
+void voice_update_devices_for_all_voice_usecases(struct audio_device *adev);
#endif //VOICE_H
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index 4db46f6..47ac2c8 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -59,8 +59,9 @@
struct pcm *pcm_rx;
struct pcm *pcm_tx;
struct stream_out *out_stream;
- int ref_count;
- int out_stream_count;
+ uint32_t out_stream_count;
+ uint32_t in_stream_count;
+ uint32_t sample_rate;
};
#define MODE_IS127 0x2
@@ -78,13 +79,15 @@
#define AUDIO_PARAMETER_VALUE_VOIP_TRUE "true"
#define AUDIO_PARAMETER_KEY_VOIP_CHECK "voip_flag"
#define AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT "voip_out_stream_count"
+#define AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE "voip_sample_rate"
static struct voip_data voip_data = {
.pcm_rx = NULL,
.pcm_tx = NULL,
.out_stream = NULL,
- .ref_count = 0,
- .out_stream_count = 0
+ .out_stream_count = 0,
+ .in_stream_count = 0,
+ .sample_rate = 0
};
static int voip_set_volume(struct audio_device *adev, int volume);
@@ -280,10 +283,10 @@
int i, ret = 0;
struct audio_usecase *uc_info;
- ALOGD("%s: enter, ref_count=%d", __func__, voip_data.ref_count);
- voip_data.ref_count--;
+ ALOGD("%s: enter, out_stream_count=%d, in_stream_count=%d",
+ __func__, voip_data.out_stream_count, voip_data.in_stream_count);
- if (!voip_data.ref_count) {
+ if (!voip_data.out_stream_count && !voip_data.in_stream_count) {
uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
if (uc_info == NULL) {
ALOGE("%s: Could not find the usecase (%d) in the list",
@@ -310,8 +313,10 @@
list_remove(&uc_info->list);
free(uc_info);
+ voip_data.sample_rate = 0;
} else
- ALOGV("%s: NO-OP because ref_count=%d", __func__, voip_data.ref_count);
+ ALOGV("%s: NO-OP because out_stream_count=%d, in_stream_count=%d",
+ __func__, voip_data.out_stream_count, voip_data.in_stream_count);
ALOGV("%s: exit: status(%d)", __func__, ret);
return ret;
@@ -327,12 +332,15 @@
ALOGD("%s: enter", __func__);
uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
- if ((uc_info == NULL) && (voip_data.out_stream)) {
+ if (uc_info == NULL) {
ALOGV("%s: voip usecase is added to the list", __func__);
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
uc_info->id = USECASE_COMPRESS_VOIP_CALL;
uc_info->type = VOIP_CALL;
- uc_info->stream.out = voip_data.out_stream;
+ if (voip_data.out_stream)
+ uc_info->stream.out = voip_data.out_stream;
+ else
+ uc_info->stream.out = adev->primary_output;
uc_info->in_snd_device = SND_DEVICE_NONE;
uc_info->out_snd_device = SND_DEVICE_NONE;
@@ -388,12 +396,15 @@
ALOGE("%s: error %d\n", __func__, ret);
goto error_start_voip;
}
- voip_data.ref_count = 0;
- }
- else
+ } else {
ALOGV("%s: voip usecase is already enabled", __func__);
+ if (voip_data.out_stream)
+ uc_info->stream.out = voip_data.out_stream;
+ else
+ uc_info->stream.out = adev->primary_output;
+ select_devices(adev, USECASE_COMPRESS_VOIP_CALL);
+ }
- voip_data.ref_count++;
return 0;
error_start_voip:
@@ -472,6 +483,13 @@
str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT,
voip_data.out_stream_count);
}
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE,
+ value, sizeof(value));
+ if (ret >= 0) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE,
+ voip_data.sample_rate);
+ }
}
void voice_extn_compress_voip_out_get_parameters(struct stream_out *out,
@@ -576,9 +594,9 @@
ALOGD("%s: enter", __func__);
+ voip_data.out_stream_count--;
ret = voip_stop_call(adev);
voip_data.out_stream = NULL;
- voip_data.out_stream_count--;
ALOGV("%s: exit: status(%d)", __func__, ret);
return ret;
@@ -600,7 +618,7 @@
voip_data.out_stream = out;
voip_data.out_stream_count++;
-
+ voip_data.sample_rate = out->sample_rate;
ret = voip_set_mode(out->dev, out->format);
ALOGV("%s: exit", __func__);
@@ -615,6 +633,7 @@
ALOGD("%s: enter", __func__);
+ voip_data.in_stream_count--;
status = voip_stop_call(adev);
ALOGV("%s: exit: status(%d)", __func__, status);
@@ -630,15 +649,25 @@
ALOGD("%s: enter", __func__);
+ if ((voip_data.sample_rate != 0) &&
+ (voip_data.sample_rate != in->config.rate)) {
+ ret = -ENOTSUP;
+ goto done;
+ } else {
+ voip_data.sample_rate = in->config.rate;
+ }
+
in->usecase = USECASE_COMPRESS_VOIP_CALL;
if (in->config.rate == 16000)
in->config = pcm_config_voip_wb;
else
in->config = pcm_config_voip_nb;
+ voip_data.in_stream_count++;
ret = voip_set_mode(in->dev, in->format);
- ALOGV("%s: exit", __func__);
+done:
+ ALOGV("%s: exit, ret=%d", __func__, ret);
return ret;
}
@@ -734,7 +763,8 @@
if (ret) {
if ((popcount(config->channel_mask) == 1) &&
(config->sample_rate == 8000 || config->sample_rate == 16000))
- ret = true;
+ ret = ((voip_data.sample_rate == 0) ? true:
+ (voip_data.sample_rate == config->sample_rate));
else
ret = false;
}
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 5612e0c..f6083f3 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -38,18 +38,22 @@
#define AUDIO_PARAMETER_KEY_CALL_STATE "call_state"
#define AUDIO_PARAMETER_KEY_AUDIO_MODE "audio_mode"
#define AUDIO_PARAMETER_KEY_ALL_CALL_STATES "all_call_states"
+#define AUDIO_PARAMETER_KEY_DEVICE_MUTE "device_mute"
+#define AUDIO_PARAMETER_KEY_DIRECTION "direction"
#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
#define VOICE2_VSID 0x10DC1000
#define VOLTE_VSID 0x10C02000
#define QCHAT_VSID 0x10803000
+#define VOWLAN_VSID 0x10002000
#define ALL_VSID 0xFFFFFFFF
/* Voice Session Indices */
#define VOICE2_SESS_IDX (VOICE_SESS_IDX + 1)
#define VOLTE_SESS_IDX (VOICE_SESS_IDX + 2)
#define QCHAT_SESS_IDX (VOICE_SESS_IDX + 3)
+#define VOWLAN_SESS_IDX (VOICE_SESS_IDX + 4)
/* Call States */
#define CALL_HOLD (BASE_CALL_STATE + 2)
@@ -83,7 +87,8 @@
if (vsid == VOICE_VSID ||
vsid == VOICE2_VSID ||
vsid == VOLTE_VSID ||
- vsid == QCHAT_VSID)
+ vsid == QCHAT_VSID ||
+ vsid == VOWLAN_VSID)
return true;
else
return false;
@@ -110,6 +115,10 @@
usecase_id = USECASE_QCHAT_CALL;
break;
+ case VOWLAN_SESS_IDX:
+ usecase_id = USECASE_VOWLAN_CALL;
+ break;
+
default:
ALOGE("%s: Invalid voice session index\n", __func__);
}
@@ -353,6 +362,7 @@
adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
adev->voice.session[VOLTE_SESS_IDX].vsid = VOLTE_VSID;
adev->voice.session[QCHAT_SESS_IDX].vsid = QCHAT_VSID;
+ adev->voice.session[VOWLAN_SESS_IDX].vsid = VOWLAN_VSID;
}
int voice_extn_get_session_from_use_case(struct audio_device *adev,
@@ -378,6 +388,10 @@
*session = &adev->voice.session[QCHAT_SESS_IDX];
break;
+ case USECASE_VOWLAN_CALL:
+ *session = &adev->voice.session[VOWLAN_SESS_IDX];
+ break;
+
default:
ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
*session = NULL;
@@ -428,6 +442,7 @@
int value;
int ret = 0, err;
char *kv_pairs = str_parms_to_str(parms);
+ char str_value[256] = {0};
ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
@@ -453,8 +468,34 @@
ret = -EINVAL;
goto done;
}
- } else {
- ALOGV("%s: Not handled here", __func__);
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE, str_value,
+ sizeof(str_value));
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE);
+ bool mute = false;
+
+ if (!strncmp("true", str_value, sizeof("true"))) {
+ mute = true;
+ }
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DIRECTION, str_value,
+ sizeof(str_value));
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_DIRECTION);
+ } else {
+ ALOGE("%s: direction key not found", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = platform_set_device_mute(adev->platform, mute, str_value);
+ if (ret != 0) {
+ ALOGE("%s: Failed to set mute err:%d", __func__, ret);
+ ret = -EINVAL;
+ goto done;
+ }
}
done:
diff --git a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
index 276eaa3..623caa8 100644
--- a/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
+++ b/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h
@@ -1,5 +1,5 @@
/*--------------------------------------------------------------------------
-Copyright (c) 2010, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2014, 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:
@@ -358,7 +358,10 @@
OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x7
};
-
+ #define MIN_BITRATE 24000
+ #define MAX_BITRATE 192000
+ #define MAX_BITRATE_MULFACTOR 12
+ #define BITRATE_DIVFACTOR 2
typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*>
input_buffer_map;
@@ -619,6 +622,7 @@
OMX_U8 num_bits_reqd,
OMX_U32 value,
OMX_U16 *hdr_bit_index);
+ int get_updated_bit_rate(int bitrate);
};
#endif
diff --git a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
index 52aa915..6521265 100644
--- a/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
+++ b/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp
@@ -1,5 +1,5 @@
/*--------------------------------------------------------------------------
-Copyright (c) 2010, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2014, 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:
@@ -1438,10 +1438,12 @@
}
drv_aac_enc_config.channels = m_aac_param.nChannels;
drv_aac_enc_config.sample_rate = m_aac_param.nSampleRate;
- drv_aac_enc_config.bit_rate = m_aac_param.nBitRate;
- DEBUG_PRINT("aac config %lu,%lu,%lu %d\n",
+ drv_aac_enc_config.bit_rate =
+ get_updated_bit_rate(m_aac_param.nBitRate);
+ DEBUG_PRINT("aac config %lu,%lu,%lu %d updated bitrate %d\n",
m_aac_param.nChannels,m_aac_param.nSampleRate,
- m_aac_param.nBitRate,m_aac_param.eAACStreamFormat);
+ m_aac_param.nBitRate,m_aac_param.eAACStreamFormat,
+ drv_aac_enc_config.bit_rate);
switch(m_aac_param.eAACStreamFormat)
{
@@ -5014,3 +5016,44 @@
}
+int omx_aac_aenc::get_updated_bit_rate(int bitrate)
+{
+ int updated_rate, min_bitrate, max_bitrate;
+
+ max_bitrate = m_aac_param.nSampleRate *
+ MAX_BITRATE_MULFACTOR;
+ switch(m_aac_param.eAACProfile)
+ {
+ case OMX_AUDIO_AACObjectLC:
+ min_bitrate = m_aac_param.nSampleRate;
+ if (m_aac_param.nChannels == 1) {
+ min_bitrate = min_bitrate/BITRATE_DIVFACTOR;
+ max_bitrate = max_bitrate/BITRATE_DIVFACTOR;
+ }
+ break;
+ case OMX_AUDIO_AACObjectHE:
+ min_bitrate = MIN_BITRATE;
+ if (m_aac_param.nChannels == 1)
+ max_bitrate = max_bitrate/BITRATE_DIVFACTOR;
+ break;
+ case OMX_AUDIO_AACObjectHE_PS:
+ min_bitrate = MIN_BITRATE;
+ break;
+ default:
+ return bitrate;
+ break;
+ }
+ /* Update MIN and MAX values*/
+ if (min_bitrate > MIN_BITRATE)
+ min_bitrate = MIN_BITRATE;
+ if (max_bitrate > MAX_BITRATE)
+ max_bitrate = MAX_BITRATE;
+ /* Update the bitrate in the range */
+ if (bitrate < min_bitrate)
+ updated_rate = min_bitrate;
+ else if(bitrate > max_bitrate)
+ updated_rate = max_bitrate;
+ else
+ updated_rate = bitrate;
+ return updated_rate;
+}
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index c68ab6e..4f3a737 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -29,6 +29,9 @@
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_INCALL_MUSIC)),true)
LOCAL_CFLAGS += -DAUDIO_EXTN_INCALL_MUSIC_ENABLED
endif
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_HDMI_SPK)),true)
+LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
+endif
ifeq ($(strip $(TARGET_BOARD_PLATFORM)),msm8916)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 5142353..8947456 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -44,6 +44,7 @@
// ----------------------------------------------------------------------------
// AudioPolicyInterface implementation
// ----------------------------------------------------------------------------
+const char* AudioPolicyManager::HDMI_SPKR_STR = "hdmi_spkr";
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
AudioSystem::device_connection_state state,
@@ -85,6 +86,15 @@
// handle output device connection
case AudioSystem::DEVICE_STATE_AVAILABLE:
if (mAvailableOutputDevices & device) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, HDMI_SPKR_STR, MAX_DEVICE_ADDRESS_LEN)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device already connected: %x", device);
return INVALID_OPERATION;
}
@@ -98,6 +108,18 @@
// register new device as available
mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, HDMI_SPKR_STR, MAX_DEVICE_ADDRESS_LEN)) {
+ mHdmiAudioDisabled = false;
+ } else {
+ mHdmiAudioEvent = true;
+ }
+ if (mHdmiAudioDisabled || !mHdmiAudioEvent) {
+ mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);
+ }
+ }
+#endif
if (!outputs.isEmpty()) {
String8 paramStr;
if (mHasA2dp && audio_is_a2dp_device(device)) {
@@ -127,6 +149,15 @@
// handle output device disconnection
case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
if (!(mAvailableOutputDevices & device)) {
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, HDMI_SPKR_STR, MAX_DEVICE_ADDRESS_LEN)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
ALOGW("setDeviceConnectionState() device not connected: %x", device);
return INVALID_OPERATION;
}
@@ -135,6 +166,15 @@
// remove device from available output devices
mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);
+#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
+ if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
+ if (!strncmp(device_address, HDMI_SPKR_STR, MAX_DEVICE_ADDRESS_LEN)) {
+ mHdmiAudioDisabled = true;
+ } else {
+ mHdmiAudioEvent = false;
+ }
+ }
+#endif
checkOutputsForDevice(device, state, outputs);
if (mHasA2dp && audio_is_a2dp_device(device)) {
// handle A2DP device disconnection
@@ -1116,16 +1156,6 @@
return false;
}
#endif
-
- // Check if offload has been disabled
- char propValue[PROPERTY_VALUE_MAX];
- if (property_get("audio.offload.disable", propValue, "0")) {
- if (atoi(propValue) != 0) {
- ALOGV("offload disabled by audio.offload.disable=%s", propValue );
- return false;
- }
- }
-
// Check if stream type is music, then only allow offload as of now.
if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
{
@@ -1133,26 +1163,65 @@
return false;
}
- //TODO: enable audio offloading with video when ready
- if (offloadInfo.has_video)
- {
- if(property_get("av.offload.enable", propValue, NULL)) {
+ char propValue[PROPERTY_VALUE_MAX];
+ bool pcmOffload = false;
+ if (audio_is_offload_pcm(offloadInfo.format)) {
+ if(property_get("audio.offload.pcm.enable", propValue, NULL)) {
bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
- if (!prop_enabled) {
- ALOGW("offload disabled by av.offload.enable = %s ", propValue );
- return false;
+ if (prop_enabled) {
+ ALOGW("PCM offload property is enabled");
+ pcmOffload = true;
}
}
- if(offloadInfo.is_streaming &&
- property_get("av.streaming.offload.enable", propValue, NULL)) {
- bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
- if (!prop_enabled) {
- ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
- return false;
+ if (!pcmOffload) {
+ ALOGV("PCM offload disabled by property audio.offload.pcm.enable");
+ return false;
+ }
+ }
+
+ if (!pcmOffload) {
+ // Check if offload has been disabled
+ if (property_get("audio.offload.disable", propValue, "0")) {
+ if (atoi(propValue) != 0) {
+ ALOGV("offload disabled by audio.offload.disable=%s", propValue );
+ return false;
}
}
- ALOGV("isOffloadSupported: has_video == true, property\
- set to enable offload");
+
+ //check if it's multi-channel AAC format
+ if (AudioSystem::popCount(offloadInfo.channel_mask) > 2
+ && offloadInfo.format == AUDIO_FORMAT_AAC) {
+ ALOGV("offload disabled for multi-channel AAC format");
+ return false;
+ }
+
+ if (offloadInfo.has_video)
+ {
+ if(property_get("av.offload.enable", propValue, NULL)) {
+ bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+ if (!prop_enabled) {
+ ALOGW("offload disabled by av.offload.enable = %s ", propValue );
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ if(offloadInfo.is_streaming) {
+ if (property_get("av.streaming.offload.enable", propValue, NULL)) {
+ bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+ if (!prop_enabled) {
+ ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
+ return false;
+ }
+ } else {
+ //Do not offload AV streamnig if the property is not defined
+ return false;
+ }
+ }
+ ALOGV("isOffloadSupported: has_video == true, property\
+ set to enable offload");
+ }
}
//If duration is less than minimum value defined in property, return false
@@ -1165,7 +1234,7 @@
ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
//duration checks only valid for MP3/AAC formats,
//do not check duration for other audio formats, e.g. dolby AAC/AC3 and amrwb+ formats
- if (offloadInfo.format == AUDIO_FORMAT_MP3 || offloadInfo.format == AUDIO_FORMAT_AAC)
+ if (offloadInfo.format == AUDIO_FORMAT_MP3 || offloadInfo.format == AUDIO_FORMAT_AAC || pcmOffload)
return false;
}
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 34ca701..188488a 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -35,7 +35,9 @@
public:
AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
- : AudioPolicyManagerBase(clientInterface) {}
+ : AudioPolicyManagerBase(clientInterface) {
+ mHdmiAudioDisabled = false;
+ mHdmiAudioEvent = false; }
virtual ~AudioPolicyManager() {}
@@ -89,5 +91,13 @@
// returns the category the device belongs to with regard to volume curve management
static device_category getDeviceCategory(audio_devices_t device);
+ static const char* HDMI_SPKR_STR;
+
+ //parameter indicates of HDMI speakers disabled from the Qualcomm settings
+ bool mHdmiAudioDisabled;
+
+ //parameter indicates if HDMI plug in/out detected
+ bool mHdmiAudioEvent;
+
};
};
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index b6966e6..2cb910c 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -25,7 +25,7 @@
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
- kernel/include/sound \
+ $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
$(call include-path-for, audio-effects)
include $(BUILD_SHARED_LIBRARY)
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index c724b58..8a19038 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -23,7 +23,7 @@
#include <cutils/list.h>
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include <audio_effects/effect_bassboost.h>
#include "effect_api.h"
@@ -153,7 +153,10 @@
bass_ctxt->device = device;
if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
- (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) ||
+ (device == AUDIO_DEVICE_OUT_PROXY) ||
+ (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
+ (device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
bass_ctxt->temp_disabled = true;
@@ -211,9 +214,14 @@
bassboost_context_t *bass_ctxt = (bassboost_context_t *)context;
ALOGV("%s", __func__);
-
- if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)))
+ if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
+ if (bass_ctxt->ctl && bass_ctxt->strength)
+ offload_bassboost_send_params(bass_ctxt->ctl,
+ bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ }
return 0;
}
diff --git a/post_proc/bundle.h b/post_proc/bundle.h
index a8e0f93..7ebea92 100644
--- a/post_proc/bundle.h
+++ b/post_proc/bundle.h
@@ -21,7 +21,7 @@
#define OFFLOAD_EFFECT_BUNDLE_H
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include "effect_api.h"
/* Retry for delay for mixer open */
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index a2e4f45..b7cf469 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -33,7 +33,7 @@
#include <stdbool.h>
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include "effect_api.h"
@@ -391,7 +391,7 @@
{
ALOGV("%s", __func__);
if (preset && (preset <= NUM_OSL_REVERB_PRESETS_SUPPORTED))
- reverb->preset = map_reverb_opensl_preset_2_offload_preset[preset][1];
+ reverb->preset = map_reverb_opensl_preset_2_offload_preset[preset-1][1];
}
void offload_reverb_set_wet_mix(struct reverb_params *reverb, int wet_mix)
diff --git a/post_proc/equalizer.c b/post_proc/equalizer.c
index 7c7ced2..bde8ef8 100644
--- a/post_proc/equalizer.c
+++ b/post_proc/equalizer.c
@@ -23,7 +23,7 @@
#include <cutils/list.h>
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include <audio_effects/effect_equalizer.h>
#include "effect_api.h"
diff --git a/post_proc/reverb.c b/post_proc/reverb.c
index d104073..7c50430 100644
--- a/post_proc/reverb.c
+++ b/post_proc/reverb.c
@@ -23,7 +23,7 @@
#include <cutils/list.h>
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include <audio_effects/effect_environmentalreverb.h>
#include <audio_effects/effect_presetreverb.h>
@@ -309,6 +309,7 @@
return -EINVAL;
*(uint16_t *)value = reverb_ctxt->next_preset;
ALOGV("get REVERB_PARAM_PRESET, preset %d", reverb_ctxt->next_preset);
+ return 0;
}
switch (param) {
case REVERB_PARAM_ROOM_LEVEL:
@@ -464,6 +465,7 @@
return -EINVAL;
}
reverb_set_preset(reverb_ctxt, preset);
+ return 0;
}
switch (param) {
case REVERB_PARAM_PROPERTIES:
@@ -603,6 +605,14 @@
ALOGV("%s", __func__);
reverb_ctxt->ctl = output->ctl;
+ if (offload_reverb_get_enable_flag(&(reverb_ctxt->offload_reverb))) {
+ if (reverb_ctxt->ctl && reverb_ctxt->preset) {
+ offload_reverb_send_params(reverb_ctxt->ctl, reverb_ctxt->offload_reverb,
+ OFFLOAD_SEND_REVERB_ENABLE_FLAG |
+ OFFLOAD_SEND_REVERB_PRESET);
+ }
+ }
+
return 0;
}
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index e9eb728..d2957e9 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -23,7 +23,7 @@
#include <cutils/list.h>
#include <cutils/log.h>
#include <tinyalsa/asoundlib.h>
-#include <audio_effects.h>
+#include <sound/audio_effects.h>
#include <audio_effects/effect_virtualizer.h>
#include "effect_api.h"
@@ -153,7 +153,10 @@
virt_ctxt->device = device;
if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
- (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) ||
+ (device == AUDIO_DEVICE_OUT_PROXY) ||
+ (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
+ (device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
virt_ctxt->temp_disabled = true;
@@ -210,9 +213,14 @@
virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context;
ALOGV("%s", __func__);
-
- if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)))
+ if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
+ if (virt_ctxt->ctl && virt_ctxt->strength)
+ offload_virtualizer_send_params(virt_ctxt->ctl,
+ virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG |
+ OFFLOAD_SEND_BASSBOOST_STRENGTH);
+ }
return 0;
}