summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-22 15:24:24 +0200
committerDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-22 15:24:24 +0200
commitd30210153d8f19a0ca825b33f2282b9ae071c6ec (patch)
tree36c5d3485edbdcc6788ae0e1f7306d0f9885b686 /audio
parent44378b730efd28a958ac35e3d294e1c04472ff79 (diff)
downloaddevice_samsung_i9300-d30210153d8f19a0ca825b33f2282b9ae071c6ec.zip
device_samsung_i9300-d30210153d8f19a0ca825b33f2282b9ae071c6ec.tar.gz
device_samsung_i9300-d30210153d8f19a0ca825b33f2282b9ae071c6ec.tar.bz2
jellybeaned
Diffstat (limited to 'audio')
-rw-r--r--audio/Android.mk6
-rwxr-xr-xaudio/audio_hw.c1218
-rw-r--r--audio/audio_hw.h48
-rwxr-xr-xaudio/ril_interface.c14
4 files changed, 978 insertions, 308 deletions
diff --git a/audio/Android.mk b/audio/Android.mk
index bc962c0..4655db0 100644
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE := audio.primary.$(TARGET_BOOTLOADER_BOARD_NAME)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_MODULE_TAGS := optional
@@ -25,8 +25,8 @@ LOCAL_SRC_FILES := audio_hw.c ril_interface.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
external/expat/lib \
- system/media/audio_utils/include \
- system/media/audio_effects/include
+ $(call include-path-for, audio-utils) \
+ $(call include-path-for, audio-effects)
LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libdl libexpat
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 4ba97bf..ebc57b3 100755
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -3,6 +3,7 @@
* Copyright (C) 2012 Wolfson Microelectronics plc
* Copyright (C) 2012 The CyanogenMod Project
* Daniel Hillenbrand <codeworkx@cyanogenmod.com>
+ * Guillaume "XpLoDWilD" Lesniak <xplodgui@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +19,7 @@
*/
#define LOG_TAG "audio_hw_primary"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#include <errno.h>
#include <pthread.h>
@@ -44,14 +45,24 @@
#include "audio_hw.h"
#include "ril_interface.h"
-struct pcm_config pcm_config_playback = {
+struct pcm_config pcm_config_mm = {
.channels = 2,
- .rate = DEFAULT_OUT_SAMPLING_RATE,
- .period_count = PLAYBACK_PERIOD_COUNT,
- .period_size = PLAYBACK_PERIOD_SIZE,
+ .rate = MM_FULL_POWER_SAMPLING_RATE,
+ .period_size = DEEP_BUFFER_LONG_PERIOD_SIZE,
+ .period_count = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
+struct pcm_config pcm_config_tones = {
+ .channels = 2,
+ .rate = MM_FULL_POWER_SAMPLING_RATE,
+ .period_size = SHORT_PERIOD_SIZE,
+ .period_count = PLAYBACK_SHORT_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = 0,
+ .avail_min = 0,
+};
+
struct pcm_config pcm_config_capture = {
.channels = 2,
.rate = DEFAULT_IN_SAMPLING_RATE,
@@ -70,18 +81,6 @@ struct pcm_config pcm_config_vx = {
#define MIN(x, y) ((x) > (y) ? (y) : (x))
-struct mixer_ctls
-{
- struct mixer_ctl *aif2dacl_source;
- struct mixer_ctl *aif2dacr_source;
- struct mixer_ctl *aif2_mode;
- struct mixer_ctl *dac1l_mixer_aif1_switch;
- struct mixer_ctl *dac1r_mixer_aif1_switch;
- struct mixer_ctl *dac1l_mixer_aif2_switch;
- struct mixer_ctl *dac1r_mixer_aif2_switch;
- struct mixer_ctl *aif2dac_mux;
-};
-
struct m0_audio_device {
struct audio_hw_device hw_device;
@@ -89,22 +88,21 @@ struct m0_audio_device {
struct m0_dev_cfg *dev_cfgs;
int num_dev_cfgs;
struct mixer *mixer;
- struct mixer_ctls mixer_ctls;
- int mode;
- int active_devices;
+ audio_mode_t mode;
+ int active_devices;
int devices;
struct pcm *pcm_modem_dl;
struct pcm *pcm_modem_ul;
int in_call;
float voice_volume;
struct m0_stream_in *active_input;
- struct m0_stream_out *active_output;
+ struct m0_stream_out *outputs[OUTPUT_TOTAL];
bool mic_mute;
int tty_mode;
struct echo_reference_itfe *echo_reference;
bool bluetooth_nrec;
int wb_amr;
- bool screen_state;
+ bool screen_off;
/* RIL */
struct ril_handle ril;
@@ -114,19 +112,35 @@ struct m0_stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
- struct pcm_config config;
- struct pcm *pcm;
+ struct pcm_config config[PCM_TOTAL];
+ struct pcm *pcm[PCM_TOTAL];
struct resampler_itfe *resampler;
char *buffer;
+ size_t buffer_frames;
int standby;
struct echo_reference_itfe *echo_reference;
- struct m0_audio_device *dev;
int write_threshold;
- bool screen_state;
+ bool use_long_periods;
+ audio_channel_mask_t channel_mask;
+ audio_channel_mask_t sup_channel_masks[3];
+
+ struct m0_audio_device *dev;
};
#define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */
+struct effect_info_s {
+ effect_handle_t effect_itfe;
+ size_t num_channel_configs;
+ channel_config_t* channel_configs;
+};
+
+#define NUM_IN_AUX_CNL_CONFIGS 2
+channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
+ { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
+ { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
+};
+
struct m0_stream_in {
struct audio_stream_in stream;
@@ -157,9 +171,12 @@ struct m0_stream_in {
int read_status;
- int num_preprocessors;
- effect_handle_t preprocessors[MAX_PREPROCESSORS];
+ int num_preprocessors;
+ struct effect_info_s preprocessors[MAX_PREPROCESSORS];
+ bool aux_channels_changed;
+ uint32_t main_channels;
+ uint32_t aux_channels;
struct m0_audio_device *dev;
};
@@ -183,6 +200,7 @@ static void select_input_device(struct m0_audio_device *adev);
static int adev_set_voice_volume(struct audio_hw_device *dev, float volume);
static int do_input_standby(struct m0_stream_in *in);
static int do_output_standby(struct m0_stream_out *out);
+static void in_update_aux_channels(struct m0_stream_in *in, effect_handle_t effect);
/* The enable flag when 0 makes the assumption that enums are disabled by
* "Off" and integers/booleans by 0 */
@@ -197,7 +215,7 @@ static int set_bigroute_by_array(struct mixer *mixer, struct route_setting *rout
while (route[i].ctl_name) {
ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
if (!ctl) {
- LOGE("Unknown control '%s'\n", route[i].ctl_name);
+ ALOGE("Unknown control '%s'\n", route[i].ctl_name);
return -EINVAL;
}
@@ -205,16 +223,16 @@ static int set_bigroute_by_array(struct mixer *mixer, struct route_setting *rout
if (enable) {
ret = mixer_ctl_set_enum_by_string(ctl, route[i].strval);
if (ret != 0) {
- LOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
+ ALOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
} else {
- LOGV("Set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
+ ALOGV("Set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
}
} else {
ret = mixer_ctl_set_enum_by_string(ctl, "Off");
if (ret != 0) {
- LOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
+ ALOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
} else {
- LOGV("Set '%s' to '%s'\n", route[i].ctl_name, "Off");
+ ALOGV("Set '%s' to '%s'\n", route[i].ctl_name, "Off");
}
}
} else {
@@ -223,16 +241,16 @@ static int set_bigroute_by_array(struct mixer *mixer, struct route_setting *rout
if (enable) {
ret = mixer_ctl_set_value(ctl, j, route[i].intval);
if (ret != 0) {
- LOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
+ ALOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
} else {
- LOGV("Set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
+ ALOGV("Set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
}
} else {
ret = mixer_ctl_set_value(ctl, j, 0);
if (ret != 0) {
- LOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
+ ALOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
} else {
- LOGV("Set '%s' to '%d'\n", route[i].ctl_name, 0);
+ ALOGV("Set '%s' to '%d'\n", route[i].ctl_name, 0);
}
}
}
@@ -255,17 +273,17 @@ static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
for (i = 0; i < len; i++) {
ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
if (!ctl) {
- LOGE("Unknown control '%s'\n", route[i].ctl_name);
+ ALOGE("Unknown control '%s'\n", route[i].ctl_name);
return -EINVAL;
}
if (route[i].strval) {
ret = mixer_ctl_set_enum_by_string(ctl, route[i].strval);
if (ret != 0) {
- LOGE("Failed to set '%s' to '%s'\n",
+ ALOGE("Failed to set '%s' to '%s'\n",
route[i].ctl_name, route[i].strval);
} else {
- LOGV("Set '%s' to '%s'\n",
+ ALOGV("Set '%s' to '%s'\n",
route[i].ctl_name, route[i].strval);
}
@@ -274,10 +292,10 @@ static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
ret = mixer_ctl_set_value(ctl, j, route[i].intval);
if (ret != 0) {
- LOGE("Failed to set '%s'.%d to %d\n",
+ ALOGE("Failed to set '%s'.%d to %d\n",
route[i].ctl_name, j, route[i].intval);
} else {
- LOGV("Set '%s'.%d to %d\n",
+ ALOGV("Set '%s'.%d to %d\n",
route[i].ctl_name, j, route[i].intval);
}
}
@@ -295,7 +313,7 @@ void select_devices(struct m0_audio_device *adev)
if (adev->active_devices == adev->devices)
return;
- LOGV("Changing devices %x => %x\n", adev->active_devices, adev->devices);
+ ALOGV("Changing devices %x => %x\n", adev->active_devices, adev->devices);
/* Turn on new devices first so we don't glitch due to powerdown... */
for (i = 0; i < adev->num_dev_cfgs; i++)
@@ -316,8 +334,7 @@ void select_devices(struct m0_audio_device *adev)
static int start_call(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
- LOGE("Opening modem PCMs");
+ ALOGE("Opening modem PCMs");
int bt_on;
bt_on = adev->devices & AUDIO_DEVICE_OUT_ALL_SCO;
@@ -330,7 +347,7 @@ static int start_call(struct m0_audio_device *adev)
else
adev->pcm_modem_dl = pcm_open(CARD_DEFAULT, PORT_MODEM, PCM_OUT, &pcm_config_vx);
if (!pcm_is_ready(adev->pcm_modem_dl)) {
- LOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
+ ALOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
goto err_open_dl;
}
}
@@ -338,7 +355,7 @@ static int start_call(struct m0_audio_device *adev)
if (adev->pcm_modem_ul == NULL) {
adev->pcm_modem_ul = pcm_open(CARD_DEFAULT, PORT_MODEM, PCM_IN, &pcm_config_vx);
if (!pcm_is_ready(adev->pcm_modem_ul)) {
- LOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
+ ALOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
goto err_open_ul;
}
}
@@ -346,8 +363,6 @@ static int start_call(struct m0_audio_device *adev)
pcm_start(adev->pcm_modem_dl);
pcm_start(adev->pcm_modem_ul);
- LOGD("%s: X", __func__);
-
return 0;
err_open_ul:
@@ -362,15 +377,14 @@ err_open_dl:
static void end_call(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
- LOGE("Closing modem PCMs");
+ ALOGE("Closing modem PCMs");
+
pcm_stop(adev->pcm_modem_dl);
pcm_stop(adev->pcm_modem_ul);
pcm_close(adev->pcm_modem_dl);
pcm_close(adev->pcm_modem_ul);
adev->pcm_modem_dl = NULL;
adev->pcm_modem_ul = NULL;
- LOGD("%s: X", __func__);
}
static void set_eq_filter(struct m0_audio_device *adev)
@@ -379,7 +393,6 @@ static void set_eq_filter(struct m0_audio_device *adev)
void audio_set_wb_amr_callback(void *data, int enable)
{
- LOGD("%s: E", __func__);
struct m0_audio_device *adev = (struct m0_audio_device *)data;
pthread_mutex_lock(&adev->lock);
@@ -394,12 +407,10 @@ void audio_set_wb_amr_callback(void *data, int enable)
}
}
pthread_mutex_unlock(&adev->lock);
- LOGD("%s: X", __func__);
}
static void set_incall_device(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
int device_type;
switch(adev->devices & AUDIO_DEVICE_OUT_ALL) {
@@ -432,9 +443,8 @@ static void set_incall_device(struct m0_audio_device *adev)
}
/* if output device isn't supported, open modem side to handset by default */
- LOGE("%s: ril_set_call_audio_path(%d)", __func__, device_type);
+ ALOGE("%s: ril_set_call_audio_path(%d)", __func__, device_type);
ril_set_call_audio_path(&adev->ril, device_type);
- LOGD("%s: X", __func__);
}
static void set_input_volumes(struct m0_audio_device *adev, int main_mic_on,
@@ -451,8 +461,11 @@ static void force_all_standby(struct m0_audio_device *adev)
struct m0_stream_in *in;
struct m0_stream_out *out;
- if (adev->active_output) {
- out = adev->active_output;
+ /* only needed for low latency output streams as other streams are not used
+ * for voice use cases */
+ if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
+ !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
+ out = adev->outputs[OUTPUT_LOW_LATENCY];
pthread_mutex_lock(&out->lock);
do_output_standby(out);
pthread_mutex_unlock(&out->lock);
@@ -468,9 +481,8 @@ static void force_all_standby(struct m0_audio_device *adev)
static void select_mode(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
if (adev->mode == AUDIO_MODE_IN_CALL) {
- LOGE("Entering IN_CALL state, in_call=%d", adev->in_call);
+ ALOGE("Entering IN_CALL state, in_call=%d", adev->in_call);
if (!adev->in_call) {
force_all_standby(adev);
/* force earpiece route for in call state if speaker is the
@@ -488,7 +500,6 @@ static void select_mode(struct m0_audio_device *adev)
AUDIO_DEVICE_IN_BUILTIN_MIC;
else
adev->devices &= ~AUDIO_DEVICE_OUT_SPEAKER;
-
select_output_device(adev);
start_call(adev);
ril_set_call_clock_sync(&adev->ril, SOUND_CLOCK_START);
@@ -496,7 +507,7 @@ static void select_mode(struct m0_audio_device *adev)
adev->in_call = 1;
}
} else {
- LOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
+ ALOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
adev->in_call, adev->mode);
if (adev->in_call) {
adev->in_call = 0;
@@ -506,19 +517,17 @@ static void select_mode(struct m0_audio_device *adev)
select_input_device(adev);
}
}
- LOGD("%s: X", __func__);
}
static void select_output_device(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
int headset_on;
int headphone_on;
int speaker_on;
int earpiece_on;
int bt_on;
bool tty_volume = false;
- unsigned int channel = 0;
+ unsigned int channel;
headset_on = adev->devices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
headphone_on = adev->devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
@@ -528,33 +537,35 @@ static void select_output_device(struct m0_audio_device *adev)
switch(adev->devices & AUDIO_DEVICE_OUT_ALL) {
case AUDIO_DEVICE_OUT_SPEAKER:
- LOGD("%s: AUDIO_DEVICE_OUT_SPEAKER", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_SPEAKER", __func__);
break;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- LOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADSET", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADSET", __func__);
break;
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- LOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADPHONE", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADPHONE", __func__);
break;
case AUDIO_DEVICE_OUT_EARPIECE:
- LOGD("%s: AUDIO_DEVICE_OUT_EARPIECE", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_EARPIECE", __func__);
break;
case AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
- LOGD("%s: AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET", __func__);
break;
case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
- LOGD("%s: AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", __func__);
break;
case AUDIO_DEVICE_OUT_ALL_SCO:
- LOGD("%s: AUDIO_DEVICE_OUT_ALL_SCO", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_ALL_SCO", __func__);
break;
default:
- LOGD("%s: AUDIO_DEVICE_OUT_ALL", __func__);
+ ALOGD("%s: AUDIO_DEVICE_OUT_ALL", __func__);
break;
}
select_devices(adev);
+ set_eq_filter(adev);
+
if (adev->mode == AUDIO_MODE_IN_CALL) {
if (!bt_on) {
/* force tx path according to TTY mode when in call */
@@ -581,15 +592,15 @@ static void select_output_device(struct m0_audio_device *adev)
}
if (headset_on || headphone_on || speaker_on || earpiece_on) {
- LOGD("%s: set bigroute: voicecall_input_default", __func__);
+ ALOGD("%s: set bigroute: voicecall_input_default", __func__);
set_bigroute_by_array(adev->mixer, voicecall_default, 1);
} else {
- LOGD("%s: set bigroute: voicecall_input_default_disable", __func__);
+ ALOGD("%s: set bigroute: voicecall_input_default_disable", __func__);
set_bigroute_by_array(adev->mixer, voicecall_default_disable, 1);
}
if (headset_on || headphone_on) {
- LOGD("%s: set bigroute: headset_input", __func__);
+ ALOGD("%s: set bigroute: headset_input", __func__);
set_bigroute_by_array(adev->mixer, headset_input, 1);
}
@@ -597,70 +608,85 @@ static void select_output_device(struct m0_audio_device *adev)
// bt uses a different port (PORT_BT) for playback, reopen the pcms
end_call(adev);
start_call(adev);
- LOGD("%s: set bigroute: bt_input", __func__);
+ ALOGD("%s: set bigroute: bt_input", __func__);
set_bigroute_by_array(adev->mixer, bt_input, 1);
- LOGD("%s: set bigroute: bt_output", __func__);
+ ALOGD("%s: set bigroute: bt_output", __func__);
set_bigroute_by_array(adev->mixer, bt_output, 1);
}
set_incall_device(adev);
}
- LOGD("%s: X", __func__);
}
static void select_input_device(struct m0_audio_device *adev)
{
- LOGD("%s: E", __func__);
-
switch(adev->devices & AUDIO_DEVICE_IN_ALL) {
case AUDIO_DEVICE_IN_BUILTIN_MIC:
- LOGD("%s: AUDIO_DEVICE_IN_BUILTIN_MIC", __func__);
+ ALOGD("%s: AUDIO_DEVICE_IN_BUILTIN_MIC", __func__);
break;
case AUDIO_DEVICE_IN_BACK_MIC:
- LOGD("%s: AUDIO_DEVICE_IN_BACK_MIC", __func__);
+ ALOGD("%s: AUDIO_DEVICE_IN_BACK_MIC", __func__);
break;
case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
- LOGD("%s: AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", __func__);
+ ALOGD("%s: AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", __func__);
break;
case AUDIO_DEVICE_IN_WIRED_HEADSET:
- LOGD("%s: AUDIO_DEVICE_IN_WIRED_HEADSET", __func__);
+ ALOGD("%s: AUDIO_DEVICE_IN_WIRED_HEADSET", __func__);
break;
default:
break;
}
select_devices(adev);
- LOGD("%s: X", __func__);
}
/* must be called with hw device and output stream mutexes locked */
-static int start_output_stream(struct m0_stream_out *out)
+static int start_output_stream_low_latency(struct m0_stream_out *out)
{
- LOGD("%s: E", __func__);
struct m0_audio_device *adev = out->dev;
- unsigned int flags = PCM_OUT | PCM_MMAP;
+ unsigned int flags = PCM_OUT;
int i;
bool success = true;
- adev->active_output = out;
-
if (adev->mode != AUDIO_MODE_IN_CALL) {
- /* FIXME: only works if only one output can be active at a time */
select_output_device(adev);
}
- out->config = pcm_config_playback;
- out->config.rate = DEFAULT_OUT_SAMPLING_RATE;
- out->pcm = pcm_open(CARD_DEFAULT, PORT_PLAYBACK, flags, &out->config);
+ /* default to low power: will be corrected in out_write if necessary before first write to
+ * tinyalsa.
+ */
- /* Close PCM that could not be opened properly and return an error */
- if (out->pcm && !pcm_is_ready(out->pcm)) {
- LOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm));
- pcm_close(out->pcm);
- out->pcm = NULL;
- success = false;
+ if (adev->devices & (AUDIO_DEVICE_OUT_ALL &
+ ~(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET | AUDIO_DEVICE_OUT_AUX_DIGITAL))) {
+ /* Something not a dock in use */
+ out->config[PCM_NORMAL] = pcm_config_tones;
+ out->config[PCM_NORMAL].rate = MM_FULL_POWER_SAMPLING_RATE;
+ out->pcm[PCM_NORMAL] = pcm_open(CARD_DEFAULT, PORT_PLAYBACK,
+ flags, &out->config[PCM_NORMAL]);
+ }
+
+ if (adev->devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
+ /* SPDIF output in use */
+ out->config[PCM_SPDIF] = pcm_config_tones;
+ out->config[PCM_SPDIF].rate = MM_FULL_POWER_SAMPLING_RATE;
+ out->pcm[PCM_SPDIF] = pcm_open(CARD_DEFAULT, PORT_PLAYBACK,
+ flags, &out->config[PCM_SPDIF]);
+ }
+
+ /* Close any PCMs that could not be opened properly and return an error */
+ for (i = 0; i < PCM_TOTAL; i++) {
+ if (out->pcm[i] && !pcm_is_ready(out->pcm[i])) {
+ ALOGE("%s: cannot open pcm_out driver %d: %s", __func__ , i, pcm_get_error(out->pcm[i]));
+ pcm_close(out->pcm[i]);
+ out->pcm[i] = NULL;
+ success = false;
+ }
}
if (success) {
+ out->buffer_frames = pcm_config_tones.period_size * 2;
+ if (out->buffer == NULL)
+ out->buffer = malloc(out->buffer_frames * audio_stream_frame_size(&out->stream.common));
+
if (adev->echo_reference != NULL)
out->echo_reference = adev->echo_reference;
out->resampler->reset(out->resampler);
@@ -668,12 +694,39 @@ static int start_output_stream(struct m0_stream_out *out)
return 0;
}
- adev->active_output = NULL;
- LOGD("%s: X", __func__);
return -ENOMEM;
}
-static int check_input_parameters(uint32_t sample_rate, int format, int channel_count)
+/* must be called with hw device and output stream mutexes locked */
+static int start_output_stream_deep_buffer(struct m0_stream_out *out)
+{
+ struct m0_audio_device *adev = out->dev;
+
+ if (adev->mode != AUDIO_MODE_IN_CALL) {
+ select_output_device(adev);
+ }
+
+ out->write_threshold = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT * DEEP_BUFFER_LONG_PERIOD_SIZE;
+ out->use_long_periods = true;
+
+ out->config[PCM_NORMAL] = pcm_config_mm;
+ out->config[PCM_NORMAL].rate = MM_FULL_POWER_SAMPLING_RATE;
+ out->pcm[PCM_NORMAL] = pcm_open(CARD_DEFAULT, PORT_PLAYBACK,
+ PCM_OUT | PCM_MMAP | PCM_NOIRQ, &out->config[PCM_NORMAL]);
+ if (out->pcm[PCM_NORMAL] && !pcm_is_ready(out->pcm[PCM_NORMAL])) {
+ ALOGE("%s: cannot open pcm_out driver: %s", __func__, pcm_get_error(out->pcm[PCM_NORMAL]));
+ pcm_close(out->pcm[PCM_NORMAL]);
+ out->pcm[PCM_NORMAL] = NULL;
+ return -ENOMEM;
+ }
+ out->buffer_frames = DEEP_BUFFER_SHORT_PERIOD_SIZE * 2;
+ if (out->buffer == NULL)
+ out->buffer = malloc(PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT * DEEP_BUFFER_LONG_PERIOD_SIZE);
+
+ return 0;
+}
+
+static int check_input_parameters(uint32_t sample_rate, audio_format_t format, int channel_count)
{
if (format != AUDIO_FORMAT_PCM_16_BIT)
return -EINVAL;
@@ -698,7 +751,7 @@ static int check_input_parameters(uint32_t sample_rate, int format, int channel_
return 0;
}
-static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channel_count)
+static size_t get_input_buffer_size(uint32_t sample_rate, audio_format_t format, int channel_count)
{
size_t size;
size_t device_rate;
@@ -740,8 +793,11 @@ static void put_echo_reference(struct m0_audio_device *adev,
{
if (adev->echo_reference != NULL &&
reference == adev->echo_reference) {
- if (adev->active_output != NULL)
- remove_echo_reference(adev->active_output, reference);
+ /* echo reference is taken from the low latency output stream used
+ * for voice use cases */
+ if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
+ !adev->outputs[OUTPUT_LOW_LATENCY]->standby)
+ remove_echo_reference(adev->outputs[OUTPUT_LOW_LATENCY], reference);
release_echo_reference(reference);
adev->echo_reference = NULL;
}
@@ -753,8 +809,12 @@ static struct echo_reference_itfe *get_echo_reference(struct m0_audio_device *ad
uint32_t sampling_rate)
{
put_echo_reference(adev, adev->echo_reference);
- if (adev->active_output != NULL) {
- struct audio_stream *stream = &adev->active_output->stream.common;
+ /* echo reference is taken from the low latency output stream used
+ * for voice use cases */
+ if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
+ !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
+ struct audio_stream *stream =
+ &adev->outputs[OUTPUT_LOW_LATENCY]->stream.common;
uint32_t wr_channel_count = popcount(stream->get_channels(stream));
uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
@@ -766,7 +826,8 @@ static struct echo_reference_itfe *get_echo_reference(struct m0_audio_device *ad
wr_sampling_rate,
&adev->echo_reference);
if (status == 0)
- add_echo_reference(adev->active_output, adev->echo_reference);
+ add_echo_reference(adev->outputs[OUTPUT_LOW_LATENCY],
+ adev->echo_reference);
}
return adev->echo_reference;
}
@@ -777,24 +838,29 @@ static int get_playback_delay(struct m0_stream_out *out,
{
size_t kernel_frames;
int status;
+ int primary_pcm = 0;
+
+ /* Find the first active PCM to act as primary */
+ while ((primary_pcm < PCM_TOTAL) && !out->pcm[primary_pcm])
+ primary_pcm++;
- status = pcm_get_htimestamp(out->pcm, &kernel_frames, &buffer->time_stamp);
+ status = pcm_get_htimestamp(out->pcm[primary_pcm], &kernel_frames, &buffer->time_stamp);
if (status < 0) {
buffer->time_stamp.tv_sec = 0;
buffer->time_stamp.tv_nsec = 0;
buffer->delay_ns = 0;
- LOGV("%s: pcm_get_htimestamp error,"
+ ALOGV("%s: pcm_get_htimestamp error,"
"setting playbackTimestamp to 0", __func__);
return status;
}
- kernel_frames = pcm_get_buffer_size(out->pcm) - kernel_frames;
+ kernel_frames = pcm_get_buffer_size(out->pcm[primary_pcm]) - kernel_frames;
/* adjust render time stamp with delay added by current driver buffer.
* Add the duration of current frame as we want the render time of the last
* sample being written. */
buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
- DEFAULT_OUT_SAMPLING_RATE);
+ MM_FULL_POWER_SAMPLING_RATE);
return 0;
}
@@ -809,30 +875,46 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
return 0;
}
-static size_t out_get_buffer_size(const struct audio_stream *stream)
+static size_t out_get_buffer_size_low_latency(const struct audio_stream *stream)
{
struct m0_stream_out *out = (struct m0_stream_out *)stream;
/* take resampling into account and return the closest majoring
multiple of 16 frames, as audioflinger expects audio buffers to
be a multiple of 16 frames. Note: we use the default rate here
- from pcm_config_playback.rate. */
- size_t size = (PLAYBACK_PERIOD_SIZE * DEFAULT_OUT_SAMPLING_RATE) / pcm_config_playback.rate;
+ from pcm_config_tones.rate. */
+ size_t size = (SHORT_PERIOD_SIZE * DEFAULT_OUT_SAMPLING_RATE) / pcm_config_tones.rate;
+ size = ((size + 15) / 16) * 16;
+ return size * audio_stream_frame_size((struct audio_stream *)stream);
+}
+
+static size_t out_get_buffer_size_deep_buffer(const struct audio_stream *stream)
+{
+ struct m0_stream_out *out = (struct m0_stream_out *)stream;
+
+ /* take resampling into account and return the closest majoring
+ multiple of 16 frames, as audioflinger expects audio buffers to
+ be a multiple of 16 frames. Note: we use the default rate here
+ from pcm_config_mm.rate. */
+ size_t size = (DEEP_BUFFER_SHORT_PERIOD_SIZE * DEFAULT_OUT_SAMPLING_RATE) /
+ pcm_config_mm.rate;
size = ((size + 15) / 16) * 16;
return size * audio_stream_frame_size((struct audio_stream *)stream);
}
static uint32_t out_get_channels(const struct audio_stream *stream)
{
- return AUDIO_CHANNEL_OUT_STEREO;
+ struct m0_stream_out *out = (struct m0_stream_out *)stream;
+
+ return out->channel_mask;
}
-static int out_get_format(const struct audio_stream *stream)
+static audio_format_t out_get_format(const struct audio_stream *stream)
{
return AUDIO_FORMAT_PCM_16_BIT;
}
-static int out_set_format(struct audio_stream *stream, int format)
+static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
return 0;
}
@@ -842,23 +924,42 @@ static int do_output_standby(struct m0_stream_out *out)
{
struct m0_audio_device *adev = out->dev;
int i;
+ bool all_outputs_in_standby = true;
if (!out->standby) {
+ out->standby = 1;
- if (out->pcm) {
- pcm_close(out->pcm);
- out->pcm = NULL;
+ for (i = 0; i < PCM_TOTAL; i++) {
+ if (out->pcm[i]) {
+ pcm_close(out->pcm[i]);
+ out->pcm[i] = NULL;
+ }
}
- adev->active_output = 0;
+ for (i = 0; i < OUTPUT_TOTAL; i++) {
+ if (adev->outputs[i] != NULL && !adev->outputs[i]->standby) {
+ all_outputs_in_standby = false;
+ break;
+ }
+ }
+
+ /* force standby on low latency output stream so that it can reuse HDMI driver if
+ * necessary when restarted */
+ if (out == adev->outputs[OUTPUT_HDMI]) {
+ if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
+ !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
+ struct m0_stream_out *ll_out = adev->outputs[OUTPUT_LOW_LATENCY];
+ pthread_mutex_lock(&ll_out->lock);
+ do_output_standby(ll_out);
+ pthread_mutex_unlock(&ll_out->lock);
+ }
+ }
/* stop writing to echo reference */
if (out->echo_reference != NULL) {
out->echo_reference->write(out->echo_reference, NULL);
out->echo_reference = NULL;
}
-
- out->standby = 1;
}
return 0;
}
@@ -883,7 +984,6 @@ static int out_dump(const struct audio_stream *stream, int fd)
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
- LOGD("%s: E", __func__);
struct m0_stream_out *out = (struct m0_stream_out *)stream;
struct m0_audio_device *adev = out->dev;
struct m0_stream_in *in;
@@ -901,16 +1001,46 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
pthread_mutex_lock(&adev->lock);
pthread_mutex_lock(&out->lock);
if (((adev->devices & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) {
- if (out == adev->active_output) {
+ /* this is needed only when changing device on low latency output
+ * as other output streams are not used for voice use cases nor
+ * handle duplication to HDMI or SPDIF */
+ if (out == adev->outputs[OUTPUT_LOW_LATENCY] && !out->standby) {
/* a change in output device may change the microphone selection */
if (adev->active_input &&
adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
force_input_standby = true;
}
+ /* force standby if moving to/from HDMI/SPDIF or if the output
+ * device changes when in HDMI/SPDIF mode */
+ /* FIXME also force standby when in call as some audio path switches do not work
+ * while in call and an output stream is active (e.g BT SCO => earpiece) */
+
+ /* FIXME workaround for audio being dropped when switching path without forcing standby
+ * (several hundred ms of audio can be lost: e.g beginning of a ringtone. We must understand
+ * the root cause in audio HAL, driver or ABE.
+ if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
+ (adev->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
+ ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
+ (adev->devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
+ (adev->devices & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)))
+ */
+ if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
+ (adev->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
+ ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
+ (adev->devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
+ (adev->devices & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
+ ((val & AUDIO_DEVICE_OUT_SPEAKER) ^
+ (adev->devices & AUDIO_DEVICE_OUT_SPEAKER)) ||
+ (adev->mode == AUDIO_MODE_IN_CALL))
+ do_output_standby(out);
+ }
+ if (out != adev->outputs[OUTPUT_HDMI]) {
+ adev->devices &= ~AUDIO_DEVICE_OUT_ALL;
+ adev->devices |= val;
+ select_output_device(adev);
}
- adev->devices &= ~AUDIO_DEVICE_OUT_ALL;
- adev->devices |= val;
- select_output_device(adev);
}
pthread_mutex_unlock(&out->lock);
if (force_input_standby) {
@@ -923,21 +1053,63 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
}
str_parms_destroy(parms);
- LOGD("%s: X", __func__);
return ret;
}
static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
{
- return strdup("");
+ struct m0_stream_out *out = (struct m0_stream_out *)stream;
+
+ struct str_parms *query = str_parms_create_str(keys);
+ char *str;
+ char value[256];
+ struct str_parms *reply = str_parms_create();
+ size_t i, j;
+ int ret;
+ bool first = true;
+
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
+ if (ret >= 0) {
+ value[0] = '\0';
+ i = 0;
+ while (out->sup_channel_masks[i] != 0) {
+ for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
+ if (out_channels_name_to_enum_table[j].value == out->sup_channel_masks[i]) {
+ if (!first) {
+ strcat(value, "|");
+ }
+ strcat(value, out_channels_name_to_enum_table[j].name);
+ first = false;
+ break;
+ }
+ }
+ i++;
+ }
+ str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
+ str = strdup(str_parms_to_str(reply));
+ } else {
+ str = strdup(keys);
+ }
+ str_parms_destroy(query);
+ str_parms_destroy(reply);
+ return str;
+}
+
+static uint32_t out_get_latency_low_latency(const struct audio_stream_out *stream)
+{
+ struct m0_stream_out *out = (struct m0_stream_out *)stream;
+
+ /* Note: we use the default rate here from pcm_config_mm.rate */
+ return (SHORT_PERIOD_SIZE * PLAYBACK_SHORT_PERIOD_COUNT * 1000) / pcm_config_tones.rate;
}
-static uint32_t out_get_latency(const struct audio_stream_out *stream)
+static uint32_t out_get_latency_deep_buffer(const struct audio_stream_out *stream)
{
struct m0_stream_out *out = (struct m0_stream_out *)stream;
- /* Note: we use the default rate here from pcm_config_playback.rate */
- return (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT * 1000) / pcm_config_playback.rate;
+ /* Note: we use the default rate here from pcm_config_mm.rate */
+ return (DEEP_BUFFER_LONG_PERIOD_SIZE * PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT * 1000) /
+ pcm_config_mm.rate;
}
static int out_set_volume(struct audio_stream_out *stream, float left,
@@ -946,7 +1118,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left,
return -ENOSYS;
}
-static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
+static ssize_t out_write_low_latency(struct audio_stream_out *stream, const void* buffer,
size_t bytes)
{
int ret;
@@ -957,14 +1129,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
size_t out_frames = in_frames;
bool force_input_standby = false;
struct m0_stream_in *in;
- bool screen_state;
- int kernel_frames;
- void *buf;
- /* If we're in out_write, we will find at least one pcm active */
- int primary_pcm = -1;
int i;
- bool use_resampler = false;
- int period_size = 0;
/* acquiring hw device mutex systematically is useful if a low priority thread is waiting
* on the output stream mutex - e.g. executing select_mode() while holding the hw device
@@ -973,7 +1138,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
pthread_mutex_lock(&adev->lock);
pthread_mutex_lock(&out->lock);
if (out->standby) {
- ret = start_output_stream(out);
+ ret = start_output_stream_low_latency(out);
if (ret != 0) {
pthread_mutex_unlock(&adev->lock);
goto exit;
@@ -984,64 +1149,147 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
force_input_standby = true;
}
+ pthread_mutex_unlock(&adev->lock);
+
+ for (i = 0; i < PCM_TOTAL; i++) {
+ /* only use resampler if required */
+ if (out->pcm[i] && (out->config[i].rate != DEFAULT_OUT_SAMPLING_RATE)) {
+ out_frames = out->buffer_frames;
+ out->resampler->resample_from_input(out->resampler,
+ (int16_t *)buffer,
+ &in_frames,
+ (int16_t *)out->buffer,
+ &out_frames);
+ break;
+ }
+ }
+
+ if (out->echo_reference != NULL) {
+ struct echo_reference_buffer b;
+ b.raw = (void *)buffer;
+ b.frame_count = in_frames;
+
+ get_playback_delay(out, out_frames, &b);
+ out->echo_reference->write(out->echo_reference, &b);
+ }
+
+ /* Write to all active PCMs */
+ for (i = 0; i < PCM_TOTAL; i++) {
+ if (out->pcm[i]) {
+ if (out->config[i].rate == DEFAULT_OUT_SAMPLING_RATE) {
+ /* PCM uses native sample rate */
+ ret = PCM_WRITE(out->pcm[i], (void *)buffer, bytes);
+ } else {
+ /* PCM needs resampler */
+ ret = PCM_WRITE(out->pcm[i], (void *)out->buffer, out_frames * frame_size);
+ }
+ if (ret)
+ break;
+ }
+ }
+
+exit:
+ pthread_mutex_unlock(&out->lock);
+
+ if (ret != 0) {
+ usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
+ out_get_sample_rate(&stream->common));
+ }
+ if (force_input_standby) {
+ pthread_mutex_lock(&adev->lock);
+ if (adev->active_input) {
+ in = adev->active_input;
+ pthread_mutex_lock(&in->lock);
+ do_input_standby(in);
+ pthread_mutex_unlock(&in->lock);
+ }
+ pthread_mutex_unlock(&adev->lock);
+ }
+
+ return bytes;
+}
+
+static ssize_t out_write_deep_buffer(struct audio_stream_out *stream, const void* buffer,
+ size_t bytes)
+{
+ int ret;
+ struct m0_stream_out *out = (struct m0_stream_out *)stream;
+ struct m0_audio_device *adev = out->dev;
+ size_t frame_size = audio_stream_frame_size(&out->stream.common);
+ size_t in_frames = bytes / frame_size;
+ size_t out_frames;
+ bool use_long_periods;
+ int kernel_frames;
+ void *buf;
+
+ /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
+ * on the output stream mutex - e.g. executing select_mode() while holding the hw device
+ * mutex
+ */
+ pthread_mutex_lock(&adev->lock);
+ pthread_mutex_lock(&out->lock);
+ if (out->standby) {
+ ret = start_output_stream_deep_buffer(out);
+ if (ret != 0) {
+ pthread_mutex_unlock(&adev->lock);
+ goto exit;
+ }
+ out->standby = 0;
+ }
+ use_long_periods = adev->screen_off && !adev->active_input;
pthread_mutex_unlock(&adev->lock);
- out->write_threshold = PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
+ if (use_long_periods != out->use_long_periods) {
+ size_t period_size;
+ size_t period_count;
- if (out->pcm) {
- if (out->config.rate != DEFAULT_OUT_SAMPLING_RATE)
- use_resampler = true;
+ if (use_long_periods) {
+ period_size = DEEP_BUFFER_LONG_PERIOD_SIZE;
+ period_count = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT;
+ } else {
+ period_size = DEEP_BUFFER_SHORT_PERIOD_SIZE;
+ period_count = PLAYBACK_DEEP_BUFFER_SHORT_PERIOD_COUNT;
+ }
+ out->write_threshold = period_size * period_count;
+ pcm_set_avail_min(out->pcm[PCM_NORMAL], period_size);
+ out->use_long_periods = use_long_periods;
}
/* only use resampler if required */
- if (use_resampler)
+ if (out->config[PCM_NORMAL].rate != DEFAULT_OUT_SAMPLING_RATE) {
+ out_frames = out->buffer_frames;
out->resampler->resample_from_input(out->resampler,
(int16_t *)buffer,
&in_frames,
(int16_t *)out->buffer,
&out_frames);
- else
+ buf = (void *)out->buffer;
+ } else {
out_frames = in_frames;
-
- if (out->echo_reference != NULL) {
- struct echo_reference_buffer b;
- b.raw = (void *)buffer;
- b.frame_count = in_frames;
-
- get_playback_delay(out, out_frames, &b);
- out->echo_reference->write(out->echo_reference, &b);
+ buf = (void *)buffer;
}
/* do not allow more than out->write_threshold frames in kernel pcm driver buffer */
do {
struct timespec time_stamp;
- if (pcm_get_htimestamp(out->pcm, (unsigned int *)&kernel_frames, &time_stamp) < 0)
+ if (pcm_get_htimestamp(out->pcm[PCM_NORMAL],
+ (unsigned int *)&kernel_frames, &time_stamp) < 0)
break;
- kernel_frames = pcm_get_buffer_size(out->pcm) - kernel_frames;
+ kernel_frames = pcm_get_buffer_size(out->pcm[PCM_NORMAL]) - kernel_frames;
if (kernel_frames > out->write_threshold) {
unsigned long time = (unsigned long)
(((int64_t)(kernel_frames - out->write_threshold) * 1000000) /
- DEFAULT_OUT_SAMPLING_RATE);
+ MM_FULL_POWER_SAMPLING_RATE);
if (time < MIN_WRITE_SLEEP_US)
time = MIN_WRITE_SLEEP_US;
usleep(time);
}
} while (kernel_frames > out->write_threshold);
- /* Write to all active PCMs */
-
- if (out->pcm) {
- if (out->config.rate == DEFAULT_OUT_SAMPLING_RATE) {
- /* PCM uses native sample rate */
- ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
- } else {
- /* PCM needs resampler */
- ret = pcm_mmap_write(out->pcm, (void *)out->buffer, out_frames * frame_size);
- }
- }
+ ret = pcm_mmap_write(out->pcm[PCM_NORMAL], buf, out_frames * frame_size);
exit:
pthread_mutex_unlock(&out->lock);
@@ -1051,17 +1299,6 @@ exit:
out_get_sample_rate(&stream->common));
}
- if (force_input_standby) {
- pthread_mutex_lock(&adev->lock);
- if (adev->active_input) {
- in = adev->active_input;
- pthread_mutex_lock(&in->lock);
- do_input_standby(in);
- pthread_mutex_unlock(&in->lock);
- }
- pthread_mutex_unlock(&adev->lock);
- }
-
return bytes;
}
@@ -1086,7 +1323,6 @@ static int out_remove_audio_effect(const struct audio_stream *stream, effect_han
/* must be called with hw device and input stream mutexes locked */
static int start_input_stream(struct m0_stream_in *in)
{
- LOGD("%s: E", __func__);
int ret = 0;
struct m0_audio_device *adev = in->dev;
@@ -1098,16 +1334,25 @@ static int start_input_stream(struct m0_stream_in *in)
select_input_device(adev);
}
- /* in case channel count has changed, restart the resampler */
- if (in->resampler) {
- release_resampler(in->resampler);
- in->resampler = NULL;
- ret = create_resampler(in->config.rate,
+ if (in->aux_channels_changed)
+ {
+ in->aux_channels_changed = false;
+ in->config.channels = popcount(in->main_channels | in->aux_channels);
+
+ if (in->resampler) {
+ /* release and recreate the resampler with the new number of channel of the input */
+ release_resampler(in->resampler);
+ in->resampler = NULL;
+ ret = create_resampler(in->config.rate,
in->requested_rate,
in->config.channels,
RESAMPLER_QUALITY_DEFAULT,
&in->buf_provider,
&in->resampler);
+ }
+ ALOGV("%s: New channel configuration, "
+ "main_channels = [%04x], aux_channels = [%04x], config.channels = %d",
+ __func__, in->main_channels, in->aux_channels, in->config.channels);
}
if (in->need_echo_reference && in->echo_reference == NULL)
@@ -1116,10 +1361,10 @@ static int start_input_stream(struct m0_stream_in *in)
in->config.channels,
in->requested_rate);
+ /* this assumes routing is done previously */
in->pcm = pcm_open(CARD_DEFAULT, PORT_CAPTURE, PCM_IN, &in->config);
-
if (!pcm_is_ready(in->pcm)) {
- LOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
+ ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
pcm_close(in->pcm);
adev->active_input = NULL;
return -ENOMEM;
@@ -1134,7 +1379,6 @@ static int start_input_stream(struct m0_stream_in *in)
if (in->resampler) {
in->resampler->reset(in->resampler);
}
- LOGD("%s: X", __func__);
return 0;
}
@@ -1156,26 +1400,22 @@ static size_t in_get_buffer_size(const struct audio_stream *stream)
return get_input_buffer_size(in->requested_rate,
AUDIO_FORMAT_PCM_16_BIT,
- in->config.channels);
+ popcount(in->main_channels));
}
static uint32_t in_get_channels(const struct audio_stream *stream)
{
struct m0_stream_in *in = (struct m0_stream_in *)stream;
- if (in->config.channels == 1) {
- return AUDIO_CHANNEL_IN_MONO;
- } else {
- return AUDIO_CHANNEL_IN_STEREO;
- }
+ return in->main_channels;
}
-static int in_get_format(const struct audio_stream *stream)
+static audio_format_t in_get_format(const struct audio_stream *stream)
{
return AUDIO_FORMAT_PCM_16_BIT;
}
-static int in_set_format(struct audio_stream *stream, int format)
+static int in_set_format(struct audio_stream *stream, audio_format_t format)
{
return 0;
}
@@ -1227,7 +1467,6 @@ static int in_dump(const struct audio_stream *stream, int fd)
static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
- LOGD("%s: E", __func__);
struct m0_stream_in *in = (struct m0_stream_in *)stream;
struct m0_audio_device *adev = in->dev;
struct str_parms *parms;
@@ -1257,6 +1496,9 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
if ((in->device != val) && (val != 0)) {
in->device = val;
do_standby = true;
+ /* make sure new device selection is incompatible with multi-mic pre processing
+ * configuration */
+ in_update_aux_channels(in, NULL);
}
}
@@ -1266,7 +1508,6 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
pthread_mutex_unlock(&adev->lock);
str_parms_destroy(parms);
- LOGD("%s: X", __func__);
return ret;
}
@@ -1298,7 +1539,7 @@ static void get_capture_delay(struct m0_stream_in *in,
buffer->time_stamp.tv_sec = 0;
buffer->time_stamp.tv_nsec = 0;
buffer->delay_ns = 0;
- LOGW("%s: pcm_htimestamp error", __func__);
+ ALOGW("%s: pcm_htimestamp error", __func__);
return;
}
@@ -1323,7 +1564,7 @@ static void get_capture_delay(struct m0_stream_in *in,
buffer->time_stamp = tstamp;
buffer->delay_ns = delay_ns;
- LOGV("%s: time_stamp = [%ld].[%ld], delay_ns: [%d],"
+ ALOGV("%s: time_stamp = [%ld].[%ld], delay_ns: [%d],"
" kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], kernel_frames:[%d], "
"in->read_buf_frames:[%d], in->proc_buf_frames:[%d], frames:[%d]",
__func__, buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns,
@@ -1337,13 +1578,17 @@ static int32_t update_echo_reference(struct m0_stream_in *in, size_t frames)
struct echo_reference_buffer b;
b.delay_ns = 0;
- LOGV("%s: frames = [%d], in->ref_frames_in = [%d], "
+ ALOGV("%s: frames = [%d], in->ref_frames_in = [%d], "
"b.frame_count = [%d]",
__func__, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
if (in->ref_buf_frames < frames) {
if (in->ref_buf_size < frames) {
in->ref_buf_size = frames;
in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
+ ALOG_ASSERT((in->ref_buf != NULL),
+ "%s failed to reallocate ref_buf", __func__);
+ ALOGV("%s: ref_buf %p extended to %d bytes",
+ __func__, in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
}
b.frame_count = frames - in->ref_buf_frames;
b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
@@ -1353,12 +1598,12 @@ static int32_t update_echo_reference(struct m0_stream_in *in, size_t frames)
if (in->echo_reference->read(in->echo_reference, &b) == 0)
{
in->ref_buf_frames += b.frame_count;
- LOGD("%s: in->ref_buf_frames:[%d], "
+ ALOGD("%s: in->ref_buf_frames:[%d], "
"in->ref_buf_size:[%d], frames:[%d], b.frame_count:[%d]",
__func__, in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
}
} else
- LOGW("%s: NOT enough frames to read ref buffer", __func__);
+ ALOGW("%s: NOT enough frames to read ref buffer", __func__);
return b.delay_ns;
}
@@ -1410,13 +1655,13 @@ static void push_echo_reference(struct m0_stream_in *in, size_t frames)
buf.raw = in->ref_buf;
for (i = 0; i < in->num_preprocessors; i++) {
- if ((*in->preprocessors[i])->process_reverse == NULL)
+ if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
continue;
- (*in->preprocessors[i])->process_reverse(in->preprocessors[i],
+ (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
&buf,
NULL);
- set_preprocessor_echo_delay(in->preprocessors[i], delay_us);
+ set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
}
in->ref_buf_frames -= buf.frameCount;
@@ -1450,14 +1695,16 @@ static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
if (in->read_buf_size < in->config.period_size) {
in->read_buf_size = in->config.period_size;
in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
- LOGI("%s: read_buf %p extended to %d bytes",
+ ALOG_ASSERT((in->read_buf != NULL),
+ "%s failed to reallocate read_buf", __func__);
+ ALOGV("%s: read_buf %p extended to %d bytes",
__func__, in->read_buf, size_in_bytes);
}
in->read_status = pcm_read(in->pcm, (void*)in->read_buf, size_in_bytes);
if (in->read_status != 0) {
- LOGE("%s: pcm_read error %d", __func__, in->read_status);
+ ALOGE("%s: pcm_read error %d", __func__, in->read_status);
buffer->raw = NULL;
buffer->frame_count = 0;
return in->read_status;
@@ -1536,7 +1783,16 @@ static ssize_t process_frames(struct m0_stream_in *in, void* buffer, ssize_t fra
audio_buffer_t in_buf;
audio_buffer_t out_buf;
int i;
+ bool has_aux_channels = (~in->main_channels & in->aux_channels);
+ void *proc_buf_out;
+ if (has_aux_channels)
+ proc_buf_out = in->proc_buf_out;
+ else
+ proc_buf_out = buffer;
+
+ /* since all the processing below is done in frames and using the config.channels
+ * as the number of channels, no changes is required in case aux_channels are present */
while (frames_wr < frames) {
/* first reload enough frames at the end of process input buffer */
if (in->proc_buf_frames < (size_t)frames) {
@@ -1547,7 +1803,16 @@ static ssize_t process_frames(struct m0_stream_in *in, void* buffer, ssize_t fra
in->proc_buf_size = (size_t)frames;
in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
- LOGD("%s: proc_buf_in %p extended to %d bytes", __func__, in->proc_buf_in, size_in_bytes);
+ ALOG_ASSERT((in->proc_buf_in != NULL),
+ "%s failed to reallocate proc_buf_in", __func__);
+ if (has_aux_channels) {
+ in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
+ ALOG_ASSERT((in->proc_buf_out != NULL),
+ "%s failed to reallocate proc_buf_out", __func__);
+ proc_buf_out = in->proc_buf_out;
+ }
+ ALOGV("process_frames(): proc_buf_in %p extended to %d bytes",
+ in->proc_buf_in, size_in_bytes);
}
frames_rd = read_frames(in,
in->proc_buf_in +
@@ -1568,12 +1833,18 @@ static ssize_t process_frames(struct m0_stream_in *in, void* buffer, ssize_t fra
in_buf.frameCount = in->proc_buf_frames;
in_buf.s16 = in->proc_buf_in;
out_buf.frameCount = frames - frames_wr;
- out_buf.s16 = (int16_t *)buffer + frames_wr * in->config.channels;
-
- for (i = 0; i < in->num_preprocessors; i++)
- (*in->preprocessors[i])->process(in->preprocessors[i],
+ out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
+
+ /* FIXME: this works because of current pre processing library implementation that
+ * does the actual process only when the last enabled effect process is called.
+ * The generic solution is to have an output buffer for each effect and pass it as
+ * input to the next.
+ */
+ for (i = 0; i < in->num_preprocessors; i++) {
+ (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
&in_buf,
&out_buf);
+ }
/* process() has updated the number of frames consumed and produced in
* in_buf.frameCount and out_buf.frameCount respectively
@@ -1587,18 +1858,47 @@ static ssize_t process_frames(struct m0_stream_in *in, void* buffer, ssize_t fra
}
/* if not enough frames were passed to process(), read more and retry. */
- if (out_buf.frameCount == 0)
+ if (out_buf.frameCount == 0) {
+ ALOGW("No frames produced by preproc");
continue;
+ }
if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
frames_wr += out_buf.frameCount;
} else {
/* The effect does not comply to the API. In theory, we should never end up here! */
- LOGE("%s: preprocessing produced too many frames: %d + %d > %d !", __func__,
+ ALOGE("%s: preprocessing produced too many frames: %d + %d > %d !", __func__,
(unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
frames_wr = frames;
}
}
+
+ /* Remove aux_channels that have been added on top of main_channels
+ * Assumption is made that the channels are interleaved and that the main
+ * channels are first. */
+ if (has_aux_channels)
+ {
+ size_t src_channels = in->config.channels;
+ size_t dst_channels = popcount(in->main_channels);
+ int16_t* src_buffer = (int16_t *)proc_buf_out;
+ int16_t* dst_buffer = (int16_t *)buffer;
+
+ if (dst_channels == 1) {
+ for (i = frames_wr; i > 0; i--)
+ {
+ *dst_buffer++ = *src_buffer;
+ src_buffer += src_channels;
+ }
+ } else {
+ for (i = frames_wr; i > 0; i--)
+ {
+ memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
+ dst_buffer += dst_channels;
+ src_buffer += src_channels;
+ }
+ }
+ }
+
return frames_wr;
}
@@ -1653,6 +1953,284 @@ static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
return 0;
}
+#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
+ do { \
+ if (fct_status != 0) \
+ status = fct_status; \
+ else if (cmd_status != 0) \
+ status = cmd_status; \
+ } while(0)
+
+static int in_configure_reverse(struct m0_stream_in *in)
+{
+ int32_t cmd_status;
+ uint32_t size = sizeof(int);
+ effect_config_t config;
+ int32_t status = 0;
+ int32_t fct_status = 0;
+ int i;
+
+ if (in->num_preprocessors > 0) {
+ config.inputCfg.channels = in->main_channels;
+ config.outputCfg.channels = in->main_channels;
+ config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.inputCfg.samplingRate = in->requested_rate;
+ config.outputCfg.samplingRate = in->requested_rate;
+ config.inputCfg.mask =
+ ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
+ config.outputCfg.mask =
+ ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
+
+ for (i = 0; i < in->num_preprocessors; i++)
+ {
+ if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
+ continue;
+ fct_status = (*(in->preprocessors[i].effect_itfe))->command(
+ in->preprocessors[i].effect_itfe,
+ EFFECT_CMD_SET_CONFIG_REVERSE,
+ sizeof(effect_config_t),
+ &config,
+ &size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+ }
+ }
+ return status;
+}
+
+#define MAX_NUM_CHANNEL_CONFIGS 10
+
+static void in_read_audio_effect_channel_configs(struct m0_stream_in *in,
+ struct effect_info_s *effect_info)
+{
+ /* size and format of the cmd are defined in hardware/audio_effect.h */
+ effect_handle_t effect = effect_info->effect_itfe;
+ uint32_t cmd_size = 2 * sizeof(uint32_t);
+ uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
+ /* reply = status + number of configs (n) + n x channel_config_t */
+ uint32_t reply_size =
+ 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
+ int32_t reply[reply_size];
+ int32_t cmd_status;
+
+ ALOG_ASSERT((effect_info->num_channel_configs == 0),
+ "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
+ ALOG_ASSERT((effect_info->channel_configs == NULL),
+ "in_read_audio_effect_channel_configs() channel_configs not cleared");
+
+ /* if this command is not supported, then the effect is supposed to return -EINVAL.
+ * This error will be interpreted as if the effect supports the main_channels but does not
+ * support any aux_channels */
+ cmd_status = (*effect)->command(effect,
+ EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
+ cmd_size,
+ (void*)&cmd,
+ &reply_size,
+ (void*)&reply);
+
+ if (cmd_status != 0) {
+ ALOGI("%s: fx->command returned %d", __func__, cmd_status);
+ return;
+ }
+
+ if (reply[0] != 0) {
+ ALOGW("%s: "
+ "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
+ __func__, reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
+ return;
+ }
+
+ /* the feature is not supported */
+ ALOGI("in_read_audio_effect_channel_configs()(): "
+ "Feature supported and adding %d channel configs to the list", reply[1]);
+ effect_info->num_channel_configs = reply[1];
+ effect_info->channel_configs =
+ (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
+ memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
+}
+
+
+static uint32_t in_get_aux_channels(struct m0_stream_in *in)
+{
+ int i;
+ channel_config_t new_chcfg = {0, 0};
+
+ if (in->num_preprocessors == 0)
+ return 0;
+
+ /* do not enable dual mic configurations when capturing from other microphones than
+ * main or sub */
+ if (!(in->device & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
+ return 0;
+
+ /* retain most complex aux channels configuration compatible with requested main channels and
+ * supported by audio driver and all pre processors */
+ for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
+ channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
+ if (cur_chcfg->main_channels == in->main_channels) {
+ size_t match_cnt;
+ size_t idx_preproc;
+ for (idx_preproc = 0, match_cnt = 0;
+ /* no need to continue if at least one preprocessor doesn't match */
+ idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
+ idx_preproc++) {
+ struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
+ size_t idx_chcfg;
+
+ for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
+ if (memcmp(effect_info->channel_configs + idx_chcfg,
+ cur_chcfg,
+ sizeof(channel_config_t)) == 0) {
+ match_cnt++;
+ break;
+ }
+ }
+ }
+ /* if all preprocessors match, we have a candidate */
+ if (match_cnt == (size_t)in->num_preprocessors) {
+ /* retain most complex aux channels configuration */
+ if (popcount(cur_chcfg->aux_channels) > popcount(new_chcfg.aux_channels)) {
+ new_chcfg = *cur_chcfg;
+ }
+ }
+ }
+ }
+
+ ALOGI("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
+
+ return new_chcfg.aux_channels;
+}
+
+static int in_configure_effect_channels(effect_handle_t effect,
+ channel_config_t *channel_config)
+{
+ int status = 0;
+ int fct_status;
+ int32_t cmd_status;
+ uint32_t reply_size;
+ effect_config_t config;
+ uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
+
+ ALOGI("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
+ channel_config->main_channels,
+ channel_config->aux_channels);
+
+ config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ reply_size = sizeof(effect_config_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_GET_CONFIG,
+ 0,
+ NULL,
+ &reply_size,
+ &config);
+ if (fct_status != 0) {
+ ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
+ return fct_status;
+ }
+
+ config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
+ config.outputCfg.channels = config.inputCfg.channels;
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &config,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
+ memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_SET_FEATURE_CONFIG,
+ sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
+ cmd,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ /* some implementations need to be re-enabled after a config change */
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_ENABLE,
+ 0,
+ NULL,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ return status;
+}
+
+static int in_reconfigure_channels(struct m0_stream_in *in,
+ effect_handle_t effect,
+ channel_config_t *channel_config,
+ bool config_changed) {
+
+ int status = 0;
+
+ ALOGI("%s: config_changed %d effect %p",
+ __func__, config_changed, effect);
+
+ /* if config changed, reconfigure all previously added effects */
+ if (config_changed) {
+ int i;
+ for (i = 0; i < in->num_preprocessors; i++)
+ {
+ int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
+ channel_config);
+ if (cur_status != 0) {
+ ALOGI("%s: error %d configuring effect "
+ "%d with channels: [%04x][%04x]",
+ __func__,
+ cur_status,
+ i,
+ channel_config->main_channels,
+ channel_config->aux_channels);
+ status = cur_status;
+ }
+ }
+ } else if (effect != NULL && channel_config->aux_channels) {
+ /* if aux channels config did not change but aux channels are present,
+ * we still need to configure the effect being added */
+ status = in_configure_effect_channels(effect, channel_config);
+ }
+ return status;
+}
+
+static void in_update_aux_channels(struct m0_stream_in *in,
+ effect_handle_t effect)
+{
+ uint32_t aux_channels;
+ channel_config_t channel_config;
+ int status;
+
+ aux_channels = in_get_aux_channels(in);
+
+ channel_config.main_channels = in->main_channels;
+ channel_config.aux_channels = aux_channels;
+ status = in_reconfigure_channels(in,
+ effect,
+ &channel_config,
+ (aux_channels != in->aux_channels));
+
+ if (status != 0) {
+ ALOGI("%s: in_reconfigure_channels error %d", __func__, status);
+ /* resetting aux channels configuration */
+ aux_channels = 0;
+ channel_config.aux_channels = 0;
+ in_reconfigure_channels(in, effect, &channel_config, true);
+ }
+ if (in->aux_channels != aux_channels) {
+ in->aux_channels_changed = true;
+ in->aux_channels = aux_channels;
+ do_input_standby(in);
+ }
+}
+
static int in_add_audio_effect(const struct audio_stream *stream,
effect_handle_t effect)
{
@@ -1671,15 +2249,26 @@ static int in_add_audio_effect(const struct audio_stream *stream,
if (status != 0)
goto exit;
- in->preprocessors[in->num_preprocessors++] = effect;
+ in->preprocessors[in->num_preprocessors].effect_itfe = effect;
+ /* add the supported channel of the effect in the channel_configs */
+ in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
+
+ in->num_preprocessors++;
+
+ /* check compatibility between main channel supported and possible auxiliary channels */
+ in_update_aux_channels(in, effect);
+
+ ALOGV("%s: effect type: %08x", __func__, desc.type.timeLow);
if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
in->need_echo_reference = true;
do_input_standby(in);
+ in_configure_reverse(in);
}
exit:
+ ALOGW_IF(status != 0, "%s: error %d", __func__, status);
pthread_mutex_unlock(&in->lock);
pthread_mutex_unlock(&in->dev->lock);
return status;
@@ -1691,7 +2280,6 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
struct m0_stream_in *in = (struct m0_stream_in *)stream;
int i;
int status = -EINVAL;
- bool found = false;
effect_descriptor_t desc;
pthread_mutex_lock(&in->dev->lock);
@@ -1702,14 +2290,17 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
}
for (i = 0; i < in->num_preprocessors; i++) {
- if (found) {
- in->preprocessors[i - 1] = in->preprocessors[i];
+ if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
+ in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
+ in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
+ in->preprocessors[i - 1].num_channel_configs = in->preprocessors[i].num_channel_configs;
+ ALOGI("in_remove_audio_effect moving fx from %d to %d", i, i - 1);
continue;
}
- if (in->preprocessors[i] == effect) {
- in->preprocessors[i] = NULL;
+ if (in->preprocessors[i].effect_itfe == effect) {
+ ALOGI("in_remove_audio_effect found fx at index %d", i);
+ free(in->preprocessors[i].channel_configs);
status = 0;
- found = true;
}
}
@@ -1717,10 +2308,21 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
goto exit;
in->num_preprocessors--;
+ /* if we remove one effect, at least the last preproc should be reset */
+ in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
+ in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
+ in->preprocessors[in->num_preprocessors].channel_configs = NULL;
+
+
+ /* check compatibility between main channel supported and possible auxiliary channels */
+ in_update_aux_channels(in, NULL);
status = (*effect)->get_descriptor(effect, &desc);
if (status != 0)
goto exit;
+
+ ALOGI("%s: effect type: %08x", __func__, desc.type.timeLow);
+
if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
in->need_echo_reference = false;
do_input_standby(in);
@@ -1728,38 +2330,53 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
exit:
+ ALOGW_IF(status != 0, "%s: error %d", __func__, status);
pthread_mutex_unlock(&in->lock);
pthread_mutex_unlock(&in->dev->lock);
return status;
}
-
static int adev_open_output_stream(struct audio_hw_device *dev,
- uint32_t devices, int *format,
- uint32_t *channels, uint32_t *sample_rate,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
struct audio_stream_out **stream_out)
{
struct m0_audio_device *ladev = (struct m0_audio_device *)dev;
struct m0_stream_out *out;
int ret;
+ int output_type;
+ *stream_out = NULL;
out = (struct m0_stream_out *)calloc(1, sizeof(struct m0_stream_out));
if (!out)
return -ENOMEM;
+ out->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
+ out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+
+ if (ladev->outputs[OUTPUT_DEEP_BUF] != NULL) {
+ ret = -ENOSYS;
+ goto err_open;
+ }
+ output_type = OUTPUT_DEEP_BUF;
+ out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ out->stream.common.get_buffer_size = out_get_buffer_size_deep_buffer;
+ out->stream.common.get_sample_rate = out_get_sample_rate;
+ out->stream.get_latency = out_get_latency_deep_buffer;
+ out->stream.write = out_write_deep_buffer;
+
ret = create_resampler(DEFAULT_OUT_SAMPLING_RATE,
- DEFAULT_OUT_SAMPLING_RATE,
+ MM_FULL_POWER_SAMPLING_RATE,
2,
RESAMPLER_QUALITY_DEFAULT,
NULL,
&out->resampler);
if (ret != 0)
goto err_open;
- out->buffer = malloc(RESAMPLER_BUFFER_SIZE); /* todo: allow for reallocing */
- out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
- out->stream.common.get_buffer_size = out_get_buffer_size;
out->stream.common.get_channels = out_get_channels;
out->stream.common.get_format = out_get_format;
out->stream.common.set_format = out_set_format;
@@ -1769,9 +2386,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->stream.common.get_parameters = out_get_parameters;
out->stream.common.add_audio_effect = out_add_audio_effect;
out->stream.common.remove_audio_effect = out_remove_audio_effect;
- out->stream.get_latency = out_get_latency;
out->stream.set_volume = out_set_volume;
- out->stream.write = out_write;
out->stream.get_render_position = out_get_render_position;
out->dev = ladev;
@@ -1781,29 +2396,39 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
* do the following:
* adev->devices &= ~AUDIO_DEVICE_OUT_ALL;
* adev->devices |= out->device;
- * select_devices(adev);
+ * select_output_device(adev);
* This is because out_set_parameters() with a route is not
* guaranteed to be called after an output stream is opened. */
- *format = out_get_format(&out->stream.common);
- *channels = out_get_channels(&out->stream.common);
- *sample_rate = out_get_sample_rate(&out->stream.common);
+ config->format = out->stream.common.get_format(&out->stream.common);
+ config->channel_mask = out->stream.common.get_channels(&out->stream.common);
+ config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
*stream_out = &out->stream;
+ ladev->outputs[output_type] = out;
+
return 0;
err_open:
free(out);
- *stream_out = NULL;
return ret;
}
static void adev_close_output_stream(struct audio_hw_device *dev,
struct audio_stream_out *stream)
{
+ struct m0_audio_device *ladev = (struct m0_audio_device *)dev;
struct m0_stream_out *out = (struct m0_stream_out *)stream;
+ int i;
out_standby(&stream->common);
+ for (i = 0; i < OUTPUT_TOTAL; i++) {
+ if (ladev->outputs[i] == out) {
+ ladev->outputs[i] = NULL;
+ break;
+ }
+ }
+
if (out->buffer)
free(out->buffer);
if (out->resampler)
@@ -1813,7 +2438,6 @@ static void adev_close_output_stream(struct audio_hw_device *dev,
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
- LOGD("%s: E", __func__);
struct m0_audio_device *adev = (struct m0_audio_device *)dev;
struct str_parms *parms;
char *str;
@@ -1853,16 +2477,15 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
adev->bluetooth_nrec = false;
}
- ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
+ ret = str_parms_get_str(parms, "screen_off", value, sizeof(value));
if (ret >= 0) {
if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
- adev->screen_state = false;
+ adev->screen_off = false;
else
- adev->screen_state = true;
+ adev->screen_off = true;
}
str_parms_destroy(parms);
- LOGD("%s: X", __func__);
return ret;
}
@@ -1894,7 +2517,7 @@ static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
return -ENOSYS;
}
-static int adev_set_mode(struct audio_hw_device *dev, int mode)
+static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
{
struct m0_audio_device *adev = (struct m0_audio_device *)dev;
@@ -1927,30 +2550,30 @@ static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
}
static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
- uint32_t sample_rate, int format,
- int channel_count)
+ const struct audio_config *config)
{
size_t size;
-
- if (check_input_parameters(sample_rate, format, channel_count) != 0)
+ int channel_count = popcount(config->channel_mask);
+ if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
return 0;
- return get_input_buffer_size(sample_rate, format, channel_count);
+ return get_input_buffer_size(config->sample_rate, config->format, channel_count);
}
-static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
- int *format, uint32_t *channel_mask,
- uint32_t *sample_rate,
- audio_in_acoustics_t acoustics,
+static int adev_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
struct audio_stream_in **stream_in)
{
- LOGD("%s: E", __func__);
struct m0_audio_device *ladev = (struct m0_audio_device *)dev;
struct m0_stream_in *in;
int ret;
- int channel_count = popcount(*channel_mask);
+ int channel_count = popcount(config->channel_mask);
+
+ *stream_in = NULL;
- if (check_input_parameters(*sample_rate, *format, channel_count) != 0)
+ if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
return -EINVAL;
in = (struct m0_stream_in *)calloc(1, sizeof(struct m0_stream_in));
@@ -1973,11 +2596,16 @@ static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
- in->requested_rate = *sample_rate;
+ in->requested_rate = config->sample_rate;
memcpy(&in->config, &pcm_config_capture, sizeof(pcm_config_capture));
in->config.channels = channel_count;
+ in->main_channels = config->channel_mask;
+
+ /* initialisation of preprocessor structure array is implicit with the calloc.
+ * same for in->aux_channels and in->aux_channels_changed */
+
if (in->requested_rate != in->config.rate) {
in->buf_provider.get_next_buffer = get_next_buffer;
in->buf_provider.release_buffer = release_buffer;
@@ -1999,7 +2627,6 @@ static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
in->device = devices;
*stream_in = &in->stream;
- LOGD("%s: X", __func__);
return 0;
err:
@@ -2007,7 +2634,6 @@ err:
release_resampler(in->resampler);
free(in);
- *stream_in = NULL;
return ret;
}
@@ -2015,10 +2641,15 @@ static void adev_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *stream)
{
struct m0_stream_in *in = (struct m0_stream_in *)stream;
+ int i;
in_standby(&stream->common);
- free(in->read_buf);
+ for (i = 0; i < in->num_preprocessors; i++) {
+ free(in->preprocessors[i].channel_configs);
+ }
+
+ free(in->read_buf);
if (in->resampler) {
release_resampler(in->resampler);
}
@@ -2114,18 +2745,18 @@ static void adev_config_start(void *data, const XML_Char *elem,
if (strcmp(elem, "device") == 0) {
if (!name) {
- LOGE("Unnamed device\n");
+ ALOGE("Unnamed device\n");
return;
}
for (i = 0; i < sizeof(dev_names) / sizeof(dev_names[0]); i++) {
if (strcmp(dev_names[i].name, name) == 0) {
- LOGI("Allocating device %s\n", name);
+ ALOGI("Allocating device %s\n", name);
dev_cfg = realloc(s->adev->dev_cfgs,
(s->adev->num_dev_cfgs + 1)
* sizeof(*dev_cfg));
if (!dev_cfg) {
- LOGE("Unable to allocate dev_cfg\n");
+ ALOGE("Unable to allocate dev_cfg\n");
return;
}
@@ -2140,7 +2771,7 @@ static void adev_config_start(void *data, const XML_Char *elem,
} else if (strcmp(elem, "path") == 0) {
if (s->path_len)
- LOGW("Nested paths\n");
+ ALOGW("Nested paths\n");
/* If this a path for a device it must have a role */
if (s->dev) {
@@ -2150,7 +2781,7 @@ static void adev_config_start(void *data, const XML_Char *elem,
} else if (strcmp(name, "off") == 0) {
s->on = false;
} else {
- LOGW("Unknown path name %s\n", name);
+ ALOGW("Unknown path name %s\n", name);
}
}
@@ -2158,20 +2789,20 @@ static void adev_config_start(void *data, const XML_Char *elem,
struct route_setting *r;
if (!name) {
- LOGE("Unnamed control\n");
+ ALOGE("Unnamed control\n");
return;
}
if (!val) {
- LOGE("No value specified for %s\n", name);
+ ALOGE("No value specified for %s\n", name);
return;
}
- LOGV("Parsing control %s => %s\n", name, val);
+ ALOGV("Parsing control %s => %s\n", name, val);
r = realloc(s->path, sizeof(*r) * (s->path_len + 1));
if (!r) {
- LOGE("Out of memory handling %s => %s\n", name, val);
+ ALOGE("Out of memory handling %s => %s\n", name, val);
return;
}
@@ -2195,10 +2826,10 @@ static void adev_config_end(void *data, const XML_Char *name)
if (strcmp(name, "path") == 0) {
if (!s->path_len)
- LOGW("Empty path\n");
+ ALOGW("Empty path\n");
if (!s->dev) {
- LOGV("Applying %d element default route\n", s->path_len);
+ ALOGV("Applying %d element default route\n", s->path_len);
set_route_by_array(s->adev->mixer, s->path, s->path_len);
@@ -2211,12 +2842,12 @@ static void adev_config_end(void *data, const XML_Char *name)
/* Refactor! */
} else if (s->on) {
- LOGV("%d element on sequence\n", s->path_len);
+ ALOGV("%d element on sequence\n", s->path_len);
s->dev->on = s->path;
s->dev->on_len = s->path_len;
} else {
- LOGV("%d element off sequence\n", s->path_len);
+ ALOGV("%d element off sequence\n", s->path_len);
/* Apply it, we'll reenable anything that's wanted later */
set_route_by_array(s->adev->mixer, s->path, s->path_len);
@@ -2247,16 +2878,16 @@ static int adev_config_parse(struct m0_audio_device *adev)
property_get("ro.product.device", property, "tiny_hw");
snprintf(file, sizeof(file), "/system/etc/sound/%s", property);
- LOGV("Reading configuration from %s\n", file);
+ ALOGV("Reading configuration from %s\n", file);
f = fopen(file, "r");
if (!f) {
- LOGE("Failed to open %s\n", file);
+ ALOGE("Failed to open %s\n", file);
return -ENODEV;
}
p = XML_ParserCreate(NULL);
if (!p) {
- LOGE("Failed to create XML parser\n");
+ ALOGE("Failed to create XML parser\n");
ret = -ENOMEM;
goto out;
}
@@ -2270,14 +2901,14 @@ static int adev_config_parse(struct m0_audio_device *adev)
while (!eof) {
len = fread(file, 1, sizeof(file), f);
if (ferror(f)) {
- LOGE("I/O error reading config\n");
+ ALOGE("I/O error reading config\n");
ret = -EIO;
goto out_parser;
}
eof = feof(f);
if (XML_Parse(p, file, len, eof) == XML_STATUS_ERROR) {
- LOGE("Parse error at line %u:\n%s\n",
+ ALOGE("Parse error at line %u:\n%s\n",
(unsigned int)XML_GetCurrentLineNumber(p),
XML_ErrorString(XML_GetErrorCode(p)));
ret = -EINVAL;
@@ -2307,7 +2938,7 @@ static int adev_open(const hw_module_t* module, const char* name,
return -ENOMEM;
adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
- adev->hw_device.common.version = 0;
+ adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_1_0;
adev->hw_device.common.module = (struct hw_module_t *) module;
adev->hw_device.common.close = adev_close;
@@ -2327,28 +2958,19 @@ static int adev_open(const hw_module_t* module, const char* name,
adev->hw_device.close_input_stream = adev_close_input_stream;
adev->hw_device.dump = adev_dump;
- adev->mixer = mixer_open(0);
+ adev->mixer = mixer_open(CARD_DEFAULT);
if (!adev->mixer) {
free(adev);
- LOGE("Unable to open the mixer, aborting.");
+ ALOGE("Unable to open the mixer, aborting.");
return -EINVAL;
}
- adev->mixer_ctls.aif2dacl_source = mixer_get_ctl_by_name(adev->mixer, "AIF2DACL Source");
- adev->mixer_ctls.aif2dacr_source = mixer_get_ctl_by_name(adev->mixer, "AIF2DACR Source");
- adev->mixer_ctls.aif2_mode = mixer_get_ctl_by_name(adev->mixer, "AIF2 Mode");
- adev->mixer_ctls.dac1l_mixer_aif1_switch = mixer_get_ctl_by_name(adev->mixer, "DAC1L Mixer AIF1.1 Switch");
- adev->mixer_ctls.dac1r_mixer_aif1_switch = mixer_get_ctl_by_name(adev->mixer, "DAC1R Mixer AIF1.1 Switch");
- adev->mixer_ctls.dac1l_mixer_aif2_switch = mixer_get_ctl_by_name(adev->mixer, "DAC1L Mixer AIF2 Switch");
- adev->mixer_ctls.dac1r_mixer_aif2_switch = mixer_get_ctl_by_name(adev->mixer, "DAC1R Mixer AIF2 Switch");
- adev->mixer_ctls.aif2dac_mux = mixer_get_ctl_by_name(adev->mixer, "AIF2DAC Mux");
-
ret = adev_config_parse(adev);
if (ret != 0)
goto err_mixer;
/* Set the default route before the PCM stream is opened */
- pthread_mutex_init(&adev->lock, NULL);
+ pthread_mutex_lock(&adev->lock);
adev->mode = AUDIO_MODE_NORMAL;
adev->devices = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_IN_BUILTIN_MIC;
select_devices(adev);
@@ -2383,11 +3005,11 @@ static struct hw_module_methods_t hal_module_methods = {
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
+ .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "M0 audio HW HAL",
- .author = "The Android Open Source Project",
+ .author = "The CyanogenMod Project",
.methods = &hal_module_methods,
},
};
diff --git a/audio/audio_hw.h b/audio/audio_hw.h
index e264c4a..3cd62db 100644
--- a/audio/audio_hw.h
+++ b/audio/audio_hw.h
@@ -3,6 +3,7 @@
* Copyright (C) 2012 Wolfson Microelectronics plc
* Copyright (C) 2012 The CyanogenMod Project
* Daniel Hillenbrand <codeworkx@cyanogenmod.com>
+ * Guillaume "XpLoDWilD" Lesniak <xplodgui@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,12 +26,28 @@
#define PORT_BT 2
#define PORT_CAPTURE 3
+#define PCM_WRITE pcm_write
+
#define PLAYBACK_PERIOD_SIZE 880
#define PLAYBACK_PERIOD_COUNT 8
+#define PLAYBACK_SHORT_PERIOD_COUNT 2
#define CAPTURE_PERIOD_SIZE 1056
#define CAPTURE_PERIOD_COUNT 2
+#define SHORT_PERIOD_SIZE 192
+
+//
+// deep buffer
+//
+/* screen on */
+#define DEEP_BUFFER_SHORT_PERIOD_SIZE 1056
+#define PLAYBACK_DEEP_BUFFER_SHORT_PERIOD_COUNT 4
+/* screen off */
+#define DEEP_BUFFER_LONG_PERIOD_SIZE 880
+#define PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT 8
+
+
/* minimum sleep time in out_write() when write threshold is not reached */
#define MIN_WRITE_SLEEP_US 5000
@@ -38,6 +55,8 @@
#define RESAMPLER_BUFFER_SIZE (4 * RESAMPLER_BUFFER_FRAMES)
#define DEFAULT_OUT_SAMPLING_RATE 44100
+#define MM_LOW_POWER_SAMPLING_RATE 44100
+#define MM_FULL_POWER_SAMPLING_RATE 44100
#define DEFAULT_IN_SAMPLING_RATE 44100
/* sampling rate when using VX port for narrow band */
@@ -49,6 +68,35 @@
#define PRODUCT_DEVICE_PROPERTY "ro.product.device"
#define PRODUCT_NAME_PROPERTY "ro.product.name"
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+#define STRING_TO_ENUM(string) { #string, string }
+
+struct string_to_enum {
+ const char *name;
+ uint32_t value;
+};
+
+const struct string_to_enum out_channels_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+
+enum pcm_type {
+ PCM_NORMAL = 0,
+ PCM_SPDIF,
+ PCM_HDMI,
+ PCM_TOTAL,
+};
+
+enum output_type {
+ OUTPUT_DEEP_BUF, // deep PCM buffers output stream
+ OUTPUT_LOW_LATENCY, // low latency output stream
+ OUTPUT_HDMI,
+ OUTPUT_TOTAL
+};
+
enum tty_modes {
TTY_MODE_OFF,
TTY_MODE_VCO,
diff --git a/audio/ril_interface.c b/audio/ril_interface.c
index 4e1e2a1..89a0aef 100755
--- a/audio/ril_interface.c
+++ b/audio/ril_interface.c
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#define LOG_TAG "audio_hw_primary"
-/*#define LOG_NDEBUG 0*/
+#define ALOG_TAG "audio_hw_primary"
+/*#define ALOG_NDEBUG 0*/
#include <dlfcn.h>
#include <stdlib.h>
@@ -72,7 +72,7 @@ static int ril_connect_if_required(struct ril_handle *ril)
return 0;
if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) {
- LOGE("ril_connect() failed");
+ ALOGE("ril_connect() failed");
return -1;
}
@@ -94,7 +94,7 @@ int ril_open(struct ril_handle *ril)
ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);
if (!ril->handle) {
- LOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
+ ALOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
return -1;
}
@@ -115,14 +115,14 @@ int ril_open(struct ril_handle *ril)
!_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume ||
!_ril_set_call_audio_path || !_ril_set_call_clock_sync ||
!_ril_register_unsolicited_handler) {
- LOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
+ ALOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
dlclose(ril->handle);
return -1;
}
ril->client = _ril_open_client();
if (!ril->client) {
- LOGE("ril_open_client() failed");
+ ALOGE("ril_open_client() failed");
dlclose(ril->handle);
return -1;
}
@@ -148,7 +148,7 @@ int ril_close(struct ril_handle *ril)
if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) ||
(_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) {
- LOGE("ril_disconnect() or ril_close_client() failed");
+ ALOGE("ril_disconnect() or ril_close_client() failed");
return -1;
}