1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "voice" 18 /*#define LOG_NDEBUG 0*/ 19 #define LOG_NDDEBUG 0 20 21 #include <stdlib.h> 22 #include <errno.h> 23 #include <math.h> 24 #include <log/log.h> 25 #include <cutils/str_parms.h> 26 27 #include "audio_hw.h" 28 #include "voice.h" 29 #include "voice_extn/voice_extn.h" 30 #include "platform.h" 31 #include "platform_api.h" 32 #include "audio_extn/tfa_98xx.h" 33 34 struct pcm_config pcm_config_voice_call = { 35 .channels = 1, 36 .rate = 8000, 37 .period_size = 160, 38 .period_count = 2, 39 .format = PCM_FORMAT_S16_LE, 40 }; 41 42 static struct voice_session *voice_get_session_from_use_case(struct audio_device *adev, 43 audio_usecase_t usecase_id) 44 { 45 struct voice_session *session = NULL; 46 int ret = 0; 47 48 ret = voice_extn_get_session_from_use_case(adev, usecase_id, &session); 49 if (ret == -ENOSYS) { 50 session = &adev->voice.session[VOICE_SESS_IDX]; 51 } 52 53 return session; 54 } 55 56 static bool voice_is_sidetone_device(snd_device_t out_device, 57 char *mixer_path) 58 { 59 bool is_sidetone_dev = true; 60 61 switch (out_device) { 62 case SND_DEVICE_OUT_VOICE_HAC_HANDSET: 63 strlcpy(mixer_path, "sidetone-hac-handset", MIXER_PATH_MAX_LENGTH); 64 break; 65 case SND_DEVICE_OUT_VOICE_HANDSET: 66 strlcpy(mixer_path, "sidetone-handset", MIXER_PATH_MAX_LENGTH); 67 break; 68 case SND_DEVICE_OUT_VOICE_HEADPHONES: 69 case SND_DEVICE_OUT_VOICE_HEADSET: 70 strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH); 71 break; 72 case SND_DEVICE_OUT_VOICE_USB_HEADSET: 73 case SND_DEVICE_OUT_USB_HEADSET: 74 // USB does not use a QC mixer. 75 mixer_path[0] = '\0'; 76 break; 77 default: 78 ALOGW("%s: %d is not a sidetone device", __func__, out_device); 79 is_sidetone_dev = false; 80 break; 81 } 82 83 return is_sidetone_dev; 84 } 85 86 void voice_set_sidetone(struct audio_device *adev, 87 snd_device_t out_snd_device, bool enable) 88 { 89 char mixer_path[MIXER_PATH_MAX_LENGTH]; 90 bool is_sidetone_dev; 91 92 ALOGD("%s: %s, out_snd_device: %d\n", 93 __func__, (enable ? "enable" : "disable"), 94 out_snd_device); 95 96 if (voice_is_sidetone_device(out_snd_device, mixer_path)) 97 platform_set_sidetone(adev, out_snd_device, enable, mixer_path); 98 99 return; 100 } 101 102 int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id) 103 { 104 int i, ret = 0; 105 struct audio_usecase *uc_info; 106 struct voice_session *session = NULL; 107 108 ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]); 109 110 session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id); 111 112 uc_info = get_usecase_from_list(adev, usecase_id); 113 if (uc_info == NULL) { 114 ALOGE("%s: Could not find the usecase (%d) in the list", 115 __func__, usecase_id); 116 return -EINVAL; 117 } 118 119 session->state.current = CALL_INACTIVE; 120 121 /* Disable sidetone only when no calls are active */ 122 if (!voice_is_call_state_active(adev)) 123 voice_set_sidetone(adev, uc_info->out_snd_device, false); 124 125 ret = platform_stop_voice_call(adev->platform, session->vsid); 126 127 /* 1. Close the PCM devices */ 128 if (session->pcm_rx) { 129 pcm_close(session->pcm_rx); 130 session->pcm_rx = NULL; 131 } 132 if (session->pcm_tx) { 133 pcm_close(session->pcm_tx); 134 session->pcm_tx = NULL; 135 } 136 137 /* 2. Get and set stream specific mixer controls */ 138 disable_audio_route(adev, uc_info); 139 140 /* 3. Disable the rx and tx devices */ 141 disable_snd_device(adev, uc_info->out_snd_device); 142 disable_snd_device(adev, uc_info->in_snd_device); 143 144 if (audio_extn_tfa_98xx_is_supported() && voice_get_mic_mute(adev)) { 145 voice_set_mic_mute(adev, false); 146 ALOGD("%s: unMute voice Tx", __func__); 147 } 148 149 list_remove(&uc_info->list); 150 free(uc_info); 151 152 ALOGD("%s: exit: status(%d)", __func__, ret); 153 return ret; 154 } 155 156 int voice_start_usecase(struct audio_device *adev, audio_usecase_t usecase_id) 157 { 158 int i, ret = 0; 159 struct audio_usecase *uc_info; 160 int pcm_dev_rx_id, pcm_dev_tx_id; 161 struct voice_session *session = NULL; 162 struct pcm_config voice_config = pcm_config_voice_call; 163 164 ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]); 165 166 session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id); 167 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); 168 uc_info->id = usecase_id; 169 uc_info->type = VOICE_CALL; 170 uc_info->stream.out = adev->current_call_output ; 171 uc_info->devices = adev->current_call_output ->devices; 172 uc_info->in_snd_device = SND_DEVICE_NONE; 173 uc_info->out_snd_device = SND_DEVICE_NONE; 174 adev->use_voice_device_mute = false; 175 176 list_add_tail(&adev->usecase_list, &uc_info->list); 177 178 select_devices(adev, usecase_id); 179 180 pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK); 181 pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE); 182 183 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) { 184 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)", 185 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); 186 ret = -EIO; 187 goto error_start_voice; 188 } 189 190 ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)", 191 __func__, adev->snd_card, pcm_dev_tx_id); 192 session->pcm_tx = pcm_open(adev->snd_card, 193 pcm_dev_tx_id, 194 PCM_IN, &voice_config); 195 if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) { 196 ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx)); 197 ret = -EIO; 198 goto error_start_voice; 199 } 200 201 ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)", 202 __func__, adev->snd_card, pcm_dev_rx_id); 203 session->pcm_rx = pcm_open(adev->snd_card, 204 pcm_dev_rx_id, 205 PCM_OUT, &voice_config); 206 if (session->pcm_rx && !pcm_is_ready(session->pcm_rx)) { 207 ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_rx)); 208 ret = -EIO; 209 goto error_start_voice; 210 } 211 212 if (adev->mic_break_enabled) 213 platform_set_mic_break_det(adev->platform, true); 214 215 ret = pcm_start(session->pcm_tx); 216 if (ret != 0) 217 goto error_start_voice; 218 219 ret = pcm_start(session->pcm_rx); 220 if (ret != 0) 221 goto error_start_voice; 222 223 audio_extn_tfa_98xx_enable_speaker(); 224 225 /* Enable sidetone only when no calls are already active */ 226 if (!voice_is_call_state_active(adev)) 227 voice_set_sidetone(adev, uc_info->out_snd_device, true); 228 229 voice_set_volume(adev, adev->voice.volume); 230 231 ret = platform_start_voice_call(adev->platform, session->vsid); 232 if (ret < 0) { 233 ALOGE("%s: platform_start_voice_call error %d\n", __func__, ret); 234 goto error_start_voice; 235 } 236 237 session->state.current = CALL_ACTIVE; 238 goto done; 239 240 error_start_voice: 241 voice_stop_usecase(adev, usecase_id); 242 243 done: 244 ALOGD("%s: exit: status(%d)", __func__, ret); 245 return ret; 246 } 247 248 bool voice_is_call_state_active(struct audio_device *adev) 249 { 250 bool call_state = false; 251 int ret = 0; 252 253 ret = voice_extn_is_call_state_active(adev, &call_state); 254 if (ret == -ENOSYS) { 255 call_state = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false; 256 } 257 258 return call_state; 259 } 260 261 bool voice_is_in_call(struct audio_device *adev) 262 { 263 return adev->voice.in_call; 264 } 265 266 bool voice_is_in_call_rec_stream(struct stream_in *in) 267 { 268 bool in_call_rec = false; 269 int ret = 0; 270 271 ret = voice_extn_is_in_call_rec_stream(in, &in_call_rec); 272 if (ret == -ENOSYS) { 273 in_call_rec = false; 274 } 275 276 return in_call_rec; 277 } 278 279 uint32_t voice_get_active_session_id(struct audio_device *adev) 280 { 281 int ret = 0; 282 uint32_t session_id; 283 284 ret = voice_extn_get_active_session_id(adev, &session_id); 285 if (ret == -ENOSYS) { 286 session_id = VOICE_VSID; 287 } 288 return session_id; 289 } 290 291 int voice_check_and_set_incall_rec_usecase(struct audio_device *adev, 292 struct stream_in *in) 293 { 294 int ret = 0; 295 uint32_t session_id; 296 int usecase_id; 297 int rec_mode = INCALL_REC_NONE; 298 299 if (voice_is_call_state_active(adev)) { 300 switch (in->source) { 301 case AUDIO_SOURCE_VOICE_UPLINK: 302 in->usecase = USECASE_INCALL_REC_UPLINK; 303 rec_mode = INCALL_REC_UPLINK; 304 break; 305 case AUDIO_SOURCE_VOICE_DOWNLINK: 306 in->usecase = USECASE_INCALL_REC_DOWNLINK; 307 rec_mode = INCALL_REC_DOWNLINK; 308 break; 309 case AUDIO_SOURCE_VOICE_CALL: 310 in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK; 311 rec_mode = INCALL_REC_UPLINK_AND_DOWNLINK; 312 break; 313 default: 314 ALOGV("%s: Source type %d doesnt match incall recording criteria", 315 __func__, in->source); 316 return ret; 317 } 318 319 session_id = voice_get_active_session_id(adev); 320 ret = platform_set_incall_recording_session_id(adev->platform, 321 session_id, rec_mode); 322 #ifdef INCALL_STEREO_CAPTURE_ENABLED 323 ret = platform_set_incall_recording_session_channels(adev->platform, 324 in->config.channels); 325 #endif 326 ALOGV("%s: Update usecase to %d",__func__, in->usecase); 327 } else { 328 ALOGV("%s: voice call not active", __func__); 329 } 330 331 return ret; 332 } 333 334 int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev, 335 struct stream_in *in) 336 { 337 int ret = 0; 338 339 if (in->source == AUDIO_SOURCE_VOICE_UPLINK || 340 in->source == AUDIO_SOURCE_VOICE_DOWNLINK || 341 in->source == AUDIO_SOURCE_VOICE_CALL) { 342 ret = platform_stop_incall_recording_usecase(adev->platform); 343 ALOGV("%s: Stop In-call recording", __func__); 344 } 345 346 return ret; 347 } 348 349 int voice_check_and_set_incall_music_usecase(struct audio_device *adev, 350 struct stream_out *out) 351 { 352 int ret = 0; 353 354 ret = voice_extn_check_and_set_incall_music_usecase(adev, out); 355 if (ret == -ENOSYS) { 356 /* Incall music delivery is used only for LCH call state */ 357 ret = -EINVAL; 358 } 359 360 return ret; 361 } 362 363 int voice_set_mic_mute(struct audio_device *adev, bool state) 364 { 365 int err = 0; 366 struct audio_usecase *usecase = NULL; 367 368 adev->voice.mic_mute = state; 369 if (adev->mode == AUDIO_MODE_IN_CALL || 370 adev->mode == AUDIO_MODE_IN_COMMUNICATION) { 371 /* Use device mute if incall music delivery usecase is in progress */ 372 if (adev->use_voice_device_mute) 373 err = platform_set_device_mute(adev->platform, state, "tx"); 374 else 375 err = platform_set_mic_mute(adev->platform, state); 376 ALOGV("%s: voice mute status=%d, use_voice_device_mute_flag=%d", 377 __func__, state, adev->use_voice_device_mute); 378 } 379 380 return err; 381 } 382 383 bool voice_get_mic_mute(struct audio_device *adev) 384 { 385 return adev->voice.mic_mute; 386 } 387 388 // Following function is called when incall music uplink usecase is 389 // created or destroyed while mic is muted. If incall music uplink 390 // usecase is active, apply voice device mute to mute only voice Tx 391 // path and not the mixed voice Tx + inncall-music path. Revert to 392 // voice stream mute once incall music uplink usecase is inactive 393 void voice_set_device_mute_flag (struct audio_device *adev, bool state) 394 { 395 if (adev->voice.mic_mute) { 396 if (state) { 397 platform_set_device_mute(adev->platform, true, "tx"); 398 platform_set_mic_mute(adev->platform, false); 399 } else { 400 platform_set_mic_mute(adev->platform, true); 401 platform_set_device_mute(adev->platform, false, "tx"); 402 } 403 } 404 adev->use_voice_device_mute = state; 405 } 406 407 int voice_set_volume(struct audio_device *adev, float volume) 408 { 409 int vol, err = 0; 410 411 adev->voice.volume = volume; 412 if (adev->mode == AUDIO_MODE_IN_CALL) { 413 if (volume < 0.0) { 414 volume = 0.0; 415 } else if (volume > 1.0) { 416 volume = 1.0; 417 } 418 419 vol = lrint(volume * 100.0); 420 421 // Voice volume levels from android are mapped to driver volume levels as follows. 422 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0 423 // So adjust the volume to get the correct volume index in driver 424 vol = 100 - vol; 425 426 err = platform_set_voice_volume(adev->platform, vol); 427 } 428 429 return err; 430 } 431 432 int voice_start_call(struct audio_device *adev) 433 { 434 int ret = 0; 435 436 adev->voice.in_call = true; 437 438 voice_set_mic_mute(adev, adev->voice.mic_mute); 439 440 ret = voice_extn_start_call(adev); 441 if (ret == -ENOSYS) { 442 ret = voice_start_usecase(adev, USECASE_VOICE_CALL); 443 } 444 445 return ret; 446 } 447 448 int voice_stop_call(struct audio_device *adev) 449 { 450 int ret = 0; 451 452 adev->voice.in_call = false; 453 ret = voice_extn_stop_call(adev); 454 if (ret == -ENOSYS) { 455 ret = voice_stop_usecase(adev, USECASE_VOICE_CALL); 456 } 457 458 return ret; 459 } 460 461 void voice_get_parameters(struct audio_device *adev, 462 struct str_parms *query, 463 struct str_parms *reply) 464 { 465 voice_extn_get_parameters(adev, query, reply); 466 } 467 468 int voice_set_parameters(struct audio_device *adev, struct str_parms *parms) 469 { 470 char *str; 471 char value[32]; 472 int val; 473 int ret = 0, err; 474 char *kv_pairs = str_parms_to_str(parms); 475 476 ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs); 477 478 ret = voice_extn_set_parameters(adev, parms); 479 if (ret != 0) { 480 if (ret == -ENOSYS) { 481 ret = 0; /* ignore error */ 482 } else { 483 goto done; 484 } 485 } 486 487 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value)); 488 if (err >= 0) { 489 int tty_mode; 490 str_parms_del(parms, AUDIO_PARAMETER_KEY_TTY_MODE); 491 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0) 492 tty_mode = TTY_MODE_OFF; 493 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0) 494 tty_mode = TTY_MODE_VCO; 495 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0) 496 tty_mode = TTY_MODE_HCO; 497 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0) 498 tty_mode = TTY_MODE_FULL; 499 else { 500 ret = -EINVAL; 501 goto done; 502 } 503 504 if (tty_mode != adev->voice.tty_mode) { 505 adev->voice.tty_mode = tty_mode; 506 adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode; 507 if (voice_is_call_state_active(adev)) 508 voice_update_devices_for_all_voice_usecases(adev); 509 } 510 } 511 512 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HAC, 513 value, sizeof(value)); 514 if (err >= 0) { 515 bool hac = false; 516 str_parms_del(parms, AUDIO_PARAMETER_KEY_HAC); 517 if (strcmp(value, AUDIO_PARAMETER_VALUE_HAC_ON) == 0) 518 hac = true; 519 520 if (hac != adev->voice.hac) { 521 adev->voice.hac = hac; 522 if (voice_is_in_call(adev)) 523 voice_update_devices_for_all_voice_usecases(adev); 524 } 525 } 526 527 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC, 528 value, sizeof(value)); 529 if (err >= 0) { 530 str_parms_del(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC); 531 if (strcmp(value, AUDIO_PARAMETER_VALUE_TRUE) == 0) 532 platform_start_incall_music_usecase(adev->platform); 533 else 534 platform_stop_incall_music_usecase(adev->platform); 535 } 536 537 done: 538 ALOGV("%s: exit with code(%d)", __func__, ret); 539 free(kv_pairs); 540 return ret; 541 } 542 543 void voice_init(struct audio_device *adev) 544 { 545 int i = 0; 546 547 memset(&adev->voice, 0, sizeof(adev->voice)); 548 adev->voice.tty_mode = TTY_MODE_OFF; 549 adev->voice.hac = false; 550 adev->voice.volume = 1.0f; 551 adev->voice.mic_mute = false; 552 adev->voice.in_call = false; 553 adev->use_voice_device_mute = false; 554 555 for (i = 0; i < MAX_VOICE_SESSIONS; i++) { 556 adev->voice.session[i].pcm_rx = NULL; 557 adev->voice.session[i].pcm_tx = NULL; 558 adev->voice.session[i].state.current = CALL_INACTIVE; 559 adev->voice.session[i].state.new = CALL_INACTIVE; 560 adev->voice.session[i].vsid = VOICE_VSID; 561 } 562 563 voice_extn_init(adev); 564 } 565 566 void voice_update_devices_for_all_voice_usecases(struct audio_device *adev) 567 { 568 struct listnode *node; 569 struct audio_usecase *usecase; 570 571 list_for_each(node, &adev->usecase_list) { 572 usecase = node_to_item(node, struct audio_usecase, list); 573 if (usecase->type == VOICE_CALL) { 574 ALOGV("%s: updating device for usecase:%s", __func__, 575 use_case_table[usecase->id]); 576 usecase->stream.out = adev->current_call_output; 577 select_devices(adev, usecase->id); 578 audio_extn_tfa_98xx_update(); 579 } 580 } 581 } 582 583 584