1/* 2 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. 3 * Not a contribution. 4 * 5 * Copyright (C) 2013 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20#define LOG_TAG "compress_voip" 21/*#define LOG_NDEBUG 0*/ 22#define LOG_NDDEBUG 0 23 24#include <errno.h> 25#include <pthread.h> 26#include <stdint.h> 27#include <sys/time.h> 28#include <stdlib.h> 29#include <math.h> 30#include <cutils/log.h> 31#include <cutils/str_parms.h> 32#include <cutils/properties.h> 33 34#include "audio_hw.h" 35#include "platform_api.h" 36#include "platform.h" 37#include "voice_extn.h" 38 39#define COMPRESS_VOIP_IO_BUF_SIZE_NB 320 40#define COMPRESS_VOIP_IO_BUF_SIZE_WB 640 41 42struct pcm_config pcm_config_voip_nb = { 43 .channels = 1, 44 .rate = 8000, /* changed when the stream is opened */ 45 .period_size = COMPRESS_VOIP_IO_BUF_SIZE_NB/2, 46 .period_count = 10, 47 .format = PCM_FORMAT_S16_LE, 48}; 49 50struct pcm_config pcm_config_voip_wb = { 51 .channels = 1, 52 .rate = 16000, /* changed when the stream is opened */ 53 .period_size = COMPRESS_VOIP_IO_BUF_SIZE_WB/2, 54 .period_count = 10, 55 .format = PCM_FORMAT_S16_LE, 56}; 57 58struct voip_data { 59 struct pcm *pcm_rx; 60 struct pcm *pcm_tx; 61 struct stream_out *out_stream; 62 uint32_t out_stream_count; 63 uint32_t in_stream_count; 64 uint32_t sample_rate; 65}; 66 67#define MODE_IS127 0x2 68#define MODE_4GV_NB 0x3 69#define MODE_4GV_WB 0x4 70#define MODE_AMR 0x5 71#define MODE_AMR_WB 0xD 72#define MODE_PCM 0xC 73#define MODE_4GV_NW 0xE 74 75#define AUDIO_PARAMETER_KEY_VOIP_RATE "voip_rate" 76#define AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN "evrc_rate_min" 77#define AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX "evrc_rate_max" 78#define AUDIO_PARAMETER_KEY_VOIP_DTX_MODE "dtx_on" 79#define AUDIO_PARAMETER_VALUE_VOIP_TRUE "true" 80#define AUDIO_PARAMETER_KEY_VOIP_CHECK "voip_flag" 81#define AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT "voip_out_stream_count" 82#define AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE "voip_sample_rate" 83 84static struct voip_data voip_data = { 85 .pcm_rx = NULL, 86 .pcm_tx = NULL, 87 .out_stream = NULL, 88 .out_stream_count = 0, 89 .in_stream_count = 0, 90 .sample_rate = 0 91}; 92 93static int voip_set_volume(struct audio_device *adev, int volume); 94static int voip_set_mic_mute(struct audio_device *adev, bool state); 95static int voip_set_mode(struct audio_device *adev, int format); 96static int voip_set_rate(struct audio_device *adev, int rate); 97static int voip_set_evrc_min_max_rate(struct audio_device *adev, int min_rate, 98 int max_rate); 99static int voip_set_dtx(struct audio_device *adev, bool enable); 100static int voip_stop_call(struct audio_device *adev); 101static int voip_start_call(struct audio_device *adev, 102 struct pcm_config *voip_config); 103 104static int audio_format_to_voip_mode(int format) 105{ 106 int mode; 107 108 switch(format) { 109 case AUDIO_FORMAT_PCM_16_BIT: 110 mode = MODE_PCM; 111 break; 112 case AUDIO_FORMAT_AMR_NB: 113 mode = MODE_AMR; 114 break; 115 case AUDIO_FORMAT_AMR_WB: 116 mode = MODE_AMR_WB; 117 break; 118 case AUDIO_FORMAT_EVRC: 119 mode = MODE_IS127; 120 break; 121 case AUDIO_FORMAT_EVRCB: 122 mode = MODE_4GV_NB; 123 break; 124 case AUDIO_FORMAT_EVRCWB: 125 mode = MODE_4GV_WB; 126 break; 127 case AUDIO_FORMAT_EVRCNW: 128 mode = MODE_4GV_NW; 129 break; 130 default: 131 mode = MODE_PCM; 132 } 133 return mode; 134} 135 136static int voip_set_volume(struct audio_device *adev, int volume) 137{ 138 struct mixer_ctl *ctl; 139 const char *mixer_ctl_name = "Voip Rx Gain"; 140 int vol_index = 0; 141 uint32_t set_values[ ] = {0, 142 DEFAULT_VOLUME_RAMP_DURATION_MS}; 143 144 ALOGV("%s: enter", __func__); 145 146 /* Voice volume levels are mapped to adsp volume levels as follows. 147 * 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1 0 -> 0 148 * But this values don't changed in kernel. So, below change is need. 149 */ 150 vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX); 151 set_values[0] = vol_index; 152 153 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 154 if (!ctl) { 155 ALOGE("%s: Could not get ctl for mixer cmd - %s", 156 __func__, mixer_ctl_name); 157 return -EINVAL; 158 } 159 ALOGV("%s: Setting voip volume index: %d", __func__, set_values[0]); 160 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 161 162 ALOGV("%s: exit", __func__); 163 return 0; 164} 165 166static int voip_set_mic_mute(struct audio_device *adev, bool state) 167{ 168 struct mixer_ctl *ctl; 169 const char *mixer_ctl_name = "Voip Tx Mute"; 170 uint32_t set_values[ ] = {0, 171 DEFAULT_VOLUME_RAMP_DURATION_MS}; 172 173 ALOGV("%s: enter, state=%d", __func__, state); 174 175 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) { 176 set_values[0] = state; 177 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 178 if (!ctl) { 179 ALOGE("%s: Could not get ctl for mixer cmd - %s", 180 __func__, mixer_ctl_name); 181 return -EINVAL; 182 } 183 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 184 } 185 186 ALOGV("%s: exit", __func__); 187 return 0; 188} 189 190static int voip_set_mode(struct audio_device *adev, int format) 191{ 192 struct mixer_ctl *ctl; 193 const char *mixer_ctl_name = "Voip Mode Config"; 194 uint32_t set_values[ ] = {0}; 195 int mode; 196 197 ALOGD("%s: enter, format=%d", __func__, format); 198 199 mode = audio_format_to_voip_mode(format); 200 ALOGD("%s: Derived mode = %d", __func__, mode); 201 202 set_values[0] = mode; 203 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 204 if (!ctl) { 205 ALOGE("%s: Could not get ctl for mixer cmd - %s", 206 __func__, mixer_ctl_name); 207 return -EINVAL; 208 } 209 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 210 211 ALOGV("%s: exit", __func__); 212 return 0; 213} 214 215static int voip_set_rate(struct audio_device *adev, int rate) 216{ 217 struct mixer_ctl *ctl; 218 const char *mixer_ctl_name = "Voip Rate Config"; 219 uint32_t set_values[ ] = {0}; 220 221 ALOGD("%s: enter, rate=%d", __func__, rate); 222 223 set_values[0] = rate; 224 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 225 if (!ctl) { 226 ALOGE("%s: Could not get ctl for mixer cmd - %s", 227 __func__, mixer_ctl_name); 228 return -EINVAL; 229 } 230 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 231 232 ALOGV("%s: exit", __func__); 233 return 0; 234} 235 236static int voip_set_evrc_min_max_rate(struct audio_device *adev, int min_rate, 237 int max_rate) 238{ 239 struct mixer_ctl *ctl; 240 const char *mixer_ctl_name = "Voip Evrc Min Max Rate Config"; 241 uint32_t set_values[ ] = {0, 0}; 242 243 ALOGD("%s: enter, min_rate=%d, max_rate=%d", 244 __func__, min_rate, max_rate); 245 246 set_values[0] = min_rate; 247 set_values[1] = max_rate; 248 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 249 if (!ctl) { 250 ALOGE("%s: Could not get ctl for mixer cmd - %s", 251 __func__, mixer_ctl_name); 252 return -EINVAL; 253 } 254 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 255 256 ALOGV("%s: exit", __func__); 257 return 0; 258} 259 260static int voip_set_dtx(struct audio_device *adev, bool enable) 261{ 262 struct mixer_ctl *ctl; 263 const char *mixer_ctl_name = "Voip Dtx Mode"; 264 uint32_t set_values[ ] = {0}; 265 266 ALOGD("%s: enter, enable=%d", __func__, enable); 267 268 set_values[0] = enable; 269 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); 270 if (!ctl) { 271 ALOGE("%s: Could not get ctl for mixer cmd - %s", 272 __func__, mixer_ctl_name); 273 return -EINVAL; 274 } 275 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values)); 276 277 ALOGV("%s: exit", __func__); 278 return 0; 279} 280 281static int voip_stop_call(struct audio_device *adev) 282{ 283 int i, ret = 0; 284 struct audio_usecase *uc_info; 285 286 ALOGD("%s: enter, out_stream_count=%d, in_stream_count=%d", 287 __func__, voip_data.out_stream_count, voip_data.in_stream_count); 288 289 if (!voip_data.out_stream_count && !voip_data.in_stream_count) { 290 voip_data.sample_rate = 0; 291 uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL); 292 if (uc_info == NULL) { 293 ALOGE("%s: Could not find the usecase (%d) in the list", 294 __func__, USECASE_COMPRESS_VOIP_CALL); 295 return -EINVAL; 296 } 297 298 /* 1. Close the PCM devices */ 299 if (voip_data.pcm_rx) { 300 pcm_close(voip_data.pcm_rx); 301 voip_data.pcm_rx = NULL; 302 } 303 if (voip_data.pcm_tx) { 304 pcm_close(voip_data.pcm_tx); 305 voip_data.pcm_tx = NULL; 306 } 307 308 /* 2. Get and set stream specific mixer controls */ 309 disable_audio_route(adev, uc_info); 310 311 /* 3. Disable the rx and tx devices */ 312 disable_snd_device(adev, uc_info->out_snd_device); 313 disable_snd_device(adev, uc_info->in_snd_device); 314 315 list_remove(&uc_info->list); 316 free(uc_info); 317 } else 318 ALOGV("%s: NO-OP because out_stream_count=%d, in_stream_count=%d", 319 __func__, voip_data.out_stream_count, voip_data.in_stream_count); 320 321 ALOGV("%s: exit: status(%d)", __func__, ret); 322 return ret; 323} 324 325static int voip_start_call(struct audio_device *adev, 326 struct pcm_config *voip_config) 327{ 328 int i, ret = 0; 329 struct audio_usecase *uc_info; 330 int pcm_dev_rx_id, pcm_dev_tx_id; 331 332 ALOGD("%s: enter", __func__); 333 334 uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL); 335 if (uc_info == NULL) { 336 ALOGV("%s: voip usecase is added to the list", __func__); 337 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); 338 339 if (!uc_info) { 340 ALOGE("failed to allocate voip usecase mem"); 341 return -ENOMEM; 342 } 343 344 uc_info->id = USECASE_COMPRESS_VOIP_CALL; 345 uc_info->type = VOIP_CALL; 346 if (voip_data.out_stream) 347 uc_info->stream.out = voip_data.out_stream; 348 else 349 uc_info->stream.out = adev->primary_output; 350 uc_info->in_snd_device = SND_DEVICE_NONE; 351 uc_info->out_snd_device = SND_DEVICE_NONE; 352 353 list_add_tail(&adev->usecase_list, &uc_info->list); 354 355 select_devices(adev, USECASE_COMPRESS_VOIP_CALL); 356 357 pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK); 358 pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE); 359 360 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) { 361 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)", 362 __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id); 363 ret = -EIO; 364 goto error_start_voip; 365 } 366 367 ALOGD("%s: Opening PCM playback device card_id(%d) device_id(%d)", 368 __func__, adev->snd_card, pcm_dev_rx_id); 369 voip_data.pcm_rx = pcm_open(adev->snd_card, 370 pcm_dev_rx_id, 371 PCM_OUT, voip_config); 372 if (voip_data.pcm_rx && !pcm_is_ready(voip_data.pcm_rx)) { 373 ALOGE("%s: %s", __func__, pcm_get_error(voip_data.pcm_rx)); 374 pcm_close(voip_data.pcm_rx); 375 voip_data.pcm_rx = NULL; 376 ret = -EIO; 377 goto error_start_voip; 378 } 379 380 ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)", 381 __func__, adev->snd_card, pcm_dev_tx_id); 382 voip_data.pcm_tx = pcm_open(adev->snd_card, 383 pcm_dev_tx_id, 384 PCM_IN, voip_config); 385 if (voip_data.pcm_tx && !pcm_is_ready(voip_data.pcm_tx)) { 386 ALOGE("%s: %s", __func__, pcm_get_error(voip_data.pcm_tx)); 387 pcm_close(voip_data.pcm_rx); 388 voip_data.pcm_tx = NULL; 389 if (voip_data.pcm_rx) { 390 pcm_close(voip_data.pcm_rx); 391 voip_data.pcm_rx = NULL; 392 } 393 ret = -EIO; 394 goto error_start_voip; 395 } 396 pcm_start(voip_data.pcm_rx); 397 pcm_start(voip_data.pcm_tx); 398 399 voice_extn_compress_voip_set_volume(adev, adev->voice.volume); 400 401 if (ret < 0) { 402 ALOGE("%s: error %d\n", __func__, ret); 403 goto error_start_voip; 404 } 405 } else { 406 ALOGV("%s: voip usecase is already enabled", __func__); 407 if (voip_data.out_stream) 408 uc_info->stream.out = voip_data.out_stream; 409 else 410 uc_info->stream.out = adev->primary_output; 411 select_devices(adev, USECASE_COMPRESS_VOIP_CALL); 412 } 413 414 return 0; 415 416error_start_voip: 417 voip_stop_call(adev); 418 419 ALOGV("%s: exit: status(%d)", __func__, ret); 420 return ret; 421} 422 423int voice_extn_compress_voip_set_parameters(struct audio_device *adev, 424 struct str_parms *parms) 425{ 426 char *str; 427 char value[32]={0}; 428 int ret = 0, err, rate; 429 int min_rate, max_rate; 430 bool flag; 431 char *kv_pairs = str_parms_to_str(parms); 432 433 ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs); 434 435 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_RATE, 436 value, sizeof(value)); 437 if (err >= 0) { 438 rate = atoi(value); 439 voip_set_rate(adev, rate); 440 voip_set_evrc_min_max_rate(adev, rate, rate); 441 } 442 443 memset(value, 0, sizeof(value)); 444 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN, 445 value, sizeof(value)); 446 if (err >= 0) { 447 min_rate = atoi(value); 448 str_parms_del(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MIN); 449 memset(value, 0, sizeof(value)); 450 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX, 451 value, sizeof(value)); 452 if (err >= 0) { 453 max_rate = atoi(value); 454 voip_set_evrc_min_max_rate(adev, min_rate, max_rate); 455 } else { 456 ALOGE("%s: AUDIO_PARAMETER_KEY_VOIP_EVRC_RATE_MAX not found", __func__); 457 ret = -EINVAL; 458 goto done; 459 } 460 } 461 462 memset(value, 0, sizeof(value)); 463 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VOIP_DTX_MODE, 464 value, sizeof(value)); 465 if (err >= 0) { 466 flag = false; 467 if (strcmp(value, AUDIO_PARAMETER_VALUE_VOIP_TRUE) == 0) 468 flag = true; 469 voip_set_dtx(adev, flag); 470 } 471 472done: 473 ALOGV("%s: exit", __func__); 474 free(kv_pairs); 475 return ret; 476} 477 478void voice_extn_compress_voip_get_parameters(struct str_parms *query, 479 struct str_parms *reply) 480{ 481 int ret; 482 char value[32]={0}; 483 char *str = NULL; 484 485 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT, 486 value, sizeof(value)); 487 if (ret >= 0) { 488 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_OUT_STREAM_COUNT, 489 voip_data.out_stream_count); 490 } 491 492 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE, 493 value, sizeof(value)); 494 if (ret >= 0) { 495 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_SAMPLE_RATE, 496 voip_data.sample_rate); 497 } 498} 499 500void voice_extn_compress_voip_out_get_parameters(struct stream_out *out, 501 struct str_parms *query, 502 struct str_parms *reply) 503{ 504 int ret, val; 505 char value[32]={0}; 506 507 ALOGD("%s: enter", __func__); 508 509 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_CHECK, value, sizeof(value)); 510 511 if (ret >= 0) { 512 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) 513 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_CHECK, true); 514 else 515 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_CHECK, false); 516 } 517 518 ALOGV("%s: exit", __func__); 519} 520 521void voice_extn_compress_voip_in_get_parameters(struct stream_in *in, 522 struct str_parms *query, 523 struct str_parms *reply) 524{ 525 int ret, val; 526 char value[32]={0}; 527 char *kv_pairs = NULL; 528 529 ALOGV("%s: enter", __func__); 530 531 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_VOIP_CHECK, value, sizeof(value)); 532 533 if (ret >= 0) { 534 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) 535 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_CHECK, true); 536 else 537 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_VOIP_CHECK, false); 538 } 539 540 kv_pairs = str_parms_to_str(reply); 541 ALOGD_IF(kv_pairs != NULL, "%s: exit: return - %s", __func__, kv_pairs); 542 free(kv_pairs); 543} 544 545int voice_extn_compress_voip_out_get_buffer_size(struct stream_out *out) 546{ 547 if (out->config.rate == 16000) 548 return COMPRESS_VOIP_IO_BUF_SIZE_WB; 549 else 550 return COMPRESS_VOIP_IO_BUF_SIZE_NB; 551} 552 553int voice_extn_compress_voip_in_get_buffer_size(struct stream_in *in) 554{ 555 if (in->config.rate == 16000) 556 return COMPRESS_VOIP_IO_BUF_SIZE_WB; 557 else 558 return COMPRESS_VOIP_IO_BUF_SIZE_NB; 559} 560 561int voice_extn_compress_voip_start_output_stream(struct stream_out *out) 562{ 563 int ret = 0; 564 struct audio_device *adev = out->dev; 565 struct audio_usecase *uc_info; 566 int snd_card_status = get_snd_card_state(adev); 567 568 ALOGD("%s: enter", __func__); 569 570 if (SND_CARD_STATE_OFFLINE == snd_card_status) { 571 ret = -ENETRESET; 572 ALOGE("%s: sound card is not active/SSR returning error %d ", __func__, ret); 573 goto error; 574 } 575 576 if (!voip_data.out_stream_count) 577 ret = voice_extn_compress_voip_open_output_stream(out); 578 579 ret = voip_start_call(adev, &out->config); 580 out->pcm = voip_data.pcm_rx; 581 uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL); 582 if (uc_info) { 583 uc_info->stream.out = out; 584 uc_info->devices = out->devices; 585 } else { 586 ret = -EINVAL; 587 ALOGE("%s: exit(%d): failed to get use case info", __func__, ret); 588 goto error; 589 } 590 591error: 592 ALOGV("%s: exit: status(%d)", __func__, ret); 593 return ret; 594} 595 596int voice_extn_compress_voip_start_input_stream(struct stream_in *in) 597{ 598 int ret = 0; 599 struct audio_usecase *uc_info; 600 struct audio_device *adev = in->dev; 601 int snd_card_status = get_snd_card_state(adev); 602 603 ALOGD("%s: enter", __func__); 604 605 if (SND_CARD_STATE_OFFLINE == snd_card_status) { 606 ret = -ENETRESET; 607 ALOGE("%s: sound card is not active/SSR returning error %d ", __func__, ret); 608 goto error; 609 } 610 611 if (!voip_data.in_stream_count) 612 ret = voice_extn_compress_voip_open_input_stream(in); 613 614 adev->active_input = in; 615 ret = voip_start_call(adev, &in->config); 616 in->pcm = voip_data.pcm_tx; 617 618error: 619 ALOGV("%s: exit: status(%d)", __func__, ret); 620 return ret; 621} 622 623int voice_extn_compress_voip_close_output_stream(struct audio_stream *stream) 624{ 625 struct stream_out *out = (struct stream_out *)stream; 626 struct audio_device *adev = out->dev; 627 int ret = 0; 628 629 ALOGD("%s: enter", __func__); 630 if (voip_data.out_stream_count > 0) { 631 voip_data.out_stream_count--; 632 ret = voip_stop_call(adev); 633 voip_data.out_stream = NULL; 634 out->pcm = NULL; 635 } 636 637 ALOGV("%s: exit: status(%d)", __func__, ret); 638 return ret; 639} 640 641int voice_extn_compress_voip_open_output_stream(struct stream_out *out) 642{ 643 int mode, ret; 644 645 ALOGD("%s: enter", __func__); 646 647 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO; 648 out->channel_mask = AUDIO_CHANNEL_OUT_MONO; 649 out->usecase = USECASE_COMPRESS_VOIP_CALL; 650 if (out->sample_rate == 16000) 651 out->config = pcm_config_voip_wb; 652 else 653 out->config = pcm_config_voip_nb; 654 655 voip_data.out_stream = out; 656 voip_data.out_stream_count++; 657 voip_data.sample_rate = out->sample_rate; 658 ret = voip_set_mode(out->dev, out->format); 659 660 ALOGV("%s: exit", __func__); 661 return ret; 662} 663 664int voice_extn_compress_voip_close_input_stream(struct audio_stream *stream) 665{ 666 struct stream_in *in = (struct stream_in *)stream; 667 struct audio_device *adev = in->dev; 668 int status = 0; 669 670 ALOGD("%s: enter", __func__); 671 672 if(voip_data.in_stream_count > 0) { 673 adev->active_input = NULL; 674 voip_data.in_stream_count--; 675 status = voip_stop_call(adev); 676 in->pcm = NULL; 677 } 678 679 ALOGV("%s: exit: status(%d)", __func__, status); 680 return status; 681} 682 683int voice_extn_compress_voip_open_input_stream(struct stream_in *in) 684{ 685 int sample_rate; 686 int buffer_size,frame_size; 687 int mode, ret; 688 689 ALOGD("%s: enter", __func__); 690 691 if ((voip_data.sample_rate != 0) && 692 (voip_data.sample_rate != in->config.rate)) { 693 ret = -ENOTSUP; 694 goto done; 695 } else { 696 voip_data.sample_rate = in->config.rate; 697 } 698 699 in->usecase = USECASE_COMPRESS_VOIP_CALL; 700 if (in->config.rate == 16000) 701 in->config = pcm_config_voip_wb; 702 else 703 in->config = pcm_config_voip_nb; 704 705 voip_data.in_stream_count++; 706 ret = voip_set_mode(in->dev, in->format); 707 708done: 709 ALOGV("%s: exit, ret=%d", __func__, ret); 710 return ret; 711} 712 713int voice_extn_compress_voip_set_volume(struct audio_device *adev, float volume) 714{ 715 int vol, err = 0; 716 717 ALOGV("%s: enter", __func__); 718 719 if (volume < 0.0) { 720 volume = 0.0; 721 } else if (volume > 1.0) { 722 volume = 1.0; 723 } 724 725 vol = lrint(volume * 100.0); 726 727 /* Voice volume levels from android are mapped to driver volume levels as follows. 728 * 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0 729 * So adjust the volume to get the correct volume index in driver 730 */ 731 vol = 100 - vol; 732 733 err = voip_set_volume(adev, vol); 734 735 ALOGV("%s: exit: status(%d)", __func__, err); 736 737 return err; 738} 739 740int voice_extn_compress_voip_set_mic_mute(struct audio_device *adev, bool state) 741{ 742 int err = 0; 743 744 ALOGV("%s: enter", __func__); 745 746 err = voip_set_mic_mute(adev, state); 747 748 ALOGV("%s: exit: status(%d)", __func__, err); 749 return err; 750} 751 752bool voice_extn_compress_voip_pcm_prop_check() 753{ 754 char prop_value[PROPERTY_VALUE_MAX] = {0}; 755 756 property_get("use.voice.path.for.pcm.voip", prop_value, "0"); 757 if (!strncmp("true", prop_value, sizeof("true"))) 758 { 759 ALOGD("%s: VoIP PCM property is enabled", __func__); 760 return true; 761 } 762 else 763 return false; 764} 765 766bool voice_extn_compress_voip_is_active(struct audio_device *adev) 767{ 768 struct audio_usecase *voip_usecase = NULL; 769 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL); 770 771 if (voip_usecase != NULL) 772 return true; 773 else 774 return false; 775} 776 777bool voice_extn_compress_voip_is_format_supported(audio_format_t format) 778{ 779 switch (format) { 780 case AUDIO_FORMAT_PCM_16_BIT: 781 if (voice_extn_compress_voip_pcm_prop_check()) 782 return true; 783 else 784 return false; 785 case AUDIO_FORMAT_AMR_NB: 786 case AUDIO_FORMAT_AMR_WB: 787 case AUDIO_FORMAT_EVRC: 788 case AUDIO_FORMAT_EVRCB: 789 case AUDIO_FORMAT_EVRCWB: 790 case AUDIO_FORMAT_EVRCNW: 791 return true; 792 default: 793 return false; 794 } 795} 796 797bool voice_extn_compress_voip_is_config_supported(struct audio_config *config) 798{ 799 bool ret = false; 800 801 ret = voice_extn_compress_voip_is_format_supported(config->format); 802 if (ret) { 803 if ((popcount(config->channel_mask) == 1) && 804 (config->sample_rate == 8000 || config->sample_rate == 16000)) 805 ret = ((voip_data.sample_rate == 0) ? true: 806 (voip_data.sample_rate == config->sample_rate)); 807 else 808 ret = false; 809 } 810 return ret; 811} 812