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