am 7106b08e: DO NOT MERGE - volume_listener: fix release
* commit '7106b08ee43b84978e370b9c25e89f1ed7bfbf0d':
DO NOT MERGE - volume_listener: fix release
diff --git a/hal/Android.mk b/hal/Android.mk
index 0d931c1..0bb29b5 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -12,15 +12,19 @@
AUDIO_PLATFORM = msm8974
ifneq ($(filter msm8226,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8x26
+ LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="2"
endif
ifneq ($(filter msm8084,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8084
+ LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="2"
endif
ifneq ($(filter msm8992,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8994
+ LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="4"
endif
ifneq ($(filter msm8994,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8994
+ LOCAL_CFLAGS += -DMAX_TARGET_SPECIFIC_CHANNEL_CNT="4"
endif
endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 8fc7764..86072c0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -62,6 +62,13 @@
#define PROXY_OPEN_RETRY_COUNT 100
#define PROXY_OPEN_WAIT_TIME 20
+#define MIN_CHANNEL_COUNT 1
+#define DEFAULT_CHANNEL_COUNT 2
+
+#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
+#define XSTR(x) STR(x)
+#define STR(x) #x
+
static unsigned int configured_low_latency_capture_period_size =
LOW_LATENCY_CAPTURE_PERIOD_SIZE;
@@ -71,7 +78,7 @@
static const bool k_enable_extended_precision = false;
struct pcm_config pcm_config_deep_buffer = {
- .channels = 2,
+ .channels = DEFAULT_CHANNEL_COUNT,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
.period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
@@ -82,7 +89,7 @@
};
struct pcm_config pcm_config_low_latency = {
- .channels = 2,
+ .channels = DEFAULT_CHANNEL_COUNT,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
.period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
.period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
@@ -104,7 +111,7 @@
};
struct pcm_config pcm_config_audio_capture = {
- .channels = 2,
+ .channels = DEFAULT_CHANNEL_COUNT,
.period_count = AUDIO_CAPTURE_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.stop_threshold = INT_MAX,
@@ -148,6 +155,7 @@
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
[USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
+ [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
[USECASE_AUDIO_RECORD] = "audio-record",
[USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
@@ -300,6 +308,8 @@
return -EINVAL;
}
+ platform_send_audio_calibration(adev->platform, snd_device);
+
adev->snd_dev_ref_cnt[snd_device]++;
if (adev->snd_dev_ref_cnt[snd_device] > 1) {
ALOGV("%s: snd_device(%d: %s) is already active",
@@ -315,13 +325,6 @@
if (audio_extn_spkr_prot_is_enabled())
audio_extn_spkr_prot_calib_cancel(adev);
- if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
- adev->snd_dev_ref_cnt[snd_device]--;
- audio_extn_sound_trigger_update_device_status(snd_device,
- ST_EVENT_SND_DEVICE_FREE);
- return -EINVAL;
- }
-
audio_extn_dsm_feedback_enable(adev, snd_device, true);
if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
@@ -339,6 +342,7 @@
for (i = 0; i < num_devices; i++) {
enable_snd_device(adev, new_snd_devices[i]);
}
+ platform_set_speaker_gain_in_combo(adev, snd_device, true);
} else {
const char * dev_path = platform_get_snd_device_name(snd_device);
ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path);
@@ -377,12 +381,14 @@
for (i = 0; i < num_devices; i++) {
disable_snd_device(adev, new_snd_devices[i]);
}
+ platform_set_speaker_gain_in_combo(adev, snd_device, false);
} else {
audio_route_reset_and_update_path(adev->audio_route, dev_path);
}
audio_extn_sound_trigger_update_device_status(snd_device,
ST_EVENT_SND_DEVICE_FREE);
}
+
return 0;
}
@@ -673,6 +679,9 @@
(usecase->in_snd_device != SND_DEVICE_NONE) &&
(usecase->out_snd_device != SND_DEVICE_NONE)) {
status = platform_switch_voice_call_device_pre(adev->platform);
+ /* Disable sidetone only if voice call already exists */
+ if (voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, usecase->out_snd_device, false);
}
/* Disable current sound devices */
@@ -724,10 +733,14 @@
* Enable device command should be sent to modem only after
* enabling voice call mixer controls
*/
- if (usecase->type == VOICE_CALL)
+ if (usecase->type == VOICE_CALL) {
status = platform_switch_voice_call_usecase_route_post(adev->platform,
out_snd_device,
in_snd_device);
+ /* Enable sidetone only if voice call already exists */
+ if (voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, out_snd_device, true);
+ }
return status;
}
@@ -820,7 +833,10 @@
break;
}
+ ALOGV("%s: pcm_prepare start", __func__);
+ pcm_prepare(in->pcm);
ALOGV("%s: exit", __func__);
+
return ret;
error_open:
@@ -1156,6 +1172,10 @@
}
break;
}
+ ALOGV("%s: pcm_prepare start", __func__);
+ if (pcm_is_ready(out->pcm))
+ pcm_prepare(out->pcm);
+
} else {
out->pcm = NULL;
out->compr = compress_open(adev->snd_card, out->pcm_device_id,
@@ -1187,9 +1207,16 @@
audio_format_t format,
int channel_count)
{
- if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
+ if (format != AUDIO_FORMAT_PCM_16_BIT) {
+ ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
+ return -EINVAL;
+ }
- if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
+ if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
+ ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d\%d)", __func__,
+ channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
+ return -EINVAL;
+ }
switch (sample_rate) {
case 8000:
@@ -1203,6 +1230,7 @@
case 48000:
break;
default:
+ ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
return -EINVAL;
}
@@ -1289,6 +1317,9 @@
pthread_mutex_lock(&out->lock);
if (!out->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, out->handle);
+
pthread_mutex_lock(&adev->lock);
out->standby = true;
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -1563,6 +1594,8 @@
out->standby = true;
goto exit;
}
+ if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
+ adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
@@ -1589,14 +1622,22 @@
if (out->pcm) {
if (out->muted)
memset((void *)buffer, 0, bytes);
+
ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, out->handle);
+
if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
}
else
ret = pcm_write(out->pcm, (void *)buffer, bytes);
+
if (ret == 0)
out->written += bytes / (out->config.channels * sizeof(short));
+
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, out->handle);
}
}
@@ -1823,6 +1864,9 @@
}
if (!in->standby) {
+ if (adev->adm_deregister_stream)
+ adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
+
pthread_mutex_lock(&adev->lock);
in->standby = true;
if (in->pcm) {
@@ -1924,8 +1968,13 @@
goto exit;
}
in->standby = 0;
+ if (adev->adm_register_input_stream)
+ adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
}
+ if (adev->adm_request_focus)
+ adev->adm_request_focus(adev->adm_data, in->capture_handle);
+
if (in->pcm) {
if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
ret = pcm_mmap_read(in->pcm, buffer, bytes);
@@ -1933,6 +1982,9 @@
ret = pcm_read(in->pcm, buffer, bytes);
}
+ if (adev->adm_abandon_focus)
+ adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
+
/*
* Instead of writing zeroes here, we could trust the hardware
* to always provide zeroes when muted.
@@ -2147,6 +2199,9 @@
} else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
out->config = pcm_config_deep_buffer;
+ } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
+ out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
+ out->config = pcm_config_low_latency;
} else {
out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
out->config = pcm_config_low_latency;
@@ -2489,6 +2544,7 @@
in->standby = 1;
in->channel_mask = config->channel_mask;
in->capture_handle = handle;
+ in->flags = flags;
/* Update config params with the requested sample rate and channels */
if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
@@ -2714,10 +2770,13 @@
for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
pcm_params_free(adev->use_case_table[i]);
}
+ if (adev->adm_deinit)
+ adev->adm_deinit(adev->adm_data);
free(device);
}
pthread_mutex_unlock(&adev_init_lock);
+
return 0;
}
@@ -2844,6 +2903,29 @@
}
}
+ if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
+ adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
+ if (adev->adm_lib == NULL) {
+ ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
+ } else {
+ ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
+ adev->adm_init = (adm_init_t)
+ dlsym(adev->adm_lib, "adm_init");
+ adev->adm_deinit = (adm_deinit_t)
+ dlsym(adev->adm_lib, "adm_deinit");
+ adev->adm_register_input_stream = (adm_register_input_stream_t)
+ dlsym(adev->adm_lib, "adm_register_input_stream");
+ adev->adm_register_output_stream = (adm_register_output_stream_t)
+ dlsym(adev->adm_lib, "adm_register_output_stream");
+ adev->adm_deregister_stream = (adm_deregister_stream_t)
+ dlsym(adev->adm_lib, "adm_deregister_stream");
+ adev->adm_request_focus = (adm_request_focus_t)
+ dlsym(adev->adm_lib, "adm_request_focus");
+ adev->adm_abandon_focus = (adm_abandon_focus_t)
+ dlsym(adev->adm_lib, "adm_abandon_focus");
+ }
+ }
+
adev->bt_wb_speech_enabled = false;
adev->enable_voicerx = false;
@@ -2873,6 +2955,9 @@
audio_device_ref_count++;
pthread_mutex_unlock(&adev_init_lock);
+ if (adev->adm_init)
+ adev->adm_data = adev->adm_init();
+
ALOGV("%s: exit", __func__);
return 0;
}
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index b4b2583..39e5263 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -29,6 +29,7 @@
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so"
+#define ADM_LIBRARY_PATH "/system/vendor/lib/libadm.so"
/* Flags used to initialize acdb_settings variable that goes to ACDB library */
#define DMIC_FLAG 0x00000002
@@ -58,6 +59,7 @@
USECASE_AUDIO_PLAYBACK_MULTI_CH,
USECASE_AUDIO_PLAYBACK_OFFLOAD,
USECASE_AUDIO_PLAYBACK_TTS,
+ USECASE_AUDIO_PLAYBACK_ULL,
/* HFP Use case*/
USECASE_AUDIO_HFP_SCO,
@@ -173,6 +175,7 @@
bool enable_ns;
audio_io_handle_t capture_handle;
+ audio_input_flags_t flags;
bool is_st_session;
bool is_st_session_active;
@@ -201,6 +204,14 @@
union stream_ptr stream;
};
+typedef void* (*adm_init_t)();
+typedef void (*adm_deinit_t)(void *);
+typedef void (*adm_register_output_stream_t)(void *, audio_io_handle_t, audio_output_flags_t);
+typedef void (*adm_register_input_stream_t)(void *, audio_io_handle_t, audio_input_flags_t);
+typedef void (*adm_deregister_stream_t)(void *, audio_io_handle_t);
+typedef void (*adm_request_focus_t)(void *, audio_io_handle_t);
+typedef void (*adm_abandon_focus_t)(void *, audio_io_handle_t);
+
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -240,6 +251,16 @@
void *offload_effects_lib;
int (*offload_effects_start_output)(audio_io_handle_t, int);
int (*offload_effects_stop_output)(audio_io_handle_t, int);
+
+ void *adm_data;
+ void *adm_lib;
+ adm_init_t adm_init;
+ adm_deinit_t adm_deinit;
+ adm_register_input_stream_t adm_register_input_stream;
+ adm_register_output_stream_t adm_register_output_stream;
+ adm_deregister_stream_t adm_deregister_stream;
+ adm_request_focus_t adm_request_focus;
+ adm_abandon_focus_t adm_abandon_focus;
};
int select_devices(struct audio_device *adev,
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 2f596ba..c78d943 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -126,6 +126,8 @@
[SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
[SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
[SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
+ [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset-tmus",
+ [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = "voice-handset-tmus",
[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
@@ -173,6 +175,8 @@
[SND_DEVICE_OUT_BT_SCO] = 22,
[SND_DEVICE_OUT_BT_SCO_WB] = 39,
[SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
+ [SND_DEVICE_OUT_VOICE_HANDSET] = 81,
+ [SND_DEVICE_OUT_VOICE_HAC_HANDSET] = 81,
[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
@@ -423,6 +427,13 @@
return -ENOSYS;
}
+void platform_add_operator_specific_device(snd_device_t snd_device __unused,
+ const char *operator __unused,
+ const char *mixer_path __unused,
+ unsigned int acdb_id __unused)
+{
+}
+
int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -540,6 +551,11 @@
return ret;
}
+void platform_set_speaker_gain_in_combo(struct audio_device *adev __unused,
+ snd_device_t snd_device __unused,
+ bool enable __unused) {
+}
+
int platform_set_voice_volume(void *platform, int volume)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 0201772..b879c0b 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -48,6 +48,8 @@
SND_DEVICE_OUT_BT_SCO,
SND_DEVICE_OUT_BT_SCO_WB,
SND_DEVICE_OUT_VOICE_HANDSET_TMUS,
+ SND_DEVICE_OUT_VOICE_HANDSET,
+ SND_DEVICE_OUT_VOICE_HAC_HANDSET,
SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES,
SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES,
SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET,
@@ -92,7 +94,7 @@
#define MIXER_CARD 0
#define SOUND_CARD 0
-
+#define MIXER_PATH_MAX_LENGTH 100
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
/*
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 03aa596..6cb46e2 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#define LOG_TAG "msm8974_platform"
/*#define LOG_NDEBUG 0*/
#define LOG_NDDEBUG 0
@@ -34,9 +33,6 @@
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
#define CVD_VERSION_MIXER_CTL "CVD Version"
-#define DUALMIC_CONFIG_NONE 0 /* Target does not contain 2 mics */
-#define DUALMIC_CONFIG_ENDFIRE 1
-#define DUALMIC_CONFIG_BROADSIDE 2
/*
* This file will have a maximum of 38 bytes:
@@ -62,6 +58,9 @@
#define DEFAULT_APP_TYPE_RX_PATH 0x11130
+#define TOSTRING_(x) #x
+#define TOSTRING(x) TOSTRING_(x)
+
struct audio_block_header
{
int reserved;
@@ -74,6 +73,24 @@
CAL_MODE_RTAC = 0x4
};
+#define PLATFORM_CONFIG_KEY_OPERATOR_INFO "operator_info"
+
+struct operator_info {
+ struct listnode list;
+ char *name;
+ char *mccmnc;
+};
+
+struct operator_specific_device {
+ struct listnode list;
+ char *operator;
+ char *mixer_path;
+ int acdb_id;
+};
+
+static struct listnode operator_info_list;
+static struct listnode *operator_specific_device_table[SND_DEVICE_MAX];
+
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
typedef int (*acdb_init_v2_cvd_t)(char *, char *);
@@ -91,7 +108,9 @@
bool fluence_in_voice_call;
bool fluence_in_voice_comm;
bool fluence_in_voice_rec;
- int dualmic_config;
+ /* 0 = no fluence, 1 = fluence, 2 = fluence pro */
+ int fluence_type;
+ int source_mic_type;
bool speaker_lr_swap;
void *acdb_handle;
@@ -104,6 +123,8 @@
char ec_ref_mixer_path[64];
char *snd_card_name;
+ int max_vol_index;
+ int max_mic_count;
};
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -115,12 +136,16 @@
MULTIMEDIA2_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE,
PLAYBACK_OFFLOAD_DEVICE},
- [USECASE_AUDIO_PLAYBACK_TTS] = {MULTIMEDIA3_PCM_DEVICE,
- MULTIMEDIA3_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_TTS] = {MULTIMEDIA2_PCM_DEVICE,
+ MULTIMEDIA2_PCM_DEVICE},
+ [USECASE_AUDIO_PLAYBACK_ULL] = {MULTIMEDIA3_PCM_DEVICE,
+ MULTIMEDIA3_PCM_DEVICE},
+
[USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE,
AUDIO_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
+
[USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
VOICE_CALL_PCM_DEVICE},
[USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
@@ -224,7 +249,11 @@
[SND_DEVICE_IN_VOICE_RX] = "voice-rx",
+ [SND_DEVICE_IN_THREE_MIC] = "three-mic",
+ [SND_DEVICE_IN_QUAD_MIC] = "quad-mic",
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = "vi-feedback",
+ [SND_DEVICE_IN_HANDSET_TMIC] = "three-mic",
+ [SND_DEVICE_IN_HANDSET_QMIC] = "quad-mic",
};
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -303,7 +332,11 @@
[SND_DEVICE_IN_VOICE_RX] = 44,
+ [SND_DEVICE_IN_THREE_MIC] = 46,
+ [SND_DEVICE_IN_QUAD_MIC] = 46,
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = 102,
+ [SND_DEVICE_IN_HANDSET_TMIC] = 125,
+ [SND_DEVICE_IN_HANDSET_QMIC] = 125,
};
struct name_to_index {
@@ -387,7 +420,11 @@
{TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_STEREO)},
{TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_THREE_MIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_QUAD_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_TMIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_QMIC)},
};
static char * backend_tag_table[SND_DEVICE_MAX] = {0};
@@ -398,6 +435,8 @@
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_TTS)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_ULL)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
{TO_NAME_INDEX(USECASE_VOICE_CALL)},
@@ -453,6 +492,71 @@
return is_tmus;
}
+static char *get_current_operator()
+{
+ struct listnode *node;
+ struct operator_info *info_item;
+ char mccmnc[PROPERTY_VALUE_MAX];
+ char *ret = NULL;
+
+ property_get("gsm.sim.operator.numeric",mccmnc,"0");
+
+ list_for_each(node, &operator_info_list) {
+ info_item = node_to_item(node, struct operator_info, list);
+ if (strstr(info_item->mccmnc, mccmnc) != NULL) {
+ ret = info_item->name;
+ }
+ }
+
+ return ret;
+}
+
+static struct operator_specific_device *get_operator_specific_device(snd_device_t snd_device)
+{
+ struct listnode *node;
+ struct operator_specific_device *ret = NULL;
+ struct operator_specific_device *device_item;
+ char *operator_name;
+
+ operator_name = get_current_operator();
+ if (operator_name == NULL)
+ return ret;
+
+ list_for_each(node, operator_specific_device_table[snd_device]) {
+ device_item = node_to_item(node, struct operator_specific_device, list);
+ if (strcmp(operator_name, device_item->operator) == 0) {
+ ret = device_item;
+ }
+ }
+
+ return ret;
+}
+
+
+static int get_operator_specific_device_acdb_id(snd_device_t snd_device)
+{
+ struct operator_specific_device *device;
+ int ret = acdb_device_table[snd_device];
+
+ device = get_operator_specific_device(snd_device);
+ if (device != NULL)
+ ret = device->acdb_id;
+
+ return ret;
+}
+
+static const char *get_operator_specific_device_mixer_path(snd_device_t snd_device)
+{
+ struct operator_specific_device *device;
+ const char *ret = device_table[snd_device];
+
+ device = get_operator_specific_device(snd_device);
+ if (device != NULL)
+ ret = device->mixer_path;
+
+ return ret;
+}
+
bool platform_send_gain_dep_cal(void *platform, int level)
{
bool ret_val = false;
@@ -712,12 +816,13 @@
#endif
}
-static void set_platform_defaults(struct platform_data * my_data __unused)
+static void set_platform_defaults(struct platform_data * my_data)
{
int32_t dev;
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
backend_tag_table[dev] = NULL;
hw_interface_table[dev] = NULL;
+ operator_specific_device_table[dev] = NULL;
}
// To overwrite these go to the audio_platform_info.xml file.
@@ -758,6 +863,8 @@
hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED] = strdup("SLIMBUS_0_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = strdup("SLIMBUS_0_RX");
+
+ my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -792,6 +899,7 @@
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data;
int retry_num = 0, snd_card_num = 0;
+ bool dual_mic_config = false;
const char *snd_card_name;
char *cvd_version = NULL;
@@ -799,6 +907,8 @@
my_data->adev = adev;
+ list_init(&operator_info_list);
+
set_platform_defaults(my_data);
/* Initialize platform specific ids and/or backends*/
@@ -850,20 +960,32 @@
goto init_failed;
}
- my_data->dualmic_config = DUALMIC_CONFIG_NONE;
+ //set max volume step for voice call
+ property_get("ro.config.vc_call_vol_steps", value, TOSTRING(MAX_VOL_INDEX));
+ my_data->max_vol_index = atoi(value);
+
+ property_get("persist.audio.dualmic.config",value,"");
+ if (!strcmp("endfire", value)) {
+ dual_mic_config = true;
+ }
+
+ my_data->source_mic_type = SOURCE_DUAL_MIC;
+
my_data->fluence_in_spkr_mode = false;
my_data->fluence_in_voice_call = false;
my_data->fluence_in_voice_comm = false;
my_data->fluence_in_voice_rec = false;
- property_get("persist.audio.dualmic.config",value,"");
- if (!strcmp("broadside", value)) {
- ALOGE("%s: Unsupported dualmic configuration", __func__);
- } else if (!strcmp("endfire", value)) {
- my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
+ property_get("ro.qc.sdk.audio.fluencetype", value, "none");
+ if (!strcmp("fluencepro", value)) {
+ my_data->fluence_type = FLUENCE_PRO_ENABLE;
+ } else if (!strcmp("fluence", value) || (dual_mic_config)) {
+ my_data->fluence_type = FLUENCE_ENABLE;
+ } else if (!strcmp("none", value)) {
+ my_data->fluence_type = FLUENCE_DISABLE;
}
- if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ if (my_data->fluence_type != FLUENCE_DISABLE) {
property_get("persist.audio.fluence.voicecall",value,"");
if (!strcmp("true", value)) {
my_data->fluence_in_voice_call = true;
@@ -885,6 +1007,30 @@
}
}
+ // support max to mono, example if max count is 3, usecase supports Three, dual and mono mic
+ switch (my_data->max_mic_count) {
+ case 4:
+ my_data->source_mic_type |= SOURCE_QUAD_MIC;
+ case 3:
+ my_data->source_mic_type |= SOURCE_THREE_MIC;
+ case 2:
+ my_data->source_mic_type |= SOURCE_DUAL_MIC;
+ case 1:
+ my_data->source_mic_type |= SOURCE_MONO_MIC;
+ break;
+ default:
+ ALOGE("%s: max_mic_count (%d), is not supported, setting to default",
+ __func__, my_data->max_mic_count);
+ my_data->source_mic_type = SOURCE_MONO_MIC|SOURCE_DUAL_MIC;
+ break;
+ }
+
+ ALOGV("%s: Fluence_Type(%d) max_mic_count(%d) mic_type(0x%x) fluence_in_voice_call(%d)"
+ " fluence_in_voice_comm(%d) fluence_in_voice_rec(%d) fluence_in_spkr_mode(%d) ",
+ __func__, my_data->fluence_type, my_data->max_mic_count, my_data->source_mic_type,
+ my_data->fluence_in_voice_call, my_data->fluence_in_voice_comm,
+ my_data->fluence_in_voice_rec, my_data->fluence_in_spkr_mode);
+
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
@@ -976,6 +1122,9 @@
void platform_deinit(void *platform)
{
int32_t dev;
+ struct operator_info *info_item;
+ struct operator_specific_device *device_item;
+ struct listnode *node;
struct platform_data *my_data = (struct platform_data *)platform;
close_csd_client(my_data->csd);
@@ -985,19 +1134,42 @@
free(backend_tag_table[dev]);
if (hw_interface_table[dev])
free(hw_interface_table[dev]);
+ if (operator_specific_device_table[dev]) {
+ while (!list_empty(operator_specific_device_table[dev])) {
+ node = list_head(operator_specific_device_table[dev]);
+ list_remove(node);
+ device_item = node_to_item(node, struct operator_specific_device, list);
+ free(device_item->operator);
+ free(device_item->mixer_path);
+ free(device_item);
+ }
+ free(operator_specific_device_table[dev]);
+ }
}
if (my_data->snd_card_name)
free(my_data->snd_card_name);
+ while (!list_empty(&operator_info_list)) {
+ node = list_head(&operator_info_list);
+ list_remove(node);
+ info_item = node_to_item(node, struct operator_info, list);
+ free(info_item->name);
+ free(info_item->mccmnc);
+ free(info_item);
+ }
+
free(platform);
}
const char *platform_get_snd_device_name(snd_device_t snd_device)
{
- if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
+ if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
+ if (operator_specific_device_table[snd_device] != NULL) {
+ return get_operator_specific_device_mixer_path(snd_device);
+ }
return device_table[snd_device];
- else
+ } else
return "none";
}
@@ -1041,7 +1213,7 @@
const char * be_itf2 = hw_interface_table[snd_device2];
if (NULL != be_itf1 && NULL != be_itf2) {
- if (0 != strcmp(be_itf1, be_itf2))
+ if ((NULL == strstr(be_itf2, be_itf1)) && (NULL == strstr(be_itf1, be_itf2)))
result = false;
}
@@ -1100,6 +1272,32 @@
return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}
+void platform_add_operator_specific_device(snd_device_t snd_device,
+ const char *operator,
+ const char *mixer_path,
+ unsigned int acdb_id)
+{
+ struct operator_specific_device *device;
+
+ if (operator_specific_device_table[snd_device] == NULL) {
+ operator_specific_device_table[snd_device] =
+ (struct listnode *)calloc(1, sizeof(struct listnode));
+ list_init(operator_specific_device_table[snd_device]);
+ }
+
+ device = (struct operator_specific_device *)calloc(1, sizeof(struct operator_specific_device));
+
+ device->operator = strdup(operator);
+ device->mixer_path = strdup(mixer_path);
+ device->acdb_id = acdb_id;
+
+ list_add_tail(operator_specific_device_table[snd_device], &device->list);
+
+ ALOGD("%s : deivce[%s] -> operator[%s] mixer_path[%s] acdb_id [%d]", __func__,
+ platform_get_snd_device_name(snd_device), operator, mixer_path, acdb_id);
+
+}
+
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
int ret = 0;
@@ -1124,7 +1322,11 @@
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
return -EINVAL;
}
- return acdb_device_table[snd_device];
+
+ if (operator_specific_device_table[snd_device] != NULL)
+ return get_operator_specific_device_acdb_id(snd_device);
+ else
+ return acdb_device_table[snd_device];
}
int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
@@ -1181,11 +1383,11 @@
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];
+ acdb_rx_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED);
else
- acdb_rx_id = acdb_device_table[out_snd_device];
+ acdb_rx_id = platform_get_snd_device_acdb_id(out_snd_device);
- acdb_tx_id = acdb_device_table[in_snd_device];
+ acdb_tx_id = platform_get_snd_device_acdb_id(in_snd_device);
if (acdb_rx_id > 0 && acdb_tx_id > 0) {
ret = my_data->csd->enable_device_config(acdb_rx_id, acdb_tx_id);
@@ -1215,8 +1417,8 @@
audio_extn_spkr_prot_is_enabled())
out_snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED;
- acdb_rx_id = acdb_device_table[out_snd_device];
- acdb_tx_id = acdb_device_table[in_snd_device];
+ acdb_rx_id = platform_get_snd_device_acdb_id(out_snd_device);
+ acdb_tx_id = platform_get_snd_device_acdb_id(in_snd_device);
if (acdb_rx_id > 0 && acdb_tx_id > 0)
my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id);
@@ -1241,11 +1443,11 @@
if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED];
+ acdb_rx_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED);
else
- acdb_rx_id = acdb_device_table[out_snd_device];
+ acdb_rx_id = platform_get_snd_device_acdb_id(out_snd_device);
- acdb_tx_id = acdb_device_table[in_snd_device];
+ acdb_tx_id = platform_get_snd_device_acdb_id(in_snd_device);
if (acdb_rx_id > 0 && acdb_tx_id > 0) {
ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id,
@@ -1303,6 +1505,43 @@
return ret;
}
+void platform_set_speaker_gain_in_combo(struct audio_device *adev,
+ snd_device_t snd_device,
+ bool enable)
+{
+ const char* name;
+ switch (snd_device) {
+ case SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES:
+ if (enable)
+ name = "spkr-gain-in-headphone-combo";
+ else
+ name = "speaker-gain-default";
+ break;
+ case SND_DEVICE_OUT_SPEAKER_AND_LINE:
+ if (enable)
+ name = "spkr-gain-in-line-combo";
+ else
+ name = "speaker-gain-default";
+ break;
+ case SND_DEVICE_OUT_SPEAKER_SAFE_AND_HEADPHONES:
+ if (enable)
+ name = "spkr-safe-gain-in-headphone-combo";
+ else
+ name = "speaker-safe-gain-default";
+ break;
+ case SND_DEVICE_OUT_SPEAKER_SAFE_AND_LINE:
+ if (enable)
+ name = "spkr-safe-gain-in-line-combo";
+ else
+ name = "speaker-safe-gain-default";
+ break;
+ default:
+ return;
+ }
+
+ audio_route_apply_and_update_path(adev->audio_route, name);
+}
+
int platform_set_voice_volume(void *platform, int volume)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -1317,7 +1556,7 @@
// Voice volume levels are mapped to adsp volume levels as follows.
// 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0
// But this values don't changed in kernel. So, below change is need.
- vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
+ vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, my_data->max_vol_index);
set_values[0] = vol_index;
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
@@ -1468,6 +1707,40 @@
goto exit;
}
+ if (popcount(devices) == 2) {
+ if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_SPEAKER) ||
+ devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
+ } else if (devices == (AUDIO_DEVICE_OUT_LINE |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_LINE;
+ } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
+ devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_HEADPHONES;
+ } else if (devices == (AUDIO_DEVICE_OUT_LINE |
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_LINE;
+ } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ } else {
+ ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
+ goto exit;
+ }
+ if (snd_device != SND_DEVICE_NONE) {
+ goto exit;
+ }
+ }
+
+ if (popcount(devices) != 1) {
+ ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
+ goto exit;
+ }
+
if (voice_is_in_call(adev) || adev->enable_voicerx) {
if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
devices & AUDIO_DEVICE_OUT_WIRED_HEADSET ||
@@ -1510,40 +1783,6 @@
}
}
- if (popcount(devices) == 2) {
- if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_SPEAKER) ||
- devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
- } else if (devices == (AUDIO_DEVICE_OUT_LINE |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_LINE;
- } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_SPEAKER_SAFE) ||
- devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_HEADPHONES;
- } else if (devices == (AUDIO_DEVICE_OUT_LINE |
- AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_SAFE_AND_LINE;
- } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
- } else {
- ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
- goto exit;
- }
- if (snd_device != SND_DEVICE_NONE) {
- goto exit;
- }
- }
-
- if (popcount(devices) != 1) {
- ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
- goto exit;
- }
-
if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
snd_device = SND_DEVICE_OUT_HEADPHONES;
@@ -1594,8 +1833,8 @@
snd_device_t snd_device = SND_DEVICE_NONE;
int channel_count = popcount(channel_mask);
- ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
- __func__, out_device, in_device);
+ ALOGV("%s: enter: out_device(%#x) in_device(%#x) channel_count (%d) channel_mask (0x%x)",
+ __func__, out_device, in_device, channel_count, channel_mask);
if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
if (adev->voice.tty_mode != TTY_MODE_OFF) {
if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
@@ -1641,17 +1880,24 @@
snd_device = SND_DEVICE_IN_BT_SCO_MIC;
}
} else if (out_device & AUDIO_DEVICE_OUT_SPEAKER ||
- out_device & AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
- out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
- out_device & AUDIO_DEVICE_OUT_LINE) {
- if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
- snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
- } else {
+ out_device & AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
+ out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
+ out_device & AUDIO_DEVICE_OUT_LINE) {
+ if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode) {
+ if (my_data->source_mic_type & SOURCE_DUAL_MIC) {
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
+ } else {
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
+ }
+ }
+
+ //select default
+ if (snd_device == SND_DEVICE_NONE) {
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
}
- } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
+ } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX) {
snd_device = SND_DEVICE_IN_VOICE_RX;
+ }
} else if (source == AUDIO_SOURCE_CAMCORDER) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
in_device & AUDIO_DEVICE_IN_BACK_MIC) {
@@ -1659,14 +1905,29 @@
}
} else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
- if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
- snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
- else if (my_data->fluence_in_voice_rec &&
- adev->active_input->enable_ns)
+ if (my_data->fluence_in_voice_rec && channel_count == 1) {
+ if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
+ (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_QMIC;
+ } else if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
+ (my_data->source_mic_type & SOURCE_THREE_MIC)) {
+ snd_device = SND_DEVICE_IN_HANDSET_TMIC;
+ } else if (((my_data->fluence_type == FLUENCE_PRO_ENABLE) ||
+ (my_data->fluence_type == FLUENCE_ENABLE)) &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
+ }
+ platform_set_echo_reference(adev, true, out_device);
+ } else if ((channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
+ } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
+ (my_data->source_mic_type & SOURCE_THREE_MIC)) {
+ snd_device = SND_DEVICE_IN_THREE_MIC;
+ } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
+ (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+ snd_device = SND_DEVICE_IN_QUAD_MIC;
}
-
if (snd_device == SND_DEVICE_NONE) {
if (adev->active_input->enable_ns)
snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
@@ -1683,16 +1944,18 @@
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_in_spkr_mode &&
my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
- } else
+ } else {
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
+ }
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
if (my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS;
- } else
+ } else {
snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS;
+ }
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
}
@@ -1701,16 +1964,18 @@
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_in_spkr_mode &&
my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
- } else
+ } else {
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
+ }
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
if (my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
- } else
+ } else {
snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
+ }
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
}
@@ -1719,16 +1984,18 @@
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_in_spkr_mode &&
my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
- } else
+ } else {
snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
+ }
} else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
if (my_data->fluence_in_voice_comm &&
- my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS;
- } else
+ } else {
snd_device = SND_DEVICE_IN_HANDSET_MIC_NS;
+ }
}
}
}
@@ -1745,17 +2012,37 @@
!(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
!(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- if (my_data->dualmic_config != DUALMIC_CONFIG_NONE &&
- channel_count == 2)
+ if ((my_data->source_mic_type & SOURCE_QUAD_MIC) &&
+ (int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) {
+ snd_device = SND_DEVICE_IN_QUAD_MIC;
+ } else if ((my_data->source_mic_type & SOURCE_THREE_MIC) &&
+ (int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) {
+ snd_device = SND_DEVICE_IN_THREE_MIC;
+ } else if ((my_data->source_mic_type & SOURCE_DUAL_MIC) &&
+ channel_count == 2) {
snd_device = SND_DEVICE_IN_HANDSET_DMIC_STEREO;
- else
+ } else if ((my_data->source_mic_type & SOURCE_MONO_MIC) &&
+ channel_count == 1) {
snd_device = SND_DEVICE_IN_HANDSET_MIC;
+ } else {
+ ALOGE("%s: something wrong (1): source type (%d) channel_count (%d) .."
+ " channel mask (0x%x) no combination found .. setting to mono", __func__,
+ my_data->source_mic_type, channel_count, channel_mask);
+ snd_device = SND_DEVICE_IN_HANDSET_MIC;
+ }
} else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->dualmic_config != DUALMIC_CONFIG_NONE &&
- channel_count == 2)
+ if ((my_data->source_mic_type & SOURCE_DUAL_MIC) &&
+ channel_count == 2) {
snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO;
- else
+ } else if ((my_data->source_mic_type & SOURCE_MONO_MIC) &&
+ channel_count == 1) {
snd_device = SND_DEVICE_IN_SPEAKER_MIC;
+ } else {
+ ALOGE("%s: something wrong (2): source type (%d) channel_count (%d) .."
+ " no combination found .. setting to mono", __func__,
+ my_data->source_mic_type, channel_count);
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC;
+ }
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_HEADSET_MIC;
} else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
@@ -1786,10 +2073,18 @@
out_device & AUDIO_DEVICE_OUT_SPEAKER_SAFE ||
out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
out_device & AUDIO_DEVICE_OUT_LINE) {
- if (channel_count == 2)
+ if ((my_data->source_mic_type & SOURCE_DUAL_MIC) &&
+ channel_count == 2) {
snd_device = SND_DEVICE_IN_SPEAKER_DMIC_STEREO;
- else
+ } else if ((my_data->source_mic_type & SOURCE_MONO_MIC) &&
+ channel_count == 1) {
snd_device = SND_DEVICE_IN_SPEAKER_MIC;
+ } else {
+ ALOGE("%s: something wrong (3): source type (%d) channel_count (%d) .."
+ " no combination found .. setting to mono", __func__,
+ my_data->source_mic_type, channel_count);
+ snd_device = SND_DEVICE_IN_SPEAKER_MIC;
+ }
} else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
if (adev->bt_wb_speech_enabled) {
if (adev->bluetooth_nrec)
@@ -1993,7 +2288,7 @@
int platform_set_parameters(void *platform, struct str_parms *parms)
{
struct platform_data *my_data = (struct platform_data *)platform;
- char value[64];
+ char value[128];
char *kv_pairs = str_parms_to_str(parms);
int ret = 0, err;
@@ -2013,6 +2308,32 @@
ALOGV("%s: sound card name %s", __func__, my_data->snd_card_name);
}
+ err = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_OPERATOR_INFO,
+ value, sizeof(value));
+ if (err >= 0) {
+ struct operator_info *info;
+ char *str = value;
+ char *name;
+
+ str_parms_del(parms, PLATFORM_CONFIG_KEY_OPERATOR_INFO);
+ info = (struct operator_info *)calloc(1, sizeof(struct operator_info));
+ name = strtok(str, ";");
+ info->name = strdup(name);
+ info->mccmnc = strdup(str + strlen(name) + 1);
+
+ list_add_tail(&operator_info_list, &info->list);
+ ALOGD("%s: add operator[%s] mccmnc[%s]", __func__, info->name, info->mccmnc);
+ }
+
+ memset(value, 0, sizeof(value));
+ err = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_MAX_MIC_COUNT,
+ value, sizeof(value));
+ if (err >= 0) {
+ str_parms_del(parms, PLATFORM_CONFIG_KEY_MAX_MIC_COUNT);
+ my_data->max_mic_count = atoi(value);
+ ALOGV("%s: max_mic_count %s/%d", __func__, value, my_data->max_mic_count);
+ }
+
done:
ALOGV("%s: exit with code(%d)", __func__, ret);
if (kv_pairs != NULL)
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index f1c5239..c1f901c 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -17,6 +17,19 @@
#ifndef QCOM_AUDIO_PLATFORM_H
#define QCOM_AUDIO_PLATFORM_H
+enum {
+ FLUENCE_DISABLE, /* Target dosent support fluence */
+ FLUENCE_ENABLE = 0x1, /* Target supports fluence */
+ FLUENCE_PRO_ENABLE = 0x2, /* Target supports fluence pro */
+};
+
+enum {
+ SOURCE_MONO_MIC = 0x1, /* Target contains 1 mic */
+ SOURCE_DUAL_MIC = 0x2, /* Target contains 2 mics */
+ SOURCE_THREE_MIC = 0x4, /* Target contains 3 mics */
+ SOURCE_QUAD_MIC = 0x8, /* Target contains 4 mics */
+};
+
/*
* 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
@@ -118,8 +131,12 @@
SND_DEVICE_IN_VOICE_RX,
+ SND_DEVICE_IN_THREE_MIC,
+ SND_DEVICE_IN_QUAD_MIC,
SND_DEVICE_IN_CAPTURE_VI_FEEDBACK,
+ SND_DEVICE_IN_HANDSET_TMIC,
+ SND_DEVICE_IN_HANDSET_QMIC,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -131,6 +148,7 @@
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
#define DEFAULT_VOLUME_RAMP_DURATION_MS 20
+#define MIXER_PATH_MAX_LENGTH 100
#define ACDB_ID_VOICE_SPEAKER 15
#define ACDB_ID_VOICE_HANDSET 7
@@ -207,6 +225,8 @@
#define LIB_MDM_DETECT "libmdmdetect.so"
#define PLATFORM_CONFIG_KEY_SOUNDCARD_NAME "snd_card_name"
+#define PLATFORM_CONFIG_KEY_MAX_MIC_COUNT "input_mic_max_count"
+#define PLATFORM_DEFAULT_MIC_COUNT 2
/* CSD-CLIENT related functions */
typedef int (*init_t)(bool);
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 61bb92f..1e41358 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -41,6 +41,9 @@
int platform_start_voice_call(void *platform, uint32_t vsid);
int platform_stop_voice_call(void *platform, uint32_t vsid);
int platform_set_voice_volume(void *platform, int volume);
+void platform_set_speaker_gain_in_combo(struct audio_device *adev,
+ snd_device_t snd_device,
+ bool enable);
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);
@@ -48,6 +51,10 @@
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);
int platform_edid_get_max_channels(void *platform);
+void platform_add_operator_specific_device(snd_device_t snd_device,
+ const char *operator,
+ const char *mixer_path,
+ unsigned int acdb_id);
/* returns the latency for a usecase in Us */
int64_t platform_render_latency(audio_usecase_t usecase);
diff --git a/hal/platform_info.c b/hal/platform_info.c
index c0527b4..4556294 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -33,6 +33,7 @@
PCM_ID,
BACKEND_NAME,
CONFIG_PARAMS,
+ OPERATOR_SPECIFIC,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -42,6 +43,7 @@
static void process_backend_name(const XML_Char **attr);
static void process_config_params(const XML_Char **attr);
static void process_root(const XML_Char **attr);
+static void process_operator_specific(const XML_Char **attr);
static section_process_fn section_table[] = {
[ROOT] = process_root,
@@ -49,6 +51,7 @@
[PCM_ID] = process_pcm_id,
[BACKEND_NAME] = process_backend_name,
[CONFIG_PARAMS] = process_config_params,
+ [OPERATOR_SPECIFIC] = process_operator_specific,
};
static section_t section;
@@ -79,10 +82,18 @@
* </pcm_ids>
* <config_params>
* <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/>
+ * <param key="operator_info" value="tmus;aa;bb;cc"/>
+ * <param key="operator_info" value="sprint;xx;yy;zz"/>
* ...
* ...
* </config_params>
*
+ * <operator_specific>
+ * <device name="???" operator="???" mixer_path="???" acdb_id="???"/>
+ * ...
+ * ...
+ * </operator_specific>
+ *
* </audio_platform_info>
*/
@@ -214,6 +225,44 @@
return;
}
+
+static void process_operator_specific(const XML_Char **attr)
+{
+ snd_device_t snd_device = SND_DEVICE_NONE;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found", __func__);
+ goto done;
+ }
+
+ snd_device = platform_get_snd_device_index((char *)attr[1]);
+ if (snd_device < 0) {
+ ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
+ __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "operator") != 0) {
+ ALOGE("%s: 'operator' not found", __func__);
+ goto done;
+ }
+
+ if (strcmp(attr[4], "mixer_path") != 0) {
+ ALOGE("%s: 'mixer_path' not found", __func__);
+ goto done;
+ }
+
+ if (strcmp(attr[6], "acdb_id") != 0) {
+ ALOGE("%s: 'acdb_id' not found", __func__);
+ goto done;
+ }
+
+ platform_add_operator_specific_device(snd_device, (char *)attr[3], (char *)attr[5], atoi((char *)attr[7]));
+
+done:
+ return;
+}
+
/* platform specific configuration key-value pairs */
static void process_config_params(const XML_Char **attr)
{
@@ -228,6 +277,7 @@
}
str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
+ platform_set_parameters(my_data.platform, my_data.kvpairs);
done:
return;
}
@@ -247,8 +297,10 @@
section = BACKEND_NAME;
} else if (strcmp(tag_name, "config_params") == 0) {
section = CONFIG_PARAMS;
+ } else if (strcmp(tag_name, "operator_specific") == 0) {
+ section = OPERATOR_SPECIFIC;
} else if (strcmp(tag_name, "device") == 0) {
- if ((section != ACDB) && (section != BACKEND_NAME)) {
+ if ((section != ACDB) && (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
ALOGE("device tag only supported for acdb/backend names");
return;
}
@@ -287,7 +339,8 @@
section = ROOT;
} else if (strcmp(tag_name, "config_params") == 0) {
section = ROOT;
- platform_set_parameters(my_data.platform, my_data.kvpairs);
+ } else if (strcmp(tag_name, "operator_specific") == 0) {
+ section = ROOT;
}
}
diff --git a/hal/voice.c b/hal/voice.c
index 1f36b36..a33305d 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -52,6 +52,58 @@
return session;
}
+static bool voice_is_sidetone_device(snd_device_t out_device,
+ char *mixer_path)
+{
+ bool is_sidetone_dev = true;
+
+ switch (out_device) {
+ case SND_DEVICE_OUT_VOICE_HAC_HANDSET:
+ strlcpy(mixer_path, "sidetone-hac-handset", MIXER_PATH_MAX_LENGTH);
+ break;
+ case SND_DEVICE_OUT_VOICE_HANDSET:
+ strlcpy(mixer_path, "sidetone-handset", MIXER_PATH_MAX_LENGTH);
+ break;
+ case SND_DEVICE_OUT_VOICE_HEADPHONES:
+ strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
+ break;
+ default:
+ is_sidetone_dev = false;
+ break;
+ }
+
+ return is_sidetone_dev;
+}
+
+void voice_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device, bool enable)
+{
+ char mixer_path[MIXER_PATH_MAX_LENGTH];
+ bool is_sidetone_dev;
+
+ ALOGD("%s: %s, out_snd_device: %d\n",
+ __func__, (enable ? "enable" : "disable"),
+ out_snd_device);
+
+ is_sidetone_dev = voice_is_sidetone_device(out_snd_device, mixer_path);
+
+ if (!is_sidetone_dev) {
+ ALOGD("%s: device %d does not support sidetone\n",
+ __func__, out_snd_device);
+ return;
+ }
+
+ ALOGD("%s: sidetone out device = %s\n",
+ __func__, mixer_path);
+
+ if (enable)
+ audio_route_apply_and_update_path(adev->audio_route, mixer_path);
+ else
+ audio_route_reset_and_update_path(adev->audio_route, mixer_path);
+
+ return;
+}
+
int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
{
int i, ret = 0;
@@ -61,8 +113,20 @@
ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
+
+ uc_info = get_usecase_from_list(adev, usecase_id);
+ if (uc_info == NULL) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, usecase_id);
+ return -EINVAL;
+ }
+
session->state.current = CALL_INACTIVE;
+ /* Disable sidetone only when no calls are active */
+ if (!voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, uc_info->out_snd_device, false);
+
ret = platform_stop_voice_call(adev->platform, session->vsid);
/* 1. Close the PCM devices */
@@ -75,13 +139,6 @@
session->pcm_tx = NULL;
}
- uc_info = get_usecase_from_list(adev, usecase_id);
- if (uc_info == NULL) {
- ALOGE("%s: Could not find the usecase (%d) in the list",
- __func__, usecase_id);
- return -EINVAL;
- }
-
/* 2. Get and set stream specific mixer controls */
disable_audio_route(adev, uc_info);
@@ -129,6 +186,17 @@
goto error_start_voice;
}
+ ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+ __func__, adev->snd_card, pcm_dev_tx_id);
+ session->pcm_tx = pcm_open(adev->snd_card,
+ pcm_dev_tx_id,
+ PCM_IN, &voice_config);
+ if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
+ ret = -EIO;
+ goto error_start_voice;
+ }
+
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
__func__, adev->snd_card, pcm_dev_rx_id);
session->pcm_rx = pcm_open(adev->snd_card,
@@ -140,18 +208,12 @@
goto error_start_voice;
}
- ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
- __func__, adev->snd_card, pcm_dev_tx_id);
- session->pcm_tx = pcm_open(adev->snd_card,
- pcm_dev_tx_id,
- PCM_IN, &voice_config);
- if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
- ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
- ret = -EIO;
- goto error_start_voice;
- }
- pcm_start(session->pcm_rx);
pcm_start(session->pcm_tx);
+ pcm_start(session->pcm_rx);
+
+ /* Enable sidetone only when no calls are already active */
+ if (!voice_is_call_state_active(adev))
+ voice_set_sidetone(adev, uc_info->out_snd_device, true);
voice_set_volume(adev, adev->voice.volume);
diff --git a/hal/voice.h b/hal/voice.h
index 76f9d0d..23b9ee3 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -40,6 +40,7 @@
struct stream_in;
struct stream_out;
typedef int audio_usecase_t;
+typedef int snd_device_t;
struct call_state {
int current;
@@ -90,4 +91,8 @@
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);
+void voice_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable);
+bool voice_is_call_state_active(struct audio_device *adev);
#endif //VOICE_H
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index cf15f1c..34954bb 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -312,6 +312,13 @@
* Effect Control Interface Implementation
*/
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
static int vol_effect_process(effect_handle_t self,
audio_buffer_t *in_buffer,
audio_buffer_t *out_buffer)
@@ -330,7 +337,15 @@
// calculation based on channel count 2
if (in_buffer->raw != out_buffer->raw) {
- memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
+ if (context->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ size_t i;
+ for (i = 0; i < out_buffer->frameCount*2; i++) {
+ out_buffer->s16[i] = clamp16(out_buffer->s16[i] + in_buffer->s16[i]);
+ }
+ } else {
+ memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
+ }
+
} else {
ALOGW("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
__func__);
@@ -374,6 +389,12 @@
case EFFECT_CMD_SET_CONFIG:
ALOGV("%s :: cmd called EFFECT_CMD_SET_CONFIG", __func__);
+ if (p_cmd_data == NULL || cmd_size != sizeof(effect_config_t)
+ || p_reply_data == NULL || reply_size == NULL || *reply_size != sizeof(int)) {
+ return -EINVAL;
+ }
+ context->config = *(effect_config_t *)p_cmd_data;
+ *(int *)p_reply_data = 0;
break;
case EFFECT_CMD_GET_CONFIG:
@@ -420,7 +441,7 @@
// After changing the state and if device is speaker
// recalculate gain dep cal level
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
check_and_set_gain_dep_cal();
}
@@ -447,7 +468,7 @@
// After changing the state and if device is speaker
// recalculate gain dep cal level
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
check_and_set_gain_dep_cal();
}
@@ -478,8 +499,8 @@
__func__, context->dev_id, new_device);
// check if old or new device is speaker
- if ((context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) ||
- (new_device & AUDIO_DEVICE_OUT_SPEAKER)) {
+ if ((context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) ||
+ (new_device == AUDIO_DEVICE_OUT_SPEAKER)) {
recompute_gain_dep_cal_Level = true;
}
@@ -504,7 +525,7 @@
goto exit;
}
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
recompute_gain_dep_cal_Level = true;
}
@@ -600,7 +621,7 @@
static int vol_prc_lib_create(const effect_uuid_t *uuid,
int32_t session_id,
- int32_t io_id,
+ int32_t io_id __unused,
effect_handle_t *p_handle)
{
int itt = 0;
@@ -682,7 +703,7 @@
ALOGV("--- Found something to remove ---");
list_remove(&context->effect_list_node);
PRINT_STREAM_TYPE(context->stream_type);
- if (context->dev_id && AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
recompute_flag = true;
}
free(context);