hal: Add support to enable VBat feature
Add support to enable VBat feature. This includes required changes
to select VBat speaker devices for audio and voice usecases and
sending the VBat calibration data to codec driver.
Change-Id: I2234bee3cc4d6f16934a4b27ef9da21cde74bb48
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index f341241..2dfd764 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -130,6 +130,7 @@
char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
[WCD9XXX_ANC_CAL] = "anc_cal",
[WCD9XXX_MBHC_CAL] = "mbhc_cal",
+ [WCD9XXX_VBAT_CAL] = "vbat_cal",
};
enum {
@@ -174,6 +175,7 @@
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
typedef int (*acdb_send_common_top_t) (void);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -206,6 +208,9 @@
bool ec_ref_enabled;
bool is_i2s_ext_modem;
bool is_acdb_initialized;
+ /* Vbat monitor related flags */
+ bool is_vbat_speaker;
+ bool gsm_mode_enabled;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -218,6 +223,7 @@
acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
acdb_get_default_app_type_t acdb_get_default_app_type;
acdb_send_common_top_t acdb_send_common_top;
+ acdb_set_codec_data_t acdb_set_codec_data;
void *hw_info;
acdb_send_gain_dep_cal_t acdb_send_gain_dep_cal;
@@ -312,6 +318,7 @@
[SND_DEVICE_OUT_SPEAKER] = "speaker",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = "speaker-ext-1",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = "speaker-vbat",
[SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
[SND_DEVICE_OUT_HEADPHONES] = "headphones",
[SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
@@ -320,6 +327,7 @@
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = "speaker-and-headphones-ext-2",
[SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
[SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = "voice-speaker-vbat",
[SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
@@ -341,6 +349,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = "speaker-protected-vbat",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = "voice-speaker-protected-vbat",
/* Capture sound devices */
[SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -410,6 +420,7 @@
[SND_DEVICE_OUT_SPEAKER] = 14,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 130,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = 14,
[SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
[SND_DEVICE_OUT_HEADPHONES] = 10,
[SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
@@ -418,6 +429,7 @@
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
[SND_DEVICE_OUT_VOICE_HANDSET] = 7,
[SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = 14,
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
@@ -439,6 +451,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = 103,
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = 124,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = 101,
[SND_DEVICE_IN_HANDSET_MIC] = 4,
[SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = 4,
@@ -510,6 +524,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
@@ -518,6 +533,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
@@ -538,6 +554,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_EXTERNAL)},
{TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)},
@@ -768,7 +786,26 @@
return ret_val;
}
-void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
+void platform_set_gsm_mode(void *platform, bool enable)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+
+ if (my_data->gsm_mode_enabled) {
+ my_data->gsm_mode_enabled = false;
+ ALOGV("%s: disabling gsm mode", __func__);
+ audio_route_reset_and_update_path(adev->audio_route, "gsm-mode");
+ }
+
+ if (enable) {
+ my_data->gsm_mode_enabled = true;
+ ALOGD("%s: enabling gsm mode", __func__);
+ audio_route_apply_and_update_path(adev->audio_route, "gsm-mode");
+ }
+}
+
+void platform_set_echo_reference(struct audio_device *adev, bool enable,
+ audio_devices_t out_device)
{
struct platform_data *my_data = (struct platform_data *)adev->platform;
snd_device_t snd_device = SND_DEVICE_NONE;
@@ -778,20 +815,27 @@
if (strcmp(my_data->ec_ref_mixer_path, "")) {
ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
- audio_route_reset_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
+ audio_route_reset_and_update_path(adev->audio_route,
+ my_data->ec_ref_mixer_path);
}
if (enable) {
- strlcpy(my_data->ec_ref_mixer_path, "echo-reference", sizeof(my_data->ec_ref_mixer_path));
snd_device = platform_get_output_snd_device(adev->platform, &out);
+
/*
* If native audio device reference count > 0, then apply codec EC otherwise
- * fallback to headphones if so or default
+ * fallback to Speakers with VBat if enabled or default
*/
if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
- platform_add_backend_name(my_data->ec_ref_mixer_path, SND_DEVICE_OUT_HEADPHONES_44_1);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference headphones-44.1",
+ sizeof(my_data->ec_ref_mixer_path));
+ else if ((snd_device == SND_DEVICE_OUT_SPEAKER_VBAT) ||
+ (snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT))
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference speaker-vbat",
+ sizeof(my_data->ec_ref_mixer_path));
else
- platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);
+ strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
+ sizeof(my_data->ec_ref_mixer_path));
ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
audio_route_apply_and_update_path(adev->audio_route, my_data->ec_ref_mixer_path);
@@ -999,6 +1043,7 @@
backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
backend_table[SND_DEVICE_OUT_HEADPHONES] = strdup("headphones");
backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+ backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("voice-speaker-vbat");
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1054,7 +1099,38 @@
void *buff;
};
-static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static int send_vbat_adc_data_to_acdb(struct platform_data *plat_data, char *cal_type)
+{
+ int ret = 0;
+ struct mixer_ctl *ctl;
+ uint16_t vbat_adc_data[2];
+ struct platform_data *my_data = plat_data;
+ struct audio_device *adev = my_data->adev;
+
+ const char *mixer_ctl_name = "Vbat ADC data";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer ctl name - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ vbat_adc_data[0] = mixer_ctl_get_value(ctl, 0);
+ vbat_adc_data[1] = mixer_ctl_get_value(ctl, 1);
+
+ ALOGD("%s: Vbat ADC output values: Dcp1: %d , Dcp2: %d",
+ __func__, vbat_adc_data[0], vbat_adc_data[1]);
+
+ ret = my_data->acdb_set_codec_data(&vbat_adc_data[0], cal_type);
+
+done:
+ return ret;
+}
+
+static void send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration,
+ struct platform_data *plat_data, int fd)
{
int type;
@@ -1068,6 +1144,13 @@
continue;
ret = 0;
+
+ if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+ ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
+ if (ret < 0)
+ ALOGE("%s error in sending vbat adc data to acdb", __func__);
+ }
+
calib.get_size = 1;
ret = acdb_loader_get_calibration(cal_name_info[type],
sizeof(struct param_data),
@@ -1128,7 +1211,7 @@
return;
}
- send_codec_cal(acdb_loader_get_calibration, fd);
+ send_codec_cal(acdb_loader_get_calibration, plat_data, fd);
}
static int platform_acdb_init(void *platform)
@@ -1168,7 +1251,7 @@
char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
- int retry_num = 0, snd_card_num = 0, key = 0, ret = 0;
+ int retry_num = 0, snd_card_num = 0, key = 0;
const char *snd_card_name;
char *cvd_version = NULL;
char *snd_internal_name = NULL;
@@ -1328,6 +1411,12 @@
}
}
+ /* Check if Vbat speaker enabled property is set, this should be done before acdb init */
+ bool ret = false;
+ ret = audio_extn_can_use_vbat();
+ if (ret)
+ my_data->is_vbat_speaker = true;
+
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1390,6 +1479,14 @@
ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
+ my_data->acdb_handle,
+ "acdb_loader_set_codec_data");
+ if (!my_data->acdb_set_codec_data)
+ ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+ __func__, LIB_ACDB_LOADER);
+
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
if (my_data->acdb_init == NULL) {
@@ -1436,7 +1533,6 @@
audio_extn_spkr_prot_init(adev);
audio_extn_dolby_set_license(adev);
- audio_hwdep_send_cal(my_data);
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -1542,13 +1638,20 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase)
{
if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
return;
}
+ if((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ !(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
+ ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
+ return;
+ }
+
const char * suffix = backend_table[snd_device];
if (suffix != NULL) {
@@ -1902,10 +2005,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -1962,10 +2069,14 @@
if (my_data->csd == NULL)
return ret;
- if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ if ((out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER ||
+ out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2224,7 +2335,10 @@
else
snd_device = SND_DEVICE_OUT_BT_SCO;
} else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
- snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
+ else
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
} else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
snd_device = SND_DEVICE_OUT_USB_HEADSET;
@@ -2263,6 +2377,8 @@
snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_2;
else if (adev->speaker_lr_swap)
snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
+ else if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
else
snd_device = SND_DEVICE_OUT_SPEAKER;
} else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {