hal: Add support for HFP feature
- Add set_parameters to be set from hfp app to enable
and disable hfp session.
- Implement start and stop hfp session which takes
care of switching device and setting the session
Change-Id: Ie8697328ccbfee09d0d162f6fad01ddb552e4f83
diff --git a/hal/Android.mk b/hal/Android.mk
index 67d7443..910edbe 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -10,6 +10,9 @@
ifneq ($(filter msm8974 msm8226 msm8084,$(TARGET_BOARD_PLATFORM)),)
# B-family platform uses msm8974 code base
AUDIO_PLATFORM = msm8974
+ifneq ($(filter msm8226,$(TARGET_BOARD_PLATFORM)),)
+ LOCAL_CFLAGS := -DPLATFORM_MSM8x26
+endif
ifneq ($(filter msm8084,$(TARGET_BOARD_PLATFORM)),)
LOCAL_CFLAGS := -DPLATFORM_MSM8084
endif
@@ -32,13 +35,19 @@
external/tinycompress/include \
$(call include-path-for, audio-route) \
$(call include-path-for, audio-effects) \
- $(LOCAL_PATH)/$(AUDIO_PLATFORM)
+ $(LOCAL_PATH)/$(AUDIO_PLATFORM) \
+ $(LOCAL_PATH)/audio_extn
ifneq ($(filter msm8084,$(TARGET_BOARD_PLATFORM)),)
LOCAL_SHARED_LIBRARIES += libmdmdetect
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libmdmdetect/inc
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HFP)),true)
+ LOCAL_CFLAGS += -DHFP_ENABLED
+ LOCAL_SRC_FILES += audio_extn/hfp.c
+endif
+
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
new file mode 100644
index 0000000..efa63aa
--- /dev/null
+++ b/hal/audio_extn/audio_extn.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 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 AUDIO_EXTN_H
+#define AUDIO_EXTN_H
+
+#include <cutils/str_parms.h>
+
+#ifndef HFP_ENABLED
+#define audio_extn_hfp_is_active(adev) (0)
+#define audio_extn_hfp_get_usecase() (-1)
+#define audio_extn_hfp_set_parameters(adev, params) (0)
+#else
+bool audio_extn_hfp_is_active(struct audio_device *adev);
+
+audio_usecase_t audio_extn_hfp_get_usecase();
+
+void audio_extn_hfp_set_parameters(struct audio_device *adev,
+ struct str_parms *parms);
+#endif
+
+#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
new file mode 100644
index 0000000..fb81c1b
--- /dev/null
+++ b/hal/audio_extn/hfp.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2014 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 LOG_TAG "audio_hw_hfp"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <math.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include <stdlib.h>
+#include <cutils/str_parms.h>
+
+#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
+#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
+#define AUDIO_PARAMETER_KEY_HFP_VOLUME "hfp_volume"
+
+static int32_t start_hfp(struct audio_device *adev,
+ struct str_parms *parms);
+
+static int32_t stop_hfp(struct audio_device *adev);
+
+struct hfp_module {
+ struct pcm *hfp_sco_rx;
+ struct pcm *hfp_sco_tx;
+ struct pcm *hfp_pcm_rx;
+ struct pcm *hfp_pcm_tx;
+ float hfp_volume;
+ bool is_hfp_running;
+ audio_usecase_t ucid;
+};
+
+static struct hfp_module hfpmod = {
+ .hfp_sco_rx = NULL,
+ .hfp_sco_tx = NULL,
+ .hfp_pcm_rx = NULL,
+ .hfp_pcm_tx = NULL,
+ .hfp_volume = 0,
+ .is_hfp_running = 0,
+ .ucid = USECASE_AUDIO_HFP_SCO,
+};
+static struct pcm_config pcm_config_hfp = {
+ .channels = 1,
+ .rate = 8000,
+ .period_size = 240,
+ .period_count = 2,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = 0,
+ .stop_threshold = INT_MAX,
+ .avail_min = 0,
+};
+
+static int32_t hfp_set_volume(struct audio_device *adev, float value)
+{
+ int32_t vol, ret = 0;
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "Internal HFP RX Volume";
+
+ ALOGV("%s: entry", __func__);
+ ALOGD("%s: (%f)\n", __func__, value);
+
+ if (value < 0.0) {
+ ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
+ value = 0.0;
+ } else {
+ value = ((value > 15.000000) ? 1.0 : (value / 15));
+ ALOGW("%s: Volume brought with in range (%f)\n", __func__, value);
+ }
+ vol = lrint((value * 0x2000) + 0.5);
+ hfpmod.hfp_volume = value;
+
+ if (!hfpmod.is_hfp_running) {
+ ALOGV("%s: HFP not active, ignoring set_hfp_volume call", __func__);
+ return -EIO;
+ }
+
+ ALOGD("%s: Setting HFP volume to %d \n", __func__, vol);
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+ if(mixer_ctl_set_value(ctl, 0, vol) < 0) {
+ ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, vol);
+ return -EINVAL;
+ }
+
+ ALOGV("%s: exit", __func__);
+ return ret;
+}
+
+static int32_t start_hfp(struct audio_device *adev,
+ struct str_parms *parms)
+{
+ int32_t i, ret = 0;
+ struct audio_usecase *uc_info;
+ int32_t pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id;
+
+ ALOGD("%s: enter", __func__);
+
+ uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+ uc_info->id = hfpmod.ucid;
+ uc_info->type = PCM_HFP_CALL;
+ uc_info->stream.out = adev->primary_output;
+ uc_info->devices = adev->primary_output->devices;
+ uc_info->in_snd_device = SND_DEVICE_NONE;
+ uc_info->out_snd_device = SND_DEVICE_NONE;
+
+ list_add_tail(&adev->usecase_list, &uc_info->list);
+
+ select_devices(adev, hfpmod.ucid);
+
+ pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
+ pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
+ pcm_dev_asm_rx_id = HFP_ASM_RX_TX;
+ pcm_dev_asm_tx_id = HFP_ASM_RX_TX;
+ if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0 ||
+ pcm_dev_asm_rx_id < 0 || pcm_dev_asm_tx_id < 0 ) {
+ ALOGE("%s: Invalid PCM devices (rx: %d tx: %d asm: rx tx %d) for the usecase(%d)",
+ __func__, pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, uc_info->id);
+ ret = -EIO;
+ goto exit;
+ }
+
+ ALOGV("%s: HFP PCM devices (hfp rx tx: %d pcm rx tx: %d) for the usecase(%d)",
+ __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
+
+ ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
+ __func__, SOUND_CARD, pcm_dev_rx_id);
+ hfpmod.hfp_sco_rx = pcm_open(SOUND_CARD,
+ pcm_dev_asm_rx_id,
+ PCM_OUT, &pcm_config_hfp);
+ if (hfpmod.hfp_sco_rx && !pcm_is_ready(hfpmod.hfp_sco_rx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_rx));
+ ret = -EIO;
+ goto exit;
+ }
+ ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+ __func__, SOUND_CARD, pcm_dev_tx_id);
+ hfpmod.hfp_pcm_rx = pcm_open(SOUND_CARD,
+ pcm_dev_rx_id,
+ PCM_OUT, &pcm_config_hfp);
+ if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_rx));
+ ret = -EIO;
+ goto exit;
+ }
+ hfpmod.hfp_sco_tx = pcm_open(SOUND_CARD,
+ pcm_dev_asm_tx_id,
+ PCM_IN, &pcm_config_hfp);
+ if (hfpmod.hfp_sco_tx && !pcm_is_ready(hfpmod.hfp_sco_tx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_tx));
+ ret = -EIO;
+ goto exit;
+ }
+ ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
+ __func__, SOUND_CARD, pcm_dev_tx_id);
+ hfpmod.hfp_pcm_tx = pcm_open(SOUND_CARD,
+ pcm_dev_tx_id,
+ PCM_IN, &pcm_config_hfp);
+ if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
+ ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_tx));
+ ret = -EIO;
+ goto exit;
+ }
+ pcm_start(hfpmod.hfp_sco_rx);
+ pcm_start(hfpmod.hfp_sco_tx);
+ pcm_start(hfpmod.hfp_pcm_rx);
+ pcm_start(hfpmod.hfp_pcm_tx);
+
+ hfpmod.is_hfp_running = true;
+ hfp_set_volume(adev, hfpmod.hfp_volume);
+
+ ALOGD("%s: exit: status(%d)", __func__, ret);
+ return 0;
+
+exit:
+ stop_hfp(adev);
+ ALOGE("%s: Problem in HFP start: status(%d)", __func__, ret);
+ return ret;
+}
+
+static int32_t stop_hfp(struct audio_device *adev)
+{
+ int32_t i, ret = 0;
+ struct audio_usecase *uc_info;
+
+ ALOGD("%s: enter", __func__);
+ hfpmod.is_hfp_running = false;
+
+ /* 1. Close the PCM devices */
+ if (hfpmod.hfp_sco_rx) {
+ pcm_close(hfpmod.hfp_sco_rx);
+ hfpmod.hfp_sco_rx = NULL;
+ }
+ if (hfpmod.hfp_sco_tx) {
+ pcm_close(hfpmod.hfp_sco_tx);
+ hfpmod.hfp_sco_tx = NULL;
+ }
+ if (hfpmod.hfp_pcm_rx) {
+ pcm_close(hfpmod.hfp_pcm_rx);
+ hfpmod.hfp_pcm_rx = NULL;
+ }
+ if (hfpmod.hfp_pcm_tx) {
+ pcm_close(hfpmod.hfp_pcm_tx);
+ hfpmod.hfp_pcm_tx = NULL;
+ }
+
+ uc_info = get_usecase_from_list(adev, hfpmod.ucid);
+ if (uc_info == NULL) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, hfpmod.ucid);
+ return -EINVAL;
+ }
+
+ /* 2. Get and set stream specific mixer controls */
+ disable_audio_route(adev, uc_info);
+
+ /* 3. Disable the rx and tx devices */
+ disable_snd_device(adev, uc_info->out_snd_device);
+ disable_snd_device(adev, uc_info->in_snd_device);
+
+ list_remove(&uc_info->list);
+ free(uc_info);
+
+ ALOGD("%s: exit: status(%d)", __func__, ret);
+ return ret;
+}
+
+bool audio_extn_hfp_is_active(struct audio_device *adev)
+{
+ struct audio_usecase *hfp_usecase = NULL;
+ hfp_usecase = get_usecase_from_list(adev, hfpmod.ucid);
+
+ if (hfp_usecase != NULL)
+ return true;
+ else
+ return false;
+}
+
+audio_usecase_t audio_extn_hfp_get_usecase()
+{
+ return hfpmod.ucid;
+}
+
+void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
+{
+ int ret;
+ int rate;
+ int val;
+ float vol;
+ char value[32]={0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (!strncmp(value,"true",sizeof(value)))
+ ret = start_hfp(adev,parms);
+ else
+ stop_hfp(adev);
+ }
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms,AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ rate = atoi(value);
+ if (rate == 8000){
+ hfpmod.ucid = USECASE_AUDIO_HFP_SCO;
+ pcm_config_hfp.rate = rate;
+ } else if (rate == 16000){
+ hfpmod.ucid = USECASE_AUDIO_HFP_SCO_WB;
+ pcm_config_hfp.rate = rate;
+ } else
+ ALOGE("Unsupported rate..");
+ }
+
+ if (hfpmod.is_hfp_running) {
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
+ value, sizeof(value));
+ if (ret >= 0) {
+ val = atoi(value);
+ if (val > 0)
+ select_devices(adev, hfpmod.ucid);
+ }
+ }
+
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_VOLUME,
+ value, sizeof(value));
+ if (ret >= 0) {
+ if (sscanf(value, "%f", &vol) != 1){
+ ALOGE("%s: error in retrieving hfp volume", __func__);
+ ret = -EIO;
+ goto exit;
+ }
+ ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
+ hfp_set_volume(adev, vol);
+ }
+exit:
+ ALOGV("%s Exit",__func__);
+}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 712b002..f7f8d28 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -45,6 +45,7 @@
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_ns.h>
#include "audio_hw.h"
+#include "audio_extn.h"
#include "platform_api.h"
#include <platform.h>
@@ -114,6 +115,8 @@
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
[USECASE_AUDIO_RECORD] = "audio-record",
[USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
+ [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
+ [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
[USECASE_VOICE_CALL] = "voice-call",
[USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
};
@@ -161,8 +164,8 @@
return id;
}
-static int enable_audio_route(struct audio_device *adev,
- struct audio_usecase *usecase)
+int enable_audio_route(struct audio_device *adev,
+ struct audio_usecase *usecase)
{
snd_device_t snd_device;
char mixer_path[50];
@@ -186,8 +189,8 @@
return 0;
}
-static int disable_audio_route(struct audio_device *adev,
- struct audio_usecase *usecase)
+int disable_audio_route(struct audio_device *adev,
+ struct audio_usecase *usecase)
{
snd_device_t snd_device;
char mixer_path[50];
@@ -209,7 +212,7 @@
return 0;
}
-static int enable_snd_device(struct audio_device *adev,
+int enable_snd_device(struct audio_device *adev,
snd_device_t snd_device)
{
if (snd_device < SND_DEVICE_MIN ||
@@ -237,7 +240,7 @@
return 0;
}
-static int disable_snd_device(struct audio_device *adev,
+int disable_snd_device(struct audio_device *adev,
snd_device_t snd_device)
{
if (snd_device < SND_DEVICE_MIN ||
@@ -413,8 +416,8 @@
return ret;
}
-static struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
- audio_usecase_t uc_id)
+struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
+ audio_usecase_t uc_id)
{
struct audio_usecase *usecase;
struct listnode *node;
@@ -427,13 +430,15 @@
return NULL;
}
-static int select_devices(struct audio_device *adev,
- audio_usecase_t uc_id)
+int select_devices(struct audio_device *adev,
+ audio_usecase_t uc_id)
{
snd_device_t out_snd_device = SND_DEVICE_NONE;
snd_device_t in_snd_device = SND_DEVICE_NONE;
struct audio_usecase *usecase = NULL;
struct audio_usecase *vc_usecase = NULL;
+ struct audio_usecase *hfp_usecase = NULL;
+ audio_usecase_t hfp_ucid;
struct listnode *node;
int status = 0;
@@ -443,7 +448,8 @@
return -EINVAL;
}
- if (usecase->type == VOICE_CALL) {
+ if ((usecase->type == VOICE_CALL) ||
+ (usecase->type == PCM_HFP_CALL)) {
out_snd_device = platform_get_output_snd_device(adev->platform,
usecase->stream.out->devices);
in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
@@ -462,6 +468,13 @@
in_snd_device = vc_usecase->in_snd_device;
out_snd_device = vc_usecase->out_snd_device;
}
+ } else if (audio_extn_hfp_is_active(adev)) {
+ hfp_ucid = audio_extn_hfp_get_usecase();
+ hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
+ if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+ in_snd_device = hfp_usecase->in_snd_device;
+ out_snd_device = hfp_usecase->out_snd_device;
+ }
}
if (usecase->type == PCM_PLAYBACK) {
usecase->devices = usecase->stream.out->devices;
@@ -2141,6 +2154,7 @@
pthread_mutex_unlock(&adev->lock);
}
+ audio_extn_hfp_set_parameters(adev, parms);
str_parms_destroy(parms);
ALOGV("%s: exit with code(%d)", __func__, status);
return status;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 3a30688..37805ab 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -17,6 +17,7 @@
#ifndef QCOM_AUDIO_HW_H
#define QCOM_AUDIO_HW_H
+#include <cutils/str_parms.h>
#include <cutils/list.h>
#include <hardware/audio.h>
@@ -55,6 +56,10 @@
USECASE_AUDIO_PLAYBACK_MULTI_CH,
USECASE_AUDIO_PLAYBACK_OFFLOAD,
+ /* HFP Use case*/
+ USECASE_AUDIO_HFP_SCO,
+ USECASE_AUDIO_HFP_SCO_WB,
+
/* Capture usecases */
USECASE_AUDIO_RECORD,
USECASE_AUDIO_RECORD_LOW_LATENCY,
@@ -150,7 +155,8 @@
typedef enum {
PCM_PLAYBACK,
PCM_CAPTURE,
- VOICE_CALL
+ VOICE_CALL,
+ PCM_HFP_CALL
} usecase_type_t;
union stream_ptr {
@@ -206,6 +212,19 @@
struct pcm_params *use_case_table[AUDIO_USECASE_MAX];
};
+int select_devices(struct audio_device *adev,
+ audio_usecase_t uc_id);
+int disable_audio_route(struct audio_device *adev,
+ struct audio_usecase *usecase);
+int disable_snd_device(struct audio_device *adev,
+ snd_device_t snd_device);
+int enable_snd_device(struct audio_device *adev,
+ snd_device_t snd_device);
+int enable_audio_route(struct audio_device *adev,
+ struct audio_usecase *usecase);
+struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
+ audio_usecase_t uc_id);
+
/*
* NOTE: when multiple mutexes have to be acquired, always take the
* stream_in or stream_out mutex first, followed by the audio_device mutex.
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 5233705..b7acc85 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -108,6 +108,7 @@
LOWLATENCY_PCM_DEVICE},
[USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
VOICE_CALL_PCM_DEVICE},
+ [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX},
};
/* Array to store sound devices */
@@ -960,6 +961,7 @@
out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
if (my_data->fluence_in_voice_call == false) {
snd_device = SND_DEVICE_IN_HANDSET_MIC;
+ set_echo_reference(adev->mixer, "SLIM_RX");
} else {
if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
if (is_operator_tmus())
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index c4f2a47..18711d8 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -143,6 +143,15 @@
#define VOICE_CALL_PCM_DEVICE 2
#endif
+#define HFP_PCM_RX 5
+#ifdef PLATFORM_MSM8x26
+#define HFP_SCO_RX 28
+#define HFP_ASM_RX_TX 29
+#else
+#define HFP_SCO_RX 23
+#define HFP_ASM_RX_TX 24
+#endif
+
#define LIB_CSD_CLIENT "libcsd-client.so"
#define LIB_MDM_DETECT "libmdmdetect.so"