Home | History | Annotate | Download | only in alsa_sound
      1 /* alsa_default.cpp
      2  **
      3  ** Copyright 2009 Wind River Systems
      4  ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
      5  **
      6  ** Licensed under the Apache License, Version 2.0 (the "License");
      7  ** you may not use this file except in compliance with the License.
      8  ** You may obtain a copy of the License at
      9  **
     10  **     http://www.apache.org/licenses/LICENSE-2.0
     11  **
     12  ** Unless required by applicable law or agreed to in writing, software
     13  ** distributed under the License is distributed on an "AS IS" BASIS,
     14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  ** See the License for the specific language governing permissions and
     16  ** limitations under the License.
     17  */
     18 
     19 #define LOG_TAG "ALSAModule"
     20 //#define LOG_NDEBUG 0
     21 #define LOG_NDDEBUG 0
     22 #include <utils/Log.h>
     23 #include <cutils/properties.h>
     24 #include <linux/ioctl.h>
     25 #include "AudioUtil.h"
     26 #include "AudioHardwareALSA.h"
     27 #include <media/AudioRecord.h>
     28 #include <dlfcn.h>
     29 #ifdef QCOM_CSDCLIENT_ENABLED
     30 extern "C" {
     31 static int (*csd_disable_device)();
     32 static int (*csd_enable_device)(int, int, uint32_t);
     33 static int (*csd_volume)(int);
     34 static int (*csd_mic_mute)(int);
     35 static int (*csd_wide_voice)(uint8_t);
     36 static int (*csd_slow_talk)(uint8_t);
     37 static int (*csd_fens)(uint8_t);
     38 static int (*csd_start_voice)();
     39 static int (*csd_stop_voice)();
     40 }
     41 #endif
     42 
     43 #ifndef ALSA_DEFAULT_SAMPLE_RATE
     44 #define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
     45 #endif
     46 
     47 #define BTSCO_RATE_16KHZ 16000
     48 #define USECASE_TYPE_RX 1
     49 #define USECASE_TYPE_TX 2
     50 #define MAX_HDMI_CHANNEL_CNT 6
     51 
     52 namespace android_audio_legacy
     53 {
     54 
     55 static int      s_device_open(const hw_module_t*, const char*, hw_device_t**);
     56 static int      s_device_close(hw_device_t*);
     57 static status_t s_init(alsa_device_t *, ALSAHandleList &);
     58 static status_t s_open(alsa_handle_t *);
     59 static status_t s_close(alsa_handle_t *);
     60 static status_t s_standby(alsa_handle_t *);
     61 static status_t s_route(alsa_handle_t *, uint32_t, int);
     62 static status_t s_start_voice_call(alsa_handle_t *);
     63 static status_t s_start_voip_call(alsa_handle_t *);
     64 static status_t s_start_fm(alsa_handle_t *);
     65 static void     s_set_voice_volume(int);
     66 static void     s_set_voip_volume(int);
     67 static void     s_set_mic_mute(int);
     68 static void     s_set_voip_mic_mute(int);
     69 static void     s_set_voip_config(int, int);
     70 static status_t s_set_fm_vol(int);
     71 static void     s_set_btsco_rate(int);
     72 static status_t s_set_lpa_vol(int);
     73 static void     s_enable_wide_voice(bool flag);
     74 static void     s_enable_fens(bool flag);
     75 static void     s_set_flags(uint32_t flags);
     76 static status_t s_set_compressed_vol(int);
     77 static void     s_enable_slow_talk(bool flag);
     78 static void     s_set_voc_rec_mode(uint8_t mode);
     79 static void     s_set_volte_mic_mute(int state);
     80 static void     s_set_volte_volume(int vol);
     81 static bool     s_is_tmus();
     82 #ifdef SEPERATED_AUDIO_INPUT
     83 static void     s_setInput(int);
     84 
     85 static int input_source;
     86 #endif
     87 static int mccmnc;
     88 #ifdef QCOM_CSDCLIENT_ENABLED
     89 static void     s_set_csd_handle(void*);
     90 #endif
     91 
     92 static char mic_type[25];
     93 static char curRxUCMDevice[50];
     94 static char curTxUCMDevice[50];
     95 static int fluence_mode;
     96 static int fmVolume;
     97 #ifdef USES_FLUENCE_INCALL
     98 static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG;
     99 #else
    100 static uint32_t mDevSettingsFlag = TTY_OFF;
    101 #endif
    102 static int btsco_samplerate = 8000;
    103 static ALSAUseCaseList mUseCaseList;
    104 static void *csd_handle;
    105 
    106 static hw_module_methods_t s_module_methods = {
    107     open            : s_device_open
    108 };
    109 
    110 extern "C" {
    111 hw_module_t HAL_MODULE_INFO_SYM = {
    112     tag             : HARDWARE_MODULE_TAG,
    113     version_major   : 1,
    114     version_minor   : 0,
    115     id              : ALSA_HARDWARE_MODULE_ID,
    116     name            : "QCOM ALSA module",
    117     author          : "QuIC Inc",
    118     methods         : &s_module_methods,
    119     dso             : 0,
    120     reserved        : {0,},
    121 };
    122 }
    123 
    124 static int s_device_open(const hw_module_t* module, const char* name,
    125         hw_device_t** device)
    126 {
    127     char value[128];
    128     alsa_device_t *dev;
    129     dev = (alsa_device_t *) malloc(sizeof(*dev));
    130     if (!dev) return -ENOMEM;
    131 
    132     memset(dev, 0, sizeof(*dev));
    133 
    134     /* initialize the procs */
    135     dev->common.tag = HARDWARE_DEVICE_TAG;
    136     dev->common.version = 0;
    137     dev->common.module = (hw_module_t *) module;
    138     dev->common.close = s_device_close;
    139     dev->init = s_init;
    140     dev->open = s_open;
    141     dev->close = s_close;
    142     dev->route = s_route;
    143     dev->standby = s_standby;
    144     dev->startVoiceCall = s_start_voice_call;
    145     dev->startVoipCall = s_start_voip_call;
    146     dev->startFm = s_start_fm;
    147     dev->setVoiceVolume = s_set_voice_volume;
    148     dev->setVoipVolume = s_set_voip_volume;
    149     dev->setMicMute = s_set_mic_mute;
    150     dev->setVoipMicMute = s_set_voip_mic_mute;
    151     dev->setVoipConfig = s_set_voip_config;
    152     dev->setFmVolume = s_set_fm_vol;
    153     dev->setBtscoRate = s_set_btsco_rate;
    154     dev->setLpaVolume = s_set_lpa_vol;
    155     dev->enableWideVoice = s_enable_wide_voice;
    156     dev->enableFENS = s_enable_fens;
    157     dev->setFlags = s_set_flags;
    158     dev->setCompressedVolume = s_set_compressed_vol;
    159     dev->enableSlowTalk = s_enable_slow_talk;
    160     dev->setVocRecMode = s_set_voc_rec_mode;
    161     dev->setVoLTEMicMute = s_set_volte_mic_mute;
    162     dev->setVoLTEVolume = s_set_volte_volume;
    163 #ifdef SEPERATED_AUDIO_INPUT
    164     dev->setInput = s_setInput;
    165 #endif
    166 #ifdef QCOM_CSDCLIENT_ENABLED
    167     dev->setCsdHandle = s_set_csd_handle;
    168 #endif
    169     *device = &dev->common;
    170 
    171     property_get("persist.audio.handset.mic",value,"0");
    172     strlcpy(mic_type, value, sizeof(mic_type));
    173     property_get("persist.audio.fluence.mode",value,"0");
    174     if (!strcmp("broadside", value)) {
    175         fluence_mode = FLUENCE_MODE_BROADSIDE;
    176     } else {
    177         fluence_mode = FLUENCE_MODE_ENDFIRE;
    178     }
    179     strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
    180     strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
    181     ALOGV("ALSA module opened");
    182 
    183     return 0;
    184 }
    185 
    186 static int s_device_close(hw_device_t* device)
    187 {
    188     free(device);
    189     device = NULL;
    190     return 0;
    191 }
    192 
    193 // ----------------------------------------------------------------------------
    194 
    195 static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
    196 
    197 static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
    198 static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
    199 static void disableDevice(alsa_handle_t *handle);
    200 int getUseCaseType(const char *useCase);
    201 
    202 static int callMode = AudioSystem::MODE_NORMAL;
    203 // ----------------------------------------------------------------------------
    204 
    205 bool platform_is_Fusion3()
    206 {
    207     char platform[128], baseband[128];
    208     property_get("ro.board.platform", platform, "");
    209     property_get("ro.baseband", baseband, "");
    210     if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
    211         return true;
    212     else
    213         return false;
    214 }
    215 
    216 int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
    217 {
    218     int ret = 0;
    219     char ident[70];
    220 
    221     if (flags & PCM_IN) {
    222         strlcpy(ident, "CapturePCM/", sizeof(ident));
    223     } else {
    224         strlcpy(ident, "PlaybackPCM/", sizeof(ident));
    225     }
    226     strlcat(ident, handle->useCase, sizeof(ident));
    227     ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
    228     ALOGD("Device value returned is %s", (*value));
    229     return ret;
    230 }
    231 
    232 status_t setHDMIChannelCount()
    233 {
    234     status_t err = NO_ERROR;
    235     int channel_count = 0;
    236     const char *channel_cnt_str = NULL;
    237     EDID_AUDIO_INFO info = { 0 };
    238 
    239     ALSAControl control("/dev/snd/controlC0");
    240     if (AudioUtil::getHDMIAudioSinkCaps(&info)) {
    241         for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) {
    242             if (info.AudioBlocksArray[i].nChannels > channel_count &&
    243                   info.AudioBlocksArray[i].nChannels <= MAX_HDMI_CHANNEL_CNT) {
    244                 channel_count = info.AudioBlocksArray[i].nChannels;
    245             }
    246         }
    247     }
    248 
    249     switch (channel_count) {
    250     case 6: channel_cnt_str = "Six"; break;
    251     case 5: channel_cnt_str = "Five"; break;
    252     case 4: channel_cnt_str = "Four"; break;
    253     case 3: channel_cnt_str = "Three"; break;
    254     default: channel_cnt_str = "Two"; break;
    255     }
    256     ALOGD("HDMI channel count: %s", channel_cnt_str);
    257     control.set("HDMI_RX Channels", channel_cnt_str);
    258 
    259     return err;
    260 }
    261 
    262 status_t setHardwareParams(alsa_handle_t *handle)
    263 {
    264     struct snd_pcm_hw_params *params;
    265     unsigned long bufferSize, reqBuffSize;
    266     unsigned int periodTime, bufferTime;
    267     unsigned int requestedRate = handle->sampleRate;
    268     int status = 0;
    269     int channels = handle->channels;
    270     snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
    271 
    272     params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
    273     if (!params) {
    274         ALOGE("Failed to allocate ALSA hardware parameters!");
    275         return NO_INIT;
    276     }
    277 
    278     reqBuffSize = handle->bufferSize;
    279     ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
    280          (int) reqBuffSize, handle->channels, handle->sampleRate);
    281 
    282 #ifdef QCOM_SSR_ENABLED
    283     if (channels == 6) {
    284         if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
    285             || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
    286             ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
    287             channels = 4;
    288         }
    289     }
    290 #endif
    291 
    292     param_init(params);
    293     param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
    294                    SNDRV_PCM_ACCESS_RW_INTERLEAVED);
    295     if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
    296         if (handle->format == AudioSystem::AMR_NB
    297             || handle->format == AudioSystem::AMR_WB
    298 #ifdef QCOM_QCHAT_ENABLED
    299             || handle->format == AudioSystem::EVRC
    300             || handle->format == AudioSystem::EVRCB
    301             || handle->format == AudioSystem::EVRCWB
    302 #endif
    303             )
    304               format = SNDRV_PCM_FORMAT_SPECIAL;
    305     }
    306     param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
    307                    format);
    308     param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
    309                    SNDRV_PCM_SUBFORMAT_STD);
    310     param_set_int(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
    311     param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
    312     param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
    313                    channels * 16);
    314     param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
    315                   channels);
    316     param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
    317     param_set_hw_refine(handle->handle, params);
    318 
    319     if (param_set_hw_params(handle->handle, params)) {
    320         ALOGE("cannot set hw params");
    321         return NO_INIT;
    322     }
    323     param_dump(params);
    324 
    325     handle->handle->buffer_size = pcm_buffer_size(params);
    326     handle->handle->period_size = pcm_period_size(params);
    327     handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
    328     ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
    329         handle->handle->buffer_size, handle->handle->period_size,
    330         handle->handle->period_cnt);
    331     handle->handle->rate = handle->sampleRate;
    332     handle->handle->channels = handle->channels;
    333     handle->periodSize = handle->handle->period_size;
    334     if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
    335         strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
    336         (6 != handle->channels)) {
    337         //Do not update buffersize for 5.1 recording
    338         handle->bufferSize = handle->handle->period_size;
    339     }
    340 
    341     return NO_ERROR;
    342 }
    343 
    344 status_t setSoftwareParams(alsa_handle_t *handle)
    345 {
    346     struct snd_pcm_sw_params* params;
    347     struct pcm* pcm = handle->handle;
    348 
    349     unsigned long periodSize = pcm->period_size;
    350     int channels = handle->channels;
    351 
    352     params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
    353     if (!params) {
    354         LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
    355         return NO_INIT;
    356     }
    357 
    358 #ifdef QCOM_SSR_ENABLED
    359     if (channels == 6) {
    360         if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
    361             || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
    362             ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
    363             channels = 4;
    364         }
    365     }
    366 #endif
    367 
    368     // Get the current software parameters
    369     params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
    370     params->period_step = 1;
    371     if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
    372         (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
    373           ALOGV("setparam:  start & stop threshold for Voip ");
    374           params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
    375           params->start_threshold = periodSize/2;
    376           params->stop_threshold = INT_MAX;
    377      } else {
    378          params->avail_min = periodSize/(channels * 2);
    379          params->start_threshold = periodSize/(channels * 2);
    380          params->stop_threshold = INT_MAX;
    381      }
    382     params->silence_threshold = 0;
    383     params->silence_size = 0;
    384 
    385     if (param_set_sw_params(handle->handle, params)) {
    386         ALOGE("cannot set sw params");
    387         return NO_INIT;
    388     }
    389     return NO_ERROR;
    390 }
    391 
    392 void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
    393 {
    394     const char **mods_list;
    395     use_case_t useCaseNode;
    396     unsigned usecase_type = 0;
    397     bool inCallDevSwitch = false;
    398     char *rxDevice, *txDevice, ident[70], *use_case = NULL;
    399     int err = 0, index, mods_size;
    400     int rx_dev_id, tx_dev_id;
    401     ALOGD("%s: device %d mode:%d", __FUNCTION__, devices, mode);
    402 
    403     if ((mode == AudioSystem::MODE_IN_CALL)  || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
    404         if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
    405             (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
    406             devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
    407                       AudioSystem::DEVICE_IN_WIRED_HEADSET);
    408         } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
    409             devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
    410                       AudioSystem::DEVICE_IN_BUILTIN_MIC);
    411         } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
    412             if (mode == AudioSystem::MODE_IN_CALL) {
    413                 devices |= AudioSystem::DEVICE_OUT_EARPIECE;
    414             } else if (mode == AudioSystem::MODE_IN_COMMUNICATION) {
    415                 if (!strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER, MAX_LEN(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER))) {
    416                     devices &= ~AudioSystem::DEVICE_IN_BUILTIN_MIC;
    417                     devices |= AudioSystem::DEVICE_IN_BACK_MIC;
    418                 }
    419             }
    420         } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
    421             devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
    422         } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
    423             devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
    424                        AudioSystem::DEVICE_OUT_SPEAKER);
    425         } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
    426                    (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
    427                    (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
    428             devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
    429                       AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
    430 #ifdef QCOM_ANC_HEADSET_ENABLED
    431         } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
    432                    (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
    433             devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
    434                       AudioSystem::DEVICE_IN_ANC_HEADSET);
    435         } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
    436             devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
    437                       AudioSystem::DEVICE_IN_BUILTIN_MIC);
    438 #endif
    439         } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
    440             if (mode == AudioSystem::MODE_IN_CALL)
    441                 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
    442                            AudioSystem::DEVICE_OUT_SPEAKER);
    443             else
    444                 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
    445                           AudioSystem::DEVICE_IN_BACK_MIC);
    446 #ifdef QCOM_PROXY_DEVICE_ENABLED
    447         } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
    448                   (devices & AudioSystem::DEVICE_IN_PROXY)) {
    449             devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
    450                       AudioSystem::DEVICE_IN_PROXY);
    451 #endif
    452         }
    453     }
    454 #ifdef QCOM_SSR_ENABLED
    455     if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
    456         if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
    457             || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
    458             ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
    459             s_set_flags(SSRQMIC_FLAG);
    460         }
    461     }
    462 #endif
    463 
    464     rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
    465     txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
    466 
    467     if ((rxDevice != NULL) && (txDevice != NULL)) {
    468         if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
    469             (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
    470             ((mode == AudioSystem::MODE_IN_CALL)  ||
    471             (mode == AudioSystem::MODE_IN_COMMUNICATION)))
    472             inCallDevSwitch = true;
    473     }
    474 
    475 #ifdef QCOM_CSDCLIENT_ENABLED
    476     if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
    477         if (csd_disable_device == NULL) {
    478             ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
    479         } else {
    480             err = csd_disable_device();
    481             if (err < 0)
    482             {
    483                 ALOGE("csd_client_disable_device, failed, error %d", err);
    484             }
    485         }
    486     }
    487 #endif
    488 
    489     snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
    490     mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
    491     if (rxDevice != NULL) {
    492         if ((strncmp(curRxUCMDevice, "None", 4)) &&
    493             ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
    494             if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
    495                 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
    496                 usecase_type = getUseCaseType(use_case);
    497                 if (usecase_type & USECASE_TYPE_RX) {
    498                     ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
    499                     strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
    500                     snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
    501                     mUseCaseList.push_front(useCaseNode);
    502                 }
    503             }
    504             if (mods_size) {
    505                 for(index = 0; index < mods_size; index++) {
    506                     usecase_type = getUseCaseType(mods_list[index]);
    507                     if (usecase_type & USECASE_TYPE_RX) {
    508                         ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
    509                         strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
    510                         snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
    511                         mUseCaseList.push_back(useCaseNode);
    512                     }
    513                 }
    514             }
    515             snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
    516         }
    517     }
    518     if (txDevice != NULL) {
    519         if ((strncmp(curTxUCMDevice, "None", 4)) &&
    520             ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
    521             if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
    522                 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
    523                 usecase_type = getUseCaseType(use_case);
    524                 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
    525                     ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
    526                     strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
    527                     snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
    528                     mUseCaseList.push_front(useCaseNode);
    529                 }
    530             }
    531             if (mods_size) {
    532                 for(index = 0; index < mods_size; index++) {
    533                     usecase_type = getUseCaseType(mods_list[index]);
    534                     if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
    535                         ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
    536                         strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
    537                         snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
    538                         mUseCaseList.push_back(useCaseNode);
    539                     }
    540                 }
    541             }
    542             snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
    543        }
    544     }
    545     ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
    546 
    547     if (rxDevice != NULL) {
    548         snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
    549         strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
    550 #ifdef QCOM_FM_ENABLED
    551         if (devices & AudioSystem::DEVICE_OUT_FM)
    552             s_set_fm_vol(fmVolume);
    553 #endif
    554     }
    555     if (txDevice != NULL) {
    556        snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
    557        strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
    558     }
    559     for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
    560         ALOGD("Route use case %s\n", it->useCase);
    561         if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
    562             strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
    563             snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
    564         } else {
    565             snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
    566         }
    567     }
    568     if (!mUseCaseList.empty())
    569         mUseCaseList.clear();
    570     if (use_case != NULL) {
    571         free(use_case);
    572         use_case = NULL;
    573     }
    574     ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
    575 
    576     if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
    577         /* get tx acdb id */
    578         memset(&ident,0,sizeof(ident));
    579         strlcpy(ident, "ACDBID/", sizeof(ident));
    580         strlcat(ident, curTxUCMDevice, sizeof(ident));
    581         tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
    582 
    583        /* get rx acdb id */
    584         memset(&ident,0,sizeof(ident));
    585         strlcpy(ident, "ACDBID/", sizeof(ident));
    586         strlcat(ident, curRxUCMDevice, sizeof(ident));
    587         rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
    588 
    589         if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
    590          && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
    591             tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
    592         }
    593 
    594 #ifdef QCOM_CSDCLIENT_ENABLED
    595         ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
    596         if (csd_enable_device == NULL) {
    597             ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
    598         } else {
    599             err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
    600             if (err < 0)
    601             {
    602                 ALOGE("csd_client_disable_device failed, error %d", err);
    603             }
    604         }
    605 #endif
    606     }
    607 
    608     if (rxDevice != NULL) {
    609         free(rxDevice);
    610         rxDevice = NULL;
    611     }
    612     if (txDevice != NULL) {
    613         free(txDevice);
    614         txDevice = NULL;
    615     }
    616 }
    617 
    618 // ----------------------------------------------------------------------------
    619 
    620 static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
    621 {
    622     ALOGV("s_init: Initializing devices for ALSA module");
    623 
    624     list.clear();
    625 
    626     return NO_ERROR;
    627 }
    628 
    629 static status_t s_open(alsa_handle_t *handle)
    630 {
    631     char *devName;
    632     unsigned flags = 0;
    633     int err = NO_ERROR;
    634 
    635     if(handle->devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
    636         err = setHDMIChannelCount();
    637         if(err != OK) {
    638             ALOGE("setHDMIChannelCount err = %d", err);
    639             return err;
    640         }
    641     }
    642     /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
    643     if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
    644     ||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
    645         ALOGV("s_open: Opening LPA /Tunnel playback");
    646         return NO_ERROR;
    647     }
    648 
    649     s_close(handle);
    650 
    651     ALOGV("s_open: handle %p", handle);
    652 
    653     // ASoC multicomponent requires a valid path (frontend/backend) for
    654     // the device to be opened
    655 
    656     // The PCM stream is opened in blocking mode, per ALSA defaults.  The
    657     // AudioFlinger seems to assume blocking mode too, so asynchronous mode
    658     // should not be used.
    659     if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
    660         (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
    661         (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
    662         (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
    663         ALOGV("LPA/tunnel use case");
    664         flags |= PCM_MMAP;
    665         flags |= DEBUG_ON;
    666     } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
    667         (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI2)) ||
    668         (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
    669         (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
    670         (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
    671         (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
    672         ALOGV("Music case");
    673         flags = PCM_OUT;
    674     } else {
    675         flags = PCM_IN;
    676     }
    677     if (handle->channels == 1) {
    678         flags |= PCM_MONO;
    679     }
    680     else if (handle->channels == 4 ) {
    681         flags |= PCM_QUAD;
    682     } else if (handle->channels == 6 ) {
    683 #ifdef QCOM_SSR_ENABLED
    684         if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
    685             || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
    686             flags |= PCM_QUAD;
    687         } else {
    688             flags |= PCM_5POINT1;
    689         }
    690 #else
    691         flags |= PCM_5POINT1;
    692 #endif
    693     }
    694     else {
    695         flags |= PCM_STEREO;
    696     }
    697     if (deviceName(handle, flags, &devName) < 0) {
    698         ALOGE("Failed to get pcm device node: %s", devName);
    699         return NO_INIT;
    700     }
    701     if (devName != NULL) {
    702         handle->handle = pcm_open(flags, (char*)devName);
    703     } else {
    704         ALOGE("Failed to get pcm device node");
    705         return NO_INIT;
    706     }
    707 
    708     if (!handle->handle) {
    709         ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
    710         free(devName);
    711         return NO_INIT;
    712     }
    713 
    714     handle->handle->flags = flags;
    715     err = setHardwareParams(handle);
    716 
    717     if (err == NO_ERROR) {
    718         err = setSoftwareParams(handle);
    719     }
    720 
    721     if(err != NO_ERROR) {
    722         ALOGE("Set HW/SW params failed: Closing the pcm stream");
    723         s_standby(handle);
    724     }
    725 
    726     free(devName);
    727     return NO_ERROR;
    728 }
    729 
    730 static status_t s_start_voip_call(alsa_handle_t *handle)
    731 {
    732 
    733     char* devName;
    734     char* devName1;
    735     unsigned flags = 0;
    736     int err = NO_ERROR;
    737     uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
    738 
    739     s_close(handle);
    740     flags = PCM_OUT;
    741     flags |= PCM_MONO;
    742     ALOGV("s_open:s_start_voip_call  handle %p", handle);
    743 
    744     if (deviceName(handle, flags, &devName) < 0) {
    745          ALOGE("Failed to get pcm device node");
    746          return NO_INIT;
    747     }
    748 
    749     if (devName != NULL) {
    750         handle->handle = pcm_open(flags, (char*)devName);
    751     } else {
    752          ALOGE("Failed to get pcm device node");
    753          return NO_INIT;
    754     }
    755 
    756      if (!handle->handle) {
    757           free(devName);
    758           ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
    759           return NO_INIT;
    760      }
    761 
    762      if (!pcm_ready(handle->handle)) {
    763          ALOGE(" pcm ready failed");
    764      }
    765 
    766      handle->handle->flags = flags;
    767      err = setHardwareParams(handle);
    768 
    769      if (err == NO_ERROR) {
    770          err = setSoftwareParams(handle);
    771      }
    772 
    773      err = pcm_prepare(handle->handle);
    774      if(err != NO_ERROR) {
    775          ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
    776      }
    777 
    778      /* first write required start dsp */
    779      memset(&voc_pkt,0,sizeof(voc_pkt));
    780      pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
    781      handle->rxHandle = handle->handle;
    782      free(devName);
    783      ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
    784      flags = PCM_IN;
    785      flags |= PCM_MONO;
    786      handle->handle = 0;
    787 
    788      if (deviceName(handle, flags, &devName1) < 0) {
    789         ALOGE("Failed to get pcm device node");
    790         return NO_INIT;
    791      }
    792     if (devName != NULL) {
    793         handle->handle = pcm_open(flags, (char*)devName1);
    794     } else {
    795          ALOGE("Failed to get pcm device node");
    796          return NO_INIT;
    797     }
    798 
    799      if (!handle->handle) {
    800          free(devName);
    801          ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
    802          return NO_INIT;
    803      }
    804 
    805      if (!pcm_ready(handle->handle)) {
    806         ALOGE(" pcm ready in failed");
    807      }
    808 
    809      handle->handle->flags = flags;
    810 
    811      err = setHardwareParams(handle);
    812 
    813      if (err == NO_ERROR) {
    814          err = setSoftwareParams(handle);
    815      }
    816 
    817 
    818      err = pcm_prepare(handle->handle);
    819      if(err != NO_ERROR) {
    820          ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
    821      }
    822 
    823      /* first read required start dsp */
    824      memset(&voc_pkt,0,sizeof(voc_pkt));
    825      pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
    826      return NO_ERROR;
    827 }
    828 
    829 static status_t s_start_voice_call(alsa_handle_t *handle)
    830 {
    831     char* devName;
    832     unsigned flags = 0;
    833     int err = NO_ERROR;
    834 
    835     ALOGV("s_start_voice_call: handle %p", handle);
    836 
    837     // ASoC multicomponent requires a valid path (frontend/backend) for
    838     // the device to be opened
    839 
    840     flags = PCM_OUT | PCM_MONO;
    841     if (deviceName(handle, flags, &devName) < 0) {
    842         ALOGE("Failed to get pcm device node");
    843         return NO_INIT;
    844     }
    845     if (devName != NULL) {
    846         handle->handle = pcm_open(flags, (char*)devName);
    847     } else {
    848          ALOGE("Failed to get pcm device node");
    849          return NO_INIT;
    850     }
    851     if (!handle->handle) {
    852         ALOGE("s_start_voicecall: could not open PCM device");
    853         goto Error;
    854     }
    855 
    856     handle->handle->flags = flags;
    857     err = setHardwareParams(handle);
    858     if(err != NO_ERROR) {
    859         ALOGE("s_start_voice_call: setHardwareParams failed");
    860         goto Error;
    861     }
    862 
    863     err = setSoftwareParams(handle);
    864     if(err != NO_ERROR) {
    865         ALOGE("s_start_voice_call: setSoftwareParams failed");
    866         goto Error;
    867     }
    868 
    869     err = pcm_prepare(handle->handle);
    870     if(err != NO_ERROR) {
    871         ALOGE("s_start_voice_call: pcm_prepare failed");
    872         goto Error;
    873     }
    874 
    875     if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
    876         ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
    877         goto Error;
    878     }
    879 
    880     // Store the PCM playback device pointer in rxHandle
    881     handle->rxHandle = handle->handle;
    882     free(devName);
    883 
    884     // Open PCM capture device
    885     flags = PCM_IN | PCM_MONO;
    886     if (deviceName(handle, flags, &devName) < 0) {
    887         ALOGE("Failed to get pcm device node");
    888         goto Error;
    889     }
    890     if (devName != NULL) {
    891         handle->handle = pcm_open(flags, (char*)devName);
    892     } else {
    893          ALOGE("Failed to get pcm device node");
    894          return NO_INIT;
    895     }
    896     if (!handle->handle) {
    897         free(devName);
    898         goto Error;
    899     }
    900 
    901     handle->handle->flags = flags;
    902     err = setHardwareParams(handle);
    903     if(err != NO_ERROR) {
    904         ALOGE("s_start_voice_call: setHardwareParams failed");
    905         goto Error;
    906     }
    907 
    908     err = setSoftwareParams(handle);
    909     if(err != NO_ERROR) {
    910         ALOGE("s_start_voice_call: setSoftwareParams failed");
    911         goto Error;
    912     }
    913 
    914     err = pcm_prepare(handle->handle);
    915     if(err != NO_ERROR) {
    916         ALOGE("s_start_voice_call: pcm_prepare failed");
    917         goto Error;
    918     }
    919 
    920     if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
    921         ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
    922         goto Error;
    923     }
    924 
    925     if (platform_is_Fusion3()) {
    926 #ifdef QCOM_CSDCLIENT_ENABLED
    927         if (csd_start_voice == NULL) {
    928             ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
    929         } else {
    930             err = csd_start_voice();
    931             if (err < 0){
    932                 ALOGE("s_start_voice_call: csd_client error %d\n", err);
    933                 goto Error;
    934             }
    935         }
    936 #endif
    937     }
    938 
    939     free(devName);
    940     return NO_ERROR;
    941 
    942 Error:
    943     ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
    944     free(devName);
    945     s_close(handle);
    946     return NO_INIT;
    947 }
    948 
    949 static status_t s_start_fm(alsa_handle_t *handle)
    950 {
    951     char *devName;
    952     unsigned flags = 0;
    953     int err = NO_ERROR;
    954 
    955     ALOGV("s_start_fm: handle %p", handle);
    956 
    957     // ASoC multicomponent requires a valid path (frontend/backend) for
    958     // the device to be opened
    959 
    960     flags = PCM_OUT | PCM_STEREO;
    961     if (deviceName(handle, flags, &devName) < 0) {
    962         ALOGE("Failed to get pcm device node");
    963         goto Error;
    964     }
    965     if (devName != NULL) {
    966         handle->handle = pcm_open(flags, (char*)devName);
    967     } else {
    968          ALOGE("Failed to get pcm device node");
    969          return NO_INIT;
    970     }
    971     if (!handle->handle) {
    972         ALOGE("s_start_fm: could not open PCM device");
    973         goto Error;
    974     }
    975 
    976     handle->handle->flags = flags;
    977     err = setHardwareParams(handle);
    978     if(err != NO_ERROR) {
    979         ALOGE("s_start_fm: setHardwareParams failed");
    980         goto Error;
    981     }
    982 
    983     err = setSoftwareParams(handle);
    984     if(err != NO_ERROR) {
    985         ALOGE("s_start_fm: setSoftwareParams failed");
    986         goto Error;
    987     }
    988 
    989     err = pcm_prepare(handle->handle);
    990     if(err != NO_ERROR) {
    991         ALOGE("s_start_fm: setSoftwareParams failed");
    992         goto Error;
    993     }
    994 
    995     if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
    996         ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
    997         goto Error;
    998     }
    999 
   1000     // Store the PCM playback device pointer in rxHandle
   1001     handle->rxHandle = handle->handle;
   1002     free(devName);
   1003 
   1004     // Open PCM capture device
   1005     flags = PCM_IN | PCM_STEREO;
   1006     if (deviceName(handle, flags, &devName) < 0) {
   1007         ALOGE("Failed to get pcm device node");
   1008         goto Error;
   1009     }
   1010     if (devName != NULL) {
   1011         handle->handle = pcm_open(flags, (char*)devName);
   1012     } else {
   1013          ALOGE("Failed to get pcm device node");
   1014          return NO_INIT;
   1015     }
   1016     if (!handle->handle) {
   1017         goto Error;
   1018     }
   1019 
   1020     handle->handle->flags = flags;
   1021     err = setHardwareParams(handle);
   1022     if(err != NO_ERROR) {
   1023         ALOGE("s_start_fm: setHardwareParams failed");
   1024         goto Error;
   1025     }
   1026 
   1027     err = setSoftwareParams(handle);
   1028     if(err != NO_ERROR) {
   1029         ALOGE("s_start_fm: setSoftwareParams failed");
   1030         goto Error;
   1031     }
   1032 
   1033     err = pcm_prepare(handle->handle);
   1034     if(err != NO_ERROR) {
   1035         ALOGE("s_start_fm: pcm_prepare failed");
   1036         goto Error;
   1037     }
   1038 
   1039     if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
   1040         ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
   1041         goto Error;
   1042     }
   1043 
   1044     s_set_fm_vol(fmVolume);
   1045     free(devName);
   1046     return NO_ERROR;
   1047 
   1048 Error:
   1049     free(devName);
   1050     s_close(handle);
   1051     return NO_INIT;
   1052 }
   1053 
   1054 static status_t s_set_fm_vol(int value)
   1055 {
   1056     status_t err = NO_ERROR;
   1057 
   1058     ALSAControl control("/dev/snd/controlC0");
   1059     control.set("Internal FM RX Volume",value,0);
   1060     fmVolume = value;
   1061 
   1062     return err;
   1063 }
   1064 
   1065 static status_t s_set_lpa_vol(int value)
   1066 {
   1067     status_t err = NO_ERROR;
   1068 
   1069     ALSAControl control("/dev/snd/controlC0");
   1070     control.set("LPA RX Volume",value,0);
   1071 
   1072     return err;
   1073 }
   1074 
   1075 static status_t s_start(alsa_handle_t *handle)
   1076 {
   1077     status_t err = NO_ERROR;
   1078 
   1079     if(!handle->handle) {
   1080         ALOGE("No active PCM driver to start");
   1081         return err;
   1082     }
   1083 
   1084     err = pcm_prepare(handle->handle);
   1085 
   1086     return err;
   1087 }
   1088 
   1089 static status_t s_close(alsa_handle_t *handle)
   1090 {
   1091     int ret;
   1092     status_t err = NO_ERROR;
   1093      struct pcm *h = handle->rxHandle;
   1094 
   1095     handle->rxHandle = 0;
   1096     ALOGV("s_close: handle %p h %p", handle, h);
   1097     if (h) {
   1098         if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
   1099              !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
   1100             platform_is_Fusion3()) {
   1101 #ifdef QCOM_CSDCLIENT_ENABLED
   1102             if (csd_stop_voice == NULL) {
   1103                 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
   1104             } else {
   1105                 err = csd_stop_voice();
   1106                 if (err < 0) {
   1107                     ALOGE("s_close: csd_client error %d\n", err);
   1108                 }
   1109             }
   1110 #endif
   1111         }
   1112 
   1113         ALOGV("s_close rxHandle\n");
   1114         err = pcm_close(h);
   1115         if(err != NO_ERROR) {
   1116             ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
   1117         }
   1118     }
   1119 
   1120     h = handle->handle;
   1121     handle->handle = 0;
   1122 
   1123     if (h) {
   1124         ALOGV("s_close handle h %p\n", h);
   1125         err = pcm_close(h);
   1126         if(err != NO_ERROR) {
   1127             ALOGE("s_close: pcm_close failed for handle with err %d", err);
   1128         }
   1129 
   1130         disableDevice(handle);
   1131     } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
   1132               (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
   1133               (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
   1134               (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
   1135         disableDevice(handle);
   1136     }
   1137 
   1138     return err;
   1139 }
   1140 
   1141 /*
   1142     this is same as s_close, but don't discard
   1143     the device/mode info. This way we can still
   1144     close the device, hit idle and power-save, reopen the pcm
   1145     for the same device/mode after resuming
   1146 */
   1147 static status_t s_standby(alsa_handle_t *handle)
   1148 {
   1149     int ret;
   1150     status_t err = NO_ERROR;
   1151     struct pcm *h = handle->rxHandle;
   1152     handle->rxHandle = 0;
   1153     ALOGV("s_standby: handle %p h %p", handle, h);
   1154     if (h) {
   1155         ALOGD("s_standby  rxHandle\n");
   1156         err = pcm_close(h);
   1157         if(err != NO_ERROR) {
   1158             ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
   1159         }
   1160     }
   1161 
   1162     h = handle->handle;
   1163     handle->handle = 0;
   1164 
   1165     if (h) {
   1166           ALOGV("s_standby handle h %p\n", h);
   1167         err = pcm_close(h);
   1168         if(err != NO_ERROR) {
   1169             ALOGE("s_standby: pcm_close failed for handle with err %d", err);
   1170         }
   1171         disableDevice(handle);
   1172     } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
   1173               (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
   1174               (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
   1175               (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
   1176         disableDevice(handle);
   1177     }
   1178 
   1179     return err;
   1180 }
   1181 
   1182 static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
   1183 {
   1184     status_t status = NO_ERROR;
   1185 
   1186     ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
   1187     callMode = mode;
   1188     switchDevice(handle, devices, mode);
   1189     return status;
   1190 }
   1191 
   1192 int getUseCaseType(const char *useCase)
   1193 {
   1194     ALOGD("use case is %s\n", useCase);
   1195     if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
   1196             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
   1197         !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
   1198             MAX_LEN(useCase, SND_USE_CASE_VERB_HIFI2)) ||
   1199         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
   1200             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
   1201         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
   1202             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
   1203         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
   1204             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
   1205         !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
   1206             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
   1207         !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
   1208             MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
   1209         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
   1210             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
   1211         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
   1212             MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
   1213         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
   1214             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
   1215         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
   1216             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
   1217         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
   1218             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
   1219         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
   1220             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
   1221         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
   1222             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
   1223         return USECASE_TYPE_RX;
   1224     } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
   1225             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
   1226         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
   1227             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
   1228         !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
   1229             MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
   1230         !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
   1231             MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
   1232         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
   1233             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
   1234         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
   1235             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
   1236         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
   1237             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
   1238         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
   1239             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
   1240         return USECASE_TYPE_TX;
   1241     } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
   1242             MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
   1243         !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
   1244             MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
   1245         !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
   1246             MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
   1247         !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
   1248             MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
   1249         !strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
   1250             MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
   1251         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
   1252             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
   1253         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
   1254             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
   1255         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
   1256             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
   1257         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
   1258             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
   1259         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
   1260             MAX_LEN(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
   1261         !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
   1262             MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
   1263         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
   1264             MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
   1265         return (USECASE_TYPE_RX | USECASE_TYPE_TX);
   1266     } else {
   1267         ALOGE("unknown use case %s\n", useCase);
   1268         return 0;
   1269     }
   1270 }
   1271 
   1272 static void disableDevice(alsa_handle_t *handle)
   1273 {
   1274     unsigned usecase_type = 0;
   1275     int i, mods_size;
   1276     char *useCase;
   1277     const char **mods_list;
   1278 
   1279     snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
   1280     if (useCase != NULL) {
   1281         if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
   1282             snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
   1283         } else {
   1284             snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
   1285         }
   1286         free(useCase);
   1287         snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
   1288         if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
   1289                strlen(SND_USE_CASE_VERB_INACTIVE)))
   1290             usecase_type |= getUseCaseType(useCase);
   1291         mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
   1292         ALOGV("Number of modifiers %d\n", mods_size);
   1293         if (mods_size) {
   1294             for(i = 0; i < mods_size; i++) {
   1295                 ALOGV("index %d modifier %s\n", i, mods_list[i]);
   1296                 usecase_type |= getUseCaseType(mods_list[i]);
   1297             }
   1298         }
   1299         ALOGV("usecase_type is %d\n", usecase_type);
   1300         if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
   1301             snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
   1302         if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
   1303             snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
   1304     } else {
   1305         ALOGE("Invalid state, no valid use case found to disable");
   1306     }
   1307     free(useCase);
   1308 }
   1309 
   1310 char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
   1311 {
   1312     bool is_tmus = s_is_tmus();
   1313 
   1314     if (!input) {
   1315         if (!(mDevSettingsFlag & TTY_OFF) &&
   1316             (callMode == AudioSystem::MODE_IN_CALL) &&
   1317             ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
   1318              (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
   1319 #ifdef QCOM_ANC_HEADSET_ENABLED
   1320              ||
   1321              (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
   1322              (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
   1323 #endif
   1324              if (mDevSettingsFlag & TTY_VCO) {
   1325                  return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
   1326              } else if (mDevSettingsFlag & TTY_FULL) {
   1327                  return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
   1328              } else if (mDevSettingsFlag & TTY_HCO) {
   1329                  return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
   1330              }
   1331         }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
   1332                   (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
   1333              return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
   1334         } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
   1335             ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
   1336             (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
   1337             if (mDevSettingsFlag & ANC_FLAG) {
   1338                 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
   1339             } else {
   1340                 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
   1341             }
   1342         } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
   1343             ((devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL))) {
   1344             return strdup(SND_USE_CASE_DEV_HDMI_SPEAKER);
   1345 #ifdef QCOM_ANC_HEADSET_ENABLED
   1346         } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
   1347             ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
   1348             (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
   1349             return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
   1350         } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
   1351                  (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
   1352             return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
   1353 #endif
   1354         } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
   1355             if (callMode == AudioSystem::MODE_IN_CALL) {
   1356                 if(is_tmus)
   1357                     return strdup(SND_USE_CASE_DEV_VOC_EARPIECE_TMUS); /* Voice HANDSET RX for TMUS */
   1358                 else
   1359                     return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
   1360             } else
   1361                 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
   1362         } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
   1363             if (callMode == AudioSystem::MODE_IN_CALL) {
   1364                 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
   1365             } else
   1366                 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
   1367         } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
   1368                    (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
   1369             if (mDevSettingsFlag & ANC_FLAG) {
   1370                 if (callMode == AudioSystem::MODE_IN_CALL) {
   1371                     return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
   1372                 } else
   1373                     return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
   1374             } else {
   1375                 if (callMode == AudioSystem::MODE_IN_CALL) {
   1376                     return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
   1377                 } else
   1378                     return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
   1379             }
   1380 #ifdef QCOM_ANC_HEADSET_ENABLED
   1381         } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
   1382                    (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
   1383             if (callMode == AudioSystem::MODE_IN_CALL) {
   1384                 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
   1385             } else
   1386                 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
   1387 #endif
   1388         } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
   1389                   (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
   1390                   (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
   1391             if (btsco_samplerate == BTSCO_RATE_16KHZ)
   1392                 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
   1393             else
   1394                 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
   1395         } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
   1396                    (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
   1397 #ifdef QCOM_VOIP_ENABLED
   1398                    (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
   1399 #endif
   1400                    (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
   1401             /* Nothing to be done, use current active device */
   1402             if (strncmp(curRxUCMDevice, "None", 4)) {
   1403                 return strdup(curRxUCMDevice);
   1404             }
   1405         } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
   1406             return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
   1407 #ifdef QCOM_PROXY_DEVICE_ENABLED
   1408         } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
   1409             return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
   1410 #endif
   1411 #ifdef QCOM_FM_TX_ENABLED
   1412         } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
   1413             return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
   1414 #endif
   1415         } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
   1416             if (callMode == AudioSystem::MODE_IN_CALL) {
   1417                 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
   1418             } else
   1419                 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
   1420         } else {
   1421             ALOGD("No valid output device: %u", devices);
   1422         }
   1423     } else {
   1424         if (!(mDevSettingsFlag & TTY_OFF) &&
   1425             (callMode == AudioSystem::MODE_IN_CALL) &&
   1426             ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)
   1427 #ifdef QCOM_ANC_HEADSET_ENABLED
   1428               || (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)
   1429 #endif
   1430             )) {
   1431              if (mDevSettingsFlag & TTY_HCO) {
   1432                  return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
   1433              } else if (mDevSettingsFlag & TTY_FULL) {
   1434                  return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
   1435              } else if (mDevSettingsFlag & TTY_VCO) {
   1436                  if (!strncmp(mic_type, "analog", 6)) {
   1437                      return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
   1438                  } else {
   1439                      return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
   1440                  }
   1441              }
   1442         } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
   1443             if (!strncmp(mic_type, "analog", 6)) {
   1444                 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
   1445             } else {
   1446                 if (mDevSettingsFlag & DMIC_FLAG) {
   1447                     if(callMode == AudioSystem::MODE_IN_CALL) {
   1448 #ifdef USES_FLUENCE_INCALL
   1449                         if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
   1450                             if(is_tmus)
   1451                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_TMUS); /* DUALMIC EF TX */
   1452                             else
   1453                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
   1454                         } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
   1455                             return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
   1456                         } else {
   1457                             return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
   1458                         }
   1459 #endif
   1460                     }
   1461                     if (((rxDevice != NULL) &&
   1462                         !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
   1463                         (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
   1464                         !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
   1465                         (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
   1466                         if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
   1467                             if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
   1468 // TODO: check if different ACDB settings are needed when speaker is enabled
   1469                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
   1470                             } else {
   1471                                 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE);
   1472                             }
   1473                         } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
   1474                             if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
   1475                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
   1476                             } else {
   1477                                 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE);
   1478                             }
   1479                         }
   1480                     } else {
   1481                         if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
   1482                             if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
   1483                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
   1484                             } else {
   1485                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE);
   1486                             }
   1487                         } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
   1488                             if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
   1489                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
   1490                             } else {
   1491                                 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE);
   1492                             }
   1493                         }
   1494                     }
   1495                 } else if (mDevSettingsFlag & QMIC_FLAG){
   1496                     return strdup(SND_USE_CASE_DEV_QUAD_MIC);
   1497                 }
   1498 #ifdef QCOM_SSR_ENABLED
   1499                 else if (mDevSettingsFlag & SSRQMIC_FLAG){
   1500                     ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
   1501                     // Mapping for quad mic input device.
   1502                     return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
   1503                 }
   1504 #endif
   1505 #ifdef SEPERATED_AUDIO_INPUT
   1506                 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
   1507                     return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
   1508                 }
   1509 #endif
   1510                 else {
   1511                     return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
   1512                 }
   1513             }
   1514         } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
   1515             return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
   1516 #ifdef QCOM_ANC_HEADSET_ENABLED
   1517         } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
   1518             return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
   1519 #endif
   1520         } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
   1521             if (callMode == AudioSystem::MODE_IN_CALL) {
   1522                 return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
   1523             } else
   1524                 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
   1525         } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
   1526              if (btsco_samplerate == BTSCO_RATE_16KHZ)
   1527                  return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
   1528              else
   1529                  return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
   1530 #ifdef QCOM_USBAUDIO_ENABLED
   1531         } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
   1532                    (devices & AudioSystem::DEVICE_IN_PROXY)) {
   1533             return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
   1534 #endif
   1535         } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
   1536                    (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
   1537             /* Nothing to be done, use current active device */
   1538             if (strncmp(curTxUCMDevice, "None", 4)) {
   1539                 return strdup(curTxUCMDevice);
   1540             }
   1541 #ifdef QCOM_FM_ENABLED
   1542         } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
   1543                    (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
   1544             /* Nothing to be done, use current tx device or set dummy device */
   1545             if (strncmp(curTxUCMDevice, "None", 4)) {
   1546                 return strdup(curTxUCMDevice);
   1547             } else {
   1548                 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
   1549             }
   1550 #endif
   1551         } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
   1552                    (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
   1553             ALOGI("No proper mapping found with UCM device list, setting default");
   1554             if (!strncmp(mic_type, "analog", 6)) {
   1555                 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
   1556             } else {
   1557                 if (callMode == AudioSystem::MODE_IN_CALL) {
   1558                     return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
   1559 #ifdef SEPERATED_AUDIO_INPUT
   1560                 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
   1561                     return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
   1562 #endif
   1563                 } else
   1564                     return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
   1565             }
   1566         } else {
   1567             ALOGD("No valid input device: %u", devices);
   1568         }
   1569     }
   1570     return NULL;
   1571 }
   1572 
   1573 void s_set_voice_volume(int vol)
   1574 {
   1575     int err = 0;
   1576     ALOGV("s_set_voice_volume: volume %d", vol);
   1577     ALSAControl control("/dev/snd/controlC0");
   1578     control.set("Voice Rx Volume", vol, 0);
   1579 
   1580     if (platform_is_Fusion3()) {
   1581 #ifdef QCOM_CSDCLIENT_ENABLED
   1582         if (csd_volume == NULL) {
   1583             ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
   1584         } else {
   1585             err = csd_volume(vol);
   1586             if (err < 0) {
   1587                 ALOGE("s_set_voice_volume: csd_client error %d", err);
   1588             }
   1589         }
   1590 #endif
   1591     }
   1592 }
   1593 
   1594 void s_set_volte_volume(int vol)
   1595 {
   1596     ALOGV("s_set_volte_volume: volume %d", vol);
   1597     ALSAControl control("/dev/snd/controlC0");
   1598     control.set("VoLTE Rx Volume", vol, 0);
   1599 }
   1600 
   1601 
   1602 void s_set_voip_volume(int vol)
   1603 {
   1604     ALOGV("s_set_voip_volume: volume %d", vol);
   1605     ALSAControl control("/dev/snd/controlC0");
   1606     control.set("Voip Rx Volume", vol, 0);
   1607 }
   1608 void s_set_mic_mute(int state)
   1609 {
   1610     int err = 0;
   1611     ALOGV("s_set_mic_mute: state %d", state);
   1612     ALSAControl control("/dev/snd/controlC0");
   1613     control.set("Voice Tx Mute", state, 0);
   1614 
   1615     if (platform_is_Fusion3()) {
   1616 #ifdef QCOM_CSDCLIENT_ENABLED
   1617         if (csd_mic_mute == NULL) {
   1618             ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
   1619         } else {
   1620             err=csd_mic_mute(state);
   1621             if (err < 0) {
   1622                 ALOGE("s_set_mic_mute: csd_client error %d", err);
   1623             }
   1624         }
   1625 #endif
   1626     }
   1627 }
   1628 void s_set_volte_mic_mute(int state)
   1629 {
   1630     ALOGV("s_set_volte_mic_mute: state %d", state);
   1631     ALSAControl control("/dev/snd/controlC0");
   1632     control.set("VoLTE Tx Mute", state, 0);
   1633 }
   1634 
   1635 void s_set_voip_mic_mute(int state)
   1636 {
   1637     ALOGV("s_set_voip_mic_mute: state %d", state);
   1638     ALSAControl control("/dev/snd/controlC0");
   1639     control.set("Voip Tx Mute", state, 0);
   1640 }
   1641 
   1642 void s_set_voip_config(int mode, int rate)
   1643 {
   1644     ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
   1645     ALSAControl control("/dev/snd/controlC0");
   1646     char** setValues;
   1647     setValues = (char**)malloc(2*sizeof(char*));
   1648     if (setValues == NULL) {
   1649           return;
   1650     }
   1651     setValues[0] = (char*)malloc(4*sizeof(char));
   1652     if (setValues[0] == NULL) {
   1653           free(setValues);
   1654           return;
   1655     }
   1656 
   1657     setValues[1] = (char*)malloc(8*sizeof(char));
   1658     if (setValues[1] == NULL) {
   1659           free(setValues);
   1660           free(setValues[0]);
   1661           return;
   1662     }
   1663 
   1664     sprintf(setValues[0], "%d",mode);
   1665     sprintf(setValues[1], "%d",rate);
   1666 
   1667     control.setext("Voip Mode Rate Config", 2, setValues);
   1668     free(setValues[1]);
   1669     free(setValues[0]);
   1670     free(setValues);
   1671     return;
   1672 }
   1673 
   1674 void s_set_btsco_rate(int rate)
   1675 {
   1676     btsco_samplerate = rate;
   1677 }
   1678 
   1679 void s_enable_wide_voice(bool flag)
   1680 {
   1681     int err = 0;
   1682 
   1683     ALOGV("s_enable_wide_voice: flag %d", flag);
   1684     ALSAControl control("/dev/snd/controlC0");
   1685     if(flag == true) {
   1686         control.set("Widevoice Enable", 1, 0);
   1687     } else {
   1688         control.set("Widevoice Enable", 0, 0);
   1689     }
   1690 
   1691     if (platform_is_Fusion3()) {
   1692 #ifdef QCOM_CSDCLIENT_ENABLED
   1693         if (csd_wide_voice == NULL) {
   1694             ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
   1695         } else {
   1696             err = csd_wide_voice(flag);
   1697             if (err < 0) {
   1698                 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
   1699             }
   1700         }
   1701 #endif
   1702     }
   1703 }
   1704 
   1705 void s_set_voc_rec_mode(uint8_t mode)
   1706 {
   1707     ALOGV("s_set_voc_rec_mode: mode %d", mode);
   1708     ALSAControl control("/dev/snd/controlC0");
   1709     control.set("Incall Rec Mode", mode, 0);
   1710 }
   1711 
   1712 void s_enable_fens(bool flag)
   1713 {
   1714     int err = 0;
   1715 
   1716     ALOGV("s_enable_fens: flag %d", flag);
   1717     ALSAControl control("/dev/snd/controlC0");
   1718     if(flag == true) {
   1719         control.set("FENS Enable", 1, 0);
   1720     } else {
   1721         control.set("FENS Enable", 0, 0);
   1722     }
   1723 
   1724     if (platform_is_Fusion3()) {
   1725 #ifdef QCOM_CSDCLIENT_ENABLED
   1726         if (csd_fens == NULL) {
   1727             ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
   1728         } else {
   1729             err = csd_fens(flag);
   1730             if (err < 0) {
   1731                 ALOGE("s_enable_fens: csd_client error %d", err);
   1732             }
   1733         }
   1734 #endif
   1735     }
   1736 }
   1737 
   1738 void s_enable_slow_talk(bool flag)
   1739 {
   1740     int err = 0;
   1741 
   1742     ALOGV("s_enable_slow_talk: flag %d", flag);
   1743     ALSAControl control("/dev/snd/controlC0");
   1744     if(flag == true) {
   1745         control.set("Slowtalk Enable", 1, 0);
   1746     } else {
   1747         control.set("Slowtalk Enable", 0, 0);
   1748     }
   1749 
   1750     if (platform_is_Fusion3()) {
   1751 #ifdef QCOM_CSDCLIENT_ENABLED
   1752         if (csd_slow_talk == NULL) {
   1753             ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
   1754         } else {
   1755             err = csd_slow_talk(flag);
   1756             if (err < 0) {
   1757                 ALOGE("s_enable_slow_talk: csd_client error %d", err);
   1758             }
   1759         }
   1760 #endif
   1761     }
   1762 }
   1763 
   1764 void s_set_flags(uint32_t flags)
   1765 {
   1766     ALOGV("s_set_flags: flags %d", flags);
   1767     mDevSettingsFlag = flags;
   1768 }
   1769 
   1770 static status_t s_set_compressed_vol(int value)
   1771 {
   1772     status_t err = NO_ERROR;
   1773 
   1774     ALSAControl control("/dev/snd/controlC0");
   1775     control.set("COMPRESSED RX Volume",value,0);
   1776 
   1777     return err;
   1778 }
   1779 
   1780 #ifdef SEPERATED_AUDIO_INPUT
   1781 void s_setInput(int input)
   1782 {
   1783     input_source = input;
   1784     ALOGD("s_setInput() : input_source = %d",input_source);
   1785 }
   1786 #endif
   1787 
   1788 #ifdef QCOM_CSDCLIENT_ENABLED
   1789 static void  s_set_csd_handle(void* handle)
   1790 {
   1791     csd_handle = static_cast<void*>(handle);
   1792     ALOGI("%s csd_handle: %p", __func__, csd_handle);
   1793 
   1794     csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
   1795     csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
   1796     csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
   1797     csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
   1798     csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
   1799     csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
   1800     csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
   1801     csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
   1802     csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
   1803 }
   1804 #endif
   1805 
   1806 static bool s_is_tmus()
   1807 {
   1808     char value[128];
   1809     bool ret = false;
   1810 
   1811     if (mccmnc == 0) {
   1812         property_get("gsm.sim.operator.numeric",value,"0");
   1813         mccmnc = atoi(value);
   1814     }
   1815 
   1816     ALOGD("%s: mnc_mcc :  %d", __FUNCTION__, mccmnc);
   1817     switch(mccmnc)
   1818     {
   1819     //TMUS MCC(310), MNC(490, 260, 026)
   1820     case 310490:
   1821     case 310260:
   1822     case 310026:
   1823         ret = true;
   1824         break;
   1825     default:
   1826         ret = false;
   1827         break;
   1828     }
   1829 
   1830     return ret;
   1831 }
   1832 
   1833 }
   1834