Some devices (often T-Mobile variants) have extra hardware for incall audio processing. Audio must be routed to the ES IC properly so it can be passed to ALSA, otherwise the RX/TX streams are lost. Change-Id: Ib29c747d5728a09726e14bab00f26ad273400abatirimbino
parent
68f8fb65aa
commit
0fdef0cbd6
@ -0,0 +1,192 @@ |
||||
/*
|
||||
* 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); |
||||
} |
@ -0,0 +1,29 @@ |
||||
/*
|
||||
* 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(); |
@ -0,0 +1,48 @@ |
||||
/*
|
||||
* 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 */ |
Loading…
Reference in new issue