LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := \
+ audience.c \
audio_hw.c \
compress_offload.c \
ril_interface.c \
--- /dev/null
+/*
+ * Copyright (C) 2017 Christopher N. Hesse <raymanfx@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_audience"
+#define LOG_NDEBUG 0
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <cutils/log.h>
+#include <audience-routes.h>
+
+#include "audience.h"
+
+/*
+ * Writes an Integer to a file.
+ *
+ * @param path The absolute path string.
+ * @param value The Integer value to be written.
+ * @return 0 on success, -1 or errno on error.
+ */
+static int write_int(char const *path, const int value)
+{
+ int fd;
+ static int already_warned;
+
+ already_warned = 0;
+
+ ALOGV("write_int: path %s, value %d", path, value);
+ fd = open(path, O_RDWR);
+
+ if (fd >= 0) {
+ char buffer[20];
+ int bytes = sprintf(buffer, "%d\n", value);
+ int amt = write(fd, buffer, bytes);
+ close(fd);
+ return amt == -1 ? -errno : 0;
+ } else {
+ if (already_warned == 0) {
+ ALOGE("write_int failed to open %s\n", path);
+ already_warned = 1;
+ }
+ return -errno;
+ }
+}
+
+/*
+ * Writes the route value to sysfs.
+ *
+ * @param value The long Integer value to be written.
+ * @return 0 on success, -1 or errno on error.
+ */
+static int es_route_value_set(int value)
+{
+ return write_int(SYSFS_PATH_PRESET, value);
+}
+
+/*
+ * Writes the veq control to sysfs.
+ *
+ * @param value The Integer value to be written.
+ * @return 0 on success, -1 or errno on error.
+ */
+static int es_veq_control_set(int value)
+{
+ return write_int(SYSFS_PATH_VEQ, value);
+}
+
+/*
+ * Writes the extra volume to sysfs.
+ *
+ * @param value The Integer value to be written.
+ * @return 0 on success, -1 or errno on error.
+ */
+static int es_extra_volume_set(int value)
+{
+ return write_int(SYSFS_PATH_EXTRAVOLUME, value);
+}
+
+/*
+ * Convertes an out_device from the session to an earSmart compatible route.
+ *
+ * @param out_device The output device to be converted.
+ * @return Audience earSmart route, coded as long Integer.
+ */
+static long es_device_to_route(struct voice_session *session)
+{
+ long ret;
+ long nb_route;
+ long wb_route;
+
+ switch(session->out_device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ nb_route = Call_CT_NB;
+ wb_route = Call_CT_WB;
+ break;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ nb_route = Call_FT_NB;
+ wb_route = Call_FT_WB;
+ break;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ nb_route = Call_HS_NB;
+ wb_route = Call_HS_WB;
+ break;
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ nb_route = Call_BT_NB;
+ wb_route = Call_BT_WB;
+ break;
+ default:
+ /* if output device isn't supported, use earpiece by default */
+ nb_route = Call_CT_NB;
+ wb_route = Call_CT_WB;
+ break;
+ }
+
+ /* TODO: Handle wb_amr=2 */
+ if (session->wb_amr_type >= 1) {
+ ret = wb_route;
+ } else {
+ ret = nb_route;
+ }
+
+ ALOGV("%s: converting out_device=%d to %s route: %ld", __func__, session->out_device,
+ ret == wb_route ? "Wide Band" : "Narrow Band", ret);
+ return ret;
+}
+
+/*
+ * Configures and enables the Audience earSmart IC.
+ *
+ * @param session Reference to the active voice call session.
+ * @return @return 0 on success, -1 or errno on error.
+ */
+int es_start_voice_session(struct voice_session *session)
+{
+ int ret;
+ long es_route = es_device_to_route(session);
+
+ /* TODO: Calculate these */
+ int extra_volume = 0;
+ int veq_control = 4;
+
+ /*
+ * The control flow for audience earSmart chip is as follows:
+ *
+ * route_value >> power_control(internal) >> extra_volume >> veq_control
+ */
+ ret = es_route_value_set(es_route);
+ if (ret != 0) {
+ ALOGE("%s: es_route_value_set(%ld) failed with code: %d", __func__, es_route, ret);
+ goto exit;
+ }
+ ret = es_extra_volume_set(extra_volume);
+ if (ret != 0) {
+ ALOGE("%s: es_extra_volume_set(%d) failed with code: %d", __func__, extra_volume, ret);
+ goto exit;
+ }
+ ret = es_veq_control_set(veq_control);
+ if (ret != 0) {
+ ALOGE("%s: es_veq_control_set(%d) failed with code: %d", __func__, veq_control, ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+/*
+ * Disables the Audience earSmart IC.
+ */
+void es_stop_voice_session()
+{
+ /* This will cancel any pending workers, stop the stream and send the IC to sleep */
+ es_route_value_set(AUDIENCE_SLEEP);
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 Christopher N. Hesse <raymanfx@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.
+ */
+
+#include "audio_hw.h"
+#include "voice.h"
+
+enum es_power_state {
+ ES_POWER_FW_LOAD,
+ ES_POWER_SLEEP,
+ ES_POWER_SLEEP_PENDING,
+ ES_POWER_AWAKE,
+ ES_MAX = ES_POWER_AWAKE
+};
+
+int es_start_voice_session(struct voice_session *session);
+void es_stop_voice_session();
--- /dev/null
+/*
+ * Copyright (C) 2017 Christopher N. Hesse <raymanfx@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.
+ */
+
+/*
+ * NOTICE
+ *
+ * This must be kept in sync with the kernel API, for exmaple
+ * "es705-routes.h" for the Galaxy Note 5 (N920T) with its ES804 IC.
+ */
+
+#define SYSFS_PATH_POWERCTRL "/sys/class/earsmart/control/power_control_set"
+#define SYSFS_PATH_PRESET "/sys/class/earsmart/control/route_value"
+#define SYSFS_PATH_VEQ "/sys/class/earsmart/control/veq_control_set"
+#define SYSFS_PATH_EXTRAVOLUME "/sys/class/earsmart/control/extra_volume"
+#define Call_HS_NB 0 /* Call, Headset, Narrow Band */
+#define Call_FT_NB 1 /* Call, Far Talk, Narrow Band */
+#define Call_CT_NB 2 /* Call, Close Talk, Narrow Band */
+#define Call_FT_NB_NR_OFF 3 /* Call, Far Talk, NB, NR off */
+#define Call_CT_NB_NR_OFF 4 /* Call, Close Talk, NB, NR off */
+#define Call_BT_NB 10 /* Call, BT, NB */
+#define Call_TTY_VCO 11 /* Call, TTY HCO NB */
+#define Call_TTY_HCO 12 /* Call, TTY VCO NB */
+#define Call_TTY_FULL 13 /* Call, TTY FULL NB */
+#define Call_FT_EVS 14 /* Call, Far Talk, EVS */
+#define Call_CT_EVS 15 /* Call, Close Talk, EVS */
+#define LOOPBACK_CT 17 /* Loopback, Close Talk */
+#define LOOPBACK_FT 18 /* Loopback, Far Talk */
+#define LOOPBACK_HS 19 /* Loopback, Headset */
+#define Call_BT_WB 20 /* Call, BT, WB */
+#define Call_HS_WB 21 /* Call, Headset, Wide Band */
+#define Call_FT_WB 22 /* Call, Far Talk, Wide Band */
+#define Call_CT_WB 23 /* Call, Close Talk, Wide Band */
+#define Call_FT_WB_NR_OFF 24 /* Call, Far Talk, WB, NR off */
+#define Call_CT_WB_NR_OFF 25 /* Call, Close Talk, WB, NR off */
+#define AUDIENCE_SLEEP 40 /* Route none, Audience Sleep State */
*/
/* #define DSP_POWEROFF_DELAY 0 */
+/*
+ * Some device variants (often T-Mobile) have a separate voice processing IC
+ * (Audience EarSmart xxx).
+ * This hooks into the voice call session and enables, configures and disables
+ * this extra firmware so RX/TX streams can be routed by the driver.
+ */
+/* #define AUDIENCE_EARSMART_IC */
+
#endif // SAMSUNG_AUDIO_H
#include "audio_hw.h"
#include "voice.h"
+#ifdef AUDIENCE_EARSMART_IC
+#include "audience.h"
+#endif
+
static struct pcm_config pcm_config_voicecall = {
.channels = 2,
.rate = 8000,
start_voice_session_bt_sco(session);
}
+#ifdef AUDIENCE_EARSMART_IC
+ ALOGV("%s: Enabling Audience IC", __func__);
+ es_start_voice_session(session);
+#endif
+
if (session->two_mic_control) {
ALOGV("%s: enabling two mic control", __func__);
ril_set_two_mic_control(&session->ril, AUDIENCE, TWO_MIC_SOLUTION_ON);
stop_voice_session_bt_sco(session);
}
+#ifdef AUDIENCE_EARSMART_IC
+ ALOGV("%s: Disabling Audience IC", __func__);
+ es_stop_voice_session();
+#endif
session->out_device = AUDIO_DEVICE_NONE;