aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/Android.mk33
-rwxr-xr-xaudio/audio_hw.c3125
-rw-r--r--audio/audio_hw.h228
-rwxr-xr-xaudio/ril_interface.c193
-rwxr-xr-xaudio/ril_interface.h83
5 files changed, 0 insertions, 3662 deletions
diff --git a/audio/Android.mk b/audio/Android.mk
deleted file mode 100644
index 4655db0..0000000
--- a/audio/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := audio.primary.$(TARGET_BOOTLOADER_BOARD_NAME)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := audio_hw.c ril_interface.c
-
-LOCAL_C_INCLUDES += \
- external/tinyalsa/include \
- external/expat/lib \
- $(call include-path-for, audio-utils) \
- $(call include-path-for, audio-effects)
-
-LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libdl libexpat
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
deleted file mode 100755
index e06946a..0000000
--- a/audio/audio_hw.c
+++ /dev/null
@@ -1,3125 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "audio_hw_primary"
-#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <expat.h>
-
-#include <cutils/log.h>
-#include <cutils/str_parms.h>
-#include <cutils/properties.h>
-
-#include <hardware/hardware.h>
-#include <system/audio.h>
-#include <hardware/audio.h>
-
-#include <tinyalsa/asoundlib.h>
-#include <audio_utils/resampler.h>
-#include <audio_utils/echo_reference.h>
-#include <hardware/audio_effect.h>
-#include <audio_effects/effect_aec.h>
-
-#include "audio_hw.h"
-#include "ril_interface.h"
-
-struct pcm_config pcm_config_mm = {
- .channels = 2,
- .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,
- .period_size = CAPTURE_PERIOD_SIZE,
- .period_count = CAPTURE_PERIOD_COUNT,
- .format = PCM_FORMAT_S16_LE,
-};
-
-struct pcm_config pcm_config_vx = {
- .channels = 2,
- .rate = VX_NB_SAMPLING_RATE,
- .period_size = 160,
- .period_count = 2,
- .format = PCM_FORMAT_S16_LE,
-};
-
-#define MIN(x, y) ((x) > (y) ? (y) : (x))
-
-struct espresso_audio_device {
- struct audio_hw_device hw_device;
-
- pthread_mutex_t lock; /* see note below on mutex acquisition order */
- struct espresso_dev_cfg *dev_cfgs;
- int num_dev_cfgs;
- struct mixer *mixer;
- audio_mode_t mode;
- int active_out_device;
- int out_device;
- int active_in_device;
- int in_device;
- struct pcm *pcm_modem_dl;
- struct pcm *pcm_modem_ul;
- struct pcm *pcm_bt_dl;
- struct pcm *pcm_bt_ul;
- int in_call;
- float voice_volume;
- struct espresso_stream_in *active_input;
- struct espresso_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_off;
-
- /* RIL */
- struct ril_handle ril;
-};
-
-struct espresso_stream_out {
- struct audio_stream_out stream;
-
- pthread_mutex_t lock; /* see note below on mutex acquisition order */
- 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;
- int write_threshold;
- bool use_long_periods;
- audio_channel_mask_t channel_mask;
- audio_channel_mask_t sup_channel_masks[3];
-
- struct espresso_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 espresso_stream_in {
- struct audio_stream_in stream;
-
- pthread_mutex_t lock; /* see note below on mutex acquisition order */
- struct pcm_config config;
- struct pcm *pcm;
- int device;
- struct resampler_itfe *resampler;
- struct resampler_buffer_provider buf_provider;
- unsigned int requested_rate;
- int standby;
- int source;
- struct echo_reference_itfe *echo_reference;
- bool need_echo_reference;
-
- int16_t *read_buf;
- size_t read_buf_size;
- size_t read_buf_frames;
-
- int16_t *proc_buf_in;
- int16_t *proc_buf_out;
- size_t proc_buf_size;
- size_t proc_buf_frames;
-
- int16_t *ref_buf;
- size_t ref_buf_size;
- size_t ref_buf_frames;
-
- int read_status;
-
- int num_preprocessors;
- struct effect_info_s preprocessors[MAX_PREPROCESSORS];
-
- bool aux_channels_changed;
- uint32_t main_channels;
- uint32_t aux_channels;
- struct espresso_audio_device *dev;
-};
-
-struct espresso_dev_cfg {
- int mask;
-
- struct route_setting *on;
- unsigned int on_len;
-
- struct route_setting *off;
- unsigned int off_len;
-};
-
-/**
- * NOTE: when multiple mutexes have to be acquired, always respect the following order:
- * hw device > in stream > out stream
- */
-
-static void select_output_device(struct espresso_audio_device *adev);
-static void select_input_device(struct espresso_audio_device *adev);
-static int adev_set_voice_volume(struct audio_hw_device *dev, float volume);
-static int do_input_standby(struct espresso_stream_in *in);
-static int do_output_standby(struct espresso_stream_out *out);
-static void in_update_aux_channels(struct espresso_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 */
-static int set_bigroute_by_array(struct mixer *mixer, struct route_setting *route,
- int enable)
-{
- struct mixer_ctl *ctl;
- unsigned int i, j, ret;
-
- /* Go through the route array and set each value */
- i = 0;
- while (route[i].ctl_name) {
- ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
- if (!ctl) {
- ALOGE("Unknown control '%s'\n", route[i].ctl_name);
- return -EINVAL;
- }
-
- if (route[i].strval) {
- if (enable) {
- ret = mixer_ctl_set_enum_by_string(ctl, route[i].strval);
- if (ret != 0) {
- ALOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
- } else {
- 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) {
- ALOGE("Failed to set '%s' to '%s'\n", route[i].ctl_name, route[i].strval);
- } else {
- ALOGV("Set '%s' to '%s'\n", route[i].ctl_name, "Off");
- }
- }
- } else {
- /* This ensures multiple (i.e. stereo) values are set jointly */
- for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
- if (enable) {
- ret = mixer_ctl_set_value(ctl, j, route[i].intval);
- if (ret != 0) {
- ALOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
- } else {
- 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) {
- ALOGE("Failed to set '%s' to '%d'\n", route[i].ctl_name, route[i].intval);
- } else {
- ALOGV("Set '%s' to '%d'\n", route[i].ctl_name, 0);
- }
- }
- }
- }
- i++;
- }
-
- return 0;
-}
-
-/* The enable flag when 0 makes the assumption that enums are disabled by
- * "Off" and integers/booleans by 0 */
-static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
- unsigned int len)
-{
- struct mixer_ctl *ctl;
- unsigned int i, j, ret;
-
- /* Go through the route array and set each value */
- for (i = 0; i < len; i++) {
- ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
- if (!ctl) {
- 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) {
- ALOGE("Failed to set '%s' to '%s'\n",
- route[i].ctl_name, route[i].strval);
- } else {
- ALOGV("Set '%s' to '%s'\n",
- route[i].ctl_name, route[i].strval);
- }
-
- } else {
- /* This ensures multiple (i.e. stereo) values are set jointly */
- for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
- ret = mixer_ctl_set_value(ctl, j, route[i].intval);
- if (ret != 0) {
- ALOGE("Failed to set '%s'.%d to %d\n",
- route[i].ctl_name, j, route[i].intval);
- } else {
- ALOGV("Set '%s'.%d to %d\n",
- route[i].ctl_name, j, route[i].intval);
- }
- }
- }
- }
-
- return 0;
-}
-
-/* Must be called with lock */
-void select_devices(struct espresso_audio_device *adev)
-{
- int i;
-
- if (adev->active_out_device == adev->out_device && adev->active_in_device == adev->in_device)
- return;
-
- ALOGV("Changing output device %x => %x\n", adev->active_out_device, adev->out_device);
- ALOGV("Changing input device %x => %x\n", adev->active_in_device, adev->in_device);
-
- /* Turn on new devices first so we don't glitch due to powerdown... */
- for (i = 0; i < adev->num_dev_cfgs; i++)
- if ((adev->out_device & adev->dev_cfgs[i].mask) &&
- !(adev->active_out_device & adev->dev_cfgs[i].mask))
- set_route_by_array(adev->mixer, adev->dev_cfgs[i].on,
- adev->dev_cfgs[i].on_len);
-
- for (i = 0; i < adev->num_dev_cfgs; i++)
- if ((adev->in_device & adev->dev_cfgs[i].mask) &&
- !(adev->active_in_device & adev->dev_cfgs[i].mask))
- set_route_by_array(adev->mixer, adev->dev_cfgs[i].on,
- adev->dev_cfgs[i].on_len);
-
- /* ...then disable old ones. */
- for (i = 0; i < adev->num_dev_cfgs; i++)
- if (!(adev->out_device & adev->dev_cfgs[i].mask) &&
- (adev->active_out_device & adev->dev_cfgs[i].mask))
- set_route_by_array(adev->mixer, adev->dev_cfgs[i].off,
- adev->dev_cfgs[i].off_len);
-
- for (i = 0; i < adev->num_dev_cfgs; i++)
- if (!(adev->in_device & adev->dev_cfgs[i].mask) &&
- (adev->active_in_device & adev->dev_cfgs[i].mask))
- set_route_by_array(adev->mixer, adev->dev_cfgs[i].off,
- adev->dev_cfgs[i].off_len);
-
- adev->active_out_device = adev->out_device;
- adev->active_in_device = adev->in_device;
-}
-
-static int start_call(struct espresso_audio_device *adev)
-{
- ALOGV("Opening modem PCMs");
- int bt_on;
-
- bt_on = adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO;
- pcm_config_vx.rate = adev->wb_amr ? VX_WB_SAMPLING_RATE : VX_NB_SAMPLING_RATE;
-
- /* Open modem PCM channels */
- if (adev->pcm_modem_dl == NULL) {
- ALOGD("Opening PCM modem DL stream");
- adev->pcm_modem_dl = pcm_open(CARD_DEFAULT, PORT_MODEM, PCM_OUT, &pcm_config_vx);
- if (!pcm_is_ready(adev->pcm_modem_dl)) {
- ALOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
- goto err_open_dl;
- }
- }
-
- if (adev->pcm_modem_ul == NULL) {
- ALOGD("Opening PCM modem UL stream");
- adev->pcm_modem_ul = pcm_open(CARD_DEFAULT, PORT_MODEM, PCM_IN, &pcm_config_vx);
- if (!pcm_is_ready(adev->pcm_modem_ul)) {
- ALOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
- goto err_open_ul;
- }
- }
-
- ALOGD("Starting PCM modem streams");
- pcm_start(adev->pcm_modem_dl);
- pcm_start(adev->pcm_modem_ul);
-
- /* Open bluetooth PCM channels */
- if (bt_on) {
- ALOGV("Opening bluetooth PCMs");
-
- if (adev->pcm_bt_dl == NULL) {
- ALOGD("Opening PCM bluetooth DL stream");
- adev->pcm_bt_dl = pcm_open(CARD_DEFAULT, PORT_BT, PCM_OUT, &pcm_config_vx);
- if (!pcm_is_ready(adev->pcm_bt_dl)) {
- ALOGE("cannot open PCM bluetooth DL stream: %s", pcm_get_error(adev->pcm_bt_dl));
- goto err_open_dl;
- }
- }
-
- if (adev->pcm_bt_ul == NULL) {
- ALOGD("Opening PCM bluetooth UL stream");
- adev->pcm_bt_ul = pcm_open(CARD_DEFAULT, PORT_BT, PCM_IN, &pcm_config_vx);
- if (!pcm_is_ready(adev->pcm_bt_ul)) {
- ALOGE("cannot open PCM bluetooth UL stream: %s", pcm_get_error(adev->pcm_bt_ul));
- goto err_open_ul;
- }
- }
- ALOGD("Starting PCM bluetooth streams");
- pcm_start(adev->pcm_bt_dl);
- pcm_start(adev->pcm_bt_ul);
- }
-
- return 0;
-
-err_open_ul:
- pcm_close(adev->pcm_modem_ul);
- adev->pcm_modem_ul = NULL;
- pcm_close(adev->pcm_bt_ul);
- adev->pcm_bt_ul = NULL;
-err_open_dl:
- pcm_close(adev->pcm_modem_dl);
- adev->pcm_modem_dl = NULL;
- pcm_close(adev->pcm_bt_dl);
- adev->pcm_bt_dl = NULL;
-
- return -ENOMEM;
-}
-
-static void end_call(struct espresso_audio_device *adev)
-{
- int bt_on;
- bt_on = adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO;
-
- if (adev->pcm_modem_dl != NULL) {
- ALOGD("Stopping modem DL PCM");
- pcm_stop(adev->pcm_modem_dl);
- ALOGV("Closing modem DL PCM");
- pcm_close(adev->pcm_modem_dl);
- }
- if (adev->pcm_modem_ul != NULL) {
- ALOGD("Stopping modem UL PCM");
- pcm_stop(adev->pcm_modem_ul);
- ALOGV("Closing modem UL PCM");
- pcm_close(adev->pcm_modem_ul);
- }
- adev->pcm_modem_dl = NULL;
- adev->pcm_modem_ul = NULL;
-
- if (bt_on) {
- if (adev->pcm_bt_dl != NULL) {
- ALOGD("Stopping bluetooth DL PCM");
- pcm_stop(adev->pcm_bt_dl);
- ALOGV("Closing bluetooth DL PCM");
- pcm_close(adev->pcm_bt_dl);
- }
- if (adev->pcm_bt_ul != NULL) {
- ALOGD("Stopping bluetooth UL PCM");
- pcm_stop(adev->pcm_bt_ul);
- ALOGV("Closing bluetooth UL PCM");
- pcm_close(adev->pcm_bt_ul);
- }
- }
- adev->pcm_bt_dl = NULL;
- adev->pcm_bt_ul = NULL;
-}
-
-static void set_eq_filter(struct espresso_audio_device *adev)
-{
-}
-
-void audio_set_wb_amr_callback(void *data, int enable)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)data;
-
- pthread_mutex_lock(&adev->lock);
- if (adev->wb_amr != enable) {
- adev->wb_amr = enable;
-
- /* reopen the modem PCMs at the new rate */
- if (adev->in_call) {
- end_call(adev);
- select_output_device(adev);
- start_call(adev);
- }
- }
- pthread_mutex_unlock(&adev->lock);
-}
-
-static void set_incall_device(struct espresso_audio_device *adev)
-{
- int device_type;
-
- switch(adev->out_device) {
- case AUDIO_DEVICE_OUT_EARPIECE:
- device_type = SOUND_AUDIO_PATH_HANDSET;
- break;
- case AUDIO_DEVICE_OUT_SPEAKER:
- case AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
- case AUDIO_DEVICE_OUT_AUX_DIGITAL:
- case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
- device_type = SOUND_AUDIO_PATH_SPEAKER;
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- device_type = SOUND_AUDIO_PATH_HEADSET;
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- device_type = SOUND_AUDIO_PATH_HEADPHONE;
- break;
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
- if (adev->bluetooth_nrec) {
- device_type = SOUND_AUDIO_PATH_BLUETOOTH;
- } else {
- device_type = SOUND_AUDIO_PATH_BLUETOOTH_NO_NR;
- }
- break;
- default:
- device_type = SOUND_AUDIO_PATH_SPEAKER;
- break;
- }
-
- /* if output device isn't supported, open modem side to handset by default */
- ALOGE("%s: ril_set_call_audio_path(%d)", __func__, device_type);
- ril_set_call_audio_path(&adev->ril, device_type);
-}
-
-static void set_input_volumes(struct espresso_audio_device *adev, int main_mic_on,
- int headset_mic_on, int sub_mic_on)
-{
-}
-
-static void set_output_volumes(struct espresso_audio_device *adev, bool tty_volume)
-{
-}
-
-static void force_all_standby(struct espresso_audio_device *adev)
-{
- struct espresso_stream_in *in;
- struct espresso_stream_out *out;
-
- /* 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);
- }
-
- if (adev->active_input) {
- in = adev->active_input;
- pthread_mutex_lock(&in->lock);
- do_input_standby(in);
- pthread_mutex_unlock(&in->lock);
- }
-}
-
-static void select_mode(struct espresso_audio_device *adev)
-{
- if (adev->mode == AUDIO_MODE_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
- only currently selected route. This prevents having to tear
- down the modem PCMs to change route from speaker to earpiece
- after the ringtone is played, but doesn't cause a route
- change if a headset or bt device is already connected. If
- speaker is not the only thing active, just remove it from
- the route. We'll assume it'll never be used initally during
- a call. This works because we're sure that the audio policy
- manager will update the output device after the audio mode
- change, even if the device selection did not change. */
- if (adev->out_device == AUDIO_DEVICE_OUT_SPEAKER) {
- adev->out_device = AUDIO_DEVICE_OUT_EARPIECE;
- adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
- } else
- adev->out_device &= ~AUDIO_DEVICE_OUT_SPEAKER;
- select_output_device(adev);
- start_call(adev);
- ril_set_call_clock_sync(&adev->ril, SOUND_CLOCK_START);
- adev_set_voice_volume(&adev->hw_device, adev->voice_volume);
- adev->in_call = 1;
- }
- } else {
- ALOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
- adev->in_call, adev->mode);
- if (adev->in_call) {
- adev->in_call = 0;
- end_call(adev);
- force_all_standby(adev);
- select_output_device(adev);
- select_input_device(adev);
- }
- }
-}
-
-static void select_output_device(struct espresso_audio_device *adev)
-{
- int headset_on;
- int headphone_on;
- int speaker_on;
- int earpiece_on;
- int bt_on;
- bool tty_volume = false;
- unsigned int channel;
-
- headset_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET;
- headphone_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
- speaker_on = adev->out_device & AUDIO_DEVICE_OUT_SPEAKER;
- earpiece_on = adev->out_device & AUDIO_DEVICE_OUT_EARPIECE;
- bt_on = adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO;
-
- switch(adev->out_device) {
- case AUDIO_DEVICE_OUT_SPEAKER:
- ALOGD("%s: AUDIO_DEVICE_OUT_SPEAKER", __func__);
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- ALOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADSET", __func__);
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- ALOGD("%s: AUDIO_DEVICE_OUT_WIRED_HEADPHONE", __func__);
- break;
- case AUDIO_DEVICE_OUT_EARPIECE:
- ALOGD("%s: AUDIO_DEVICE_OUT_EARPIECE", __func__);
- break;
- case AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
- ALOGD("%s: AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET", __func__);
- break;
- case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
- ALOGD("%s: AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", __func__);
- break;
- case AUDIO_DEVICE_OUT_AUX_DIGITAL:
- ALOGD("%s: AUDIO_DEVICE_OUT_AUX_DIGITAL", __func__);
- break;
- case AUDIO_DEVICE_OUT_ALL_SCO:
- ALOGD("%s: AUDIO_DEVICE_OUT_ALL_SCO", __func__);
- break;
- case AUDIO_DEVICE_OUT_USB_ACCESSORY:
- ALOGD("%s: AUDIO_DEVICE_OUT_USB_ACCESSORY", __func__);
- break;
- case AUDIO_DEVICE_OUT_USB_DEVICE:
- ALOGD("%s: AUDIO_DEVICE_OUT_USB_DEVICE", __func__);
- break;
- default:
- 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 */
- switch(adev->tty_mode) {
- case TTY_MODE_FULL:
- case TTY_MODE_HCO:
- /* tx path from headset mic */
- headphone_on = 0;
- headset_on = 1;
- speaker_on = 0;
- earpiece_on = 0;
- break;
- case TTY_MODE_VCO:
- /* tx path from device sub mic */
- headphone_on = 0;
- headset_on = 0;
- speaker_on = 1;
- earpiece_on = 0;
- break;
- case TTY_MODE_OFF:
- default:
- break;
- }
- }
-
- if (headset_on || headphone_on || speaker_on || earpiece_on) {
- ALOGD("%s: set voicecall route: voicecall_default", __func__);
- set_bigroute_by_array(adev->mixer, voicecall_default, 1);
- } else {
- ALOGD("%s: set voicecall route: voicecall_default_disable", __func__);
- set_bigroute_by_array(adev->mixer, voicecall_default_disable, 1);
- }
-
- if (speaker_on || earpiece_on || headphone_on) {
- ALOGD("%s: set voicecall route: default_input", __func__);
- set_bigroute_by_array(adev->mixer, default_input, 1);
- } else {
- ALOGD("%s: set voicecall route: default_input_disable", __func__);
- set_bigroute_by_array(adev->mixer, default_input_disable, 1);
- }
-
- if (headset_on) {
- ALOGD("%s: set voicecall route: headset_input", __func__);
- set_bigroute_by_array(adev->mixer, headset_input, 1);
- } else {
- ALOGD("%s: set voicecall route: headset_input_disable", __func__);
- set_bigroute_by_array(adev->mixer, headset_input_disable, 1);
- }
-
- if (bt_on) {
- // bt uses a different port (PORT_BT) for playback, reopen the pcms
- end_call(adev);
- start_call(adev);
- ALOGD("%s: set voicecall route: bt_input", __func__);
- set_bigroute_by_array(adev->mixer, bt_input, 1);
- ALOGD("%s: set voicecall route: bt_output", __func__);
- set_bigroute_by_array(adev->mixer, bt_output, 1);
- } else {
- ALOGD("%s: set voicecall route: bt_input_disable", __func__);
- set_bigroute_by_array(adev->mixer, bt_input_disable, 1);
- ALOGD("%s: set voicecall route: bt_output_disable", __func__);
- set_bigroute_by_array(adev->mixer, bt_output_disable, 1);
- }
- set_incall_device(adev);
- }
-}
-
-static void select_input_device(struct espresso_audio_device *adev)
-{
- switch(adev->in_device) {
- case AUDIO_DEVICE_IN_BUILTIN_MIC:
- ALOGD("%s: AUDIO_DEVICE_IN_BUILTIN_MIC", __func__);
- break;
- case AUDIO_DEVICE_IN_WIRED_HEADSET:
- ALOGD("%s: AUDIO_DEVICE_IN_WIRED_HEADSET", __func__);
- break;
- case AUDIO_DEVICE_IN_ALL_SCO:
- ALOGD("%s: AUDIO_DEVICE_IN_ALL_SCO", __func__);
- break;
- default:
- ALOGD("%s: AUDIO_DEVICE_IN_DEFAULT", __func__);
- break;
- }
-
- select_devices(adev);
-}
-
-/* must be called with hw device and output stream mutexes locked */
-static int start_output_stream_low_latency(struct espresso_stream_out *out)
-{
- struct espresso_audio_device *adev = out->dev;
- unsigned int flags = PCM_OUT;
- int i;
- bool success = true;
-
- if (adev->mode != AUDIO_MODE_IN_CALL) {
- select_output_device(adev);
- }
-
- /* default to low power: will be corrected in out_write if necessary before first write to
- * tinyalsa.
- */
-
- if (adev->out_device & ~(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->out_device & 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);
-
- return 0;
- }
-
- return -ENOMEM;
-}
-
-/* must be called with hw device and output stream mutexes locked */
-static int start_output_stream_deep_buffer(struct espresso_stream_out *out)
-{
- struct espresso_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;
-
- if ((channel_count < 1) || (channel_count > 2))
- return -EINVAL;
-
- switch(sample_rate) {
- case 8000:
- case 11025:
- case 16000:
- case 22050:
- case 24000:
- case 32000:
- case 44100:
- case 48000:
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-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;
-
- if (check_input_parameters(sample_rate, format, channel_count) != 0)
- return 0;
-
- /* 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 */
- size = (pcm_config_capture.period_size * sample_rate) / pcm_config_capture.rate;
- size = ((size + 15) / 16) * 16;
-
- return size * channel_count * sizeof(short);
-}
-
-static void add_echo_reference(struct espresso_stream_out *out,
- struct echo_reference_itfe *reference)
-{
- pthread_mutex_lock(&out->lock);
- out->echo_reference = reference;
- pthread_mutex_unlock(&out->lock);
-}
-
-static void remove_echo_reference(struct espresso_stream_out *out,
- struct echo_reference_itfe *reference)
-{
- pthread_mutex_lock(&out->lock);
- if (out->echo_reference == reference) {
- /* stop writing to echo reference */
- reference->write(reference, NULL);
- out->echo_reference = NULL;
- }
- pthread_mutex_unlock(&out->lock);
-}
-
-static void put_echo_reference(struct espresso_audio_device *adev,
- struct echo_reference_itfe *reference)
-{
- if (adev->echo_reference != NULL &&
- reference == adev->echo_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;
- }
-}
-
-static struct echo_reference_itfe *get_echo_reference(struct espresso_audio_device *adev,
- audio_format_t format,
- uint32_t channel_count,
- uint32_t sampling_rate)
-{
- put_echo_reference(adev, adev->echo_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) {
- 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);
-
- int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
- channel_count,
- sampling_rate,
- AUDIO_FORMAT_PCM_16_BIT,
- wr_channel_count,
- wr_sampling_rate,
- &adev->echo_reference);
- if (status == 0)
- add_echo_reference(adev->outputs[OUTPUT_LOW_LATENCY],
- adev->echo_reference);
- }
- return adev->echo_reference;
-}
-
-static int get_playback_delay(struct espresso_stream_out *out,
- size_t frames,
- struct echo_reference_buffer *buffer)
-{
- 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[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;
- ALOGV("%s: pcm_get_htimestamp error,"
- "setting playbackTimestamp to 0", __func__);
- return status;
- }
-
- 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)/
- MM_FULL_POWER_SAMPLING_RATE);
-
- return 0;
-}
-
-static uint32_t out_get_sample_rate(const struct audio_stream *stream)
-{
- return DEFAULT_OUT_SAMPLING_RATE;
-}
-
-static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
-{
- return 0;
-}
-
-static size_t out_get_buffer_size_low_latency(const struct audio_stream *stream)
-{
- struct espresso_stream_out *out = (struct espresso_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_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 espresso_stream_out *out = (struct espresso_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 audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
-{
- struct espresso_stream_out *out = (struct espresso_stream_out *)stream;
-
- return out->channel_mask;
-}
-
-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, audio_format_t format)
-{
- return 0;
-}
-
-/* must be called with hw device and output stream mutexes locked */
-static int do_output_standby(struct espresso_stream_out *out)
-{
- struct espresso_audio_device *adev = out->dev;
- int i;
- bool all_outputs_in_standby = true;
-
- if (!out->standby) {
- out->standby = 1;
-
- for (i = 0; i < PCM_TOTAL; i++) {
- if (out->pcm[i]) {
- pcm_close(out->pcm[i]);
- out->pcm[i] = NULL;
- }
- }
-
- 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 espresso_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;
- }
- }
- return 0;
-}
-
-static int out_standby(struct audio_stream *stream)
-{
- struct espresso_stream_out *out = (struct espresso_stream_out *)stream;
- int status;
-
- pthread_mutex_lock(&out->dev->lock);
- pthread_mutex_lock(&out->lock);
- status = do_output_standby(out);
- pthread_mutex_unlock(&out->lock);
- pthread_mutex_unlock(&out->dev->lock);
- return status;
-}
-
-static int out_dump(const struct audio_stream *stream, int fd)
-{
- return 0;
-}
-
-static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
-{
- struct espresso_stream_out *out = (struct espresso_stream_out *)stream;
- struct espresso_audio_device *adev = out->dev;
- struct espresso_stream_in *in;
- struct str_parms *parms;
- char *str;
- char value[32];
- int ret, val = 0;
- bool force_input_standby = false;
-
- parms = str_parms_create_str(kvpairs);
-
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
- if (ret >= 0) {
- val = atoi(value);
- pthread_mutex_lock(&adev->lock);
- pthread_mutex_lock(&out->lock);
- if (((adev->out_device) != val) && (val != 0)) {
- /* 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->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
- ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
- (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
- (adev->out_device & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)))
- */
- if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
- (adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
- ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
- (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
- (adev->out_device & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
- ((val & AUDIO_DEVICE_OUT_SPEAKER) ^
- (adev->out_device & AUDIO_DEVICE_OUT_SPEAKER)) ||
- (adev->mode == AUDIO_MODE_IN_CALL))
- do_output_standby(out);
- }
- if (out != adev->outputs[OUTPUT_HDMI]) {
- adev->out_device = val;
- select_output_device(adev);
- }
- }
- pthread_mutex_unlock(&out->lock);
- if (force_input_standby) {
- in = adev->active_input;
- pthread_mutex_lock(&in->lock);
- do_input_standby(in);
- pthread_mutex_unlock(&in->lock);
- }
- pthread_mutex_unlock(&adev->lock);
- }
-
- str_parms_destroy(parms);
- return ret;
-}
-
-static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
-{
- struct espresso_stream_out *out = (struct espresso_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 espresso_stream_out *out = (struct espresso_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_deep_buffer(const struct audio_stream_out *stream)
-{
- struct espresso_stream_out *out = (struct espresso_stream_out *)stream;
-
- /* 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,
- float right)
-{
- return -ENOSYS;
-}
-
-static ssize_t out_write_low_latency(struct audio_stream_out *stream, const void* buffer,
- size_t bytes)
-{
- int ret;
- struct espresso_stream_out *out = (struct espresso_stream_out *)stream;
- struct espresso_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 = in_frames;
- bool force_input_standby = false;
- struct espresso_stream_in *in;
- int i;
-
- /* 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_low_latency(out);
- if (ret != 0) {
- pthread_mutex_unlock(&adev->lock);
- goto exit;
- }
- out->standby = 0;
- /* 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;
- }
- 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 espresso_stream_out *out = (struct espresso_stream_out *)stream;
- struct espresso_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);
-
- if (use_long_periods != out->use_long_periods) {
- size_t period_size;
- size_t period_count;
-
- 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 (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);
- buf = (void *)out->buffer;
- } else {
- out_frames = in_frames;
- 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[PCM_NORMAL],
- (unsigned int *)&kernel_frames, &time_stamp) < 0)
- break;
- 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) /
- MM_FULL_POWER_SAMPLING_RATE);
- if (time < MIN_WRITE_SLEEP_US)
- time = MIN_WRITE_SLEEP_US;
- usleep(time);
- }
- } while (kernel_frames > out->write_threshold);
-
- ret = pcm_mmap_write(out->pcm[PCM_NORMAL], buf, out_frames * frame_size);
-
-exit:
- pthread_mutex_unlock(&out->lock);
-
- if (ret != 0) {
- usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
- out_get_sample_rate(&stream->common));
- }
-
- return bytes;
-}
-
-static int out_get_render_position(const struct audio_stream_out *stream,
- uint32_t *dsp_frames)
-{
- return -EINVAL;
-}
-
-static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
- return 0;
-}
-
-static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
- return 0;
-}
-
-/** audio_stream_in implementation **/
-
-/* must be called with hw device and input stream mutexes locked */
-static int start_input_stream(struct espresso_stream_in *in)
-{
- int ret = 0;
- struct espresso_audio_device *adev = in->dev;
-
- adev->active_input = in;
-
- if (adev->mode != AUDIO_MODE_IN_CALL) {
- adev->in_device = in->device;
- select_input_device(adev);
- }
-
- 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)
- in->echo_reference = get_echo_reference(adev,
- AUDIO_FORMAT_PCM_16_BIT,
- popcount(in->main_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)) {
- ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
- pcm_close(in->pcm);
- adev->active_input = NULL;
- return -ENOMEM;
- }
-
- /* force read and proc buf reallocation case of frame size or channel count change */
- in->read_buf_frames = 0;
- in->read_buf_size = 0;
- in->proc_buf_frames = 0;
- in->proc_buf_size = 0;
- /* if no supported sample rate is available, use the resampler */
- if (in->resampler) {
- in->resampler->reset(in->resampler);
- }
- return 0;
-}
-
-static uint32_t in_get_sample_rate(const struct audio_stream *stream)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
-
- return in->requested_rate;
-}
-
-static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
-{
- return 0;
-}
-
-static size_t in_get_buffer_size(const struct audio_stream *stream)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
-
- return get_input_buffer_size(in->requested_rate,
- AUDIO_FORMAT_PCM_16_BIT,
- popcount(in->main_channels));
-}
-
-static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
-
- return AUDIO_CHANNEL_IN_STEREO;
-}
-
-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, audio_format_t format)
-{
- return 0;
-}
-
-/* must be called with hw device and input stream mutexes locked */
-static int do_input_standby(struct espresso_stream_in *in)
-{
- struct espresso_audio_device *adev = in->dev;
-
- if (!in->standby) {
- pcm_close(in->pcm);
- in->pcm = NULL;
-
- adev->active_input = 0;
- if (adev->mode != AUDIO_MODE_IN_CALL) {
- adev->in_device = AUDIO_DEVICE_NONE;
- select_input_device(adev);
- }
-
- if (in->echo_reference != NULL) {
- /* stop reading from echo reference */
- in->echo_reference->read(in->echo_reference, NULL);
- put_echo_reference(adev, in->echo_reference);
- in->echo_reference = NULL;
- }
-
- in->standby = 1;
- }
- return 0;
-}
-
-static int in_standby(struct audio_stream *stream)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- int status;
-
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
- status = do_input_standby(in);
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&in->dev->lock);
- return status;
-}
-
-static int in_dump(const struct audio_stream *stream, int fd)
-{
- return 0;
-}
-
-static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- struct espresso_audio_device *adev = in->dev;
- struct str_parms *parms;
- char *str;
- char value[32];
- int ret, val = 0;
- bool do_standby = false;
-
- parms = str_parms_create_str(kvpairs);
-
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
-
- pthread_mutex_lock(&adev->lock);
- pthread_mutex_lock(&in->lock);
- if (ret >= 0) {
- val = atoi(value);
- /* no audio source uses val == 0 */
- if ((in->source != val) && (val != 0)) {
- in->source = val;
- do_standby = true;
- }
- }
-
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
- if (ret >= 0) {
- val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
- 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);
- }
- }
-
- if (do_standby)
- do_input_standby(in);
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&adev->lock);
-
- str_parms_destroy(parms);
- return ret;
-}
-
-static char * in_get_parameters(const struct audio_stream *stream,
- const char *keys)
-{
- return strdup("");
-}
-
-static int in_set_gain(struct audio_stream_in *stream, float gain)
-{
- return 0;
-}
-
-static void get_capture_delay(struct espresso_stream_in *in,
- size_t frames,
- struct echo_reference_buffer *buffer)
-{
-
- /* read frames available in kernel driver buffer */
- size_t kernel_frames;
- struct timespec tstamp;
- long buf_delay;
- long rsmp_delay;
- long kernel_delay;
- long delay_ns;
-
- if (pcm_get_htimestamp(in->pcm, &kernel_frames, &tstamp) < 0) {
- buffer->time_stamp.tv_sec = 0;
- buffer->time_stamp.tv_nsec = 0;
- buffer->delay_ns = 0;
- ALOGW("%s: pcm_htimestamp error", __func__);
- return;
- }
-
- /* read frames available in audio HAL input buffer
- * add number of frames being read as we want the capture time of first sample
- * in current buffer */
- /* frames in in->buffer are at driver sampling rate while frames in in->proc_buf are
- * at requested sampling rate */
- buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
- ((int64_t)(in->proc_buf_frames) * 1000000000) /
- in->requested_rate);
-
- /* add delay introduced by resampler */
- rsmp_delay = 0;
- if (in->resampler) {
- rsmp_delay = in->resampler->delay_ns(in->resampler);
- }
-
- kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
-
- delay_ns = kernel_delay + buf_delay + rsmp_delay;
-
- buffer->time_stamp = tstamp;
- buffer->delay_ns = delay_ns;
- 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,
- kernel_delay, buf_delay, rsmp_delay, kernel_frames,
- in->read_buf_frames, in->proc_buf_frames, frames);
-
-}
-
-static int32_t update_echo_reference(struct espresso_stream_in *in, size_t frames)
-{
- struct echo_reference_buffer b;
- b.delay_ns = 0;
-
- 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);
-
- get_capture_delay(in, frames, &b);
-
- if (in->echo_reference->read(in->echo_reference, &b) == 0)
- {
- in->ref_buf_frames += b.frame_count;
- 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
- ALOGW("%s: NOT enough frames to read ref buffer", __func__);
- return b.delay_ns;
-}
-
-static int set_preprocessor_param(effect_handle_t handle,
- effect_param_t *param)
-{
- uint32_t size = sizeof(int);
- uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
- param->vsize;
-
- int status = (*handle)->command(handle,
- EFFECT_CMD_SET_PARAM,
- sizeof (effect_param_t) + psize,
- param,
- &size,
- &param->status);
- if (status == 0)
- status = param->status;
-
- return status;
-}
-
-static int set_preprocessor_echo_delay(effect_handle_t handle,
- int32_t delay_us)
-{
- uint32_t buf[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
- effect_param_t *param = (effect_param_t *)buf;
-
- param->psize = sizeof(uint32_t);
- param->vsize = sizeof(uint32_t);
- *(uint32_t *)param->data = AEC_PARAM_ECHO_DELAY;
- *((int32_t *)param->data + 1) = delay_us;
-
- return set_preprocessor_param(handle, param);
-}
-
-static void push_echo_reference(struct espresso_stream_in *in, size_t frames)
-{
- /* read frames from echo reference buffer and update echo delay
- * in->ref_buf_frames is updated with frames available in in->ref_buf */
- int32_t delay_us = update_echo_reference(in, frames)/1000;
- int i;
- audio_buffer_t buf;
-
- if (in->ref_buf_frames < frames)
- frames = in->ref_buf_frames;
-
- buf.frameCount = frames;
- buf.raw = in->ref_buf;
-
- for (i = 0; i < in->num_preprocessors; i++) {
- if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
- continue;
-
- (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
- &buf,
- NULL);
- set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
- }
-
- in->ref_buf_frames -= buf.frameCount;
- if (in->ref_buf_frames) {
- memcpy(in->ref_buf,
- in->ref_buf + buf.frameCount * in->config.channels,
- in->ref_buf_frames * in->config.channels * sizeof(int16_t));
- }
-}
-
-static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
- struct resampler_buffer* buffer)
-{
- struct espresso_stream_in *in;
-
- if (buffer_provider == NULL || buffer == NULL)
- return -EINVAL;
-
- in = (struct espresso_stream_in *)((char *)buffer_provider -
- offsetof(struct espresso_stream_in, buf_provider));
-
- if (in->pcm == NULL) {
- buffer->raw = NULL;
- buffer->frame_count = 0;
- in->read_status = -ENODEV;
- return -ENODEV;
- }
-
- if (in->read_buf_frames == 0) {
- size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, in->config.period_size);
- 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);
- 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) {
- ALOGE("%s: pcm_read error %d", __func__, in->read_status);
- buffer->raw = NULL;
- buffer->frame_count = 0;
- return in->read_status;
- }
- in->read_buf_frames = in->config.period_size;
- }
-
- buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
- in->read_buf_frames : buffer->frame_count;
- buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
- in->config.channels;
-
- return in->read_status;
-
-}
-
-static void release_buffer(struct resampler_buffer_provider *buffer_provider,
- struct resampler_buffer* buffer)
-{
- struct espresso_stream_in *in;
-
- if (buffer_provider == NULL || buffer == NULL)
- return;
-
- in = (struct espresso_stream_in *)((char *)buffer_provider -
- offsetof(struct espresso_stream_in, buf_provider));
-
- in->read_buf_frames -= buffer->frame_count;
-}
-
-/* read_frames() reads frames from kernel driver, down samples to capture rate
- * if necessary and output the number of frames requested to the buffer specified */
-static ssize_t read_frames(struct espresso_stream_in *in, void *buffer, ssize_t frames)
-{
- ssize_t frames_wr = 0;
-
- while (frames_wr < frames) {
- size_t frames_rd = frames - frames_wr;
- if (in->resampler != NULL) {
- in->resampler->resample_from_provider(in->resampler,
- (int16_t *)((char *)buffer +
- pcm_frames_to_bytes(in->pcm ,frames_wr)),
- &frames_rd);
-
- } else {
- struct resampler_buffer buf = {
- { raw : NULL, },
- frame_count : frames_rd,
- };
- get_next_buffer(&in->buf_provider, &buf);
- if (buf.raw != NULL) {
- memcpy((char *)buffer +
- pcm_frames_to_bytes(in->pcm, frames_wr),
- buf.raw,
- pcm_frames_to_bytes(in->pcm, buf.frame_count));
- frames_rd = buf.frame_count;
- }
- release_buffer(&in->buf_provider, &buf);
- }
- /* in->read_status is updated by getNextBuffer() also called by
- * in->resampler->resample_from_provider() */
- if (in->read_status != 0)
- return in->read_status;
-
- frames_wr += frames_rd;
- }
- return frames_wr;
-}
-
-/* process_frames() reads frames from kernel driver (via read_frames()),
- * calls the active audio pre processings and output the number of frames requested
- * to the buffer specified */
-static ssize_t process_frames(struct espresso_stream_in *in, void* buffer, ssize_t frames)
-{
- ssize_t frames_wr = 0;
- 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) {
- ssize_t frames_rd;
-
- if (in->proc_buf_size < (size_t)frames) {
- size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, frames);
-
- in->proc_buf_size = (size_t)frames;
- in->proc_buf_in = (int16_t *)realloc(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 +
- in->proc_buf_frames * in->config.channels,
- frames - in->proc_buf_frames);
- if (frames_rd < 0) {
- frames_wr = frames_rd;
- break;
- }
- in->proc_buf_frames += frames_rd;
- }
-
- if (in->echo_reference != NULL)
- push_echo_reference(in, in->proc_buf_frames);
-
- /* in_buf.frameCount and out_buf.frameCount indicate respectively
- * the maximum number of frames to be consumed and produced by process() */
- 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 *)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
- * move remaining frames to the beginning of in->proc_buf_in */
- in->proc_buf_frames -= in_buf.frameCount;
-
- if (in->proc_buf_frames) {
- memcpy(in->proc_buf_in,
- in->proc_buf_in + in_buf.frameCount * in->config.channels,
- in->proc_buf_frames * in->config.channels * sizeof(int16_t));
- }
-
- /* if not enough frames were passed to process(), read more and retry. */
- 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! */
- 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;
-}
-
-static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
- size_t bytes)
-{
- int ret = 0;
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- struct espresso_audio_device *adev = in->dev;
- size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
-
- /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
- * on the input stream mutex - e.g. executing select_mode() while holding the hw device
- * mutex
- */
- pthread_mutex_lock(&adev->lock);
- pthread_mutex_lock(&in->lock);
- if (in->standby) {
- ret = start_input_stream(in);
- if (ret == 0)
- in->standby = 0;
- }
- pthread_mutex_unlock(&adev->lock);
-
- if (ret < 0)
- goto exit;
-
- if (in->num_preprocessors != 0)
- ret = process_frames(in, buffer, frames_rq);
- else if (in->resampler != NULL)
- ret = read_frames(in, buffer, frames_rq);
- else
- ret = pcm_read(in->pcm, buffer, bytes);
-
- if (ret > 0)
- ret = 0;
-
- if (ret == 0 && adev->mic_mute)
- memset(buffer, 0, bytes);
-
-exit:
- if (ret < 0)
- usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
- in_get_sample_rate(&stream->common));
-
- pthread_mutex_unlock(&in->lock);
- return bytes;
-}
-
-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 espresso_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 espresso_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 espresso_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 espresso_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 espresso_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)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- int status;
- effect_descriptor_t desc;
-
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
- if (in->num_preprocessors >= MAX_PREPROCESSORS) {
- status = -ENOSYS;
- goto exit;
- }
-
- status = (*effect)->get_descriptor(effect, &desc);
- if (status != 0)
- goto exit;
-
- 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;
-}
-
-static int in_remove_audio_effect(const struct audio_stream *stream,
- effect_handle_t effect)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- int i;
- int status = -EINVAL;
- effect_descriptor_t desc;
-
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
- if (in->num_preprocessors <= 0) {
- status = -ENOSYS;
- goto exit;
- }
-
- for (i = 0; i < in->num_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_itfe == effect) {
- ALOGI("in_remove_audio_effect found fx at index %d", i);
- free(in->preprocessors[i].channel_configs);
- status = 0;
- }
- }
-
- if (status != 0)
- 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;
-
- 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 = false;
- do_input_standby(in);
- }
-
-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,
- 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 espresso_audio_device *ladev = (struct espresso_audio_device *)dev;
- struct espresso_stream_out *out;
- int ret;
- int output_type;
-
- *stream_out = NULL;
-
- out = (struct espresso_stream_out *)calloc(1, sizeof(struct espresso_stream_out));
- if (!out) {
- ALOGE("%s: out of memory!", __func__);
- 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;
- ALOGW("%s: output not available!", __func__);
- 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,
- MM_FULL_POWER_SAMPLING_RATE,
- 2,
- RESAMPLER_QUALITY_DEFAULT,
- NULL,
- &out->resampler);
- if (ret != 0) {
- ALOGE("%s: error on resampler create!", __func__);
- goto err_open;
- }
-
- out->stream.common.set_sample_rate = out_set_sample_rate;
- out->stream.common.get_channels = out_get_channels;
- out->stream.common.get_format = out_get_format;
- out->stream.common.set_format = out_set_format;
- out->stream.common.standby = out_standby;
- out->stream.common.dump = out_dump;
- out->stream.common.set_parameters = out_set_parameters;
- 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.set_volume = out_set_volume;
- out->stream.get_render_position = out_get_render_position;
-
- out->dev = ladev;
- out->standby = 1;
-
- /* FIXME: when we support multiple output devices, we will want to
- * do the following:
- * adev->out_device = out->device;
- * 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. */
-
- 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:
- ALOGE("%s: error opening output stream", __func__);
- free(out);
- return ret;
-}
-
-static void adev_close_output_stream(struct audio_hw_device *dev,
- struct audio_stream_out *stream)
-{
- struct espresso_audio_device *ladev = (struct espresso_audio_device *)dev;
- struct espresso_stream_out *out = (struct espresso_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)
- release_resampler(out->resampler);
- free(stream);
-}
-
-static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)dev;
- struct str_parms *parms;
- char *str;
- char value[32];
- int ret;
-
- parms = str_parms_create_str(kvpairs);
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
- if (ret >= 0) {
- int tty_mode;
-
- if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
- tty_mode = TTY_MODE_OFF;
- else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
- tty_mode = TTY_MODE_VCO;
- else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
- tty_mode = TTY_MODE_HCO;
- else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
- tty_mode = TTY_MODE_FULL;
- else
- return -EINVAL;
-
- pthread_mutex_lock(&adev->lock);
- if (tty_mode != adev->tty_mode) {
- adev->tty_mode = tty_mode;
- if (adev->mode == AUDIO_MODE_IN_CALL)
- select_output_device(adev);
- }
- pthread_mutex_unlock(&adev->lock);
- }
-
- ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
- if (ret >= 0) {
- if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
- adev->bluetooth_nrec = true;
- else
- adev->bluetooth_nrec = false;
- }
-
- ret = str_parms_get_str(parms, "screen_off", value, sizeof(value));
- if (ret >= 0) {
- if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
- adev->screen_off = false;
- else
- adev->screen_off = true;
- }
-
- ret = str_parms_get_str(parms, "noise_suppression", value, sizeof(value));
- if (ret >= 0) {
- if (strcmp(value, "on") == 0) {
- ALOGE("%s: enabling two mic control", __func__);
- ril_set_two_mic_control(&adev->ril, AUDIENCE, TWO_MIC_SOLUTION_ON);
- /* sub mic */
- set_bigroute_by_array(adev->mixer, noise_suppression, 1);
- } else {
- ALOGE("%s: disabling two mic control", __func__);
- ril_set_two_mic_control(&adev->ril, AUDIENCE, TWO_MIC_SOLUTION_OFF);
- /* sub mic */
- set_bigroute_by_array(adev->mixer, noise_suppression_disable, 1);
- }
- }
-
- str_parms_destroy(parms);
- return ret;
-}
-
-static char * adev_get_parameters(const struct audio_hw_device *dev,
- const char *keys)
-{
- return strdup("");
-}
-
-static int adev_init_check(const struct audio_hw_device *dev)
-{
- return 0;
-}
-
-static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)dev;
-
- adev->voice_volume = volume;
-
- if (adev->mode == AUDIO_MODE_IN_CALL)
- ril_set_call_volume(&adev->ril, SOUND_TYPE_VOICE, volume);
-
- return 0;
-}
-
-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, audio_mode_t mode)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)dev;
-
- pthread_mutex_lock(&adev->lock);
- if (adev->mode != mode) {
- adev->mode = mode;
- select_mode(adev);
- }
- pthread_mutex_unlock(&adev->lock);
-
- return 0;
-}
-
-static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)dev;
-
- adev->mic_mute = state;
-
- return 0;
-}
-
-static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)dev;
-
- *state = adev->mic_mute;
-
- return 0;
-}
-
-static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
- const struct audio_config *config)
-{
- size_t size;
- 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(config->sample_rate, config->format, channel_count);
-}
-
-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)
-{
- struct espresso_audio_device *ladev = (struct espresso_audio_device *)dev;
- struct espresso_stream_in *in;
- int ret;
-
- /* Respond with a request for stereo if a different format is given. */
- if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
- config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
- return -EINVAL;
- }
-
- int channel_count = popcount(config->channel_mask);
-
- *stream_in = NULL;
-
- if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
- return -EINVAL;
-
- in = (struct espresso_stream_in *)calloc(1, sizeof(struct espresso_stream_in));
- if (!in)
- return -ENOMEM;
-
- in->stream.common.get_sample_rate = in_get_sample_rate;
- in->stream.common.set_sample_rate = in_set_sample_rate;
- in->stream.common.get_buffer_size = in_get_buffer_size;
- in->stream.common.get_channels = in_get_channels;
- in->stream.common.get_format = in_get_format;
- in->stream.common.set_format = in_set_format;
- in->stream.common.standby = in_standby;
- in->stream.common.dump = in_dump;
- in->stream.common.set_parameters = in_set_parameters;
- in->stream.common.get_parameters = in_get_parameters;
- in->stream.common.add_audio_effect = in_add_audio_effect;
- in->stream.common.remove_audio_effect = in_remove_audio_effect;
- in->stream.set_gain = in_set_gain;
- in->stream.read = in_read;
- in->stream.get_input_frames_lost = in_get_input_frames_lost;
-
- 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;
-
- ret = create_resampler(in->config.rate,
- in->requested_rate,
- in->config.channels,
- RESAMPLER_QUALITY_DEFAULT,
- &in->buf_provider,
- &in->resampler);
- if (ret != 0) {
- ret = -EINVAL;
- goto err;
- }
- }
-
- in->dev = ladev;
- in->standby = 1;
- in->device = devices & ~AUDIO_DEVICE_BIT_IN;
-
- *stream_in = &in->stream;
- return 0;
-
-err:
- if (in->resampler)
- release_resampler(in->resampler);
-
- free(in);
- return ret;
-}
-
-static void adev_close_input_stream(struct audio_hw_device *dev,
- struct audio_stream_in *stream)
-{
- struct espresso_stream_in *in = (struct espresso_stream_in *)stream;
- int i;
-
- in_standby(&stream->common);
-
- 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);
- }
- if (in->proc_buf_in)
- free(in->proc_buf_in);
- if (in->proc_buf_out)
- free(in->proc_buf_out);
- if (in->ref_buf)
- free(in->ref_buf);
-
- free(stream);
- return;
-}
-
-static int adev_dump(const audio_hw_device_t *device, int fd)
-{
- return 0;
-}
-
-static int adev_close(hw_device_t *device)
-{
- struct espresso_audio_device *adev = (struct espresso_audio_device *)device;
-
- /* RIL */
- ril_close(&adev->ril);
-
- mixer_close(adev->mixer);
- free(device);
- return 0;
-}
-
-struct config_parse_state {
- struct espresso_audio_device *adev;
- struct espresso_dev_cfg *dev;
- bool on;
-
- struct route_setting *path;
- unsigned int path_len;
-};
-
-static const struct {
- int mask;
- const char *name;
-} dev_names[] = {
- { AUDIO_DEVICE_OUT_SPEAKER, "speaker" },
- { AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "headphone" },
- { AUDIO_DEVICE_OUT_EARPIECE, "earpiece" },
- { AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "dock" },
- { AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "dock" },
- { AUDIO_DEVICE_OUT_ALL_SCO, "sco-out" },
-
- { AUDIO_DEVICE_IN_BUILTIN_MIC, "builtin-mic" },
- { AUDIO_DEVICE_IN_BACK_MIC, "back-mic" },
- { AUDIO_DEVICE_IN_WIRED_HEADSET, "headset-in" },
- { AUDIO_DEVICE_IN_ALL_SCO, "sco-in" },
-};
-
-static void adev_config_start(void *data, const XML_Char *elem,
- const XML_Char **attr)
-{
- struct config_parse_state *s = data;
- struct espresso_dev_cfg *dev_cfg;
- const XML_Char *name = NULL;
- const XML_Char *val = NULL;
- unsigned int i, j;
-
- for (i = 0; attr[i]; i += 2) {
- if (strcmp(attr[i], "name") == 0)
- name = attr[i + 1];
-
- if (strcmp(attr[i], "val") == 0)
- val = attr[i + 1];
- }
-
- if (strcmp(elem, "device") == 0) {
- if (!name) {
- 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) {
- 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) {
- ALOGE("Unable to allocate dev_cfg\n");
- return;
- }
-
- s->dev = &dev_cfg[s->adev->num_dev_cfgs];
- memset(s->dev, 0, sizeof(*s->dev));
- s->dev->mask = dev_names[i].mask;
-
- s->adev->dev_cfgs = dev_cfg;
- s->adev->num_dev_cfgs++;
- }
- }
-
- } else if (strcmp(elem, "path") == 0) {
- if (s->path_len)
- ALOGW("Nested paths\n");
-
- /* If this a path for a device it must have a role */
- if (s->dev) {
- /* Need to refactor a bit... */
- if (strcmp(name, "on") == 0) {
- s->on = true;
- } else if (strcmp(name, "off") == 0) {
- s->on = false;
- } else {
- ALOGW("Unknown path name %s\n", name);
- }
- }
-
- } else if (strcmp(elem, "ctl") == 0) {
- struct route_setting *r;
-
- if (!name) {
- ALOGE("Unnamed control\n");
- return;
- }
-
- if (!val) {
- ALOGE("No value specified for %s\n", name);
- return;
- }
-
- ALOGV("Parsing control %s => %s\n", name, val);
-
- r = realloc(s->path, sizeof(*r) * (s->path_len + 1));
- if (!r) {
- ALOGE("Out of memory handling %s => %s\n", name, val);
- return;
- }
-
- r[s->path_len].ctl_name = strdup(name);
- r[s->path_len].strval = NULL;
-
- /* This can be fooled but it'll do */
- r[s->path_len].intval = atoi(val);
- if (!r[s->path_len].intval && strcmp(val, "0") != 0)
- r[s->path_len].strval = strdup(val);
-
- s->path = r;
- s->path_len++;
- }
-}
-
-static void adev_config_end(void *data, const XML_Char *name)
-{
- struct config_parse_state *s = data;
- unsigned int i;
-
- if (strcmp(name, "path") == 0) {
- if (!s->path_len)
- ALOGW("Empty path\n");
-
- if (!s->dev) {
- ALOGV("Applying %d element default route\n", s->path_len);
-
- set_route_by_array(s->adev->mixer, s->path, s->path_len);
-
- for (i = 0; i < s->path_len; i++) {
- free(s->path[i].ctl_name);
- free(s->path[i].strval);
- }
-
- free(s->path);
-
- /* Refactor! */
- } else if (s->on) {
- ALOGV("%d element on sequence\n", s->path_len);
- s->dev->on = s->path;
- s->dev->on_len = s->path_len;
-
- } else {
- 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);
-
- s->dev->off = s->path;
- s->dev->off_len = s->path_len;
- }
-
- s->path_len = 0;
- s->path = NULL;
-
- } else if (strcmp(name, "device") == 0) {
- s->dev = NULL;
- }
-}
-
-static int adev_config_parse(struct espresso_audio_device *adev)
-{
- struct config_parse_state s;
- FILE *f;
- XML_Parser p;
- char property[PROPERTY_VALUE_MAX];
- char file[80];
- int ret = 0;
- bool eof = false;
- int len;
-
- property_get("ro.product.device", property, "tiny_hw");
- snprintf(file, sizeof(file), "/system/etc/sound/%s", property);
-
- ALOGV("Reading configuration from %s\n", file);
- f = fopen(file, "r");
- if (!f) {
- ALOGE("Failed to open %s\n", file);
- return -ENODEV;
- }
-
- p = XML_ParserCreate(NULL);
- if (!p) {
- ALOGE("Failed to create XML parser\n");
- ret = -ENOMEM;
- goto out;
- }
-
- memset(&s, 0, sizeof(s));
- s.adev = adev;
- XML_SetUserData(p, &s);
-
- XML_SetElementHandler(p, adev_config_start, adev_config_end);
-
- while (!eof) {
- len = fread(file, 1, sizeof(file), f);
- if (ferror(f)) {
- 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) {
- ALOGE("Parse error at line %u:\n%s\n",
- (unsigned int)XML_GetCurrentLineNumber(p),
- XML_ErrorString(XML_GetErrorCode(p)));
- ret = -EINVAL;
- goto out_parser;
- }
- }
-
- out_parser:
- XML_ParserFree(p);
- out:
- fclose(f);
-
- return ret;
-}
-
-static int adev_open(const hw_module_t* module, const char* name,
- hw_device_t** device)
-{
- struct espresso_audio_device *adev;
- int i, ret;
-
- if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
- return -EINVAL;
-
- adev = calloc(1, sizeof(struct espresso_audio_device));
- if (!adev)
- return -ENOMEM;
-
- adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
- adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
- adev->hw_device.common.module = (struct hw_module_t *) module;
- adev->hw_device.common.close = adev_close;
-
- adev->hw_device.init_check = adev_init_check;
- adev->hw_device.set_voice_volume = adev_set_voice_volume;
- adev->hw_device.set_master_volume = adev_set_master_volume;
- adev->hw_device.set_mode = adev_set_mode;
- adev->hw_device.set_mic_mute = adev_set_mic_mute;
- adev->hw_device.get_mic_mute = adev_get_mic_mute;
- adev->hw_device.set_parameters = adev_set_parameters;
- adev->hw_device.get_parameters = adev_get_parameters;
- adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
- adev->hw_device.open_output_stream = adev_open_output_stream;
- adev->hw_device.close_output_stream = adev_close_output_stream;
- adev->hw_device.open_input_stream = adev_open_input_stream;
- adev->hw_device.close_input_stream = adev_close_input_stream;
- adev->hw_device.dump = adev_dump;
-
- adev->mixer = mixer_open(CARD_DEFAULT);
- if (!adev->mixer) {
- free(adev);
- ALOGE("Unable to open the mixer, aborting.");
- return -EINVAL;
- }
-
- 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);
- adev->mode = AUDIO_MODE_NORMAL;
- adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
- adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
- select_devices(adev);
-
- for (i = 0; i < OUTPUT_TOTAL; i++) {
- adev->outputs[i] = NULL;
- }
-
- adev->pcm_modem_dl = NULL;
- adev->pcm_modem_ul = NULL;
- adev->pcm_bt_dl = NULL;
- adev->pcm_bt_ul = NULL;
- adev->voice_volume = 1.0f;
- adev->tty_mode = TTY_MODE_OFF;
- adev->bluetooth_nrec = true;
- adev->wb_amr = 0;
-
- /* RIL */
- ril_open(&adev->ril);
- pthread_mutex_unlock(&adev->lock);
- /* register callback for wideband AMR setting */
- ril_register_set_wb_amr_callback(audio_set_wb_amr_callback, (void *)adev);
-
- *device = &adev->hw_device.common;
-
- return 0;
-
-err_mixer:
- mixer_close(adev->mixer);
-err:
- return -EINVAL;
-}
-
-static struct hw_module_methods_t hal_module_methods = {
- .open = adev_open,
-};
-
-struct audio_module HAL_MODULE_INFO_SYM = {
- .common = {
- .tag = HARDWARE_MODULE_TAG,
- .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
- .hal_api_version = HARDWARE_HAL_API_VERSION,
- .id = AUDIO_HARDWARE_MODULE_ID,
- .name = "Piranha audio HW HAL",
- .author = "The CyanogenMod Project",
- .methods = &hal_module_methods,
- },
-};
diff --git a/audio/audio_hw.h b/audio/audio_hw.h
deleted file mode 100644
index d2b2e0e..0000000
--- a/audio/audio_hw.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* ALSA cards for WM1811 */
-#define CARD_DEFAULT 0
-
-#define PORT_PLAYBACK 0
-#define PORT_CAPTURE 0
-#define PORT_MODEM 1
-#define PORT_BT 2
-
-#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
-
-#define RESAMPLER_BUFFER_FRAMES (PLAYBACK_PERIOD_SIZE * 2)
-#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 */
-#define VX_NB_SAMPLING_RATE 8000
-/* sampling rate when using VX port for wide band */
-#define VX_WB_SAMPLING_RATE 16000
-
-/* product-specific defines */
-#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,
- TTY_MODE_HCO,
- TTY_MODE_FULL
-};
-
-struct route_setting
-{
- char *ctl_name;
- int intval;
- char *strval;
-};
-
-struct route_setting voicecall_default[] = {
- { .ctl_name = "HP Output Mode", .intval = 0, },
- { .ctl_name = "AIF2 Mode", .intval = 0, },
- { .ctl_name = "AIF2DACL Source", .intval = 0, },
- { .ctl_name = "AIF2DACR Source", .intval = 0, },
- { .ctl_name = "DAC1L Mixer AIF1.1 Switch", .intval = 1, },
- { .ctl_name = "DAC1R Mixer AIF1.1 Switch", .intval = 1, },
- { .ctl_name = "DAC1L Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "DAC1R Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC Mux", .strval = "AIF2DACDAT", },
- { .ctl_name = NULL, },
-};
-
-struct route_setting voicecall_default_disable[] = {
- { .ctl_name = "AIF2 Mode", .intval = 0, },
- { .ctl_name = "AIF2DACL Source", .intval = 0, },
- { .ctl_name = "AIF2DACR Source", .intval = 1, },
- { .ctl_name = "DAC1L Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "DAC1R Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC Mux", .strval = "AIF2DACDAT", },
- { .ctl_name = NULL, },
-};
-
-struct route_setting default_input[] = {
- { .ctl_name = "Main Mic Switch", .intval = 1, },
- { .ctl_name = "IN1L Volume", .intval = 30, },
- { .ctl_name = "MIXINL IN1L Switch", .intval = 1, },
- { .ctl_name = "MIXINL IN1L Volume", .intval = 0, },
- { .ctl_name = "AIF1ADC1 HPF Mode", .intval = 1, },
- { .ctl_name = "AIF1ADC1 HPF Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2L Mixer Left Sidetone Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2L Mixer Right Sidetone Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2R Mixer Left Sidetone Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2R Mixer Right Sidetone Switch", .intval = 0, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting default_input_disable[] = {
- { .ctl_name = "Main Mic Switch", .intval = 0, },
- { .ctl_name = "MIXINL IN1L Switch", .intval = 0, },
- { .ctl_name = "AIF1ADC1 HPF Mode", .intval = 0, },
- { .ctl_name = "AIF1ADC1 HPF Switch", .intval = 0, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting noise_suppression[] = {
- { .ctl_name = "Sub Mic Switch", .intval = 1, },
- { .ctl_name = "AIF1ADCR Source", .intval = 1, },
- { .ctl_name = "MIXINR IN2R Switch", .intval = 1, },
- { .ctl_name = "IN2R Volume", .intval = 25, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting noise_suppression_disable[] = {
- { .ctl_name = "Sub Mic Switch", .intval = 0, },
- { .ctl_name = "AIF1ADCR Source", .intval = 0, },
- { .ctl_name = "MIXINR IN2R Switch", .intval = 0, },
- { .ctl_name = "IN2R Volume", .intval = 11, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting headset_input[] = {
- { .ctl_name = "Headset Mic Switch", .intval = 1, },
- { .ctl_name = "MIXINR IN1R Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2L Mixer Left Sidetone Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2L Mixer Right Sidetone Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2R Mixer Left Sidetone Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2R Mixer Right Sidetone Switch", .intval = 1, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting headset_input_disable[] = {
- { .ctl_name = "Headset Mic Switch", .intval = 0, },
- { .ctl_name = "MIXINR IN1R Switch", .intval = 0, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting bt_output[] = {
- { .ctl_name = "AIF2DAC2L Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2R Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC Volume", .intval = 96, },
- { .ctl_name = "DAC2 Volume", .intval = 96, },
- { .ctl_name = "AIF2ADC Volume", .intval = 96, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting bt_output_disable[] = {
- { .ctl_name = "AIF2DAC2L Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2R Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting bt_input[] = {
- { .ctl_name = "AIF2ADC Mux", .intval = 1, },
- { .ctl_name = "AIF2DACR Source", .intval = 1, },
- { .ctl_name = "HP Switch", .intval = 0, },
- { .ctl_name = "DAC1L Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "DAC1R Mixer AIF2 Switch", .intval = 1, },
- { .ctl_name = "AIF1ADC1R Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "AIF1ADC1L Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2L Mixer Left Sidetone Switch", .intval = 1, },
- { .ctl_name = "AIF2DAC2L Mixer Right Sidetone Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2R Mixer Left Sidetone Switch", .intval = 0, },
- { .ctl_name = "AIF2DAC2R Mixer Right Sidetone Switch", .intval = 1, },
- { .ctl_name = "AIF1ADC1R Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "AIF1ADC1L Mixer AIF2 Switch", .intval = 0, },
- { .ctl_name = "MIXINL IN1L Switch", .intval = 0, },
- { .ctl_name = NULL, },
-};
-
-struct route_setting bt_input_disable[] = {
- { .ctl_name = "AIF2ADC Mux", .intval = 0, },
- { .ctl_name = "HP Switch", .intval = 1, },
- { .ctl_name = NULL, },
-};
diff --git a/audio/ril_interface.c b/audio/ril_interface.c
deleted file mode 100755
index a77efc0..0000000
--- a/audio/ril_interface.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define ALOG_TAG "audio_hw_primary"
-/*#define ALOG_NDEBUG 0*/
-
-#include <dlfcn.h>
-#include <stdlib.h>
-
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-#include "ril_interface.h"
-
-#define VOLUME_STEPS_DEFAULT "5"
-#define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps"
-
-/* Function pointers */
-void *(*_ril_open_client)(void);
-int (*_ril_close_client)(void *);
-int (*_ril_connect)(void *);
-int (*_ril_is_connected)(void *);
-int (*_ril_disconnect)(void *);
-int (*_ril_set_call_volume)(void *, enum ril_sound_type, int);
-int (*_ril_set_call_audio_path)(void *, enum ril_audio_path);
-int (*_ril_set_call_clock_sync)(void *, enum ril_clock_state);
-int (*_ril_set_two_mic_control)(void *, enum ril_two_mic_device, enum ril_two_mic_state);
-int (*_ril_register_unsolicited_handler)(void *, int, void *);
-int (*_ril_get_wb_amr)(void *, void *);
-
-/* Audio WB AMR callback */
-void (*_audio_set_wb_amr_callback)(void *, int);
-void *callback_data = NULL;
-
-void ril_register_set_wb_amr_callback(void *function, void *data)
-{
- _audio_set_wb_amr_callback = function;
- callback_data = data;
-}
-
-/* This is the callback function that the RIL uses to
-set the wideband AMR state */
-static int ril_set_wb_amr_callback(void *ril_client,
- const void *data,
- size_t datalen)
-{
- int enable = ((int *)data)[0];
-
- if (!callback_data || !_audio_set_wb_amr_callback)
- return -1;
-
- _audio_set_wb_amr_callback(callback_data, enable);
-
- return 0;
-}
-
-static int ril_connect_if_required(struct ril_handle *ril)
-{
- if (_ril_is_connected(ril->client))
- return 0;
-
- if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) {
- ALOGE("ril_connect() failed");
- return -1;
- }
-
- /* get wb amr status to set pcm samplerate depending on
- wb amr status when ril is connected. */
- if(_ril_get_wb_amr)
- _ril_get_wb_amr(ril->client, ril_set_wb_amr_callback);
-
- return 0;
-}
-
-int ril_open(struct ril_handle *ril)
-{
- char property[PROPERTY_VALUE_MAX];
-
- if (!ril)
- return -1;
-
- ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);
-
- if (!ril->handle) {
- ALOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
- return -1;
- }
-
- _ril_open_client = dlsym(ril->handle, "OpenClient_RILD");
- _ril_close_client = dlsym(ril->handle, "CloseClient_RILD");
- _ril_connect = dlsym(ril->handle, "Connect_RILD");
- _ril_is_connected = dlsym(ril->handle, "isConnected_RILD");
- _ril_disconnect = dlsym(ril->handle, "Disconnect_RILD");
- _ril_set_call_volume = dlsym(ril->handle, "SetCallVolume");
- _ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath");
- _ril_set_call_clock_sync = dlsym(ril->handle, "SetCallClockSync");
- _ril_set_two_mic_control = dlsym(ril->handle, "SetTwoMicControl");
- _ril_register_unsolicited_handler = dlsym(ril->handle,
- "RegisterUnsolicitedHandler");
- /* since this function is not supported in all RILs, don't require it */
- _ril_get_wb_amr = dlsym(ril->handle, "GetWB_AMR");
-
- if (!_ril_open_client || !_ril_close_client || !_ril_connect ||
- !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume ||
- !_ril_set_call_audio_path || !_ril_set_two_mic_control || !_ril_set_call_clock_sync ||
- !_ril_register_unsolicited_handler) {
- ALOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
- dlclose(ril->handle);
- return -1;
- }
-
- ril->client = _ril_open_client();
- if (!ril->client) {
- ALOGE("ril_open_client() failed");
- dlclose(ril->handle);
- return -1;
- }
-
- /* register the wideband AMR callback */
- _ril_register_unsolicited_handler(ril->client, RIL_UNSOL_WB_AMR_STATE,
- ril_set_wb_amr_callback);
-
- property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
- ril->volume_steps_max = atoi(property);
- /* this catches the case where VOLUME_STEPS_PROPERTY does not contain
- an integer */
- if (ril->volume_steps_max == 0)
- ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);
-
- return 0;
-}
-
-int ril_close(struct ril_handle *ril)
-{
- if (!ril || !ril->handle || !ril->client)
- return -1;
-
- if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) ||
- (_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) {
- ALOGE("ril_disconnect() or ril_close_client() failed");
- return -1;
- }
-
- dlclose(ril->handle);
- return 0;
-}
-
-int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type,
- float volume)
-{
- if (ril_connect_if_required(ril))
- return 0;
-
- return _ril_set_call_volume(ril->client, sound_type,
- (int)(volume * ril->volume_steps_max));
-}
-
-int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path)
-{
- if (ril_connect_if_required(ril))
- return 0;
-
- return _ril_set_call_audio_path(ril->client, path);
-}
-
-int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state)
-{
- if (ril_connect_if_required(ril))
- return 0;
-
- return _ril_set_call_clock_sync(ril->client, state);
-}
-
-int ril_set_two_mic_control(struct ril_handle *ril, enum ril_two_mic_device device, enum ril_two_mic_state state)
-{
- if (ril_connect_if_required(ril))
- return 0;
-
- return _ril_set_two_mic_control(ril->client, device, state);
-}
diff --git a/audio/ril_interface.h b/audio/ril_interface.h
deleted file mode 100755
index 4b401aa..0000000
--- a/audio/ril_interface.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RIL_INTERFACE_H
-#define RIL_INTERFACE_H
-
-#define RIL_CLIENT_LIBPATH "libsecril-client.so"
-
-#define RIL_CLIENT_ERR_SUCCESS 0
-#define RIL_CLIENT_ERR_AGAIN 1
-#define RIL_CLIENT_ERR_INIT 2 // Client is not initialized
-#define RIL_CLIENT_ERR_INVAL 3 // Invalid value
-#define RIL_CLIENT_ERR_CONNECT 4 // Connection error
-#define RIL_CLIENT_ERR_IO 5 // IO error
-#define RIL_CLIENT_ERR_RESOURCE 6 // Resource not available
-#define RIL_CLIENT_ERR_UNKNOWN 7
-
-#define RIL_OEM_UNSOL_RESPONSE_BASE 11000 // RIL response base index
-#define RIL_UNSOL_WB_AMR_STATE \
- (RIL_OEM_UNSOL_RESPONSE_BASE + 17) // RIL AMR state index
-
-struct ril_handle
-{
- void *handle;
- void *client;
- int volume_steps_max;
-};
-
-enum ril_sound_type {
- SOUND_TYPE_VOICE,
- SOUND_TYPE_SPEAKER,
- SOUND_TYPE_HEADSET,
- SOUND_TYPE_BTVOICE
-};
-
-enum ril_audio_path {
- SOUND_AUDIO_PATH_HANDSET,
- SOUND_AUDIO_PATH_HEADSET,
- SOUND_AUDIO_PATH_SPEAKER,
- SOUND_AUDIO_PATH_BLUETOOTH,
- SOUND_AUDIO_PATH_BLUETOOTH_NO_NR,
- SOUND_AUDIO_PATH_HEADPHONE
-};
-
-enum ril_clock_state {
- SOUND_CLOCK_STOP,
- SOUND_CLOCK_START
-};
-
-enum ril_two_mic_device {
- AUDIENCE,
- FORTEMEDIA
-};
-
-enum ril_two_mic_state {
- TWO_MIC_SOLUTION_OFF,
- TWO_MIC_SOLUTION_ON
-};
-
-/* Function prototypes */
-int ril_open(struct ril_handle *ril);
-int ril_close(struct ril_handle *ril);
-int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type,
- float volume);
-int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path);
-int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state);
-void ril_register_set_wb_amr_callback(void *function, void *data);
-int ril_set_two_mic_control(struct ril_handle *ril, enum ril_two_mic_device device, enum ril_two_mic_state state);
-#endif
-