Merge "hal: mpq: configure HDMI channel number"
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 3f457d2..80ce063 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -61,13 +61,6 @@
void audio_extn_hfp_set_parameters(struct audio_device *adev,
struct str_parms *parms);
#endif
-#ifndef SSR_ENABLED
-#define audio_extn_ssr_get_parameters(query, reply) (0)
-#else
-void audio_extn_ssr_get_parameters(struct str_parms *query,
-
- struct str_parms *reply);
-#endif
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
@@ -335,7 +328,6 @@
struct str_parms *reply)
{
audio_extn_get_afe_proxy_parameters(query, reply);
- audio_extn_ssr_get_parameters(query, reply);
ALOGD("%s: returns %s", __func__, str_parms_to_str(reply));
}
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 6bd03ee..72f8642 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -70,14 +70,14 @@
#ifndef SSR_ENABLED
#define audio_extn_ssr_init(adev, in) (0)
#define audio_extn_ssr_deinit() (0)
-#define audio_extn_ssr_update_enabled(adev) (0)
+#define audio_extn_ssr_update_enabled() (0)
#define audio_extn_ssr_get_enabled() (0)
#define audio_extn_ssr_read(stream, buffer, bytes) (0)
#else
int32_t audio_extn_ssr_init(struct audio_device *adev,
struct stream_in *in);
int32_t audio_extn_ssr_deinit();
-int32_t audio_extn_ssr_update_enabled(struct audio_device *adev);
+void audio_extn_ssr_update_enabled();
bool audio_extn_ssr_get_enabled();
int32_t audio_extn_ssr_read(struct audio_stream_in *stream,
void *buffer, size_t bytes);
@@ -165,4 +165,10 @@
int audio_extn_dolby_set_DMID(struct audio_device *adev);
#endif
+#ifndef HFP_ENABLED
+#define audio_extn_hfp_is_active(adev) (0)
+#else
+bool audio_extn_hfp_is_active(struct audio_device *adev);
+#endif
+
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index 6b0546a..2d6e1e0 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -42,6 +42,7 @@
#ifdef HFP_ENABLED
#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
+#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
static int32_t start_hfp(struct audio_device *adev,
struct str_parms *parms);
@@ -55,6 +56,7 @@
struct pcm *hfp_pcm_tx;
bool is_hfp_running;
int hfp_volume;
+ audio_usecase_t ucid;
};
static struct hfp_module hfpmod = {
@@ -64,6 +66,7 @@
.hfp_pcm_tx = NULL,
.hfp_volume = 0,
.is_hfp_running = 0,
+ .ucid = USECASE_AUDIO_HFP_SCO,
};
static struct pcm_config pcm_config_hfp = {
.channels = 1,
@@ -86,7 +89,7 @@
ALOGD("%s: enter", __func__);
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
- uc_info->id = USECASE_AUDIO_HFP_SCO;
+ uc_info->id = hfpmod.ucid;
uc_info->type = PCM_HFP_CALL;
uc_info->stream.out = adev->primary_output;
uc_info->devices = adev->primary_output->devices;
@@ -95,7 +98,7 @@
list_add_tail(&adev->usecase_list, &uc_info->list);
- select_devices(adev, USECASE_AUDIO_HFP_SCO);
+ select_devices(adev, hfpmod.ucid);
pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
@@ -193,10 +196,10 @@
hfpmod.hfp_pcm_tx = NULL;
}
- uc_info = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
+ uc_info = get_usecase_from_list(adev, hfpmod.ucid);
if (uc_info == NULL) {
ALOGE("%s: Could not find the usecase (%d) in the list",
- __func__, USECASE_AUDIO_HFP_SCO);
+ __func__, hfpmod.ucid);
return -EINVAL;
}
@@ -214,9 +217,22 @@
return ret;
}
+bool audio_extn_hfp_is_active(struct audio_device *adev)
+{
+ struct audio_usecase *hfp_usecase = NULL;
+ hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
+
+ if (hfp_usecase != NULL)
+ return true;
+ else
+ return false;
+}
+
void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
{
int ret;
+ int rate;
+ int val;
char value[32]={0};
ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
@@ -227,5 +243,32 @@
else
stop_hfp(adev);
}
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms,AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ rate = atoi(value);
+ if (rate == 8000){
+ hfpmod.ucid = USECASE_AUDIO_HFP_SCO;
+ pcm_config_hfp.rate = rate;
+ }
+ else if (rate == 16000){
+ hfpmod.ucid = USECASE_AUDIO_HFP_SCO_WB;
+ pcm_config_hfp.rate = rate;
+ }
+ else
+ ALOGE("Unsupported rate..");
+ }
+
+ if(hfpmod.is_hfp_running) {
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
+ value, sizeof(value));
+ if (ret >= 0) {
+ val = atoi(value);
+ if(val > 0)
+ select_devices(adev, hfpmod.ucid);
+ }
+ }
}
#endif /*HFP_ENABLED*/
diff --git a/hal/audio_extn/ssr.c b/hal/audio_extn/ssr.c
index efd92ea..ac6da8b 100644
--- a/hal/audio_extn/ssr.c
+++ b/hal/audio_extn/ssr.c
@@ -34,14 +34,13 @@
#include "surround_filters_interface.h"
#ifdef SSR_ENABLED
-#define COEFF_ARRAY_SIZE 4
-#define FILT_SIZE ((512+1)* 6) /* # ((FFT bins)/2+1)*numOutputs */
-#define SSR_FRAME_SIZE 512
-#define SSR_INPUT_FRAME_SIZE (SSR_FRAME_SIZE * 4)
-#define SSR_OUTPUT_FRAME_SIZE (SSR_FRAME_SIZE * 6)
-#define SSR_CHANNEL_COUNT 4
-#define SSR_PERIOD_SIZE 256
-#define SSR_PERIOD_COUNT 8
+#define COEFF_ARRAY_SIZE 4
+#define FILT_SIZE ((512+1)* 6) /* # ((FFT bins)/2+1)*numOutputs */
+#define SSR_CHANNEL_INPUT_NUM 4
+#define SSR_CHANNEL_OUTPUT_NUM 6
+#define SSR_PERIOD_COUNT 8
+#define SSR_PERIOD_SIZE 512
+#define SSR_INPUT_FRAME_SIZE (SSR_PERIOD_SIZE * SSR_PERIOD_COUNT)
#define SURROUND_FILE_1R "/system/etc/surround_sound/filter1r.pcm"
#define SURROUND_FILE_2R "/system/etc/surround_sound/filter2r.pcm"
@@ -52,7 +51,7 @@
#define SURROUND_FILE_2I "/system/etc/surround_sound/filter2i.pcm"
#define SURROUND_FILE_3I "/system/etc/surround_sound/filter3i.pcm"
#define SURROUND_FILE_4I "/system/etc/surround_sound/filter4i.pcm"
-#define AUDIO_PARAMETER_KEY_SSR "ssr"
+
#define LIB_SURROUND_PROC "libsurround_proc.so"
typedef int (*surround_filters_init_t)(void *, int, int, Word16 **,
@@ -67,11 +66,7 @@
int16_t **real_coeffs;
int16_t **imag_coeffs;
void *surround_obj;
-
- int16_t *surround_input_buffer;
- int16_t *surround_output_buffer;
- int surround_input_bufferIdx;
- int surround_output_bufferIdx;
+ int16_t *surround_raw_buffer;
bool is_ssr_enabled;
void *surround_filters_handle;
@@ -81,19 +76,13 @@
surround_filters_intl_process_t surround_filters_intl_process;
};
-static int32_t ssr_init_surround_sound_lib(unsigned long buffersize);
-static int32_t ssr_read_coeffs_from_file();
-
static struct ssr_module ssrmod = {
.fp_4ch = NULL,
- .fp_6ch= NULL,
+ .fp_6ch = NULL,
.real_coeffs = NULL,
.imag_coeffs = NULL,
.surround_obj = NULL,
- .surround_output_buffer = NULL,
- .surround_input_buffer = NULL,
- .surround_output_bufferIdx = 0,
- .surround_input_bufferIdx= 0,
+ .surround_raw_buffer = NULL,
.is_ssr_enabled = 0,
.surround_filters_handle = NULL,
@@ -230,32 +219,20 @@
int high_freq = 100;
int i, ret = 0;
- ssrmod.surround_input_bufferIdx = 0;
- ssrmod.surround_output_bufferIdx = 0;
-
if ( ssrmod.surround_obj ) {
ALOGE("%s: ola filter library is already initialized", __func__);
return 0;
}
/* Allocate memory for input buffer */
- ssrmod.surround_input_buffer = (Word16 *) calloc(2 * SSR_INPUT_FRAME_SIZE,
+ ssrmod.surround_raw_buffer = (Word16 *) calloc(buffersize,
sizeof(Word16));
- if ( !ssrmod.surround_input_buffer ) {
+ if ( !ssrmod.surround_raw_buffer ) {
ALOGE("%s: Memory allocation failure. Not able to allocate "
"memory for surroundInputBuffer", __func__);
goto init_fail;
}
- /* Allocate memory for output buffer */
- ssrmod.surround_output_buffer = (Word16 *) calloc(2 * SSR_OUTPUT_FRAME_SIZE,
- sizeof(Word16));
- if ( !ssrmod.surround_output_buffer ) {
- ALOGE("%s: Memory allocation failure. Not able to "
- "allocate memory for surroundOutputBuffer", __func__);
- goto init_fail;
- }
-
/* Allocate memory for real and imag coeffs array */
ssrmod.real_coeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
if ( !ssrmod.real_coeffs ) {
@@ -353,13 +330,9 @@
free(ssrmod.surround_obj);
ssrmod.surround_obj = NULL;
}
- if (ssrmod.surround_output_buffer) {
- free(ssrmod.surround_output_buffer);
- ssrmod.surround_output_buffer = NULL;
- }
- if (ssrmod.surround_input_buffer) {
- free(ssrmod.surround_input_buffer);
- ssrmod.surround_input_buffer = NULL;
+ if (ssrmod.surround_raw_buffer) {
+ free(ssrmod.surround_raw_buffer);
+ ssrmod.surround_raw_buffer = NULL;
}
if (ssrmod.real_coeffs){
for (i =0; i<COEFF_ARRAY_SIZE; i++ ) {
@@ -385,7 +358,7 @@
return -ENOMEM;
}
-int32_t audio_extn_ssr_update_enabled(struct audio_device *adev)
+void audio_extn_ssr_update_enabled()
{
char ssr_enabled[PROPERTY_VALUE_MAX] = "false";
@@ -397,7 +370,6 @@
ALOGD("%s: surround sound recording is not supported", __func__);
ssrmod.is_ssr_enabled = false;
}
- return 0;
}
bool audio_extn_ssr_get_enabled()
@@ -414,12 +386,13 @@
uint32_t buffer_size;
ALOGD("%s: ssr case ", __func__);
- in->config.channels = SSR_CHANNEL_COUNT;
+ in->config.channels = SSR_CHANNEL_INPUT_NUM;
in->config.period_size = SSR_PERIOD_SIZE;
in->config.period_count = SSR_PERIOD_COUNT;
- buffer_size = (SSR_PERIOD_SIZE)*(SSR_PERIOD_COUNT);
- ALOGD("%s: buffer_size: %d", __func__, buffer_size);
+ /* use 4k hardcoded buffer size for ssr*/
+ buffer_size = SSR_INPUT_FRAME_SIZE;
+ ALOGV("%s: buffer_size: %d", __func__, buffer_size);
ret = ssr_init_surround_sound_lib(buffer_size);
if (0 != ret) {
@@ -429,16 +402,16 @@
}
property_get("ssr.pcmdump",c_multi_ch_dump,"0");
- if (0 == strncmp("true",c_multi_ch_dump, sizeof("ssr.dump-pcm"))) {
- /* Remember to change file system permission of data(e.g. chmod 777 data/),
- otherwise, fopen may fail */
- if ( !ssrmod.fp_4ch)
- ssrmod.fp_4ch = fopen("/data/media/0/4ch_ssr.pcm", "wb");
- if ( !ssrmod.fp_6ch)
- ssrmod.fp_6ch = fopen("/data/media/0/6ch_ssr.pcm", "wb");
- if ((!ssrmod.fp_4ch) || (!ssrmod.fp_6ch))
- ALOGE("%s: mfp_4ch or mfp_6ch open failed: mfp_4ch:%p mfp_6ch:%p",
- __func__, ssrmod.fp_4ch, ssrmod.fp_6ch);
+ if (0 == strncmp("true", c_multi_ch_dump, sizeof("ssr.dump-pcm"))) {
+ /* Remember to change file system permission of data(e.g. chmod 777 data/),
+ otherwise, fopen may fail */
+ if ( !ssrmod.fp_4ch)
+ ssrmod.fp_4ch = fopen("/data/4ch.pcm", "wb");
+ if ( !ssrmod.fp_6ch)
+ ssrmod.fp_6ch = fopen("/data/6ch.pcm", "wb");
+ if ((!ssrmod.fp_4ch) || (!ssrmod.fp_6ch))
+ ALOGE("%s: mfp_4ch or mfp_6ch open failed: mfp_4ch:%p mfp_6ch:%p",
+ __func__, ssrmod.fp_4ch, ssrmod.fp_6ch);
}
return 0;
@@ -449,7 +422,7 @@
int i;
if (ssrmod.surround_obj) {
- ALOGD("%s: entry", __func__);
+ ALOGV("%s: entry", __func__);
ssrmod.surround_filters_release(ssrmod.surround_obj);
if (ssrmod.surround_obj)
free(ssrmod.surround_obj);
@@ -474,25 +447,21 @@
free(ssrmod.imag_coeffs);
ssrmod.imag_coeffs = NULL;
}
- if (ssrmod.surround_output_buffer){
- free(ssrmod.surround_output_buffer);
- ssrmod.surround_output_buffer = NULL;
+ if (ssrmod.surround_raw_buffer) {
+ free(ssrmod.surround_raw_buffer);
+ ssrmod.surround_raw_buffer = NULL;
}
- if (ssrmod.surround_input_buffer) {
- free(ssrmod.surround_input_buffer);
- ssrmod.surround_input_buffer = NULL;
- }
-
- if ( ssrmod.fp_4ch ) fclose(ssrmod.fp_4ch);
- if ( ssrmod.fp_6ch ) fclose(ssrmod.fp_6ch);
+ if (ssrmod.fp_4ch)
+ fclose(ssrmod.fp_4ch);
+ if (ssrmod.fp_6ch)
+ fclose(ssrmod.fp_6ch);
}
- if(ssrmod.surround_filters_handle)
- {
+ if(ssrmod.surround_filters_handle) {
dlclose(ssrmod.surround_filters_handle);
ssrmod.surround_filters_handle = NULL;
}
- ALOGD("%s: exit", __func__);
+ ALOGV("%s: exit", __func__);
return 0;
}
@@ -500,120 +469,36 @@
int32_t audio_extn_ssr_read(struct audio_stream_in *stream,
void *buffer, size_t bytes)
{
- int processed = 0;
- int processed_pending;
- void *buffer_start = buffer;
- unsigned period_bytes;
- unsigned period_samples;
- int read_pending, n;
- size_t read_bytes = 0;
- int samples = bytes >> 1;
-
struct stream_in *in = (struct stream_in *)stream;
struct audio_device *adev = in->dev;
+ size_t peroid_bytes;
+ int32_t ret;
- period_bytes = in->config.period_size;
- ALOGD("%s: period_size: %d", __func__, in->config.period_size);
- period_samples = period_bytes >> 1;
+ /* Convert bytes for 6ch to 4ch*/
+ peroid_bytes = (bytes / SSR_CHANNEL_OUTPUT_NUM) * SSR_CHANNEL_INPUT_NUM;
- if (!ssrmod.surround_obj)
+ if (!ssrmod.surround_obj) {
+ ALOGE("%s: surround_obj not initialized", __func__);
return -ENOMEM;
-
- do {
- if (ssrmod.surround_output_bufferIdx > 0) {
- ALOGV("%s: copy processed output "
- "to buffer, surround_output_bufferIdx = %d",
- __func__, ssrmod.surround_output_bufferIdx);
- /* Copy processed output to buffer */
- processed_pending = ssrmod.surround_output_bufferIdx;
- if (processed_pending > (samples - processed)) {
- processed_pending = (samples - processed);
- }
- memcpy(buffer, ssrmod.surround_output_buffer, processed_pending * sizeof(Word16));
- buffer = (char*)buffer + processed_pending * sizeof(Word16);
- processed += processed_pending;
- if (ssrmod.surround_output_bufferIdx > processed_pending) {
- /* Shift leftover samples to beginning of the buffer */
- memcpy(&ssrmod.surround_output_buffer[0],
- &ssrmod.surround_output_buffer[processed_pending],
- (ssrmod.surround_output_bufferIdx - processed_pending) * sizeof(Word16));
- }
- ssrmod.surround_output_bufferIdx -= processed_pending;
- }
-
- if (processed >= samples) {
- ALOGV("%s: done processing buffer, "
- "processed = %d", __func__, processed);
- /* Done processing this buffer */
- break;
- }
-
- /* Fill input buffer until there is enough to process */
- read_pending = SSR_INPUT_FRAME_SIZE - ssrmod.surround_input_bufferIdx;
- read_bytes = ssrmod.surround_input_bufferIdx;
- while (in->pcm && read_pending > 0) {
- n = pcm_read(in->pcm, &ssrmod.surround_input_buffer[read_bytes],
- period_bytes);
- ALOGV("%s: pcm_read() returned n = %d buffer:%p size:%d", __func__,
- n, &ssrmod.surround_input_buffer[read_bytes], period_bytes);
- if (n && n != -EAGAIN) {
- /* Recovery part of pcm_read. TODO:split recovery */
- return (ssize_t)n;
- }
- else if (n < 0) {
- /* Recovery is part of pcm_write. TODO split is later */
- return (ssize_t)n;
- }
- else {
- read_pending -= period_samples;
- read_bytes += period_samples;
- }
- }
-
-
- if (ssrmod.fp_4ch) {
- fwrite( ssrmod.surround_input_buffer, 1,
- SSR_INPUT_FRAME_SIZE * sizeof(Word16), ssrmod.fp_4ch);
- }
-
- /* apply ssr libs to conver 4ch to 6ch */
- ssrmod.surround_filters_intl_process(ssrmod.surround_obj,
- &ssrmod.surround_output_buffer[ssrmod.surround_output_bufferIdx],
- (Word16 *)ssrmod.surround_input_buffer);
-
- /* Shift leftover samples to beginning of input buffer */
- if (read_pending < 0) {
- memcpy(&ssrmod.surround_input_buffer[0],
- &ssrmod.surround_input_buffer[SSR_INPUT_FRAME_SIZE],
- (-read_pending) * sizeof(Word16));
- }
- ssrmod.surround_input_bufferIdx = -read_pending;
-
- if (ssrmod.fp_6ch) {
- fwrite( &ssrmod.surround_output_buffer[ssrmod.surround_output_bufferIdx],
- 1, SSR_OUTPUT_FRAME_SIZE * sizeof(Word16), ssrmod.fp_6ch);
- }
-
- ssrmod.surround_output_bufferIdx += SSR_OUTPUT_FRAME_SIZE;
- ALOGV("%s: do_while loop: processed=%d, samples=%d\n", __func__, processed, samples);
- } while (in->pcm && processed < samples);
- read_bytes = processed * sizeof(Word16);
- buffer = buffer_start;
-
- return 0;
-}
-
-void audio_extn_ssr_get_parameters(struct str_parms *query,
- struct str_parms *reply)
-{
- int ret, val;
- char value[32]={0};
-
- ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SSR, value, sizeof(value));
-
- if (ret >= 0) {
- memcpy(value, "true", 4);
- str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SSR, value);
}
+
+ ret = pcm_read(in->pcm, ssrmod.surround_raw_buffer, peroid_bytes);
+ if (ret < 0) {
+ ALOGE("%s: %s ret:%d", __func__, pcm_get_error(in->pcm),ret);
+ return ret;
+ }
+
+ /* apply ssr libs to conver 4ch to 6ch */
+ ssrmod.surround_filters_intl_process(ssrmod.surround_obj,
+ buffer, ssrmod.surround_raw_buffer);
+
+ /*dump for raw pcm data*/
+ if (ssrmod.fp_4ch)
+ fwrite(ssrmod.surround_raw_buffer, 1, peroid_bytes, ssrmod.fp_4ch);
+ if (ssrmod.fp_6ch)
+ fwrite(buffer, 1, bytes, ssrmod.fp_6ch);
+
+ return ret;
}
+
#endif /* SSR_ENABLED */
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index ec24265..19fdda2 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -53,7 +53,8 @@
#include "voice_extn.h"
#include "sound/compress_params.h"
-
+#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
+#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (8 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
/* ToDo: Check and update a proper value in msec */
@@ -112,6 +113,7 @@
[USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
[USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
[USECASE_AUDIO_HFP_SCO] = "hfp-sco",
+ [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
[USECASE_VOICE_CALL] = "voice-call",
[USECASE_VOICE2_CALL] = "voice2-call",
@@ -150,6 +152,8 @@
static unsigned int audio_device_ref_count;
static int set_voice_volume_l(struct audio_device *adev, float volume);
+static uint32_t get_offload_buffer_size();
+static int set_gapless_mode(struct audio_device *adev);
static bool is_supported_format(audio_format_t format)
{
@@ -366,7 +370,7 @@
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == PCM_PLAYBACK &&
+ if (usecase->type != PCM_CAPTURE &&
usecase != uc_info &&
usecase->out_snd_device != snd_device &&
usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
@@ -410,8 +414,6 @@
enable_audio_route(adev, usecase, false);
}
}
-
- audio_route_update_mixer(adev->audio_route);
}
}
@@ -439,7 +441,7 @@
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == PCM_CAPTURE &&
+ if (usecase->type != PCM_PLAYBACK &&
usecase != uc_info &&
usecase->in_snd_device != snd_device) {
ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
@@ -459,6 +461,12 @@
usecase = node_to_item(node, struct audio_usecase, list);
if (switch_device[usecase->id]) {
disable_snd_device(adev, usecase->in_snd_device, false);
+ }
+ }
+
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (switch_device[usecase->id]) {
enable_snd_device(adev, snd_device, false);
}
}
@@ -476,57 +484,9 @@
enable_audio_route(adev, usecase, false);
}
}
-
- audio_route_update_mixer(adev->audio_route);
}
}
-static int disable_all_usecases_of_type(struct audio_device *adev,
- usecase_type_t usecase_type,
- bool update_mixer)
-{
- struct audio_usecase *usecase;
- struct listnode *node;
- int ret = 0;
-
- list_for_each(node, &adev->usecase_list) {
- usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == usecase_type) {
- ALOGV("%s: usecase id %d", __func__, usecase->id);
- ret = disable_audio_route(adev, usecase, update_mixer);
- if (ret) {
- ALOGE("%s: Failed to disable usecase id %d",
- __func__, usecase->id);
- }
- }
- }
-
- return ret;
-}
-
-static int enable_all_usecases_of_type(struct audio_device *adev,
- usecase_type_t usecase_type,
- bool update_mixer)
-{
- struct audio_usecase *usecase;
- struct listnode *node;
- int ret = 0;
-
- list_for_each(node, &adev->usecase_list) {
- usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase->type == usecase_type) {
- ALOGV("%s: usecase id %d", __func__, usecase->id);
- ret = enable_audio_route(adev, usecase, update_mixer);
- if (ret) {
- ALOGE("%s: Failed to enable usecase id %d",
- __func__, usecase->id);
- }
- }
- }
-
- return ret;
-}
-
/* must be called with hw device mutex locked */
static int read_hdmi_channel_masks(struct stream_out *out)
{
@@ -555,6 +515,21 @@
return ret;
}
+static void update_devices_for_all_voice_usecases(struct audio_device *adev)
+{
+ struct listnode *node;
+ struct audio_usecase *usecase;
+
+ list_for_each(node, &adev->usecase_list) {
+ usecase = node_to_item(node, struct audio_usecase, list);
+ if (usecase->type == VOICE_CALL) {
+ ALOGV("%s: updating device for usecase:%s", __func__,
+ use_case_table[usecase->id]);
+ select_devices(adev, usecase->id);
+ }
+ }
+}
+
static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
{
struct audio_usecase *usecase;
@@ -591,6 +566,7 @@
struct audio_usecase *usecase = NULL;
struct audio_usecase *vc_usecase = NULL;
struct audio_usecase *voip_usecase = NULL;
+ struct audio_usecase *hfp_usecase = NULL;
struct listnode *node;
int status = 0;
@@ -629,6 +605,12 @@
in_snd_device = voip_usecase->in_snd_device;
out_snd_device = voip_usecase->out_snd_device;
}
+ } else if (audio_extn_hfp_is_active(adev)) {
+ hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
+ if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+ in_snd_device = hfp_usecase->in_snd_device;
+ out_snd_device = hfp_usecase->out_snd_device;
+ }
}
if (usecase->type == PCM_PLAYBACK) {
usecase->devices = usecase->stream.out->devices;
@@ -674,7 +656,6 @@
*/
if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
status = platform_switch_voice_call_device_pre(adev->platform);
- disable_all_usecases_of_type(adev, VOICE_CALL, true);
}
/* Disable current sound devices */
@@ -710,10 +691,7 @@
usecase->in_snd_device = in_snd_device;
usecase->out_snd_device = out_snd_device;
- if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
- enable_all_usecases_of_type(adev, usecase->type, true);
- else
- enable_audio_route(adev, usecase, true);
+ enable_audio_route(adev, usecase, true);
/* Applicable only on the targets that has external modem.
* Enable device command should be sent to modem only after
@@ -1302,26 +1280,39 @@
{
int ret = 0;
char value[32];
+ bool is_meta_data_params = false;
struct compr_gapless_mdata tmp_mdata;
-
+ tmp_mdata.encoder_delay = 0;
+ tmp_mdata.encoder_padding = 0;
if (!out || !parms) {
+ ALOGE("%s: return invalid ",__func__);
return -EINVAL;
}
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
+ if(ret >= 0)
+ is_meta_data_params = true;
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
+ if(ret >= 0 )
+ is_meta_data_params = true;
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
+ if(ret >= 0 )
+ is_meta_data_params = true;
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
if (ret >= 0) {
+ is_meta_data_params = true;
tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
- } else {
- return -EINVAL;
}
-
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
+ is_meta_data_params = true;
tmp_mdata.encoder_padding = atoi(value);
- } else {
- return -EINVAL;
}
+ if(!is_meta_data_params) {
+ ALOGV("%s: Not gapless meta data params", __func__);
+ return 0;
+ }
out->gapless_mdata = tmp_mdata;
out->send_new_metadata = 1;
ALOGV("%s new encoder delay %u and padding %u", __func__,
@@ -1339,14 +1330,14 @@
struct listnode *node;
struct str_parms *parms;
char value[32];
- int ret, val = 0;
+ int ret = 0, val = 0, err;
bool select_new_device = false;
ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
__func__, out->usecase, use_case_table[out->usecase], kvpairs);
parms = str_parms_create_str(kvpairs);
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
- if (ret >= 0) {
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
+ if (err >= 0) {
val = atoi(value);
pthread_mutex_lock(&out->lock);
pthread_mutex_lock(&adev->lock);
@@ -1390,18 +1381,18 @@
if ((adev->mode == AUDIO_MODE_IN_CALL) &&
!voice_is_in_call(adev) &&
(out == adev->primary_output)) {
- voice_start_call(adev);
+ ret = voice_start_call(adev);
} else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
voice_is_in_call(adev) &&
(out == adev->primary_output)) {
- select_devices(adev, get_voice_usecase_id_from_list(adev));
+ update_devices_for_all_voice_usecases(adev);
}
}
if ((adev->mode == AUDIO_MODE_NORMAL) &&
voice_is_in_call(adev) &&
(out == adev->primary_output)) {
- voice_stop_call(adev);
+ ret = voice_stop_call(adev);
}
pthread_mutex_unlock(&adev->lock);
@@ -1414,7 +1405,9 @@
pthread_mutex_unlock(&adev->lock);
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ pthread_mutex_lock(&out->lock);
parse_compress_metadata(out, parms);
+ pthread_mutex_unlock(&out->lock);
}
str_parms_destroy(parms);
@@ -1819,16 +1812,16 @@
struct str_parms *parms;
char *str;
char value[32];
- int ret, val = 0;
+ int ret = 0, val = 0, err;
ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
parms = str_parms_create_str(kvpairs);
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
-
pthread_mutex_lock(&in->lock);
pthread_mutex_lock(&adev->lock);
- if (ret >= 0) {
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
+ if (err >= 0) {
val = atoi(value);
/* no audio source uses val == 0 */
if ((in->source != val) && (val != 0)) {
@@ -1836,8 +1829,8 @@
}
}
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
- if (ret >= 0) {
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
+ if (err >= 0) {
val = atoi(value);
if ((in->device != val) && (val != 0)) {
in->device = val;
@@ -1990,7 +1983,7 @@
{
struct audio_device *adev = (struct audio_device *)dev;
struct stream_out *out;
- int i, ret;
+ int i, ret = 0;
ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
__func__, config->sample_rate, config->channel_mask, devices, flags);
@@ -2089,7 +2082,7 @@
else
out->compr_config.codec->id =
get_snd_codec_id(config->offload_info.format);
- out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ out->compr_config.fragment_size = get_offload_buffer_size();
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
out->compr_config.codec->sample_rate =
compress_get_alsa_rate(config->offload_info.sample_rate);
@@ -2120,6 +2113,9 @@
}
}
+ //Decide if we need to use gapless mode by default
+ set_gapless_mode(adev);
+
} else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
ret = voice_check_and_set_incall_music_usecase(adev, out);
if (ret != 0) {
@@ -2234,18 +2230,23 @@
char *str;
char value[32];
int val;
- int ret;
+ int ret = 0, err;
ALOGD("%s: enter: %s", __func__, kvpairs);
pthread_mutex_lock(&adev->lock);
parms = str_parms_create_str(kvpairs);
- voice_set_parameters(adev, parms);
- platform_set_parameters(adev->platform, parms);
+ ret = voice_set_parameters(adev, parms);
+ if (ret != 0)
+ goto done;
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
- if (ret >= 0) {
+ ret = platform_set_parameters(adev->platform, parms);
+ if (ret != 0)
+ goto done;
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
+ if (err >= 0) {
/* When set to false, HAL should disable EC and NS
* But it is currently not supported.
*/
@@ -2255,16 +2256,16 @@
adev->bluetooth_nrec = false;
}
- ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
- if (ret >= 0) {
+ err = str_parms_get_str(parms, "screen_state", value, sizeof(value));
+ if (err >= 0) {
if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
adev->screen_off = false;
else
adev->screen_off = true;
}
- ret = str_parms_get_int(parms, "rotation", &val);
- if (ret >= 0) {
+ err = str_parms_get_int(parms, "rotation", &val);
+ if (err >= 0) {
bool reverse_speakers = false;
switch(val) {
// FIXME: note that the code below assumes that the speakers are in the correct placement
@@ -2296,8 +2297,9 @@
}
audio_extn_set_parameters(adev, parms);
- str_parms_destroy(parms);
+done:
+ str_parms_destroy(parms);
pthread_mutex_unlock(&adev->lock);
ALOGV("%s: exit with code(%d)", __func__, ret);
return ret;
@@ -2314,7 +2316,7 @@
pthread_mutex_lock(&adev->lock);
audio_extn_get_parameters(adev, query, reply);
- voice_extn_get_parameters(adev, query, reply);
+ voice_get_parameters(adev, query, reply);
platform_get_parameters(adev->platform, query, reply);
str = str_parms_to_str(reply);
str_parms_destroy(query);
@@ -2648,6 +2650,55 @@
return 0;
}
+/* Read offload buffer size from a property.
+ * If value is not power of 2 round it to
+ * power of 2.
+ */
+static uint32_t get_offload_buffer_size()
+{
+ char value[PROPERTY_VALUE_MAX] = {0};
+ uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ if((property_get("audio.offload.buffer.size.kb", value, "")) &&
+ atoi(value)) {
+ fragment_size = atoi(value) * 1024;
+ //ring buffer size needs to be 4k aligned.
+ CHECK(!(fragment_size * COMPRESS_OFFLOAD_NUM_FRAGMENTS % 4096));
+ }
+ if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGVV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
+static int set_gapless_mode(struct audio_device *adev) {
+
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ bool gapless_enabled = false;
+ const char *mixer_ctl_name = "Compress Gapless Playback";
+ struct mixer_ctl *ctl;
+
+ ALOGV("%s:", __func__);
+ property_get("audio.offload.gapless.enabled", value, NULL);
+ gapless_enabled = atoi(value) || !strncmp("true", value, 4);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
+ ALOGE("%s: Could not set gapless mode %d",
+ __func__, gapless_enabled);
+ return -EINVAL;
+ }
+ return 0;
+
+}
static struct hw_module_methods_t hal_module_methods = {
.open = adev_open,
};
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 3055470..205977b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -65,6 +65,7 @@
/* HFP Use case*/
USECASE_AUDIO_HFP_SCO,
+ USECASE_AUDIO_HFP_SCO_WB,
/* Capture usecases */
USECASE_AUDIO_RECORD,
@@ -250,6 +251,12 @@
bool update_mixer);
struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
audio_usecase_t uc_id);
+
+#define LITERAL_TO_STRING(x) #x
+#define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__)\
+ " ASSERT_FATAL(" #condition ") failed.")
+
/*
* NOTE: when multiple mutexes have to be acquired, always take the
* stream_in or stream_out mutex first, followed by the audio_device mutex.
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 58ca4dc..128e4af 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -51,11 +51,6 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#define LITERAL_TO_STRING(x) #x
-#define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\
- __FILE__ ":" LITERAL_TO_STRING(__LINE__)\
- " ASSERT_FATAL(" #condition ") failed.")
-
static const snd_device_t taiko_fluid_variant_devices[] = {
SND_DEVICE_OUT_SPEAKER,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
@@ -266,8 +261,7 @@
ALOGV("8084 - variant soundcard");
update_hardware_info_8084(hw_info, snd_card_name);
} else {
- ALOGE("%s: Unupported target %s:",__func__, snd_card_name);
- CHECK(0);
+ ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
free(hw_info);
hw_info = NULL;
}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 272dea8..c7896ae 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -61,6 +61,12 @@
#define AUDIO_PARAMETER_KEY_FLUENCE_TYPE "fluence"
#define AUDIO_PARAMETER_KEY_BTSCO "bt_samplerate"
#define AUDIO_PARAMETER_KEY_SLOWTALK "st_enable"
+#define AUDIO_PARAMETER_KEY_VOLUME_BOOST "volume_boost"
+
+enum {
+ VOICE_FEATURE_SET_DEFAULT,
+ VOICE_FEATURE_SET_VOLUME_BOOST
+};
struct audio_block_header
{
@@ -73,6 +79,7 @@
typedef int (*acdb_init_t)();
typedef void (*acdb_send_audio_cal_t)(int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
+typedef int (*acdb_reload_vocvoltable_t)(int);
struct platform_data {
struct audio_device *adev;
@@ -84,11 +91,13 @@
int btsco_sample_rate;
bool slowtalk;
/* Audio calibration related functions */
- void *acdb_handle;
- acdb_init_t acdb_init;
- acdb_deallocate_t acdb_deallocate;
- acdb_send_audio_cal_t acdb_send_audio_cal;
- acdb_send_voice_cal_t acdb_send_voice_cal;
+ void *acdb_handle;
+ int voice_feature_set;
+ acdb_init_t acdb_init;
+ acdb_deallocate_t acdb_deallocate;
+ acdb_send_audio_cal_t acdb_send_audio_cal;
+ acdb_send_voice_cal_t acdb_send_voice_cal;
+ acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
void *hw_info;
struct csd_data *csd;
@@ -111,6 +120,7 @@
MULTIMEDIA2_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
[USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
+ [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX},
[USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE},
[USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
[USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
@@ -194,6 +204,7 @@
[SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
[SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef",
[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef",
+ [SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = "voice-speaker-qmic",
[SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
[SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
[SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
@@ -266,6 +277,7 @@
[SND_DEVICE_IN_CAMCORDER_MIC] = 4,
[SND_DEVICE_IN_VOICE_DMIC] = 41,
[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43,
+ [SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = 19,
[SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
[SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
[SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
@@ -522,6 +534,7 @@
}
}
+ 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) {
ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
@@ -529,13 +542,28 @@
ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
"acdb_loader_deallocate_ACDB");
+ if (!my_data->acdb_deallocate)
+ ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s",
+ __func__, LIB_ACDB_LOADER);
+
my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
"acdb_loader_send_audio_cal");
if (!my_data->acdb_send_audio_cal)
- ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
+ ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
__func__, LIB_ACDB_LOADER);
+
my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
"acdb_loader_send_voice_cal");
+ if (!my_data->acdb_send_voice_cal)
+ ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s",
+ __func__, LIB_ACDB_LOADER);
+
+ my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_reload_vocvoltable");
+ if (!my_data->acdb_reload_vocvoltable)
+ ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
+ __func__, LIB_ACDB_LOADER);
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_ACDB");
if (my_data->acdb_init == NULL)
@@ -561,7 +589,7 @@
audio_extn_usb_set_proxy_sound_card(adev->snd_card);
/* Read one time ssr property */
- audio_extn_ssr_update_enabled(adev);
+ audio_extn_ssr_update_enabled();
audio_extn_spkr_prot_init(adev);
return my_data;
}
@@ -843,6 +871,36 @@
goto exit;
}
+ if (popcount(devices) == 2) {
+ if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ 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
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
+ } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
+ } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
+ } 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 ((mode == AUDIO_MODE_IN_CALL) ||
voice_extn_compress_voip_is_active(adev)) {
if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
@@ -894,36 +952,6 @@
}
}
- if (popcount(devices) == 2) {
- if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- 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
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
- } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
- } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
- AUDIO_DEVICE_OUT_SPEAKER)) {
- snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
- } 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) {
if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET
@@ -1329,14 +1357,14 @@
{
struct platform_data *my_data = (struct platform_data *)platform;
char *str;
- char value[32];
+ char value[256] = {0};
int val;
- int ret = 0;
+ int ret = 0, err;
ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
- ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
- if (ret >= 0) {
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val);
+ if (err >= 0) {
str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO);
my_data->btsco_sample_rate = val;
if (val == SAMPLE_RATE_16KHZ) {
@@ -1346,14 +1374,37 @@
}
}
- ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SLOWTALK, &val);
- if (ret >= 0) {
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SLOWTALK, value, sizeof(value));
+ if (err >= 0) {
+ bool state = false;
+ if (!strncmp("true", value, sizeof("true"))) {
+ state = true;
+ }
+
str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK);
- ret = platform_set_slowtalk(my_data, val);
+ ret = platform_set_slowtalk(my_data, state);
if (ret)
ALOGE("%s: Failed to set slow talk err: %d", __func__, ret);
}
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOLUME_BOOST,
+ value, sizeof(value));
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_VOLUME_BOOST);
+
+ if (my_data->acdb_reload_vocvoltable == NULL) {
+ ALOGE("%s: acdb_reload_vocvoltable is NULL", __func__);
+ } else if (!strcmp(value, "on")) {
+ if (!my_data->acdb_reload_vocvoltable(VOICE_FEATURE_SET_VOLUME_BOOST)) {
+ my_data->voice_feature_set = 1;
+ }
+ } else {
+ if (!my_data->acdb_reload_vocvoltable(VOICE_FEATURE_SET_DEFAULT)) {
+ my_data->voice_feature_set = 0;
+ }
+ }
+ }
+
ALOGV("%s: exit with code(%d)", __func__, ret);
return ret;
}
@@ -1472,8 +1523,20 @@
ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
value, sizeof(value));
if (ret >= 0) {
- str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SLOWTALK,
- my_data->slowtalk);
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SLOWTALK,
+ my_data->slowtalk?"true":"false");
+ }
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOLUME_BOOST,
+ value, sizeof(value));
+ if (ret >= 0) {
+ if (my_data->voice_feature_set == VOICE_FEATURE_SET_VOLUME_BOOST) {
+ strlcpy(value, "on", sizeof(value));
+ } else {
+ strlcpy(value, "off", sizeof(value));
+ }
+
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VOLUME_BOOST, value);
}
ALOGV("%s: exit: returns - %s", __func__, str_parms_to_str(reply));
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index e7980d6..bb1f787 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -204,8 +204,8 @@
#elif PLATFORM_MSM8610
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 13
-#define VOLTE_CALL_PCM_DEVICE 14
-#define QCHAT_CALL_PCM_DEVICE 20
+#define VOLTE_CALL_PCM_DEVICE 15
+#define QCHAT_CALL_PCM_DEVICE 14
#else
#define VOICE_CALL_PCM_DEVICE 2
#define VOICE2_CALL_PCM_DEVICE 22
diff --git a/hal/voice.c b/hal/voice.c
index cbf8956..8783f01 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -351,20 +351,32 @@
return ret;
}
+void voice_get_parameters(struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ voice_extn_get_parameters(adev, query, reply);
+}
+
int voice_set_parameters(struct audio_device *adev, struct str_parms *parms)
{
char *str;
char value[32];
int val;
- int ret = 0;
+ int ret = 0, err;
ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
- voice_extn_set_parameters(adev, parms);
- voice_extn_compress_voip_set_parameters(adev, parms);
+ ret = voice_extn_set_parameters(adev, parms);
+ if (ret != 0)
+ goto done;
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
- if (ret >= 0) {
+ ret = voice_extn_compress_voip_set_parameters(adev, parms);
+ if (ret != 0)
+ goto done;
+
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
+ if (err >= 0) {
int tty_mode;
str_parms_del(parms, AUDIO_PARAMETER_KEY_TTY_MODE);
if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
@@ -389,9 +401,9 @@
}
}
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC,
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC,
value, sizeof(value));
- if (ret >= 0) {
+ if (err >= 0) {
str_parms_del(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC);
if (strcmp(value, AUDIO_PARAMETER_VALUE_TRUE) == 0)
platform_start_incall_music_usecase(adev->platform);
@@ -412,6 +424,7 @@
adev->voice.tty_mode = TTY_MODE_OFF;
adev->voice.volume = 1.0f;
adev->voice.mic_mute = false;
+ adev->voice.voice_device_set = false;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
adev->voice.session[i].pcm_rx = NULL;
adev->voice.session[i].pcm_tx = NULL;
diff --git a/hal/voice.h b/hal/voice.h
index eeb65dc..a7733b1 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -60,6 +60,7 @@
int tty_mode;
bool mic_mute;
float volume;
+ bool voice_device_set;
};
enum {
@@ -72,6 +73,8 @@
int voice_start_call(struct audio_device *adev);
int voice_stop_call(struct audio_device *adev);
int voice_set_parameters(struct audio_device *adev, struct str_parms *parms);
+void voice_get_parameters(struct audio_device *adev, struct str_parms *query,
+ struct str_parms *reply);
void voice_init(struct audio_device *adev);
bool voice_is_in_call(struct audio_device *adev);
int voice_set_mic_mute(struct audio_device *dev, bool state);
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index ee9fd30..5c87c9c 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -60,6 +60,7 @@
struct pcm *pcm_tx;
struct stream_out *out_stream;
int ref_count;
+ int out_stream_count;
};
#define MODE_IS127 0x2
@@ -76,12 +77,14 @@
#define AUDIO_PARAMETER_KEY_VOIP_DTX_MODE "dtx_on"
#define AUDIO_PARAMETER_VALUE_VOIP_TRUE "true"
#define AUDIO_PARAMETER_KEY_VOIP_CHECK "voip_flag"
+#define AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT "voip_out_stream_count"
static struct voip_data voip_data = {
.pcm_rx = NULL,
.pcm_tx = NULL,
.out_stream = NULL,
- .ref_count = 0
+ .ref_count = 0,
+ .out_stream_count = 0
};
static int voip_set_volume(struct audio_device *adev, int volume);
@@ -400,53 +403,73 @@
return ret;
}
-void voice_extn_compress_voip_set_parameters(struct audio_device *adev,
+int voice_extn_compress_voip_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
char *str;
char value[32]={0};
- int ret, rate;
+ int ret = 0, err, rate;
int min_rate, max_rate;
bool flag;
ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_RATE,
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_RATE,
value, sizeof(value));
- if (ret >= 0) {
+ if (err >= 0) {
rate = atoi(value);
voip_set_rate(adev, rate);
voip_set_evrc_min_max_rate(adev, rate, rate);
}
memset(value, 0, sizeof(value));
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN,
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN,
value, sizeof(value));
- if (ret >= 0) {
+ if (err >= 0) {
min_rate = atoi(value);
str_parms_del(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN);
memset(value, 0, sizeof(value));
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX,
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX,
value, sizeof(value));
- if (ret >= 0) {
+ if (err >= 0) {
max_rate = atoi(value);
voip_set_evrc_min_max_rate(adev, min_rate, max_rate);
- }
- else
+ } else {
ALOGE("%s: AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX not found", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
}
memset(value, 0, sizeof(value));
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_DTX_MODE,
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_DTX_MODE,
value, sizeof(value));
- if (ret >= 0) {
+ if (err >= 0) {
flag = false;
if (strcmp(value, AUDIO_PARAMETER_VALUE_VOIP_TRUE) == 0)
flag = true;
voip_set_dtx(adev, flag);
}
+done:
ALOGV("%s: exit", __func__);
+ return ret;
+}
+
+void voice_extn_compress_voip_get_parameters(const struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ int ret;
+ char value[32]={0};
+ char *str = NULL;
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT,
+ value, sizeof(value));
+ if (ret >= 0) {
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT,
+ voip_data.out_stream_count);
+ }
}
void voice_extn_compress_voip_out_get_parameters(struct stream_out *out,
@@ -550,6 +573,7 @@
ret = voip_stop_call(adev);
voip_data.out_stream = NULL;
+ voip_data.out_stream_count--;
ALOGV("%s: exit: status(%d)", __func__, ret);
return ret;
@@ -570,6 +594,7 @@
out->config = pcm_config_voip_nb;
voip_data.out_stream = out;
+ voip_data.out_stream_count++;
ret = voip_set_mode(out->dev, out->format);
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 989a871..b8bc2df 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -34,8 +34,12 @@
#include "platform_api.h"
#include "voice_extn.h"
-#define AUDIO_PARAMETER_KEY_VSID "vsid"
-#define AUDIO_PARAMETER_KEY_CALL_STATE "call_state"
+#define AUDIO_PARAMETER_KEY_VSID "vsid"
+#define AUDIO_PARAMETER_KEY_CALL_STATE "call_state"
+#define AUDIO_PARAMETER_KEY_AUDIO_MODE "audio_mode"
+#define AUDIO_PARAMETER_KEY_ALL_CALL_STATES "all_call_states"
+
+#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
#define VOICE2_VSID 0x10DC1000
#define VOLTE_VSID 0x10C02000
@@ -139,6 +143,7 @@
struct voice_session *session = NULL;
int fd = 0;
int ret = 0;
+ bool is_in_call = false;
ALOGD("%s: enter:", __func__);
@@ -198,6 +203,10 @@
ALOGE("%s: voice_end_call() failed for usecase: %d\n",
__func__, usecase_id);
} else {
+ voice_extn_is_in_call(adev, &is_in_call);
+ if (!is_in_call) {
+ adev->voice.voice_device_set = false;
+ }
session->state.current = session->state.new;
}
break;
@@ -270,6 +279,7 @@
struct voice_session *session = NULL;
int i = 0;
bool is_in_call;
+ int no_of_calls_active = 0;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
if (vsid == adev->voice.session[i].vsid) {
@@ -278,17 +288,27 @@
}
}
+ for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
+ if (CALL_INACTIVE != adev->voice.session[i].state.current)
+ no_of_calls_active++;
+ }
+
+ /* When there is only one call active, wait for audio policy manager to set
+ * the mode to AUDIO_MODE_NORMAL and trigger routing to end the last call.
+ */
+ if (no_of_calls_active == 1 && call_state == CALL_INACTIVE)
+ return 0;
+
if (session) {
session->state.new = call_state;
voice_extn_is_in_call(adev, &is_in_call);
- ALOGD("%s is_in_call:%d mode:%d\n", __func__, is_in_call, adev->mode);
+ ALOGD("%s is_in_call:%d voice_device_set:%d, mode:%d\n",
+ __func__, is_in_call, adev->voice.voice_device_set, adev->mode);
/* Dont start voice call before device routing for voice usescases has
* occured, otherwise voice calls will be started unintendedly on
* speaker.
*/
- if (is_in_call ||
- (adev->mode == AUDIO_MODE_IN_CALL &&
- adev->primary_output->devices != AUDIO_DEVICE_OUT_SPEAKER)) {
+ if (is_in_call || adev->voice.voice_device_set) {
/* Device routing is not triggered for voice calls on the subsequent
* subs, Hence update the call states if voice call is already
* active on other sub.
@@ -373,6 +393,7 @@
* udpated.
*/
ALOGV("%s: enter:", __func__);
+ adev->voice.voice_device_set = true;
return update_calls(adev);
}
@@ -405,17 +426,17 @@
{
char *str;
int value;
- int ret = 0;
+ int ret = 0, err;
ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms));
- ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
- if (ret >= 0) {
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
+ if (err >= 0) {
str_parms_del(parms, AUDIO_PARAMETER_KEY_VSID);
- int vsid = value;
+ uint32_t vsid = value;
int call_state = -1;
- ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
- if (ret >= 0) {
+ err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
+ if (err >= 0) {
call_state = value;
} else {
ALOGE("%s: call_state key not found", __func__);
@@ -432,7 +453,7 @@
goto done;
}
} else {
- ALOGD("%s: Not handled here", __func__);
+ ALOGV("%s: Not handled here", __func__);
}
done:
@@ -440,21 +461,53 @@
return ret;
}
+int get_all_call_states_str(const struct audio_device *adev,
+ char *value)
+{
+ int ret = 0;
+ char *cur_ptr = value;
+ int i, len=0;
+
+ for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
+ snprintf(cur_ptr, VOICE_EXTN_PARAMETER_VALUE_MAX_LEN - len,
+ "%d:%d,",adev->voice.session[i].vsid,
+ adev->voice.session[i].state.current);
+ len = strlen(cur_ptr);
+ cur_ptr = cur_ptr + len;
+ }
+ ALOGV("%s:value=%s", __func__, value);
+ return ret;
+}
+
void voice_extn_get_parameters(const struct audio_device *adev,
struct str_parms *query,
struct str_parms *reply)
{
int ret;
- char value[32]={0};
+ char value[VOICE_EXTN_PARAMETER_VALUE_MAX_LEN] = {0};
char *str = NULL;
- ret = str_parms_get_str(query, "audio_mode", value,
+ ALOGV("%s: enter %s", __func__, str_parms_to_str(query));
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_AUDIO_MODE, value,
sizeof(value));
if (ret >= 0) {
- str_parms_add_int(reply, "audio_mode", adev->mode);
+ str_parms_add_int(reply, AUDIO_PARAMETER_KEY_AUDIO_MODE, adev->mode);
}
- ALOGV("%s: returns %s", __func__, str_parms_to_str(reply));
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ALL_CALL_STATES,
+ value, sizeof(value));
+ if (ret >= 0) {
+ ret = get_all_call_states_str(adev, value);
+ if (ret) {
+ ALOGE("%s: Error fetching call states, err:%d", __func__, ret);
+ return;
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_KEY_ALL_CALL_STATES, value);
+ }
+ voice_extn_compress_voip_get_parameters(adev, query, reply);
+
+ ALOGV("%s: exit: returns \"%s\"", __func__, str_parms_to_str(reply));
}
void voice_extn_out_get_parameters(struct stream_out *out,
diff --git a/hal/voice_extn/voice_extn.h b/hal/voice_extn/voice_extn.h
index 0ca2386..f7d20e4 100644
--- a/hal/voice_extn/voice_extn.h
+++ b/hal/voice_extn/voice_extn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -128,8 +128,11 @@
int voice_extn_compress_voip_select_devices(struct audio_device *adev,
snd_device_t *out_snd_device,
snd_device_t *in_snd_device);
-void voice_extn_compress_voip_set_parameters(struct audio_device *adev,
+int voice_extn_compress_voip_set_parameters(struct audio_device *adev,
struct str_parms *parms);
+void voice_extn_compress_voip_get_parameters(const struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply);
void voice_extn_compress_voip_out_get_parameters(struct stream_out *out,
struct str_parms *query,
@@ -166,7 +169,7 @@
return -ENOSYS;
}
-static int voice_extn_compress_voip_out_get_buffer_size(struct audio_stream *stream)
+static int voice_extn_compress_voip_out_get_buffer_size(struct stream_out *stream)
{
ALOGE("%s: COMPRESS_VOIP_ENABLED is not defined", __func__);
return -ENOSYS;
@@ -210,10 +213,18 @@
return -ENOSYS;
}
-static void voice_extn_compress_voip_set_parameters(struct audio_device *adev,
+static int voice_extn_compress_voip_set_parameters(struct audio_device *adev,
struct str_parms *parms)
{
ALOGE("%s: COMPRESS_VOIP_ENABLED is not defined", __func__);
+ return -ENOSYS;
+}
+
+static void voice_extn_compress_voip_get_parameters(const struct audio_device *adev,
+ struct str_parms *query,
+ struct str_parms *reply)
+{
+ ALOGE("%s: COMPRESS_VOIP_ENABLED is not defined", __func__);
}
static void voice_extn_compress_voip_out_get_parameters(struct stream_out *out,
diff --git a/hal_mpq/Android.mk b/hal_mpq/Android.mk
index 683de7a..1cb7e60 100644
--- a/hal_mpq/Android.mk
+++ b/hal_mpq/Android.mk
@@ -44,9 +44,9 @@
$(call include-path-for, audio-effects) \
$(LOCAL_PATH)/$(AUDIO_PLATFORM)
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUXPCM_BT)),true)
- LOCAL_CFLAGS += -DAUXPCM_BT_ENABLED
-endif
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
diff --git a/hal_mpq/audio_stream_out.c b/hal_mpq/audio_stream_out.c
index b766770..e7f29de 100644
--- a/hal_mpq/audio_stream_out.c
+++ b/hal_mpq/audio_stream_out.c
@@ -1043,6 +1043,7 @@
handle->compr_config.codec->ch_in =
popcount(out->channel_mask);
handle->compr_config.codec->ch_out = handle->compr_config.codec->ch_in;
+ handle->compr_config.codec->format = out->compr_config.codec->format;
memcpy(&handle->compr_config.codec->options,
&out->compr_config.codec->options,
sizeof(union snd_codec_options));
@@ -1328,9 +1329,18 @@
static bool is_supported_format(audio_format_t format)
{
- if (format == AUDIO_FORMAT_MP3 ||
- format == AUDIO_FORMAT_AAC)
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ case AUDIO_FORMAT_MP3:
+ case AUDIO_FORMAT_AAC:
+ case AUDIO_FORMAT_WMA:
+ case AUDIO_FORMAT_WMA_PRO:
+ case AUDIO_FORMAT_MP2:
return true;
+ default:
+ ALOGE("%s: Unsupported audio format: %x", __func__, format);
+ break;
+ }
return false;
}
@@ -1340,14 +1350,26 @@
int id = 0;
switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ id = SND_AUDIOCODEC_PCM;
+ break;
case AUDIO_FORMAT_MP3:
id = SND_AUDIOCODEC_MP3;
break;
case AUDIO_FORMAT_AAC:
id = SND_AUDIOCODEC_AAC;
break;
+ case AUDIO_FORMAT_WMA:
+ id = SND_AUDIOCODEC_WMA;
+ break;
+ case AUDIO_FORMAT_WMA_PRO:
+ id = SND_AUDIOCODEC_WMA_PRO;
+ break;
+ case AUDIO_FORMAT_MP2:
+ id = SND_AUDIOCODEC_MP2;
+ break;
default:
- ALOGE("%s: Unsupported audio format", __func__);
+ ALOGE("%s: Unsupported audio format %x", __func__, format);
}
return id;
@@ -1829,6 +1851,7 @@
int ret = 0;
char value[32];
struct compr_gapless_mdata tmp_mdata;
+ bool gapless_meta_set = true;
if (!out || !parms) {
return -EINVAL;
@@ -1838,21 +1861,61 @@
if (ret >= 0) {
tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
} else {
- return -EINVAL;
+ gapless_meta_set = false;
}
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
tmp_mdata.encoder_padding = atoi(value);
} else {
- return -EINVAL;
+ gapless_meta_set = false;
}
- out->gapless_mdata = tmp_mdata;
- out->send_new_metadata = 1;
- ALOGV("%s new encoder delay %u and padding %u", __func__,
- out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
+ if (gapless_meta_set) {
+ out->gapless_mdata = tmp_mdata;
+ out->send_new_metadata = 1;
+ ALOGV("%s new encoder delay %u and padding %u", __func__,
+ out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
+ }
+ if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->format = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.super_block_align = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.channelmask = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
+ }
+ ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+ out->compr_config.codec->format,
+ out->compr_config.codec->options.wma.super_block_align,
+ out->compr_config.codec->options.wma.bits_per_sample,
+ out->compr_config.codec->options.wma.channelmask,
+ out->compr_config.codec->options.wma.encodeopt,
+ out->compr_config.codec->options.wma.encodeopt1,
+ out->compr_config.codec->options.wma.encodeopt2);
+ }
return 0;
}
@@ -1968,7 +2031,7 @@
}
if (out->uc_strm_type == OFFLOAD_PLAYBACK_STREAM) {
- parse_compress_metadata(out, parms);
+ ret = parse_compress_metadata(out, parms);
}
str_parms_destroy(parms);
@@ -2076,6 +2139,7 @@
/* TODO:disnable this if ms12 */
if (ret >= 0 && ret < (ssize_t)bytes) {
+ handle->cmd_pending = true;
send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
}
return ret;
diff --git a/hal_mpq/mpq8092/hw_info.c b/hal_mpq/mpq8092/hw_info.c
index 97b7804..2a0231f 100644
--- a/hal_mpq/mpq8092/hw_info.c
+++ b/hal_mpq/mpq8092/hw_info.c
@@ -285,8 +285,7 @@
ALOGV("8084 - variant soundcard");
update_hardware_info_8084(hw_info, snd_card_name);
} else {
- ALOGE("%s: Unupported target %s:",__func__, snd_card_name);
- CHECK(0);
+ ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
free(hw_info);
hw_info = NULL;
}
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 4fa2356..f64bbfe 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2009 The Android Open Source Project
@@ -539,9 +539,9 @@
if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
+ device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
}
- device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
if (device) break;
device = mDefaultOutputDevice;
@@ -590,7 +590,7 @@
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
- if (isInCall()) {
+ if (isInCall() && (device == AUDIO_DEVICE_NONE)) {
// when in call, get the device for Phone strategy
device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/);
break;
@@ -637,7 +637,8 @@
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
- (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_ANALOG_DOCK)) {
+ (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_ANALOG_DOCK)
+ && (strategy != STRATEGY_SONIFICATION)) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
#ifdef AUDIO_EXTN_FM_ENABLED