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