Promotion of audio-userspace.lnx.2.2-00019.
CRs Change ID Subject
--------------------------------------------------------------------------------------------------------------
1081424 I2877239e61d3841e6ae90af2d39fb0b93cc2b6db audio: Changes to support Aptx decoder in offload mode
1116977 I62193c26731f115695cff4386b96917b672eeec6 hal: audio: correct ANC headphone path
1111827 I217f72be4471fbe998f7d684b3c08399729725a3 hal: parse wav header based on chunksize
1081424 Ia287a27c86f63fea16cdb35d553de6e2e853b4e9 audio: Add support for multiple metainfo keys update
1081424 Ie7913d5a0b0091ce50d9066b7d85100e7f884f83 qahw: test: Add support to test aptx decoder
1071692 I326cb9e906268566ecc4a7639804f06585b4004b hal: audio: Add support to pick 32KHz and 144KHz samplin
Change-Id: Ic126658515dc6436c23e51f366f0f1f82141ca77
CRs-Fixed: 1071692, 1111827, 1116977, 1081424
diff --git a/configs/msm8998/audio_platform_info.xml b/configs/msm8998/audio_platform_info.xml
index 3bc8c11..d6ac0d5 100644
--- a/configs/msm8998/audio_platform_info.xml
+++ b/configs/msm8998/audio_platform_info.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
-<!-- Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved. -->
+<!-- Copyright (c) 2014, 2016-2017, 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 -->
@@ -95,11 +95,14 @@
<device name="SND_DEVICE_OUT_BT_A2DP" backend="bt-a2dp" interface="SLIMBUS_7_RX"/>
<device name="SND_DEVICE_OUT_LINE" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_ANC_HEADSET" backend="headphones" interface="SLIMBUS_6_RX"/>
+ <device name="SND_DEVICE_OUT_ANC_FB_HEADSET" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES" backend="speaker-and-headphones" interface="SLIMBUS_0_RX-and-SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_SPEAKER_AND_LINE" backend="speaker-and-headphones" interface="SLIMBUS_0_RX-and-SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET" backend="speaker-and-headphones" interface="SLIMBUS_0_RX-and-SLIMBUS_6_RX"/>
+ <device name="SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET" backend="speaker-and-headphones" interface="SLIMBUS_0_RX-and-SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_VOICE_HEADPHONES" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_VOICE_ANC_HEADSET" backend="headphones" interface="SLIMBUS_6_RX"/>
+ <device name="SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_VOICE_LINE" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES" backend="headphones" interface="SLIMBUS_6_RX"/>
<device name="SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES" backend="headphones" interface="SLIMBUS_6_RX"/>
diff --git a/configs/msm8998/mixer_paths_tavil.xml b/configs/msm8998/mixer_paths_tavil.xml
index b2c6fd9..7fbef34 100644
--- a/configs/msm8998/mixer_paths_tavil.xml
+++ b/configs/msm8998/mixer_paths_tavil.xml
@@ -347,8 +347,8 @@
<ctl name="RX7 Digital Volume" value="84" />
<ctl name="ADC1 Volume" value="12" />
<ctl name="ADC2 Volume" value="12" />
- <ctl name="ADC3 Volume" value="12" />
- <ctl name="ADC4 Volume" value="12" />
+ <ctl name="ADC3 Volume" value="0" />
+ <ctl name="ADC4 Volume" value="0" />
<ctl name="DEC0 Volume" value="84" />
<ctl name="DEC1 Volume" value="84" />
<ctl name="DEC2 Volume" value="84" />
@@ -406,6 +406,7 @@
<ctl name="AMIC MUX12" value="ZERO" />
<ctl name="AMIC MUX13" value="ZERO" />
+ <ctl name="AMIC4_5 SEL" value="AMIC4" />
<!-- CDC_IF and SLIM controls -->
<ctl name="SLIM RX0 MUX" value="ZERO" />
<ctl name="SLIM RX1 MUX" value="ZERO" />
@@ -525,6 +526,8 @@
<ctl name="ANC OUT EAR Enable Switch" value="0" />
<ctl name="ANC OUT EAR SPKR Enable Switch" value="0" />
<ctl name="ANC SPKR PA Enable Switch" value="0" />
+ <ctl name="ANC OUT HPHL Enable Switch" value="0" />
+ <ctl name="ANC OUT HPHR Enable Switch" value="0" />
<!-- vbat related data -->
<!-- vbat related data end -->
@@ -2145,7 +2148,27 @@
</path>
<path name="anc-headphones">
- <path name="headphones" />
+ <ctl name="COMP1 Switch" value="0" />
+ <ctl name="COMP2 Switch" value="0" />
+ <ctl name="ANC Function" value="ON" />
+ <ctl name="ANC Slot" value="0" />
+ <ctl name="SLIM RX2 MUX" value="AIF4_PB" />
+ <ctl name="SLIM RX3 MUX" value="AIF4_PB" />
+ <ctl name="SLIM_6_RX Channels" value="Two" />
+ <ctl name="ADC MUX10" value="AMIC" />
+ <ctl name="AMIC MUX10" value="ADC3" />
+ <ctl name="ADC MUX12" value="AMIC" />
+ <ctl name="AMIC MUX12" value="ADC4" />
+ <ctl name="ANC0 FB MUX" value="ANC_IN_HPHL" />
+ <ctl name="ANC1 FB MUX" value="ANC_IN_HPHR" />
+ <ctl name="ADC3 Volume" value="8" />
+ <ctl name="ADC4 Volume" value="8" />
+ <ctl name="RX INT1_1 MIX1 INP0" value="RX2" />
+ <ctl name="RX INT2_1 MIX1 INP0" value="RX3" />
+ <ctl name="RX1 Digital Volume" value="81" />
+ <ctl name="RX2 Digital Volume" value="81" />
+ <ctl name="ANC OUT HPHL Enable Switch" value="1" />
+ <ctl name="ANC OUT HPHR Enable Switch" value="1" />
</path>
<path name="speaker-and-anc-headphones">
@@ -2155,6 +2178,7 @@
<path name="anc-fb-headphones">
<path name="anc-headphones" />
+ <ctl name="ANC Slot" value="1" />
</path>
<path name="speaker-and-anc-fb-headphones">
@@ -2163,11 +2187,11 @@
</path>
<path name="voice-anc-headphones">
- <path name="voice-headphones" />
+ <path name="anc-headphones" />
</path>
<path name="voice-anc-fb-headphones">
- <path name="voice-headphones" />
+ <path name="anc-fb-headphones" />
</path>
<path name="speaker-and-anc-headphones-liquid">
diff --git a/configure.ac b/configure.ac
index 694697c..16544a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,6 +106,7 @@
AM_CONDITIONAL([COMPRESS_PASSTHROUGH], [test x$AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH = xtrue])
AM_CONDITIONAL([KEEP_ALIVE], [test x$AUDIO_FEATURE_ENABLED_KEEP_ALIVE = xtrue])
AM_CONDITIONAL([GEF], [test x$AUDIO_FEATURE_ENABLED_GEF_SUPPORT = xtrue])
+AM_CONDITIONAL([APTX_DECODER], [test x$AUDIO_FEATURE_ENABLED_APTX_DECODER = xtrue])
AC_CONFIG_FILES([ \
Makefile \
diff --git a/hal/Makefile.am b/hal/Makefile.am
index ba53446..e72d350 100644
--- a/hal/Makefile.am
+++ b/hal/Makefile.am
@@ -148,6 +148,10 @@
c_sources += audio_extn/gef.c
endif
+if APTX_DECODER
+AM_CFLAGS += -DAPTX_DECODER_ENABLED
+endif
+
h_sources = audio_extn/audio_defs.h \
audio_extn/audio_extn.h \
audio_hw.h \
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 94b43ba..ae90cb3 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2017, 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
@@ -128,14 +128,26 @@
uint16_t gain_step;
};
+struct aptx_dec_bt_addr {
+ uint32_t nap;
+ uint32_t uap;
+ uint32_t lap;
+};
+
+struct aptx_dec_param {
+ struct aptx_dec_bt_addr bt_addr;
+};
+
typedef union {
struct source_tracking_param st_params;
struct sound_focus_param sf_params;
+ struct aptx_dec_param aptx_params;
} audio_extn_param_payload;
typedef enum {
AUDIO_EXTN_PARAM_SOURCE_TRACK,
- AUDIO_EXTN_PARAM_SOUND_FOCUS
+ AUDIO_EXTN_PARAM_SOUND_FOCUS,
+ AUDIO_EXTN_PARAM_APTX_DEC
} audio_extn_param_id;
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index d2e5434..5a244e5 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -66,6 +66,7 @@
bool vbat_enabled;
bool hifi_audio_enabled;
bool ras_enabled;
+ struct aptx_dec_bt_addr addr;
};
static struct audio_extn_module aextnmod;
@@ -77,6 +78,7 @@
/* Query offload playback instances count */
#define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
#define AUDIO_PARAMETER_HPX "HPX"
+#define AUDIO_PARAMETER_APTX_DEC_BT_ADDR "bt_addr"
/*
* update sysfs node hdmi_audio_cb to enable notification acknowledge feature
@@ -762,7 +764,7 @@
return ret;
}
-void audio_extn_init(void)
+void audio_extn_init(struct audio_device *adev)
{
aextnmod.anc_enabled = 0;
aextnmod.aanc_enabled = 0;
@@ -771,6 +773,12 @@
aextnmod.hpx_enabled = 0;
aextnmod.vbat_enabled = 0;
aextnmod.hifi_audio_enabled = 0;
+ aextnmod.addr.nap = 0;
+ aextnmod.addr.uap = 0;
+ aextnmod.addr.lap = 0;
+
+ audio_extn_dolby_set_license(adev);
+ audio_extn_aptx_dec_set_license(adev);
}
void audio_extn_set_parameters(struct audio_device *adev,
@@ -798,6 +806,7 @@
audio_extn_qaf_set_parameters(adev, parms);
if (adev->offload_effects_set_parameters != NULL)
adev->offload_effects_set_parameters(parms);
+ audio_extn_set_aptx_dec_bt_addr(adev, parms);
}
void audio_extn_get_parameters(const struct audio_device *adev,
@@ -1217,3 +1226,83 @@
update_params);
}
}
+
+#ifdef APTX_DECODER_ENABLED
+static void audio_extn_aptx_dec_set_license(struct audio_device *adev)
+{
+ int ret, key = 0;
+ char value[128] = {0};
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "APTX Dec License";
+
+ 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;
+ }
+ key = platform_get_meta_info_key_from_list(adev->platform, "aptx");
+
+ ALOGD("%s Setting APTX License with key:0x%x",__func__, key);
+ ret = mixer_ctl_set_value(ctl, 0, key);
+ if (ret)
+ ALOGE("%s: cannot set license, error:%d",__func__, ret);
+}
+
+static void audio_extn_set_aptx_dec_bt_addr(struct audio_device *adev, struct str_parms *parms)
+{
+ int ret = 0;
+ char value[256];
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_APTX_DEC_BT_ADDR, value,
+ sizeof(value));
+ if (ret >= 0) {
+ audio_extn_parse_aptx_dec_bt_addr(value);
+ }
+}
+
+int audio_extn_set_aptx_dec_params(struct aptx_dec_param *payload)
+{
+ struct aptx_dec_param *aptx_cfg = payload;
+
+ aextnmod.addr.nap = aptx_cfg->bt_addr.nap;
+ aextnmod.addr.uap = aptx_cfg->bt_addr.uap;
+ aextnmod.addr.lap = aptx_cfg->bt_addr.lap;
+}
+
+static void audio_extn_parse_aptx_dec_bt_addr(char *value)
+{
+ int ba[6];
+ char *str, *tok;
+ uint32_t addr[3];
+ int i = 0;
+
+ ALOGV("%s: value %s", __func__, value);
+ tok = strtok_r(value, ":", &str);
+ while (tok != NULL) {
+ ba[i] = strtol(tok, NULL, 16);
+ i++;
+ tok = strtok_r(NULL, ":", &str);
+ }
+ addr[0] = (ba[0] << 8) | ba[1];
+ addr[1] = ba[2];
+ addr[2] = (ba[3] << 16) | (ba[4] << 8) | ba[5];
+
+ aextnmod.addr.nap = addr[0];
+ aextnmod.addr.uap = addr[1];
+ aextnmod.addr.lap = addr[2];
+}
+
+void audio_extn_send_aptx_dec_bt_addr_to_dsp(struct stream_out *out)
+{
+ char mixer_ctl_name[128];
+ struct mixer_ctl *ctl;
+ uint32_t addr[3];
+
+ ALOGV("%s", __func__);
+ out->compr_config.codec->options.aptx_dec.nap = aextnmod.addr.nap;
+ out->compr_config.codec->options.aptx_dec.uap = aextnmod.addr.uap;
+ out->compr_config.codec->options.aptx_dec.lap = aextnmod.addr.lap;
+}
+
+#endif //APTX_DECODER_ENABLED
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 9a2f825..dab53ed 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -531,7 +531,7 @@
void audio_extn_pm_unvote(void);
#endif
-void audio_extn_init(void);
+void audio_extn_init(struct audio_device *adev);
void audio_extn_utils_update_streams_cfg_lists(void *platform,
struct mixer *mixer,
struct listnode *streams_output_cfg_list,
@@ -801,4 +801,18 @@
struct sound_focus_param *payload);
#endif
+#ifndef APTX_DECODER_ENABLED
+#define audio_extn_aptx_dec_set_license(adev); (0)
+#define audio_extn_set_aptx_dec_bt_addr(adev, parms); (0)
+#define audio_extn_send_aptx_dec_bt_addr_to_dsp(out); (0)
+#define audio_extn_parse_aptx_dec_bt_addr(value); (0)
+#define audio_extn_set_aptx_dec_params(payload); (0)
+#else
+static void audio_extn_aptx_dec_set_license(struct audio_device *adev);
+static void audio_extn_set_aptx_dec_bt_addr(struct audio_device *adev, struct str_parms *parms);
+void audio_extn_send_aptx_dec_bt_addr_to_dsp(struct stream_out *out);
+static void audio_extn_parse_aptx_dec_bt_addr(char *value);
+int audio_extn_set_aptx_dec_params(struct aptx_dec_param *payload);
+#endif
+
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index b958bf6..fee0543 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2010 The Android Open Source Project
@@ -445,7 +445,6 @@
void audio_extn_dolby_set_license(struct audio_device *adev)
{
int ret, key=0;
- char value[128] = {0};
struct mixer_ctl *ctl;
const char *mixer_ctl_name = "DS1 License";
@@ -456,9 +455,8 @@
return;
}
- property_get("audio.ds1.metainfo.key",value,"0");
#ifdef DOLBY_ACDB_LICENSE
- key = atoi(value);
+ key = platform_get_meta_info_key_from_list(adev->platform, "dolby");
#else
key = 0;
#endif
@@ -598,14 +596,12 @@
void audio_extn_dolby_set_license(struct audio_device *adev __unused)
{
int i_key=0;
- char c_key[128] = {0};
char c_dmid[128] = {0};
int i_dmid;
struct dolby_param_license dolby_license;
#ifdef DOLBY_ACDB_LICENSE
- property_get("audio.ds1.metainfo.key",c_key,"0");
- i_key = atoi(c_key);
+ i_key = platform_get_meta_info_key_from_list(adev->platform, "dolby");
#else
/* As ACDB based license mechanism is disabled, force set the license key to 0*/
i_key = 0;
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 17fe4c9..7a4a0ed 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -151,6 +151,7 @@
STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_LC),
STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V1),
STRING_TO_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V2),
+ STRING_TO_ENUM(AUDIO_FORMAT_APTX),
#endif
};
@@ -1160,6 +1161,9 @@
case AUDIO_FORMAT_DSD:
id = SND_AUDIOCODEC_DSD;
break;
+ case AUDIO_FORMAT_APTX:
+ id = SND_AUDIOCODEC_APTX;
+ break;
default:
ALOGE("%s: Unsupported audio format :%x", __func__, format);
}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 71c05df..dc933d3 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -521,7 +521,8 @@
format == AUDIO_FORMAT_DSD ||
format == AUDIO_FORMAT_VORBIS ||
format == AUDIO_FORMAT_WMA ||
- format == AUDIO_FORMAT_WMA_PRO)
+ format == AUDIO_FORMAT_WMA_PRO ||
+ format == AUDIO_FORMAT_APTX)
return true;
return false;
@@ -3986,7 +3987,11 @@
out->compr_config.codec->ch_in =
audio_channel_count_from_out_mask(out->channel_mask);
out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
- out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
+ /* Update bit width only for non passthrough usecases.
+ * For passthrough usecases, the output will always be opened @16 bit
+ */
+ if (!audio_extn_passthru_is_passthrough_stream(out))
+ out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
/*TODO: Do we need to change it for passthrough */
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
@@ -4052,6 +4057,10 @@
if (config->offload_info.format == AUDIO_FORMAT_FLAC)
out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
+ if (config->offload_info.format == AUDIO_FORMAT_APTX) {
+ audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
+ }
+
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
out->non_blocking = 1;
@@ -5069,7 +5078,7 @@
"visualizer_hal_stop_output");
}
}
- audio_extn_init();
+ audio_extn_init(adev);
audio_extn_listen_init(adev, adev->snd_card);
audio_extn_sound_trigger_init(adev);
audio_extn_gef_init(adev);
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
index 39d81fb..f36d85d 100644
--- a/hal/audio_hw_extn_api.c
+++ b/hal/audio_hw_extn_api.c
@@ -104,6 +104,9 @@
ret = audio_extn_set_soundfocus_data(dev,
(struct sound_focus_param *)payload);
break;
+ case AUDIO_EXTN_PARAM_APTX_DEC:
+ audio_extn_set_aptx_dec_params((struct aptx_dec_param *)payload);
+ break;
default:
ALOGE("%s::INVALID PARAM ID:%d\n",__func__,param_id);
ret = -EINVAL;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index d9c7642..fad2c04 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -38,6 +38,8 @@
#include "sound/msmcal-hwdep.h"
#include <dirent.h>
#include <linux/msm_audio.h>
+#include "linux/msm_audio_calibration.h"
+
#define SOUND_TRIGGER_DEVICE_HANDSET_MONO_LOW_POWER_ACDB_ID (100)
#define MAX_MIXER_XML_PATH 100
#define MIXER_XML_PATH_QRD_SKUH "/system/etc/mixer_paths_qrd_skuh.xml"
@@ -212,6 +214,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
typedef int (*acdb_init_t)(const char *, char *, int);
+typedef int (*acdb_init_v3_t)(const char *, char *, struct listnode *);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -224,6 +227,7 @@
typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef int (*acdb_reload_t) (char *, char *, char *, int);
typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
+typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -237,6 +241,12 @@
static native_audio_prop na_props = {0, 0, 0};
static bool supports_true_32_bit = false;
+struct meta_key_list {
+ struct listnode list;
+ struct audio_cal_info_metainfo cal_info;
+ char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
+};
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -263,6 +273,7 @@
void *acdb_handle;
int voice_feature_set;
acdb_init_t acdb_init;
+ acdb_init_v3_t acdb_init_v3;
acdb_deallocate_t acdb_deallocate;
acdb_send_audio_cal_t acdb_send_audio_cal;
acdb_set_audio_cal_t acdb_set_audio_cal;
@@ -273,6 +284,7 @@
acdb_send_common_top_t acdb_send_common_top;
acdb_set_codec_data_t acdb_set_codec_data;
acdb_reload_t acdb_reload;
+ acdb_reload_v2_t acdb_reload_v2;
#ifdef RECORD_PLAY_CONCURRENCY
bool rec_play_conc_set;
#endif
@@ -288,11 +300,11 @@
int hw_dep_fd;
char cvd_version[MAX_CVD_VERSION_STRING_SIZE];
char snd_card_name[MAX_SND_CARD_STRING_SIZE];
- int metainfo_key;
int source_mic_type;
int max_mic_count;
bool is_dsd_supported;
bool is_asrc_supported;
+ struct listnode acdb_meta_key_list;
};
static bool is_external_codec = false;
@@ -1631,10 +1643,12 @@
{
struct platform_data *my_data = (struct platform_data *)platform;
char *cvd_version = NULL;
- int key = 0;
const char *snd_card_name, *acdb_snd_card_name;
- int result;
- char value[PROPERTY_VALUE_MAX];
+ int result = -1;
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ int key = 0;
+
cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
if (!cvd_version) {
ALOGE("Failed to allocate cvd version");
@@ -1643,19 +1657,23 @@
get_cvd_version(cvd_version, my_data->adev);
}
- property_get("audio.ds1.metainfo.key",value,"0");
- key = atoi(value);
snd_card_name = mixer_get_name(my_data->adev->mixer);
acdb_snd_card_name = get_snd_card_name_for_acdb_loader(snd_card_name);
- result = my_data->acdb_init(acdb_snd_card_name, cvd_version, key);
-
+ if (my_data->acdb_init_v3) {
+ result = my_data->acdb_init_v3(acdb_snd_card_name, cvd_version,
+ &my_data->acdb_meta_key_list);
+ } else if (my_data->acdb_init) {
+ node = list_head(&my_data->acdb_meta_key_list);
+ key_info = node_to_item(node, struct meta_key_list, list);
+ key = key_info->cal_info.nKey;
+ result = my_data->acdb_init(acdb_snd_card_name, cvd_version, key);
+ }
/* Save these variables in platform_data. These will be used
while reloading ACDB files during run time. */
strlcpy(my_data->cvd_version, cvd_version, MAX_CVD_VERSION_STRING_SIZE);
strlcpy(my_data->snd_card_name, acdb_snd_card_name,
MAX_SND_CARD_STRING_SIZE);
- my_data->metainfo_key = key;
if (cvd_version)
free(cvd_version);
@@ -1940,6 +1958,16 @@
if (ret || is_external_codec)
my_data->hifi_audio = true;
+ list_init(&my_data->acdb_meta_key_list);
+
+ set_platform_defaults(my_data);
+
+ /* Initialize ACDB and PCM ID's */
+ if (is_external_codec)
+ platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
+ else
+ platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+
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) {
@@ -2009,6 +2037,12 @@
ALOGV("%s: Could not find the symbol acdb_loader_send_gain_dep_cal from %s",
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_init_v3");
+ if (my_data->acdb_init_v3 == NULL) {
+ ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
+ }
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
if (my_data->acdb_init == NULL) {
@@ -2016,12 +2050,19 @@
goto acdb_init_fail;
}
+ my_data->acdb_reload_v2 = (acdb_reload_v2_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_reload_acdb_files_v2");
+ if (my_data->acdb_reload_v2 == NULL) {
+ ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files_v2", __func__, dlerror());
+ }
+
my_data->acdb_reload = (acdb_reload_t)dlsym(my_data->acdb_handle,
"acdb_loader_reload_acdb_files");
if (my_data->acdb_reload == NULL) {
ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files", __func__, dlerror());
goto acdb_init_fail;
}
+
platform_acdb_init(my_data);
}
audio_extn_pm_vote();
@@ -2035,14 +2076,6 @@
acdb_init_fail:
- set_platform_defaults(my_data);
-
- /* Initialize ACDB and PCM ID's */
- if (is_external_codec)
- platform_info_init(PLATFORM_INFO_XML_PATH_EXTCODEC, my_data);
- else
- platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
-
if (audio_extn_can_use_ras()) {
if (property_get_bool("persist.speaker.prot.enable", false)) {
platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED,
@@ -2075,8 +2108,6 @@
/* init dap hal */
audio_extn_dap_hal_init(adev->snd_card);
- audio_extn_dolby_set_license(adev);
-
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -2497,6 +2528,45 @@
return ret;
}
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
+{
+ struct meta_key_list *key_info;
+ struct platform_data *pdata = (struct platform_data *)platform;
+
+ key_info = (struct meta_key_list *)calloc(1, sizeof(struct meta_key_list));
+ if (!key_info) {
+ ALOGE("%s: Could not allocate memory for key %d", __func__, key);
+ return -ENOMEM;
+ }
+
+ key_info->cal_info.nKey = key;
+ strlcpy(key_info->name, name, sizeof(key_info->name));
+ list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);
+ ALOGD("%s: successfully added module %s and key %d to the list", __func__,
+ key_info->name, key_info->cal_info.nKey);
+ return 0;
+}
+
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name)
+{
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ struct platform_data *pdata = (struct platform_data *)platform;
+ int key = 0;
+
+ ALOGV("%s: for module %s", __func__, mod_name);
+
+ list_for_each(node, &pdata->acdb_meta_key_list) {
+ key_info = node_to_item(node, struct meta_key_list, list);
+ if (strcmp(key_info->name, mod_name) == 0) {
+ key = key_info->cal_info.nKey;
+ ALOGD("%s: Found key %d for module %s", __func__, key, mod_name);
+ break;
+ }
+ }
+ return key;
+}
+
int platform_get_default_app_type(void *platform)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -4032,6 +4102,9 @@
int len;
int ret = 0, err;
char *kv_pairs = NULL;
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ int key = 0;
kv_pairs = str_parms_to_str(parms);
if(!kv_pairs)
@@ -4093,9 +4166,16 @@
if (err >= 0) {
str_parms_del(parms, AUDIO_PARAMETER_KEY_RELOAD_ACDB);
- my_data->acdb_reload(value, my_data->snd_card_name,
- my_data->cvd_version, my_data->metainfo_key);
-
+ if (my_data->acdb_reload_v2) {
+ my_data->acdb_reload_v2(value, my_data->snd_card_name,
+ my_data->cvd_version, &my_data->acdb_meta_key_list);
+ } else if (my_data->acdb_reload) {
+ node = list_head(&my_data->acdb_meta_key_list);
+ key_info = node_to_item(node, struct meta_key_list, list);
+ key = key_info->cal_info.nKey;
+ my_data->acdb_reload(value, my_data->snd_card_name,
+ my_data->cvd_version, key);
+ }
}
if (hw_info_is_stereo_spkr(my_data->hw_info)) {
@@ -4609,11 +4689,11 @@
*/
// TODO: This has to be more dynamic based on policy file
- if ((my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl) &&
+ if (passthrough_enabled || ((my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl) &&
(sample_rate != my_data->current_backend_cfg[(int)backend_idx].sample_rate) &&
(my_data->hifi_audio ||
backend_idx == USB_AUDIO_RX_BACKEND ||
- backend_idx == USB_AUDIO_TX_BACKEND)) {
+ backend_idx == USB_AUDIO_TX_BACKEND))) {
/*
* sample rate update is needed only for hifi audio enabled platforms
*/
@@ -4621,11 +4701,15 @@
struct mixer_ctl *ctl = NULL;
switch (sample_rate) {
+ case 32000:
+ if (passthrough_enabled) {
+ rate_str = "KHZ_32";
+ break;
+ }
case 8000:
case 11025:
case 16000:
case 22050:
- case 32000:
case 48000:
rate_str = "KHZ_48";
break;
@@ -4651,6 +4735,11 @@
case 384000:
rate_str = "KHZ_384";
break;
+ case 144000:
+ if (passthrough_enabled) {
+ rate_str = "KHZ_144";
+ break;
+ }
default:
rate_str = "KHZ_48";
break;
@@ -5566,6 +5655,7 @@
format = AAC;
break;
case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
ALOGV("%s:E_AC3", __func__);
format = DOLBY_DIGITAL_PLUS;
break;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 31d86f4..0835329 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -1350,3 +1350,15 @@
{
return 0;
}
+
+int platform_get_meta_info_key_from_list(void *platform __unused,
+ char *mod_name __unused)
+{
+ return 0;
+}
+
+int platform_set_acdb_metainfo_key(void *platform __unused, char *name __unused,
+ int key __unused)
+{
+ return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 74c429b..1028e2d 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -190,6 +190,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
typedef int (*acdb_init_t)(const char *, char *, int);
+typedef int (*acdb_init_v3_t)(const char *, char *, struct listnode *);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -201,6 +202,7 @@
typedef int (*acdb_send_common_top_t) (void);
typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef int (*acdb_reload_t) (char *, char *, char *, int);
+typedef int (*acdb_reload_v2_t) (char *, char *, char *, struct listnode *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -215,6 +217,12 @@
static bool supports_true_32_bit = false;
typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);
+struct meta_key_list {
+ struct listnode list;
+ struct audio_cal_info_metainfo cal_info;
+ char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
+};
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -240,6 +248,7 @@
void *acdb_handle;
int voice_feature_set;
acdb_init_t acdb_init;
+ acdb_init_v3_t acdb_init_v3;
acdb_deallocate_t acdb_deallocate;
acdb_send_audio_cal_t acdb_send_audio_cal;
acdb_set_audio_cal_t acdb_set_audio_cal;
@@ -250,6 +259,7 @@
acdb_send_common_top_t acdb_send_common_top;
acdb_set_codec_data_t acdb_set_codec_data;
acdb_reload_t acdb_reload;
+ acdb_reload_v2_t acdb_reload_v2;
void *hw_info;
acdb_send_gain_dep_cal_t acdb_send_gain_dep_cal;
struct csd_data *csd;
@@ -262,11 +272,11 @@
int hw_dep_fd;
char cvd_version[MAX_CVD_VERSION_STRING_SIZE];
char snd_card_name[MAX_SND_CARD_STRING_SIZE];
- int metainfo_key;
int source_mic_type;
int max_mic_count;
bool is_dsd_supported;
bool is_asrc_supported;
+ struct listnode acdb_meta_key_list;
};
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -394,6 +404,7 @@
[SND_DEVICE_OUT_VOICE_ANC_HEADSET] = "voice-anc-headphones",
[SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = "voice-anc-fb-headphones",
[SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = "speaker-and-anc-headphones",
+ [SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET] = "speaker-and-anc-fb-headphones",
[SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
@@ -523,6 +534,7 @@
[SND_DEVICE_OUT_VOICE_ANC_HEADSET] = 26,
[SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = 27,
[SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = 26,
+ [SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET] = 27,
[SND_DEVICE_OUT_ANC_HANDSET] = 103,
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
@@ -652,6 +664,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_ANC_HEADSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET)},
{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)},
@@ -1419,10 +1432,12 @@
{
struct platform_data *my_data = (struct platform_data *)platform;
char *cvd_version = NULL;
- int key = 0;
const char *snd_card_name;
- int result;
- char value[PROPERTY_VALUE_MAX];
+ int result = -1;
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ int key = 0;
+
cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
if (!cvd_version) {
ALOGE("Failed to allocate cvd version");
@@ -1431,17 +1446,22 @@
get_cvd_version(cvd_version, my_data->adev);
}
- property_get("audio.ds1.metainfo.key",value,"0");
- key = atoi(value);
snd_card_name = mixer_get_name(my_data->adev->mixer);
- result = my_data->acdb_init(snd_card_name, cvd_version, key);
+ if (my_data->acdb_init_v3) {
+ result = my_data->acdb_init_v3(snd_card_name, cvd_version,
+ &my_data->acdb_meta_key_list);
+ } else if (my_data->acdb_init) {
+ node = list_head(&my_data->acdb_meta_key_list);
+ key_info = node_to_item(node, struct meta_key_list, list);
+ key = key_info->cal_info.nKey;
+ result = my_data->acdb_init(snd_card_name, cvd_version, key);
+ }
/* Save these variables in platform_data. These will be used
while reloading ACDB files during run time. */
strlcpy(my_data->cvd_version, cvd_version, MAX_CVD_VERSION_STRING_SIZE);
strlcpy(my_data->snd_card_name, snd_card_name,
MAX_SND_CARD_STRING_SIZE);
- my_data->metainfo_key = key;
if (cvd_version)
free(cvd_version);
@@ -1671,6 +1691,16 @@
if (ret)
my_data->is_vbat_speaker = true;
+ list_init(&my_data->acdb_meta_key_list);
+
+ set_platform_defaults(my_data);
+
+ /* Initialize ACDB ID's */
+ if (my_data->is_i2s_ext_modem)
+ platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
+ else
+ platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
+
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) {
@@ -1741,13 +1771,25 @@
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_init_v3");
+ if (my_data->acdb_init_v3 == NULL) {
+ ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
+ }
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
- "acdb_loader_init_v2");
+ "acdb_loader_init_v3");
if (my_data->acdb_init == NULL) {
- ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
+ ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
goto acdb_init_fail;
}
+ my_data->acdb_reload_v2 = (acdb_reload_v2_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_reload_acdb_files_v2");
+ if (my_data->acdb_reload_v2 == NULL) {
+ ALOGE("%s: dlsym error %s for acdb_loader_reload_acdb_files_v2", __func__, dlerror());
+ }
+
my_data->acdb_reload = (acdb_reload_t)dlsym(my_data->acdb_handle,
"acdb_loader_reload_acdb_files");
if (my_data->acdb_reload == NULL) {
@@ -1762,13 +1804,6 @@
acdb_init_fail:
- set_platform_defaults(my_data);
-
- /* Initialize ACDB ID's */
- if (my_data->is_i2s_ext_modem)
- platform_info_init(PLATFORM_INFO_XML_PATH_I2S, my_data);
- else
- platform_info_init(PLATFORM_INFO_XML_PATH, my_data);
if (audio_extn_can_use_ras()) {
if (property_get_bool("persist.speaker.prot.enable", false)) {
@@ -1815,7 +1850,6 @@
audio_extn_ssr_update_enabled();
audio_extn_spkr_prot_init(adev);
- audio_extn_dolby_set_license(adev);
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -2194,6 +2228,46 @@
return ret;
}
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key)
+{
+ struct meta_key_list *key_info;
+ struct platform_data *pdata = (struct platform_data *)platform;
+
+ key_info = (struct meta_key_list *)calloc(1, sizeof(struct meta_key_list));
+ if (!key_info) {
+ ALOGE("%s: Could not allocate memory for key %d", __func__, key);
+ return -ENOMEM;
+ }
+
+ key_info->cal_info.nKey = key;
+ strlcpy(key_info->name, name, sizeof(key_info->name));
+ list_add_tail(&pdata->acdb_meta_key_list, &key_info->list);
+
+ ALOGD("%s: successfully added module %s and key %d to the list", __func__,
+ key_info->name, key_info->cal_info.nKey);
+ return 0;
+}
+
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name)
+{
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ struct platform_data *pdata = (struct platform_data *)platform;
+ int key = 0;
+
+ ALOGV("%s: for module %s", __func__, mod_name);
+
+ list_for_each(node, &pdata->acdb_meta_key_list) {
+ key_info = node_to_item(node, struct meta_key_list, list);
+ if (strcmp(key_info->name, mod_name) == 0) {
+ key = key_info->cal_info.nKey;
+ ALOGD("%s: Found key %d for module %s", __func__, key, mod_name);
+ break;
+ }
+ }
+ return key;
+}
+
int platform_get_default_app_type(void *platform)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -2393,7 +2467,8 @@
SND_DEVICE_OUT_SPEAKER_AND_LINE == snd_device ||
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1 == snd_device ||
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2 == snd_device ||
- SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET == snd_device)
+ SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET == snd_device ||
+ SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET == snd_device)
ret = true;
return ret;
@@ -2901,9 +2976,12 @@
snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
} else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
AUDIO_DEVICE_OUT_SPEAKER)) {
- if (audio_extn_get_anc_enabled())
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET;
- else if (my_data->external_spk_1)
+ if (audio_extn_get_anc_enabled()) {
+ if (audio_extn_should_use_fb_anc())
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET;
+ else
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET;
+ } else if (my_data->external_spk_1)
snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1;
else if (my_data->external_spk_2)
snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2;
@@ -3866,6 +3944,9 @@
int len;
int ret = 0, err;
char *kv_pairs = str_parms_to_str(parms);
+ struct listnode *node;
+ struct meta_key_list *key_info;
+ int key = 0;
if(kv_pairs == NULL) {
ret = -ENOMEM;
@@ -3935,9 +4016,16 @@
if (err >= 0) {
str_parms_del(parms, AUDIO_PARAMETER_KEY_RELOAD_ACDB);
- my_data->acdb_reload(value, my_data->snd_card_name,
- my_data->cvd_version, my_data->metainfo_key);
-
+ if (my_data->acdb_reload_v2) {
+ my_data->acdb_reload_v2(value, my_data->snd_card_name,
+ my_data->cvd_version, &my_data->acdb_meta_key_list);
+ } else if (my_data->acdb_reload) {
+ node = list_head(&my_data->acdb_meta_key_list);
+ key_info = node_to_item(node, struct meta_key_list, list);
+ key = key_info->cal_info.nKey;
+ my_data->acdb_reload(value, my_data->snd_card_name,
+ my_data->cvd_version, key);
+ }
}
if (hw_info_is_stereo_spkr(my_data->hw_info)) {
@@ -4510,17 +4598,21 @@
ret = 0;
}
- if ((my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl) &&
- (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate)) {
+ if (passthrough_enabled || ((my_data->current_backend_cfg[backend_idx].samplerate_mixer_ctl) &&
+ (sample_rate != my_data->current_backend_cfg[backend_idx].sample_rate))) {
char *rate_str = NULL;
struct mixer_ctl *ctl = NULL;
switch (sample_rate) {
+ case 32000:
+ if (passthrough_enabled) {
+ rate_str = "KHZ_32";
+ break;
+ }
case 8000:
case 11025:
case 16000:
case 22050:
- case 32000:
case 48000:
rate_str = "KHZ_48";
break;
@@ -4546,7 +4638,12 @@
case 384000:
rate_str = "KHZ_384";
break;
- default:
+ case 144000:
+ if (passthrough_enabled) {
+ rate_str = "KHZ_144";
+ break;
+ }
+ default:
rate_str = "KHZ_48";
break;
}
@@ -5412,6 +5509,7 @@
format = AAC;
break;
case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
ALOGV("%s:E_AC3", __func__);
format = DOLBY_DIGITAL_PLUS;
break;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 731d81c..0018427 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -120,6 +120,7 @@
SND_DEVICE_OUT_VOICE_ANC_HEADSET,
SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET,
SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
+ SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET,
SND_DEVICE_OUT_ANC_HANDSET,
SND_DEVICE_OUT_SPEAKER_PROTECTED,
SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index e274e48..82bef97 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -31,6 +31,7 @@
#define SAMPLE_RATE_11025 11025
#define sample_rate_multiple(sr, base) ((sr % base)== 0?true:false)
#define MAX_VOLUME_CAL_STEPS 15
+#define ACDB_METAINFO_KEY_MODULE_NAME_LEN 100
struct amp_db_and_gain_table {
float amp;
@@ -82,6 +83,8 @@
int platform_get_snd_device_acdb_id(snd_device_t snd_device);
int platform_set_snd_device_bit_width(snd_device_t snd_device, unsigned int bit_width);
int platform_get_snd_device_bit_width(snd_device_t snd_device);
+int platform_set_acdb_metainfo_key(void *platform, char *name, int key);
+int platform_get_meta_info_key_from_list(void *platform, char *mod_name);
int platform_set_native_support(int na_mode);
int platform_get_native_support();
int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 8e12dd6..a63b215 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, 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
@@ -51,6 +51,7 @@
INTERFACE_NAME,
CONFIG_PARAMS,
GAIN_LEVEL_MAPPING,
+ ACDB_METAINFO_KEY,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -63,6 +64,7 @@
static void process_config_params(const XML_Char **attr);
static void process_root(const XML_Char **attr);
static void process_gain_db_to_level_map(const XML_Char **attr);
+static void process_acdb_metainfo_key(const XML_Char **attr);
static section_process_fn section_table[] = {
[ROOT] = process_root,
@@ -73,6 +75,7 @@
[INTERFACE_NAME] = process_interface_name,
[CONFIG_PARAMS] = process_config_params,
[GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map,
+ [ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
};
static section_t section;
@@ -350,6 +353,29 @@
return;
}
+/* process acdb meta info key value */
+static void process_acdb_metainfo_key(const XML_Char **attr)
+{
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found", __func__);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "value") != 0) {
+ ALOGE("%s: 'value' not found", __func__);
+ goto done;
+ }
+
+ int key = atoi((char *)attr[3]);
+ if (platform_set_acdb_metainfo_key(my_data.platform, (char*)attr[1], key) < 0) {
+ ALOGE("%s: key %d was not set!", __func__, key);
+ goto done;
+ }
+
+done:
+ return;
+}
+
static void start_tag(void *userdata __unused, const XML_Char *tag_name,
const XML_Char **attr)
{
@@ -367,6 +393,8 @@
section = INTERFACE_NAME;
} else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
section = GAIN_LEVEL_MAPPING;
+ } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
+ section = ACDB_METAINFO_KEY;
} else if (strcmp(tag_name, "device") == 0) {
if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
(section != INTERFACE_NAME)) {
@@ -394,7 +422,7 @@
section_process_fn fn = section_table[PCM_ID];
fn(attr);
} else if (strcmp(tag_name, "param") == 0) {
- if (section != CONFIG_PARAMS) {
+ if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) {
ALOGE("param tag only supported with CONFIG_PARAMS section");
return;
}
@@ -423,6 +451,8 @@
section = ROOT;
} else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
section = ROOT;
+ } else if (strcmp(tag_name, "acdb_metainfo_key") == 0) {
+ section = ROOT;
}
}
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
index 8b890b9..eb500a2 100644
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2011 The Android Open Source Project *
@@ -233,14 +233,26 @@
uint16_t gain_step;
};
+struct aptx_dec_bt_addr {
+ uint32_t nap;
+ uint32_t uap;
+ uint32_t lap;
+};
+
+struct qahw_aptx_dec_param {
+ struct aptx_dec_bt_addr bt_addr;
+};
+
typedef union {
struct qahw_source_tracking_param st_params;
struct qahw_sound_focus_param sf_params;
+ struct qahw_aptx_dec_param aptx_params;
} qahw_param_payload;
typedef enum {
QAHW_PARAM_SOURCE_TRACK,
- QAHW_PARAM_SOUND_FOCUS
+ QAHW_PARAM_SOUND_FOCUS,
+ QAHW_PARAM_APTX_DEC
} qahw_param_id;
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index 900f189..223726d 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -46,6 +46,7 @@
#define ID_DATA 0x61746164
#define FORMAT_PCM 1
+#define WAV_HEADER_LENGTH_MAX 46
static thread_data_t *ethread_data = NULL;
static cmd_data_t cmd_data;
@@ -102,7 +103,8 @@
FILE_EAC3,
FILE_EAC3_JOC,
FILE_DTS,
- FILE_MP2
+ FILE_MP2,
+ FILE_APTX
};
typedef enum {
@@ -552,6 +554,28 @@
return rc;
}
+void parse_aptx_dec_bt_addr(char *value, struct qahw_aptx_dec_param *aptx_cfg)
+{
+ int ba[6];
+ char *str, *tok;
+ uint32_t addr[3];
+ int i = 0;
+
+ tok = strtok_r(value, ":", &str);
+ while (tok != NULL) {
+ ba[i] = strtol(tok, NULL, 16);
+ i++;
+ tok = strtok_r(NULL, ":", &str);
+ }
+ addr[0] = (ba[0] << 8) | ba[1];
+ addr[1] = ba[2];
+ addr[2] = (ba[3] << 16) | (ba[4] << 8) | ba[5];
+
+ aptx_cfg->bt_addr.nap = addr[0];
+ aptx_cfg->bt_addr.uap = addr[1];
+ aptx_cfg->bt_addr.lap = addr[2];
+}
+
void usage() {
printf(" \n Command \n");
printf(" \n hal_play_test -f file-path <options> - Plays audio file from the path provided\n");
@@ -583,6 +607,7 @@
printf(" file path and other file specific options would be ignored in this mode.\n\n");
printf(" -e --effect-type <effect type> - Effect used for test\n");
printf(" 0:bassboost 1:virtualizer 2:equalizer 3:visualizer(NA) 4:reverb 5:audiosphere others:null");
+ printf(" -A --bt-addr <bt device addr> - Required to set bt device adress for aptx decoder\n");
printf(" \n Examples \n");
printf(" hal_play_test -f /etc/Anukoledenadu.wav -> plays Wav stream with default params\n\n");
printf(" hal_play_test -f /etc/MateRani.mp3 -t 2 -d 2 -v 0.01 -r 44100 -c 2 \n");
@@ -621,6 +646,10 @@
printf(" -> kvpair(-k) values represent media-info of clip & values should be in below mentioned sequence\n");
printf(" ->avg_bit_rate,sample_rate,wma_bit_per_sample,wma_block_align\n");
printf(" ->wma_channel_mask,wma_encode_option,wma_format_tag\n");
+ printf(" hal_play_test -f /etc/03_Kuch_Khaas_BE.btaptx -t 9 -d 2 -v 0.2 -r 44100 -c 2 -A 00:02:5b:00:ff:03 \n");
+ printf(" -> Play aptx clip (-t = 9)\n");
+ printf(" -> 2 channels and 44100 sample rate\n");
+ printf(" -> BT addr: bt_addr=00:02:5b:00:ff:03\n");
printf(" hal_play_test -K -F 4 -> Measure latency KPIs for low latency output\n\n");
printf(" hal_play_test -f /etc//Moto_320kbps.mp3 -t 2 -d 2 -v 0.1 -r 44100 -c 2 -e 2\n");
printf(" -> plays MP3 stream(-t = 2) on speaker device(-d = 2)\n");
@@ -628,19 +657,53 @@
printf(" -> sound effect equalizer enabled\n\n");
}
+static int get_wav_header_length (FILE* file_stream)
+{
+ int subchunk_size = 0, wav_header_len = 0;
+
+ fseek(file_stream, 16, SEEK_SET);
+ if(fread(&subchunk_size, 4, 1, file_stream) != 1) {
+ fprintf(stdout, "Unable to read subchunk:\n");
+ exit (1);
+ }
+ if(subchunk_size < 16) {
+ fprintf(stdout, "This is not a valid wav file \n");
+ } else {
+ switch (subchunk_size) {
+ case 16:
+ fprintf(stdout, "44-byte wav header \n");
+ wav_header_len = 44;
+ break;
+ case 18:
+ fprintf(stdout, "46-byte wav header \n");
+ wav_header_len = 46;
+ break;
+ default:
+ fprintf(stdout, "Header contains extra data and is larger than 46 bytes: subchunk_size=%d \n", subchunk_size);
+ wav_header_len = subchunk_size;
+ break;
+ }
+ }
+ return wav_header_len;
+}
+
+
int main(int argc, char* argv[]) {
FILE *file_stream = NULL;
- char header[44] = {0};
+ char header[WAV_HEADER_LENGTH_MAX] = {0};
char* filename = nullptr;
qahw_module_handle_t *qahw_mod_handle = NULL;
const char *mod_name = "audio.primary";
qahw_stream_handle_t* out_handle = nullptr;
- int rc = 0;
+ int rc = 0, wav_header_len = 0;
char *kvpair_values = NULL;
char kvpair[1000] = {0};
struct proxy_data proxy_params;
-
+ char *ba = NULL;
+ qahw_param_payload payload;
+ qahw_param_id param_id;
+ struct qahw_aptx_dec_param aptx_params;
/*
* Default values
*/
@@ -675,6 +738,7 @@
{"flags", required_argument, 0, 'F'},
{"kpi-mode", no_argument, 0, 'K'},
{"effect-path", required_argument, 0, 'e'},
+ {"bt-addr", required_argument, 0, 'A'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
@@ -698,7 +762,7 @@
proxy_params.hdr.data_sz = 0;
while ((opt = getopt_long(argc,
argv,
- "-f:r:c:b:d:v:l:t:a:w:k:D:KF:e:h",
+ "-f:r:c:b:d:v:l:t:a:w:k:D:KF:e:A:h",
long_options,
&option_index)) != -1) {
switch (opt) {
@@ -767,6 +831,9 @@
ethread_func = effect_thread_funcs[effect_index];
}
break;
+ case 'A':
+ ba = optarg;
+ break;
case 'h':
usage();
return 0;
@@ -839,7 +906,12 @@
/*
* Read the wave header
*/
- rc = fread (header, 44 , 1, file_stream);
+ if((wav_header_len = get_wav_header_length(file_stream)) <= 0) {
+ fprintf(stdout, "wav header length is invalid:%d\n", wav_header_len);
+ exit(1);
+ }
+ fseek(file_stream, 0, SEEK_SET);
+ rc = fread (header, wav_header_len, 1, file_stream);
if (rc != 1) {
fprintf(stdout, "Error .Fread failed\n");
exit(0);
@@ -902,6 +974,9 @@
case FILE_DTS:
config.offload_info.format = AUDIO_FORMAT_DTS;
break;
+ case FILE_APTX:
+ config.offload_info.format = AUDIO_FORMAT_APTX;
+ break;
default:
fprintf(stderr, "Does not support given filetype\n");
usage();
@@ -924,6 +999,23 @@
if (output_device & AUDIO_DEVICE_OUT_ALL_A2DP) {
output_device = AUDIO_DEVICE_OUT_PROXY;
}
+ if (filetype == FILE_APTX) {
+ if (ba != NULL) {
+ parse_aptx_dec_bt_addr(ba, &aptx_params);
+ payload = (qahw_param_payload)aptx_params;
+ param_id = QAHW_PARAM_APTX_DEC;
+ fprintf(log_file, "Send BT addr nap %d, uap %d lap %d to HAL\n", aptx_params.bt_addr.nap,
+ aptx_params.bt_addr.uap, aptx_params.bt_addr.lap);
+ rc = qahw_set_param_data(qahw_mod_handle, param_id, &payload);
+ if (rc != 0)
+ printf("Error.Failed Set BT addr\n");
+ } else {
+ fprintf(log_file, "BT addr is NULL, Need valid BT addr for aptx file playback to work\n");
+ fprintf(stderr, "BT addr is NULL, Need valid BT addr for aptx file playback to work\n");
+ goto EXIT;
+ }
+ }
+
fprintf(log_file, "calling open_out_put_stream:\n");
rc = qahw_open_output_stream(qahw_mod_handle,
handle,