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
42 struct 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
50 struct 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
58 struct 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
84 static 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
93 static int voip_set_volume(struct audio_device *adev, int volume);
94 static int voip_set_mic_mute(struct audio_device *adev, bool state);
95 static int voip_set_mode(struct audio_device *adev, int format);
96 static int voip_set_rate(struct audio_device *adev, int rate);
97 static int voip_set_evrc_min_max_rate(struct audio_device *adev, int min_rate,
98 int max_rate);
99 static int voip_set_dtx(struct audio_device *adev, bool enable);
100 static int voip_stop_call(struct audio_device *adev);
101 static int voip_start_call(struct audio_device *adev,
102 struct pcm_config *voip_config);
103
audio_format_to_voip_mode(int format)104 static 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
voip_set_volume(struct audio_device * adev,int volume)136 static 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
voip_set_mic_mute(struct audio_device * adev,bool state)166 static 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
voip_set_mode(struct audio_device * adev,int format)190 static 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
voip_set_rate(struct audio_device * adev,int rate)215 static 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
voip_set_evrc_min_max_rate(struct audio_device * adev,int min_rate,int max_rate)236 static 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
voip_set_dtx(struct audio_device * adev,bool enable)260 static 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
voip_stop_call(struct audio_device * adev)281 static 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
voip_start_call(struct audio_device * adev,struct pcm_config * voip_config)325 static 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
416 error_start_voip:
417 voip_stop_call(adev);
418
419 ALOGV("%s: exit: status(%d)", __func__, ret);
420 return ret;
421 }
422
voice_extn_compress_voip_set_parameters(struct audio_device * adev,struct str_parms * parms)423 int 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
472 done:
473 ALOGV("%s: exit", __func__);
474 free(kv_pairs);
475 return ret;
476 }
477
voice_extn_compress_voip_get_parameters(struct str_parms * query,struct str_parms * reply)478 void 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
voice_extn_compress_voip_out_get_parameters(struct stream_out * out,struct str_parms * query,struct str_parms * reply)500 void 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
voice_extn_compress_voip_in_get_parameters(struct stream_in * in,struct str_parms * query,struct str_parms * reply)521 void 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
voice_extn_compress_voip_out_get_buffer_size(struct stream_out * out)545 int 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
voice_extn_compress_voip_in_get_buffer_size(struct stream_in * in)553 int 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
voice_extn_compress_voip_start_output_stream(struct stream_out * out)561 int 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
591 error:
592 ALOGV("%s: exit: status(%d)", __func__, ret);
593 return ret;
594 }
595
voice_extn_compress_voip_start_input_stream(struct stream_in * in)596 int 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
618 error:
619 ALOGV("%s: exit: status(%d)", __func__, ret);
620 return ret;
621 }
622
voice_extn_compress_voip_close_output_stream(struct audio_stream * stream)623 int 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
voice_extn_compress_voip_open_output_stream(struct stream_out * out)641 int 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
voice_extn_compress_voip_close_input_stream(struct audio_stream * stream)664 int 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
voice_extn_compress_voip_open_input_stream(struct stream_in * in)683 int 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
708 done:
709 ALOGV("%s: exit, ret=%d", __func__, ret);
710 return ret;
711 }
712
voice_extn_compress_voip_set_volume(struct audio_device * adev,float volume)713 int 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
voice_extn_compress_voip_set_mic_mute(struct audio_device * adev,bool state)740 int 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
voice_extn_compress_voip_pcm_prop_check()752 bool 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
voice_extn_compress_voip_is_active(struct audio_device * adev)766 bool 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
voice_extn_compress_voip_is_format_supported(audio_format_t format)777 bool 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
voice_extn_compress_voip_is_config_supported(struct audio_config * config)797 bool 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