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