• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
s_device_open(const hw_module_t * module,const char * name,hw_device_t ** device)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 
s_device_close(hw_device_t * device)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 
platform_is_Fusion3()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 
deviceName(alsa_handle_t * handle,unsigned flags,char ** value)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 
setHDMIChannelCount()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 
setHardwareParams(alsa_handle_t * handle)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 
setSoftwareParams(alsa_handle_t * handle)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 
switchDevice(alsa_handle_t * handle,uint32_t devices,uint32_t mode)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 
s_init(alsa_device_t * module,ALSAHandleList & list)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 
s_open(alsa_handle_t * handle)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 
s_start_voip_call(alsa_handle_t * handle)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 
s_start_voice_call(alsa_handle_t * handle)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 
s_start_fm(alsa_handle_t * handle)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 
s_set_fm_vol(int value)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 
s_set_lpa_vol(int value)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 
s_start(alsa_handle_t * handle)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 
s_close(alsa_handle_t * handle)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 */
s_standby(alsa_handle_t * handle)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 
s_route(alsa_handle_t * handle,uint32_t devices,int mode)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 
getUseCaseType(const char * useCase)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 
disableDevice(alsa_handle_t * handle)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 
getUCMDevice(uint32_t devices,int input,char * rxDevice)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