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