diff --git a/Android.mk b/Android.mk index 9bb3250a..c63df058 100644 --- a/Android.mk +++ b/Android.mk @@ -1,4 +1,4 @@ -ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084,$(TARGET_BOARD_PLATFORM)),) +ifneq ($(filter mpq8092 msm8960 msm8226 msm8x26 msm8610 msm8974 msm8x74 apq8084 msm8916,$(TARGET_BOARD_PLATFORM)),) MY_LOCAL_PATH := $(call my-dir) diff --git a/hal/Android.mk b/hal/Android.mk index a7e0a026..d78d13b0 100644 --- a/hal/Android.mk +++ b/hal/Android.mk @@ -23,6 +23,12 @@ ifneq ($(filter apq8084,$(TARGET_BOARD_PLATFORM)),) endif endif +ifneq ($(filter msm8916,$(TARGET_BOARD_PLATFORM)),) + AUDIO_PLATFORM = msm8916 + MULTIPLE_HW_VARIANTS_ENABLED := true + LOCAL_CFLAGS := -DPLATFORM_MSM8916 +endif + LOCAL_SRC_FILES := \ audio_hw.c \ voice.c \ diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c new file mode 100644 index 00000000..63506f90 --- /dev/null +++ b/hal/msm8916/hw_info.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "hardware_info" +/*#define LOG_NDEBUG 0*/ +#define LOG_NDDEBUG 0 + +#include +#include +#include +#include +#include "audio_hw.h" +#include "platform.h" +#include "platform_api.h" + + +struct hardware_info { + char name[HW_INFO_ARRAY_MAX_SIZE]; + char type[HW_INFO_ARRAY_MAX_SIZE]; + /* variables for handling target variants */ + uint32_t num_snd_devices; + char dev_extn[HW_INFO_ARRAY_MAX_SIZE]; + snd_device_t *snd_devices; +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static const snd_device_t taiko_fluid_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, +}; + +static const snd_device_t taiko_CDP_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, + SND_DEVICE_IN_QUAD_MIC, +}; + +static const snd_device_t taiko_apq8084_CDP_variant_devices[] = { + SND_DEVICE_IN_HANDSET_MIC, +}; + +static const snd_device_t taiko_liquid_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, + SND_DEVICE_IN_SPEAKER_MIC, + SND_DEVICE_IN_HEADSET_MIC, + SND_DEVICE_IN_VOICE_DMIC, + SND_DEVICE_IN_VOICE_SPEAKER_DMIC, + SND_DEVICE_IN_VOICE_REC_DMIC_STEREO, + SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE, + SND_DEVICE_IN_QUAD_MIC, + SND_DEVICE_IN_HANDSET_STEREO_DMIC, + SND_DEVICE_IN_SPEAKER_STEREO_DMIC, +}; + +static const snd_device_t taiko_DB_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, + SND_DEVICE_IN_SPEAKER_MIC, + SND_DEVICE_IN_HEADSET_MIC, + SND_DEVICE_IN_QUAD_MIC, +}; + +static const snd_device_t tapan_lite_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_VOICE_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES, +}; + +static const snd_device_t tapan_skuf_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, + /*SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET,*/ +}; + +static const snd_device_t tapan_lite_skuf_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_VOICE_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES, +}; + +static const snd_device_t helicon_skuab_variant_devices[] = { + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, +}; + +static void update_hardware_info_8916(struct hardware_info *hw_info, const char *snd_card_name) +{ + if (!strcmp(snd_card_name, "msm8916-snd-card")) { + strlcpy(hw_info->type, "", sizeof(hw_info->type)); + strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name)); + hw_info->snd_devices = NULL; + hw_info->num_snd_devices = 0; + strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); + } else if (!strcmp(snd_card_name, "msm8916-skuab-snd-card")) { + strlcpy(hw_info->type, "skuab", sizeof(hw_info->type)); + strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name)); + hw_info->snd_devices = (snd_device_t *)helicon_skuab_variant_devices; + hw_info->num_snd_devices = ARRAY_SIZE(helicon_skuab_variant_devices); + strlcpy(hw_info->dev_extn, "-skuab", sizeof(hw_info->dev_extn)); + } else if (!strcmp(snd_card_name, "msm8916-skuaa-snd-card")) { + strlcpy(hw_info->type, " skuaa", sizeof(hw_info->type)); + strlcpy(hw_info->name, "msm8916", sizeof(hw_info->name)); + hw_info->snd_devices = NULL; + hw_info->num_snd_devices = 0; + strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); + } else { + ALOGW("%s: Not an 8916 device", __func__); + } +} + +void *hw_info_init(const char *snd_card_name) +{ + struct hardware_info *hw_info; + + hw_info = malloc(sizeof(struct hardware_info)); + + if(strstr(snd_card_name, "msm8916")) { + ALOGV("8916 - variant soundcard"); + update_hardware_info_8916(hw_info, snd_card_name); + } else { + ALOGE("%s: Unsupported target %s:",__func__, snd_card_name); + free(hw_info); + hw_info = NULL; + } + + return hw_info; +} + +void hw_info_deinit(void *hw_info) +{ + struct hardware_info *my_data = (struct hardware_info*) hw_info; + + if(!my_data) + free(my_data); +} + +void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device, + char *device_name) +{ + struct hardware_info *my_data = (struct hardware_info*) hw_info; + uint32_t i = 0; + + snd_device_t *snd_devices = + (snd_device_t *) my_data->snd_devices; + + if(snd_devices != NULL) { + for (i = 0; i < my_data->num_snd_devices; i++) { + if (snd_device == (snd_device_t)snd_devices[i]) { + ALOGV("extract dev_extn device %d, extn = %s", + (snd_device_t)snd_devices[i], my_data->dev_extn); + CHECK(strlcat(device_name, my_data->dev_extn, + DEVICE_NAME_MAX_SIZE) < DEVICE_NAME_MAX_SIZE); + break; + } + } + } + ALOGD("%s : device_name = %s", __func__,device_name); +} diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c new file mode 100644 index 00000000..afdc2378 --- /dev/null +++ b/hal/msm8916/platform.c @@ -0,0 +1,1685 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2013 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 "msm8916_platform" +/*#define LOG_NDEBUG 0*/ +#define LOG_NDDEBUG 0 + +#include +#include +#include +#include +#include +#include +#include +#include "platform.h" +#include "audio_extn.h" +#include "voice_extn.h" + +#define MIXER_XML_PATH "/system/etc/mixer_paths.xml" +#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml" +#define LIB_ACDB_LOADER "libacdbloader.so" +#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID" + +/* + * This file will have a maximum of 38 bytes: + * + * 4 bytes: number of audio blocks + * 4 bytes: total length of Short Audio Descriptor (SAD) blocks + * Maximum 10 * 3 bytes: SAD blocks + */ +#define MAX_SAD_BLOCKS 10 +#define SAD_BLOCK_SIZE 3 + +/* EDID format ID for LPCM audio */ +#define EDID_FORMAT_LPCM 1 + +/* Retry for delay in FW loading*/ +#define RETRY_NUMBER 10 +#define RETRY_US 500000 +#define MAX_SND_CARD 8 + +#define SAMPLE_RATE_8KHZ 8000 +#define SAMPLE_RATE_16KHZ 16000 + +#define AUDIO_PARAMETER_KEY_FLUENCE_TYPE "fluence" +#define AUDIO_PARAMETER_KEY_BTSCO "bt_samplerate" +#define AUDIO_PARAMETER_KEY_SLOWTALK "st_enable" +#define AUDIO_PARAMETER_KEY_VOLUME_BOOST "volume_boost" + +enum { + VOICE_FEATURE_SET_DEFAULT, + VOICE_FEATURE_SET_VOLUME_BOOST +}; + +struct audio_block_header +{ + int reserved; + int length; +}; + +/* Audio calibration related functions */ +typedef void (*acdb_deallocate_t)(); +typedef int (*acdb_init_t)(); +typedef void (*acdb_send_audio_cal_t)(int, int); +typedef void (*acdb_send_voice_cal_t)(int, int); +typedef int (*acdb_reload_vocvoltable_t)(int); + +struct platform_data { + struct audio_device *adev; + bool fluence_in_spkr_mode; + bool fluence_in_voice_call; + bool fluence_in_voice_rec; + bool fluence_in_audio_rec; + int fluence_type; + int btsco_sample_rate; + bool slowtalk; + /* Audio calibration related functions */ + void *acdb_handle; + int voice_feature_set; + acdb_init_t acdb_init; + acdb_deallocate_t acdb_deallocate; + acdb_send_audio_cal_t acdb_send_audio_cal; + acdb_send_voice_cal_t acdb_send_voice_cal; + acdb_reload_vocvoltable_t acdb_reload_vocvoltable; + + void *hw_info; + struct csd_data *csd; +}; + +static const int pcm_device_table[AUDIO_USECASE_MAX][2] = { + [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE, + DEEP_BUFFER_PCM_DEVICE}, + [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, + LOWLATENCY_PCM_DEVICE}, + [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTIMEDIA2_PCM_DEVICE, + MULTIMEDIA2_PCM_DEVICE}, + [USECASE_AUDIO_PLAYBACK_OFFLOAD] = + {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE}, + [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE}, + [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE}, + [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, + LOWLATENCY_PCM_DEVICE}, + [USECASE_AUDIO_RECORD_FM_VIRTUAL] = {MULTIMEDIA2_PCM_DEVICE, + MULTIMEDIA2_PCM_DEVICE}, + [USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE}, + [USECASE_AUDIO_HFP_SCO] = {HFP_PCM_RX, HFP_SCO_RX}, + [USECASE_AUDIO_HFP_SCO_WB] = {HFP_PCM_RX, HFP_SCO_RX}, + [USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE, VOICE_CALL_PCM_DEVICE}, + [USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE}, + [USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE}, + [USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE}, + [USECASE_COMPRESS_VOIP_CALL] = {COMPRESS_VOIP_CALL_PCM_DEVICE, COMPRESS_VOIP_CALL_PCM_DEVICE}, + [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE, + AUDIO_RECORD_PCM_DEVICE}, + [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE, + AUDIO_RECORD_PCM_DEVICE}, + [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE, + AUDIO_RECORD_PCM_DEVICE}, + [USECASE_INCALL_REC_UPLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, + COMPRESS_CAPTURE_DEVICE}, + [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, + COMPRESS_CAPTURE_DEVICE}, + [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, + COMPRESS_CAPTURE_DEVICE}, + [USECASE_INCALL_MUSIC_UPLINK] = {INCALL_MUSIC_UPLINK_PCM_DEVICE, + INCALL_MUSIC_UPLINK_PCM_DEVICE}, + [USECASE_INCALL_MUSIC_UPLINK2] = {INCALL_MUSIC_UPLINK2_PCM_DEVICE, + INCALL_MUSIC_UPLINK2_PCM_DEVICE}, + [USECASE_AUDIO_SPKR_CALIB_RX] = {SPKR_PROT_CALIB_RX_PCM_DEVICE, -1}, + [USECASE_AUDIO_SPKR_CALIB_TX] = {-1, SPKR_PROT_CALIB_TX_PCM_DEVICE}, +}; + +/* Array to store sound devices */ +static const char * const device_table[SND_DEVICE_MAX] = { + [SND_DEVICE_NONE] = "none", + /* Playback sound devices */ + [SND_DEVICE_OUT_HANDSET] = "handset", + [SND_DEVICE_OUT_SPEAKER] = "speaker", + [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse", + [SND_DEVICE_OUT_HEADPHONES] = "headphones", + [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones", + [SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset", + [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker", + [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones", + [SND_DEVICE_OUT_HDMI] = "hdmi", + [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi", + [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset", + [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb", + [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones", + [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones", + [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset", + [SND_DEVICE_OUT_AFE_PROXY] = "afe-proxy", + [SND_DEVICE_OUT_USB_HEADSET] = "usb-headphones", + [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = "speaker-and-usb-headphones", + [SND_DEVICE_OUT_TRANSMISSION_FM] = "transmission-fm", + [SND_DEVICE_OUT_ANC_HEADSET] = "anc-headphones", + [SND_DEVICE_OUT_ANC_FB_HEADSET] = "anc-fb-headphones", + [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = "voice-anc-headphones", + [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = "voice-anc-fb-headphones", + [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = "speaker-and-anc-headphones", + [SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset", + [SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected", + + /* Capture sound devices */ + [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic", + [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic", + [SND_DEVICE_IN_HANDSET_MIC_NS] = "handset-mic", + [SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = "handset-mic", + [SND_DEVICE_IN_HANDSET_DMIC] = "dmic-endfire", + [SND_DEVICE_IN_HANDSET_DMIC_AEC] = "dmic-endfire", + [SND_DEVICE_IN_HANDSET_DMIC_NS] = "dmic-endfire", + [SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = "dmic-endfire", + [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic", + [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "speaker-mic", + [SND_DEVICE_IN_SPEAKER_MIC_NS] = "speaker-mic", + [SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = "speaker-mic", + [SND_DEVICE_IN_SPEAKER_DMIC] = "speaker-dmic-endfire", + [SND_DEVICE_IN_SPEAKER_DMIC_AEC] = "speaker-dmic-endfire", + [SND_DEVICE_IN_SPEAKER_DMIC_NS] = "speaker-dmic-endfire", + [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = "speaker-dmic-endfire", + [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic", + [SND_DEVICE_IN_HEADSET_MIC_FLUENCE] = "headset-mic", + [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic", + [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic", + [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic", + [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic", + [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb", + [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic", + [SND_DEVICE_IN_VOICE_DMIC] = "voice-dmic-ef", + [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = "voice-speaker-dmic-ef", + [SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = "voice-speaker-qmic", + [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic", + [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic", + [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic", + [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic", + [SND_DEVICE_IN_VOICE_REC_MIC_NS] = "voice-rec-mic", + [SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = "voice-rec-dmic-ef", + [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = "voice-rec-dmic-ef-fluence", + [SND_DEVICE_IN_USB_HEADSET_MIC] = "usb-headset-mic", + [SND_DEVICE_IN_CAPTURE_FM] = "capture-fm", + [SND_DEVICE_IN_AANC_HANDSET_MIC] = "aanc-handset-mic", + [SND_DEVICE_IN_QUAD_MIC] = "quad-mic", + [SND_DEVICE_IN_HANDSET_STEREO_DMIC] = "handset-stereo-dmic-ef", + [SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = "speaker-stereo-dmic-ef", + [SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = "vi-feedback", +}; + +/* ACDB IDs (audio DSP path configuration IDs) for each sound device */ +static int acdb_device_table[SND_DEVICE_MAX] = { + [SND_DEVICE_NONE] = -1, + [SND_DEVICE_OUT_HANDSET] = 7, + [SND_DEVICE_OUT_SPEAKER] = 14, + [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14, + [SND_DEVICE_OUT_HEADPHONES] = 10, + [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10, + [SND_DEVICE_OUT_VOICE_HANDSET] = 7, + [SND_DEVICE_OUT_VOICE_SPEAKER] = 14, + [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10, + [SND_DEVICE_OUT_HDMI] = 18, + [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14, + [SND_DEVICE_OUT_BT_SCO] = 22, + [SND_DEVICE_OUT_BT_SCO_WB] = 39, + [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17, + [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17, + [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37, + [SND_DEVICE_OUT_AFE_PROXY] = 0, + [SND_DEVICE_OUT_USB_HEADSET] = 45, + [SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 14, + [SND_DEVICE_OUT_TRANSMISSION_FM] = 0, + [SND_DEVICE_OUT_ANC_HEADSET] = 26, + [SND_DEVICE_OUT_ANC_FB_HEADSET] = 27, + [SND_DEVICE_OUT_VOICE_ANC_HEADSET] = 26, + [SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = 27, + [SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = 26, + [SND_DEVICE_OUT_ANC_HANDSET] = 103, + [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 101, + + [SND_DEVICE_IN_HANDSET_MIC] = 4, + [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106, + [SND_DEVICE_IN_HANDSET_MIC_NS] = 107, + [SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = 108, + [SND_DEVICE_IN_HANDSET_DMIC] = 41, + [SND_DEVICE_IN_HANDSET_DMIC_AEC] = 109, + [SND_DEVICE_IN_HANDSET_DMIC_NS] = 110, + [SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = 111, + [SND_DEVICE_IN_SPEAKER_MIC] = 11, + [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 112, + [SND_DEVICE_IN_SPEAKER_MIC_NS] = 113, + [SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = 114, + [SND_DEVICE_IN_SPEAKER_DMIC] = 43, + [SND_DEVICE_IN_SPEAKER_DMIC_AEC] = 115, + [SND_DEVICE_IN_SPEAKER_DMIC_NS] = 116, + [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = 117, + [SND_DEVICE_IN_HEADSET_MIC] = 8, + [SND_DEVICE_IN_HEADSET_MIC_FLUENCE] = 47, + [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11, + [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8, + [SND_DEVICE_IN_HDMI_MIC] = 4, + [SND_DEVICE_IN_BT_SCO_MIC] = 21, + [SND_DEVICE_IN_BT_SCO_MIC_WB] = 38, + [SND_DEVICE_IN_CAMCORDER_MIC] = 4, + [SND_DEVICE_IN_VOICE_DMIC] = 41, + [SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = 43, + [SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = 19, + [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16, + [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36, + [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16, + [SND_DEVICE_IN_VOICE_REC_MIC] = 4, + [SND_DEVICE_IN_VOICE_REC_MIC_NS] = 107, + [SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = 34, + [SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = 41, + [SND_DEVICE_IN_USB_HEADSET_MIC] = 44, + [SND_DEVICE_IN_CAPTURE_FM] = 0, + [SND_DEVICE_IN_AANC_HANDSET_MIC] = 104, + [SND_DEVICE_IN_QUAD_MIC] = 46, + [SND_DEVICE_IN_HANDSET_STEREO_DMIC] = 34, + [SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = 35, + [SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = 102, +}; + +struct snd_device_index { + char name[100]; + unsigned int index; +}; + +#define TO_NAME_INDEX(X) #X, X + +/* Used to get index from parsed sting */ +struct snd_device_index snd_device_name_index[SND_DEVICE_MAX] = { + {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_BT_SCO_WB)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_AFE_PROXY)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_TRANSMISSION_FM)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_ANC_FB_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_ANC_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)}, + {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC_AEC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_DMIC_AEC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_MIC_AEC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HEADSET_MIC_FLUENCE)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEADSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HDMI_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_BT_SCO_MIC_WB)}, + {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_SPEAKER_QMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_MIC_NS)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_STEREO)}, + {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE)}, + {TO_NAME_INDEX(SND_DEVICE_IN_USB_HEADSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_CAPTURE_FM)}, + {TO_NAME_INDEX(SND_DEVICE_IN_AANC_HANDSET_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_QUAD_MIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_STEREO_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_STEREO_DMIC)}, + {TO_NAME_INDEX(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK)}, +}; + +#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) +#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) + +static int set_echo_reference(struct mixer *mixer, const char* ec_ref) +{ + struct mixer_ctl *ctl; + const char *mixer_ctl_name = "EC_REF_RX"; + + ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name); + if (!ctl) { + ALOGE("%s: Could not get ctl for mixer cmd - %s", + __func__, mixer_ctl_name); + return -EINVAL; + } + ALOGV("Setting EC Reference: %s", ec_ref); + mixer_ctl_set_enum_by_string(ctl, ec_ref); + return 0; +} + +static struct csd_data *open_csd_client() +{ + struct csd_data *csd = calloc(1, sizeof(struct csd_data)); + + csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW); + if (csd->csd_client == NULL) { + ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT); + goto error; + } else { + ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT); + + csd->deinit = (deinit_t)dlsym(csd->csd_client, + "csd_client_deinit"); + if (csd->deinit == NULL) { + ALOGE("%s: dlsym error %s for csd_client_deinit", __func__, + dlerror()); + goto error; + } + csd->disable_device = (disable_device_t)dlsym(csd->csd_client, + "csd_client_disable_device"); + if (csd->disable_device == NULL) { + ALOGE("%s: dlsym error %s for csd_client_disable_device", + __func__, dlerror()); + goto error; + } + csd->enable_device = (enable_device_t)dlsym(csd->csd_client, + "csd_client_enable_device"); + if (csd->enable_device == NULL) { + ALOGE("%s: dlsym error %s for csd_client_enable_device", + __func__, dlerror()); + goto error; + } + csd->start_voice = (start_voice_t)dlsym(csd->csd_client, + "csd_client_start_voice"); + if (csd->start_voice == NULL) { + ALOGE("%s: dlsym error %s for csd_client_start_voice", + __func__, dlerror()); + goto error; + } + csd->stop_voice = (stop_voice_t)dlsym(csd->csd_client, + "csd_client_stop_voice"); + if (csd->stop_voice == NULL) { + ALOGE("%s: dlsym error %s for csd_client_stop_voice", + __func__, dlerror()); + goto error; + } + csd->volume = (volume_t)dlsym(csd->csd_client, + "csd_client_volume"); + if (csd->volume == NULL) { + ALOGE("%s: dlsym error %s for csd_client_volume", + __func__, dlerror()); + goto error; + } + csd->mic_mute = (mic_mute_t)dlsym(csd->csd_client, + "csd_client_mic_mute"); + if (csd->mic_mute == NULL) { + ALOGE("%s: dlsym error %s for csd_client_mic_mute", + __func__, dlerror()); + goto error; + } + csd->slow_talk = (slow_talk_t)dlsym(csd->csd_client, + "csd_client_slow_talk"); + if (csd->slow_talk == NULL) { + ALOGE("%s: dlsym error %s for csd_client_slow_talk", + __func__, dlerror()); + goto error; + } + csd->start_playback = (start_playback_t)dlsym(csd->csd_client, + "csd_client_start_playback"); + if (csd->start_playback == NULL) { + ALOGE("%s: dlsym error %s for csd_client_start_playback", + __func__, dlerror()); + goto error; + } + csd->stop_playback = (stop_playback_t)dlsym(csd->csd_client, + "csd_client_stop_playback"); + if (csd->stop_playback == NULL) { + ALOGE("%s: dlsym error %s for csd_client_stop_playback", + __func__, dlerror()); + goto error; + } + csd->start_record = (start_record_t)dlsym(csd->csd_client, + "csd_client_start_record"); + if (csd->start_record == NULL) { + ALOGE("%s: dlsym error %s for csd_client_start_record", + __func__, dlerror()); + goto error; + } + csd->stop_record = (stop_record_t)dlsym(csd->csd_client, + "csd_client_stop_record"); + if (csd->stop_record == NULL) { + ALOGE("%s: dlsym error %s for csd_client_stop_record", + __func__, dlerror()); + goto error; + } + csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init"); + + if (csd->init == NULL) { + ALOGE("%s: dlsym error %s for csd_client_init", + __func__, dlerror()); + goto error; + } else { + csd->init(); + } + } + return csd; + +error: + free(csd); + csd = NULL; + return csd; +} + +void close_csd_client(struct csd_data *csd) +{ + if (csd != NULL) { + csd->deinit(); + dlclose(csd->csd_client); + free(csd); + csd = NULL; + } +} + +void *platform_init(struct audio_device *adev) +{ + char platform[PROPERTY_VALUE_MAX]; + char baseband[PROPERTY_VALUE_MAX]; + char value[PROPERTY_VALUE_MAX]; + struct platform_data *my_data = NULL; + int retry_num = 0, snd_card_num = 0; + const char *snd_card_name; + + my_data = calloc(1, sizeof(struct platform_data)); + + while (snd_card_num < MAX_SND_CARD) { + adev->mixer = mixer_open(snd_card_num); + + while (!adev->mixer && retry_num < RETRY_NUMBER) { + usleep(RETRY_US); + adev->mixer = mixer_open(snd_card_num); + retry_num++; + } + + if (!adev->mixer) { + ALOGE("%s: Unable to open the mixer card: %d", __func__, + snd_card_num); + retry_num = 0; + snd_card_num++; + continue; + } + + snd_card_name = mixer_get_name(adev->mixer); + ALOGV("%s: snd_card_name: %s", __func__, snd_card_name); + + my_data->hw_info = hw_info_init(snd_card_name); + if (!my_data->hw_info) { + ALOGE("%s: Failed to init hardware info", __func__); + } else { + if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH, + MIXER_XML_PATH_AUXPCM) == -ENOSYS) + adev->audio_route = audio_route_init(snd_card_num, + MIXER_XML_PATH); + if (!adev->audio_route) { + ALOGE("%s: Failed to init audio route controls, aborting.", + __func__); + free(my_data); + return NULL; + } + adev->snd_card = snd_card_num; + ALOGD("%s: Opened sound card:%d", __func__, snd_card_num); + break; + } + retry_num = 0; + snd_card_num++; + } + + if (snd_card_num >= MAX_SND_CARD) { + ALOGE("%s: Unable to find correct sound card, aborting.", __func__); + free(my_data); + return NULL; + } + + my_data->adev = adev; + my_data->btsco_sample_rate = SAMPLE_RATE_8KHZ; + my_data->fluence_in_spkr_mode = false; + my_data->fluence_in_voice_call = false; + my_data->fluence_in_voice_rec = false; + my_data->fluence_in_audio_rec = false; + my_data->fluence_type = FLUENCE_NONE; + + property_get("ro.qc.sdk.audio.fluencetype", value, ""); + if (!strncmp("fluencepro", value, sizeof("fluencepro"))) { + my_data->fluence_type = FLUENCE_QUAD_MIC | FLUENCE_DUAL_MIC; + } else if (!strncmp("fluence", value, sizeof("fluence"))) { + my_data->fluence_type = FLUENCE_DUAL_MIC; + } else { + my_data->fluence_type = FLUENCE_NONE; + } + + if (my_data->fluence_type != FLUENCE_NONE) { + property_get("persist.audio.fluence.voicecall",value,""); + if (!strncmp("true", value, sizeof("true"))) { + my_data->fluence_in_voice_call = true; + } + + property_get("persist.audio.fluence.voicerec",value,""); + if (!strncmp("true", value, sizeof("true"))) { + my_data->fluence_in_voice_rec = true; + } + + property_get("persist.audio.fluence.audiorec",value,""); + if (!strncmp("true", value, sizeof("true"))) { + my_data->fluence_in_audio_rec = true; + } + + property_get("persist.audio.fluence.speaker",value,""); + if (!strncmp("true", value, sizeof("true"))) { + my_data->fluence_in_spkr_mode = true; + } + } + + my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT; + my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW); + if (my_data->acdb_handle == NULL) { + ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER); + } else { + ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER); + my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle, + "acdb_loader_deallocate_ACDB"); + if (!my_data->acdb_deallocate) + ALOGE("%s: Could not find the symbol acdb_loader_deallocate_ACDB from %s", + __func__, LIB_ACDB_LOADER); + + my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle, + "acdb_loader_send_audio_cal"); + if (!my_data->acdb_send_audio_cal) + ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s", + __func__, LIB_ACDB_LOADER); + + my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle, + "acdb_loader_send_voice_cal"); + if (!my_data->acdb_send_voice_cal) + ALOGE("%s: Could not find the symbol acdb_loader_send_voice_cal from %s", + __func__, LIB_ACDB_LOADER); + + my_data->acdb_reload_vocvoltable = (acdb_reload_vocvoltable_t)dlsym(my_data->acdb_handle, + "acdb_loader_reload_vocvoltable"); + if (!my_data->acdb_reload_vocvoltable) + ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s", + __func__, LIB_ACDB_LOADER); + + my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, + "acdb_loader_init_ACDB"); + if (my_data->acdb_init == NULL) + ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror()); + else + my_data->acdb_init(); + } + + /* Initialize ACDB ID's */ + platform_info_init(); + + /* init usb */ + audio_extn_usb_init(adev); + /* update sound cards appropriately */ + audio_extn_usb_set_proxy_sound_card(adev->snd_card); + + /* Read one time ssr property */ + audio_extn_ssr_update_enabled(); + audio_extn_spkr_prot_init(adev); + return my_data; +} + +void platform_deinit(void *platform) +{ + struct platform_data *my_data = (struct platform_data *)platform; + + hw_info_deinit(my_data->hw_info); + close_csd_client(my_data->csd); + + free(platform); + /* deinit usb */ + audio_extn_usb_deinit(); +} + +const char *platform_get_snd_device_name(snd_device_t snd_device) +{ + if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) + return device_table[snd_device]; + else + return ""; +} + +int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device, + char *device_name) +{ + struct platform_data *my_data = (struct platform_data *)platform; + + if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) { + strlcpy(device_name, device_table[snd_device], DEVICE_NAME_MAX_SIZE); + hw_info_append_hw_type(my_data->hw_info, snd_device, device_name); + } else { + strlcpy(device_name, "", DEVICE_NAME_MAX_SIZE); + return -EINVAL; + } + + return 0; +} + +void platform_add_backend_name(char *mixer_path, snd_device_t snd_device) +{ + if (snd_device == SND_DEVICE_IN_BT_SCO_MIC) + strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB) + strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH); + else if(snd_device == SND_DEVICE_OUT_BT_SCO) + strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH); + else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB) + strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_HDMI) + strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI) + strlcat(mixer_path, " speaker-and-hdmi", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_AFE_PROXY) + strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_USB_HEADSET) + strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET) + strlcat(mixer_path, " speaker-and-usb-headphones", + MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC) + strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_IN_CAPTURE_FM) + strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH); + else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM) + strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH); +} + +int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type) +{ + int device_id; + if (device_type == PCM_PLAYBACK) + device_id = pcm_device_table[usecase][0]; + else + device_id = pcm_device_table[usecase][1]; + return device_id; +} + +int platform_get_snd_device_index(char *snd_device_index_name) +{ + int ret = 0; + int i; + + if (snd_device_index_name == NULL) { + ALOGE("%s: snd_device_index_name is NULL", __func__); + ret = -ENODEV; + goto done; + } + + for (i=0; i < SND_DEVICE_MAX; i++) { + if(strcmp(snd_device_name_index[i].name, snd_device_index_name) == 0) { + ret = snd_device_name_index[i].index; + goto done; + } + } + ALOGE("%s: Could not find index for snd_device_index_name = %s", + __func__, snd_device_index_name); + ret = -ENODEV; +done: + return ret; +} + +int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id) +{ + int ret = 0; + + if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { + ALOGE("%s: Invalid snd_device = %d", + __func__, snd_device); + ret = -EINVAL; + goto done; + } + + acdb_device_table[snd_device] = acdb_id; +done: + return ret; +} + +int platform_send_audio_calibration(void *platform, snd_device_t snd_device) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int acdb_dev_id, acdb_dev_type; + + acdb_dev_id = acdb_device_table[snd_device]; + if (acdb_dev_id < 0) { + ALOGE("%s: Could not find acdb id for device(%d)", + __func__, snd_device); + return -EINVAL; + } + if (my_data->acdb_send_audio_cal) { + ("%s: sending audio calibration for snd_device(%d) acdb_id(%d)", + __func__, snd_device, acdb_dev_id); + if (snd_device >= SND_DEVICE_OUT_BEGIN && + snd_device < SND_DEVICE_OUT_END) + acdb_dev_type = ACDB_DEV_TYPE_OUT; + else + acdb_dev_type = ACDB_DEV_TYPE_IN; + my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type); + } + return 0; +} + +int platform_switch_voice_call_device_pre(void *platform) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int ret = 0; + + if (my_data->csd != NULL && + my_data->adev->mode == AUDIO_MODE_IN_CALL) { + /* This must be called before disabling mixer controls on APQ side */ + ret = my_data->csd->disable_device(); + if (ret < 0) { + ALOGE("%s: csd_client_disable_device, failed, error %d", + __func__, ret); + } + } + return ret; +} + +int platform_switch_voice_call_device_post(void *platform, + snd_device_t out_snd_device, + snd_device_t in_snd_device) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int acdb_rx_id, acdb_tx_id; + + if (my_data->acdb_send_voice_cal == NULL) { + ALOGE("%s: dlsym error for acdb_send_voice_call", __func__); + } else { + acdb_rx_id = acdb_device_table[out_snd_device]; + acdb_tx_id = acdb_device_table[in_snd_device]; + + if (acdb_rx_id > 0 && acdb_tx_id > 0) + my_data->acdb_send_voice_cal(acdb_rx_id, acdb_tx_id); + else + ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, + acdb_rx_id, acdb_tx_id); + } + + return 0; +} + +int platform_switch_voice_call_usecase_route_post(void *platform, + snd_device_t out_snd_device, + snd_device_t in_snd_device) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int acdb_rx_id, acdb_tx_id; + int ret = 0; + + acdb_rx_id = acdb_device_table[out_snd_device]; + acdb_tx_id = acdb_device_table[in_snd_device]; + + if (my_data->csd != NULL) { + if (acdb_rx_id > 0 && acdb_tx_id > 0) { + ret = my_data->csd->enable_device(acdb_rx_id, acdb_tx_id, + my_data->adev->acdb_settings); + if (ret < 0) { + ALOGE("%s: csd_enable_device, failed, error %d", + __func__, ret); + } + } else { + ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__, + acdb_rx_id, acdb_tx_id); + } + } + return ret; +} + +int platform_start_voice_call(void *platform, uint32_t vsid) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int ret = 0; + + if (my_data->csd != NULL) { + ret = my_data->csd->start_voice(vsid); + if (ret < 0) { + ALOGE("%s: csd_start_voice error %d\n", __func__, ret); + } + } + return ret; +} + +int platform_stop_voice_call(void *platform, uint32_t vsid) +{ + struct platform_data *my_data = (struct platform_data *)platform; + int ret = 0; + + if (my_data->csd != NULL) { + ret = my_data->csd->stop_voice(vsid); + if (ret < 0) { + ALOGE("%s: csd_stop_voice error %d\n", __func__, ret); + } + } + return ret; +} + +int platform_set_voice_volume(void *platform, int volume) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + struct mixer_ctl *ctl; + const char *mixer_ctl_name = "Voice Rx Gain"; + int vol_index = 0, ret = 0; + uint32_t set_values[ ] = {0, + ALL_SESSION_VSID, + DEFAULT_VOLUME_RAMP_DURATION_MS}; + + // Voice volume levels are mapped to adsp volume levels as follows. + // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0 + // But this values don't changed in kernel. So, below change is need. + vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX); + set_values[0] = vol_index; + + 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; + } + ALOGV("Setting voice volume index: %d", set_values[0]); + mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); + + if (my_data->csd != NULL) { + ret = my_data->csd->volume(ALL_SESSION_VSID, volume); + if (ret < 0) { + ALOGE("%s: csd_volume error %d", __func__, ret); + } + } + return ret; +} + +int platform_set_mic_mute(void *platform, bool state) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + struct mixer_ctl *ctl; + const char *mixer_ctl_name = "Voice Tx Mute"; + int ret = 0; + uint32_t set_values[ ] = {0, + ALL_SESSION_VSID, + DEFAULT_VOLUME_RAMP_DURATION_MS}; + + set_values[0] = state; + 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; + } + ALOGV("Setting voice mute state: %d", state); + mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); + + if (my_data->csd != NULL) { + ret = my_data->csd->mic_mute(ALL_SESSION_VSID, state); + if (ret < 0) { + ALOGE("%s: csd_mic_mute error %d", __func__, ret); + } + } + return ret; +} + +snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + audio_mode_t mode = adev->mode; + snd_device_t snd_device = SND_DEVICE_NONE; + + audio_channel_mask_t channel_mask = (adev->active_input == NULL) ? + AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask; + int channel_count = popcount(channel_mask); + + ALOGV("%s: enter: output devices(%#x)", __func__, devices); + if (devices == AUDIO_DEVICE_NONE || + devices & AUDIO_DEVICE_BIT_IN) { + ALOGV("%s: Invalid output devices (%#x)", __func__, devices); + goto exit; + } + + if (popcount(devices) == 2) { + if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE | + AUDIO_DEVICE_OUT_SPEAKER)) { + snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; + } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET | + AUDIO_DEVICE_OUT_SPEAKER)) { + if (audio_extn_get_anc_enabled()) + snd_device = SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET; + else + snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES; + } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL | + AUDIO_DEVICE_OUT_SPEAKER)) { + snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI; + } else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET | + AUDIO_DEVICE_OUT_SPEAKER)) { + snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET; + } else { + ALOGE("%s: Invalid combo device(%#x)", __func__, devices); + goto exit; + } + if (snd_device != SND_DEVICE_NONE) { + goto exit; + } + } + + if (popcount(devices) != 1) { + ALOGE("%s: Invalid output devices(%#x)", __func__, devices); + goto exit; + } + + if ((mode == AUDIO_MODE_IN_CALL) || + voice_extn_compress_voip_is_active(adev)) { + if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || + devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + if ((adev->voice.tty_mode != TTY_MODE_OFF) && + !voice_extn_compress_voip_is_active(adev)) { + switch (adev->voice.tty_mode) { + case TTY_MODE_FULL: + snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES; + break; + case TTY_MODE_VCO: + snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES; + break; + case TTY_MODE_HCO: + snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET; + break; + default: + ALOGE("%s: Invalid TTY mode (%#x)", + __func__, adev->voice.tty_mode); + } + } else if (audio_extn_get_anc_enabled()) { + if (audio_extn_should_use_fb_anc()) + snd_device = SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET; + else + snd_device = SND_DEVICE_OUT_VOICE_ANC_HEADSET; + } else { + snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES; + } + } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { + if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ) + snd_device = SND_DEVICE_OUT_BT_SCO_WB; + else + snd_device = SND_DEVICE_OUT_BT_SCO; + } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { + snd_device = SND_DEVICE_OUT_VOICE_SPEAKER; + } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET || + devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) { + snd_device = SND_DEVICE_OUT_USB_HEADSET; + } else if (devices & AUDIO_DEVICE_OUT_FM_TX) { + snd_device = SND_DEVICE_OUT_TRANSMISSION_FM; + } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { + if (audio_extn_should_use_handset_anc(channel_count)) + snd_device = SND_DEVICE_OUT_ANC_HANDSET; + else + snd_device = SND_DEVICE_OUT_VOICE_HANDSET; + } + if (snd_device != SND_DEVICE_NONE) { + goto exit; + } + } + + if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || + devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET + && audio_extn_get_anc_enabled()) { + if (audio_extn_should_use_fb_anc()) + snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET; + else + snd_device = SND_DEVICE_OUT_ANC_HEADSET; + } + else + snd_device = SND_DEVICE_OUT_HEADPHONES; + } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) { + if (adev->speaker_lr_swap) + snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE; + else + snd_device = SND_DEVICE_OUT_SPEAKER; + } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) { + if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ) + snd_device = SND_DEVICE_OUT_BT_SCO_WB; + else + snd_device = SND_DEVICE_OUT_BT_SCO; + } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { + snd_device = SND_DEVICE_OUT_HDMI ; + } else if (devices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET || + devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) { + snd_device = SND_DEVICE_OUT_USB_HEADSET; + } else if (devices & AUDIO_DEVICE_OUT_FM_TX) { + snd_device = SND_DEVICE_OUT_TRANSMISSION_FM; + } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) { + snd_device = SND_DEVICE_OUT_HANDSET; + } else if (devices & AUDIO_DEVICE_OUT_PROXY) { + ALOGD("%s: setting sink capability for Proxy", __func__); + audio_extn_set_afe_proxy_channel_mixer(adev); + snd_device = SND_DEVICE_OUT_AFE_PROXY; + } else { + ALOGE("%s: Unknown device(s) %#x", __func__, devices); + } +exit: + ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]); + return snd_device; +} + +snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + audio_source_t source = (adev->active_input == NULL) ? + AUDIO_SOURCE_DEFAULT : adev->active_input->source; + + audio_mode_t mode = adev->mode; + audio_devices_t in_device = ((adev->active_input == NULL) ? + AUDIO_DEVICE_NONE : adev->active_input->device) + & ~AUDIO_DEVICE_BIT_IN; + audio_channel_mask_t channel_mask = (adev->active_input == NULL) ? + AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask; + snd_device_t snd_device = SND_DEVICE_NONE; + int channel_count = popcount(channel_mask); + + ALOGV("%s: enter: out_device(%#x) in_device(%#x)", + __func__, out_device, in_device); + if ((out_device != AUDIO_DEVICE_NONE) && ((mode == AUDIO_MODE_IN_CALL) || + voice_extn_compress_voip_is_active(adev))) { + if ((adev->voice.tty_mode != TTY_MODE_OFF) && + !voice_extn_compress_voip_is_active(adev)) { + if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE || + out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + switch (adev->voice.tty_mode) { + case TTY_MODE_FULL: + snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC; + break; + case TTY_MODE_VCO: + snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC; + break; + case TTY_MODE_HCO: + snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC; + break; + default: + ALOGE("%s: Invalid TTY mode (%#x)", + __func__, adev->voice.tty_mode); + } + goto exit; + } + } + if (out_device & AUDIO_DEVICE_OUT_EARPIECE || + out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { + if (out_device & AUDIO_DEVICE_OUT_EARPIECE && + audio_extn_should_use_handset_anc(channel_count)) { + snd_device = SND_DEVICE_IN_AANC_HANDSET_MIC; + } else if (my_data->fluence_type == FLUENCE_NONE || + my_data->fluence_in_voice_call == false) { + snd_device = SND_DEVICE_IN_HANDSET_MIC; + set_echo_reference(adev->mixer, EC_REF_RX); + } else { + snd_device = SND_DEVICE_IN_VOICE_DMIC; + adev->acdb_settings |= DMIC_FLAG; + } + } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) { + if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ) + snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; + else + snd_device = SND_DEVICE_IN_BT_SCO_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { + if (my_data->fluence_type != FLUENCE_NONE && + my_data->fluence_in_voice_call && + my_data->fluence_in_spkr_mode) { + if(my_data->fluence_type & FLUENCE_QUAD_MIC) { + adev->acdb_settings |= QMIC_FLAG; + snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC; + } else { + adev->acdb_settings |= DMIC_FLAG; + snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC; + } + } else { + snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC; + } + } + } else if (source == AUDIO_SOURCE_CAMCORDER) { + if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC || + in_device & AUDIO_DEVICE_IN_BACK_MIC) { + snd_device = SND_DEVICE_IN_CAMCORDER_MIC; + } + } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) { + if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { + if (channel_count == 2) { + snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO; + adev->acdb_settings |= DMIC_FLAG; + } else if (adev->active_input->enable_ns) + snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS; + else if (my_data->fluence_type != FLUENCE_NONE && + my_data->fluence_in_voice_rec) { + snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE; + adev->acdb_settings |= DMIC_FLAG; + } else { + snd_device = SND_DEVICE_IN_VOICE_REC_MIC; + } + } + } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) { + if (out_device & AUDIO_DEVICE_OUT_SPEAKER) + in_device = AUDIO_DEVICE_IN_BACK_MIC; + if (adev->active_input) { + if (adev->active_input->enable_aec && + adev->active_input->enable_ns) { + if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC && + my_data->fluence_in_spkr_mode) { + snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS; + } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC_NS; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC_NS; + } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE; + } + set_echo_reference(adev->mixer, EC_REF_RX); + } else if (adev->active_input->enable_aec) { + if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC; + } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC; + } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE; + } + set_echo_reference(adev->mixer, EC_REF_RX); + } else if (adev->active_input->enable_ns) { + if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS; + } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { + if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + snd_device = SND_DEVICE_IN_HANDSET_DMIC_NS; + adev->acdb_settings |= DMIC_FLAG; + } else + snd_device = SND_DEVICE_IN_HANDSET_MIC_NS; + } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE; + } + set_echo_reference(adev->mixer, "NONE"); + } else + set_echo_reference(adev->mixer, "NONE"); + } + } else if (source == AUDIO_SOURCE_MIC) { + if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC && + channel_count == 1 ) { + if(my_data->fluence_type & FLUENCE_DUAL_MIC && + my_data->fluence_in_audio_rec) + snd_device = SND_DEVICE_IN_HANDSET_DMIC; + } + } else if (source == AUDIO_SOURCE_FM_RX || + source == AUDIO_SOURCE_FM_RX_A2DP) { + snd_device = SND_DEVICE_IN_CAPTURE_FM; + } else if (source == AUDIO_SOURCE_DEFAULT) { + goto exit; + } + + + if (snd_device != SND_DEVICE_NONE) { + goto exit; + } + + if (in_device != AUDIO_DEVICE_NONE && + !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) && + !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) { + if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) { + if (audio_extn_ssr_get_enabled() && channel_count == 6) + snd_device = SND_DEVICE_IN_QUAD_MIC; + else if (channel_count == 2) + snd_device = SND_DEVICE_IN_HANDSET_STEREO_DMIC; + else + snd_device = SND_DEVICE_IN_HANDSET_MIC; + } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) { + snd_device = SND_DEVICE_IN_SPEAKER_MIC; + } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_HEADSET_MIC; + } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { + if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ) + snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; + else + snd_device = SND_DEVICE_IN_BT_SCO_MIC; + } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) { + snd_device = SND_DEVICE_IN_HDMI_MIC; + } else if (in_device & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET || + in_device & AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET) { + snd_device = SND_DEVICE_IN_USB_HEADSET_MIC; + } else if (in_device & AUDIO_DEVICE_IN_FM_RX) { + snd_device = SND_DEVICE_IN_CAPTURE_FM; + } else { + ALOGE("%s: Unknown input device(s) %#x", __func__, in_device); + ALOGW("%s: Using default handset-mic", __func__); + snd_device = SND_DEVICE_IN_HANDSET_MIC; + } + } else { + if (out_device & AUDIO_DEVICE_OUT_EARPIECE) { + snd_device = SND_DEVICE_IN_HANDSET_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + snd_device = SND_DEVICE_IN_HEADSET_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) { + if (channel_count > 1) + snd_device = SND_DEVICE_IN_SPEAKER_STEREO_DMIC; + else + snd_device = SND_DEVICE_IN_SPEAKER_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { + snd_device = SND_DEVICE_IN_HANDSET_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) { + if (my_data->btsco_sample_rate == SAMPLE_RATE_16KHZ) + snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB; + else + snd_device = SND_DEVICE_IN_BT_SCO_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) { + snd_device = SND_DEVICE_IN_HDMI_MIC; + } else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET || + out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) { + snd_device = SND_DEVICE_IN_USB_HEADSET_MIC; + } else { + ALOGE("%s: Unknown output device(s) %#x", __func__, out_device); + ALOGW("%s: Using default handset-mic", __func__); + snd_device = SND_DEVICE_IN_HANDSET_MIC; + } + } +exit: + ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]); + return snd_device; +} + +int platform_set_hdmi_channels(void *platform, int channel_count) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + struct mixer_ctl *ctl; + const char *channel_cnt_str = NULL; + const char *mixer_ctl_name = "HDMI_RX Channels"; + switch (channel_count) { + case 8: + channel_cnt_str = "Eight"; break; + case 7: + channel_cnt_str = "Seven"; break; + case 6: + channel_cnt_str = "Six"; break; + case 5: + channel_cnt_str = "Five"; break; + case 4: + channel_cnt_str = "Four"; break; + case 3: + channel_cnt_str = "Three"; break; + default: + channel_cnt_str = "Two"; break; + } + 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; + } + ALOGV("HDMI channel count: %s", channel_cnt_str); + mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); + return 0; +} + +int platform_edid_get_max_channels(void *platform) +{ + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE]; + char *sad = block; + int num_audio_blocks; + int channel_count; + int max_channels = 0; + int i, ret, count; + + struct mixer_ctl *ctl; + + ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_DATA_BLOCK_MIXER_CTL); + if (!ctl) { + ALOGE("%s: Could not get ctl for mixer cmd - %s", + __func__, AUDIO_DATA_BLOCK_MIXER_CTL); + return 0; + } + + mixer_ctl_update(ctl); + + count = mixer_ctl_get_num_values(ctl); + + /* Read SAD blocks, clamping the maximum size for safety */ + if (count > (int)sizeof(block)) + count = (int)sizeof(block); + + ret = mixer_ctl_get_array(ctl, block, count); + if (ret != 0) { + ALOGE("%s: mixer_ctl_get_array() failed to get EDID info", __func__); + return 0; + } + + /* Calculate the number of SAD blocks */ + num_audio_blocks = count / SAD_BLOCK_SIZE; + + for (i = 0; i < num_audio_blocks; i++) { + /* Only consider LPCM blocks */ + if ((sad[0] >> 3) != EDID_FORMAT_LPCM) { + sad += 3; + continue; + } + + channel_count = (sad[0] & 0x7) + 1; + if (channel_count > max_channels) + max_channels = channel_count; + + /* Advance to next block */ + sad += 3; + } + + return max_channels; +} + +static int platform_set_slowtalk(struct platform_data *my_data, bool state) +{ + int ret = 0; + struct audio_device *adev = my_data->adev; + struct mixer_ctl *ctl; + const char *mixer_ctl_name = "Slowtalk Enable"; + uint32_t set_values[ ] = {0, + ALL_SESSION_VSID}; + + set_values[0] = state; + 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); + ret = -EINVAL; + } else { + ALOGV("Setting slowtalk state: %d", state); + ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); + my_data->slowtalk = state; + } + + if (my_data->csd != NULL) { + ret = my_data->csd->slow_talk(ALL_SESSION_VSID, state); + if (ret < 0) { + ALOGE("%s: csd_client_disable_device, failed, error %d", + __func__, ret); + } + } + return ret; +} + +int platform_set_parameters(void *platform, struct str_parms *parms) +{ + struct platform_data *my_data = (struct platform_data *)platform; + char *str; + char value[256] = {0}; + int val; + int ret = 0, err; + + ALOGV("%s: enter: %s", __func__, str_parms_to_str(parms)); + + err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_BTSCO, &val); + if (err >= 0) { + str_parms_del(parms, AUDIO_PARAMETER_KEY_BTSCO); + my_data->btsco_sample_rate = val; + if (val == SAMPLE_RATE_16KHZ) { + audio_route_apply_path(my_data->adev->audio_route, + "bt-sco-wb-samplerate"); + audio_route_update_mixer(my_data->adev->audio_route); + } + } + + err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SLOWTALK, value, sizeof(value)); + if (err >= 0) { + bool state = false; + if (!strncmp("true", value, sizeof("true"))) { + state = true; + } + + str_parms_del(parms, AUDIO_PARAMETER_KEY_SLOWTALK); + ret = platform_set_slowtalk(my_data, state); + if (ret) + ALOGE("%s: Failed to set slow talk err: %d", __func__, ret); + } + + err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOLUME_BOOST, + value, sizeof(value)); + if (err >= 0) { + str_parms_del(parms, AUDIO_PARAMETER_KEY_VOLUME_BOOST); + + if (my_data->acdb_reload_vocvoltable == NULL) { + ALOGE("%s: acdb_reload_vocvoltable is NULL", __func__); + } else if (!strcmp(value, "on")) { + if (!my_data->acdb_reload_vocvoltable(VOICE_FEATURE_SET_VOLUME_BOOST)) { + my_data->voice_feature_set = 1; + } + } else { + if (!my_data->acdb_reload_vocvoltable(VOICE_FEATURE_SET_DEFAULT)) { + my_data->voice_feature_set = 0; + } + } + } + + ALOGV("%s: exit with code(%d)", __func__, ret); + return ret; +} + +int platform_set_incall_recording_session_id(void *platform, + uint32_t session_id, int rec_mode) +{ + int ret = 0; + struct platform_data *my_data = (struct platform_data *)platform; + struct audio_device *adev = my_data->adev; + struct mixer_ctl *ctl; + const char *mixer_ctl_name = "Voc VSID"; + int num_ctl_values; + int i; + + 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); + ret = -EINVAL; + } else { + num_ctl_values = mixer_ctl_get_num_values(ctl); + for (i = 0; i < num_ctl_values; i++) { + if (mixer_ctl_set_value(ctl, i, session_id)) { + ALOGV("Error: invalid session_id: %x", session_id); + ret = -EINVAL; + break; + } + } + } + + if (my_data->csd != NULL) { + ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode); + if (ret < 0) { + ALOGE("%s: csd_client_start_record failed, error %d", + __func__, ret); + } + } + + return ret; +} + +int platform_stop_incall_recording_usecase(void *platform) +{ + int ret = 0; + struct platform_data *my_data = (struct platform_data *)platform; + + if (my_data->csd != NULL) { + ret = my_data->csd->stop_record(ALL_SESSION_VSID); + if (ret < 0) { + ALOGE("%s: csd_client_stop_record failed, error %d", + __func__, ret); + } + } + + return ret; +} + +int platform_start_incall_music_usecase(void *platform) +{ + int ret = 0; + struct platform_data *my_data = (struct platform_data *)platform; + + if (my_data->csd != NULL) { + ret = my_data->csd->start_playback(ALL_SESSION_VSID); + if (ret < 0) { + ALOGE("%s: csd_client_start_playback failed, error %d", + __func__, ret); + } + } + + return ret; +} + +int platform_stop_incall_music_usecase(void *platform) +{ + int ret = 0; + struct platform_data *my_data = (struct platform_data *)platform; + + if (my_data->csd != NULL) { + ret = my_data->csd->stop_playback(ALL_SESSION_VSID); + if (ret < 0) { + ALOGE("%s: csd_client_stop_playback failed, error %d", + __func__, ret); + } + } + + return ret; +} + +void platform_get_parameters(void *platform, + struct str_parms *query, + struct str_parms *reply) +{ + struct platform_data *my_data = (struct platform_data *)platform; + char *str = NULL; + char value[256] = {0}; + int ret; + int fluence_type; + + ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, + value, sizeof(value)); + if (ret >= 0) { + if (my_data->fluence_type & FLUENCE_QUAD_MIC) { + strlcpy(value, "fluencepro", sizeof(value)); + } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) { + strlcpy(value, "fluence", sizeof(value)); + } else { + strlcpy(value, "none", sizeof(value)); + } + + str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE_TYPE, value); + } + + memset(value, 0, sizeof(value)); + ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK, + value, sizeof(value)); + if (ret >= 0) { + str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SLOWTALK, + my_data->slowtalk?"true":"false"); + } + + ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOLUME_BOOST, + value, sizeof(value)); + if (ret >= 0) { + if (my_data->voice_feature_set == VOICE_FEATURE_SET_VOLUME_BOOST) { + strlcpy(value, "on", sizeof(value)); + } else { + strlcpy(value, "off", sizeof(value)); + } + + str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VOLUME_BOOST, value); + } + + ALOGV("%s: exit: returns - %s", __func__, str_parms_to_str(reply)); +} + +/* Delay in Us */ +int64_t platform_render_latency(audio_usecase_t usecase) +{ + switch (usecase) { + case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: + return DEEP_BUFFER_PLATFORM_DELAY; + case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: + return LOW_LATENCY_PLATFORM_DELAY; + default: + return 0; + } +} + +int platform_update_usecase_from_source(int source, int usecase) +{ + ALOGV("%s: input source :%d", __func__, source); + if(source == AUDIO_SOURCE_FM_RX_A2DP) + usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL; + return usecase; +} + +bool platform_listen_update_status(snd_device_t snd_device) +{ + if ((snd_device >= SND_DEVICE_IN_BEGIN) && + (snd_device < SND_DEVICE_IN_END) && + (snd_device != SND_DEVICE_IN_CAPTURE_FM) && + (snd_device != SND_DEVICE_IN_CAPTURE_VI_FEEDBACK)) + return true; + else + return false; +} diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h new file mode 100644 index 00000000..378d5788 --- /dev/null +++ b/hal/msm8916/platform.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2013 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 QCOM_AUDIO_PLATFORM_H +#define QCOM_AUDIO_PLATFORM_H + +enum { + FLUENCE_NONE, + FLUENCE_DUAL_MIC = 0x1, + FLUENCE_QUAD_MIC = 0x2, +}; + +/* + * Below are the devices for which is back end is same, SLIMBUS_0_RX. + * All these devices are handled by the internal HW codec. We can + * enable any one of these devices at any time + */ +#define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \ + (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \ + AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE) + +/* Sound devices specific to the platform + * The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound + * devices to enable corresponding mixer paths + */ +enum { + SND_DEVICE_NONE = 0, + + /* Playback devices */ + SND_DEVICE_MIN, + SND_DEVICE_OUT_BEGIN = SND_DEVICE_MIN, + SND_DEVICE_OUT_HANDSET = SND_DEVICE_OUT_BEGIN, + SND_DEVICE_OUT_SPEAKER, + SND_DEVICE_OUT_SPEAKER_REVERSE, + SND_DEVICE_OUT_HEADPHONES, + SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, + SND_DEVICE_OUT_VOICE_HANDSET, + SND_DEVICE_OUT_VOICE_SPEAKER, + SND_DEVICE_OUT_VOICE_HEADPHONES, + SND_DEVICE_OUT_HDMI, + SND_DEVICE_OUT_SPEAKER_AND_HDMI, + SND_DEVICE_OUT_BT_SCO, + SND_DEVICE_OUT_BT_SCO_WB, + SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES, + SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET, + SND_DEVICE_OUT_AFE_PROXY, + SND_DEVICE_OUT_USB_HEADSET, + SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET, + SND_DEVICE_OUT_TRANSMISSION_FM, + SND_DEVICE_OUT_ANC_HEADSET, + SND_DEVICE_OUT_ANC_FB_HEADSET, + SND_DEVICE_OUT_VOICE_ANC_HEADSET, + SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET, + SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, + SND_DEVICE_OUT_ANC_HANDSET, + SND_DEVICE_OUT_SPEAKER_PROTECTED, + SND_DEVICE_OUT_END, + + /* + * Note: IN_BEGIN should be same as OUT_END because total number of devices + * SND_DEVICES_MAX should not exceed MAX_RX + MAX_TX devices. + */ + /* Capture devices */ + SND_DEVICE_IN_BEGIN = SND_DEVICE_OUT_END, + SND_DEVICE_IN_HANDSET_MIC = SND_DEVICE_IN_BEGIN, + SND_DEVICE_IN_HANDSET_MIC_AEC, + SND_DEVICE_IN_HANDSET_MIC_NS, + SND_DEVICE_IN_HANDSET_MIC_AEC_NS, + SND_DEVICE_IN_HANDSET_DMIC, + SND_DEVICE_IN_HANDSET_DMIC_AEC, + SND_DEVICE_IN_HANDSET_DMIC_NS, + SND_DEVICE_IN_HANDSET_DMIC_AEC_NS, + SND_DEVICE_IN_SPEAKER_MIC, + SND_DEVICE_IN_SPEAKER_MIC_AEC, + SND_DEVICE_IN_SPEAKER_MIC_NS, + SND_DEVICE_IN_SPEAKER_MIC_AEC_NS, + SND_DEVICE_IN_SPEAKER_DMIC, + SND_DEVICE_IN_SPEAKER_DMIC_AEC, + SND_DEVICE_IN_SPEAKER_DMIC_NS, + SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS, + SND_DEVICE_IN_HEADSET_MIC, + SND_DEVICE_IN_HEADSET_MIC_FLUENCE, + SND_DEVICE_IN_VOICE_SPEAKER_MIC, + SND_DEVICE_IN_VOICE_HEADSET_MIC, + SND_DEVICE_IN_HDMI_MIC, + SND_DEVICE_IN_BT_SCO_MIC, + SND_DEVICE_IN_BT_SCO_MIC_WB, + SND_DEVICE_IN_CAMCORDER_MIC, + SND_DEVICE_IN_VOICE_DMIC, + SND_DEVICE_IN_VOICE_SPEAKER_DMIC, + SND_DEVICE_IN_VOICE_SPEAKER_QMIC, + SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC, + SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC, + SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC, + SND_DEVICE_IN_VOICE_REC_MIC, + SND_DEVICE_IN_VOICE_REC_MIC_NS, + SND_DEVICE_IN_VOICE_REC_DMIC_STEREO, + SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE, + SND_DEVICE_IN_USB_HEADSET_MIC, + SND_DEVICE_IN_CAPTURE_FM, + SND_DEVICE_IN_AANC_HANDSET_MIC, + SND_DEVICE_IN_QUAD_MIC, + SND_DEVICE_IN_HANDSET_STEREO_DMIC, + SND_DEVICE_IN_SPEAKER_STEREO_DMIC, + SND_DEVICE_IN_CAPTURE_VI_FEEDBACK, + SND_DEVICE_IN_END, + + SND_DEVICE_MAX = SND_DEVICE_IN_END, + +}; + +#define DEFAULT_OUTPUT_SAMPLING_RATE 48000 + +#define ALL_SESSION_VSID 0xFFFFFFFF +#define DEFAULT_MUTE_RAMP_DURATION 500 +#define DEFAULT_VOLUME_RAMP_DURATION_MS 20 +#define MIXER_PATH_MAX_LENGTH 100 + +#define MAX_VOL_INDEX 5 +#define MIN_VOL_INDEX 0 +#define percent_to_index(val, min, max) \ + ((val) * ((max) - (min)) * 0.01 + (min) + .5) + +/* + * tinyAlsa library interprets period size as number of frames + * one frame = channel_count * sizeof (pcm sample) + * so if format = 16-bit PCM and channels = Stereo, frame size = 2 ch * 2 = 4 bytes + * DEEP_BUFFER_OUTPUT_PERIOD_SIZE = 1024 means 1024 * 4 = 4096 bytes + * We should take care of returning proper size when AudioFlinger queries for + * the buffer size of an input/output stream + */ +#define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 960 +#define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 4 +#define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240 +#define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2 + +#define HDMI_MULTI_PERIOD_SIZE 336 +#define HDMI_MULTI_PERIOD_COUNT 8 +#define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6 +#define HDMI_MULTI_PERIOD_BYTES (HDMI_MULTI_PERIOD_SIZE * HDMI_MULTI_DEFAULT_CHANNEL_COUNT * 2) + +#define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20 +#define AUDIO_CAPTURE_PERIOD_COUNT 2 + +#define DEVICE_NAME_MAX_SIZE 128 +#define HW_INFO_ARRAY_MAX_SIZE 32 + +#define DEEP_BUFFER_PCM_DEVICE 0 +#define AUDIO_RECORD_PCM_DEVICE 0 +#define MULTIMEDIA2_PCM_DEVICE 1 +#define FM_PLAYBACK_PCM_DEVICE 5 +#define FM_CAPTURE_PCM_DEVICE 6 +#define HFP_PCM_RX 5 +#define HFP_SCO_RX 23 +#define HFP_ASM_RX_TX 24 + +#define INCALL_MUSIC_UPLINK_PCM_DEVICE 1 +#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16 +#define SPKR_PROT_CALIB_RX_PCM_DEVICE 5 +#define SPKR_PROT_CALIB_TX_PCM_DEVICE 22 +#define PLAYBACK_OFFLOAD_DEVICE 9 +#define COMPRESS_VOIP_CALL_PCM_DEVICE 3 + + +#define LOWLATENCY_PCM_DEVICE 12 +#define EC_REF_RX "I2S_RX" +#define COMPRESS_CAPTURE_DEVICE 19 + +#define VOICE_CALL_PCM_DEVICE 2 +#define VOICE2_CALL_PCM_DEVICE 13 +#define VOLTE_CALL_PCM_DEVICE 15 +#define QCHAT_CALL_PCM_DEVICE 14 + +#define LIB_CSD_CLIENT "libcsd-client.so" +/* CSD-CLIENT related functions */ +typedef int (*init_t)(); +typedef int (*deinit_t)(); +typedef int (*disable_device_t)(); +typedef int (*enable_device_t)(int, int, uint32_t); +typedef int (*volume_t)(uint32_t, int); +typedef int (*mic_mute_t)(uint32_t, int); +typedef int (*slow_talk_t)(uint32_t, uint8_t); +typedef int (*start_voice_t)(uint32_t); +typedef int (*stop_voice_t)(uint32_t); +typedef int (*start_playback_t)(uint32_t); +typedef int (*stop_playback_t)(uint32_t); +typedef int (*start_record_t)(uint32_t, int); +typedef int (*stop_record_t)(uint32_t); +/* CSD Client structure */ +struct csd_data { + void *csd_client; + init_t init; + deinit_t deinit; + disable_device_t disable_device; + enable_device_t enable_device; + volume_t volume; + mic_mute_t mic_mute; + slow_talk_t slow_talk; + start_voice_t start_voice; + stop_voice_t stop_voice; + start_playback_t start_playback; + stop_playback_t stop_playback; + start_record_t start_record; + stop_record_t stop_record; +}; + +#endif // QCOM_AUDIO_PLATFORM_H diff --git a/mm-audio/aenc-aac/Android.mk b/mm-audio/aenc-aac/Android.mk index 8ab45b3a..7cd804a4 100644 --- a/mm-audio/aenc-aac/Android.mk +++ b/mm-audio/aenc-aac/Android.mk @@ -24,6 +24,8 @@ endif ifeq ($(call is-board-platform,mpq8092),true) include $(AENC_AAC_PATH)/qdsp6/Android.mk endif - +ifeq ($(call is-board-platform,msm8916),true) +include $(AENC_AAC_PATH)/qdsp6/Android.mk +endif endif diff --git a/mm-audio/aenc-amrnb/Android.mk b/mm-audio/aenc-amrnb/Android.mk index 2601edeb..79474c60 100644 --- a/mm-audio/aenc-amrnb/Android.mk +++ b/mm-audio/aenc-amrnb/Android.mk @@ -24,6 +24,8 @@ endif ifeq ($(call is-board-platform,mpq8092),true) include $(AENC_AMR_PATH)/qdsp6/Android.mk endif - +ifeq ($(call is-board-platform,msm8916),true) +include $(AENC_AMR_PATH)/qdsp6/Android.mk +endif endif diff --git a/mm-audio/aenc-evrc/Android.mk b/mm-audio/aenc-evrc/Android.mk index 2f42d6ba..649f8607 100644 --- a/mm-audio/aenc-evrc/Android.mk +++ b/mm-audio/aenc-evrc/Android.mk @@ -24,6 +24,8 @@ endif ifeq ($(call is-board-platform,mpq8092),true) include $(AENC_EVRC_PATH)/qdsp6/Android.mk endif - +ifeq ($(call is-board-platform,msm8916),true) +include $(AENC_EVRC_PATH)/qdsp6/Android.mk +endif endif diff --git a/mm-audio/aenc-qcelp13/Android.mk b/mm-audio/aenc-qcelp13/Android.mk index fe18efc5..c919f190 100644 --- a/mm-audio/aenc-qcelp13/Android.mk +++ b/mm-audio/aenc-qcelp13/Android.mk @@ -24,5 +24,8 @@ endif ifeq ($(call is-board-platform,mpq8092),true) include $(AENC_QCELP13_PATH)/qdsp6/Android.mk endif +ifeq ($(call is-board-platform,msm8916),true) +include $(AENC_QCELP13_PATH)/qdsp6/Android.mk +endif endif