• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "audio_hw_hfp"
18 /*#define LOG_NDEBUG 0*/
19 #define LOG_NDDEBUG 0
20 
21 #include <errno.h>
22 #include <math.h>
23 #include <log/log.h>
24 
25 #include "audio_hw.h"
26 #include "platform.h"
27 #include "platform_api.h"
28 #include <stdlib.h>
29 #include <cutils/str_parms.h>
30 #include "audio_extn/tfa_98xx.h"
31 #include "audio_extn.h"
32 
33 #define AUDIO_PARAMETER_HFP_ENABLE            "hfp_enable"
34 #define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
35 #define AUDIO_PARAMETER_KEY_HFP_VOLUME        "hfp_volume"
36 #define AUDIO_PARAMETER_HFP_VOL_MIXER_CTL     "hfp_vol_mixer_ctl"
37 #define AUDIO_PARAMATER_HFP_VALUE_MAX         128
38 
39 #define AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME "hfp_mic_volume"
40 #define PLAYBACK_VOLUME_MAX 0x2000
41 #define CAPTURE_VOLUME_DEFAULT                (15.0)
42 
43 static int32_t start_hfp(struct audio_device *adev,
44                                struct str_parms *parms);
45 
46 static int32_t stop_hfp(struct audio_device *adev);
47 
48 struct hfp_module {
49     struct pcm *hfp_sco_rx;
50     struct pcm *hfp_sco_tx;
51     struct pcm *hfp_pcm_rx;
52     struct pcm *hfp_pcm_tx;
53     float  hfp_volume;
54     float  mic_volume;
55     char   hfp_vol_mixer_ctl[AUDIO_PARAMATER_HFP_VALUE_MAX];
56     bool   is_hfp_running;
57     bool   mic_mute;
58     audio_usecase_t ucid;
59 };
60 
61 static struct hfp_module hfpmod = {
62     .hfp_sco_rx = NULL,
63     .hfp_sco_tx = NULL,
64     .hfp_pcm_rx = NULL,
65     .hfp_pcm_tx = NULL,
66     .hfp_volume = 0,
67     .mic_volume = CAPTURE_VOLUME_DEFAULT,
68     .hfp_vol_mixer_ctl = {0, },
69     .is_hfp_running = 0,
70     .mic_mute = 0,
71     .ucid = USECASE_AUDIO_HFP_SCO,
72 };
73 static struct pcm_config pcm_config_hfp = {
74     .channels = 1,
75     .rate = 8000,
76     .period_size = 240,
77     .period_count = 2,
78     .format = PCM_FORMAT_S16_LE,
79     .start_threshold = 0,
80     .stop_threshold = INT_MAX,
81     .avail_min = 0,
82 };
83 
hfp_set_volume(struct audio_device * adev,float value)84 static int32_t hfp_set_volume(struct audio_device *adev, float value)
85 {
86     int32_t vol, ret = 0;
87     struct mixer_ctl *ctl;
88 
89     ALOGV("%s: entry", __func__);
90     ALOGD("%s: (%f)\n", __func__, value);
91 
92     hfpmod.hfp_volume = value;
93     audio_extn_tfa_98xx_set_voice_vol(value);
94 
95     if (value < 0.0) {
96         ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
97         value = 0.0;
98     } else {
99         value = ((value > 15.000000) ? 1.0 : (value / 15));
100         ALOGW("%s: Volume brought with in range (%f)\n", __func__, value);
101     }
102     vol  = lrint((value * 0x2000) + 0.5);
103 
104     if (!hfpmod.is_hfp_running) {
105         ALOGV("%s: HFP not active, ignoring set_hfp_volume call", __func__);
106         return -EIO;
107     }
108 
109     ALOGD("%s: Setting HFP volume to %d \n", __func__, vol);
110     if (0 == hfpmod.hfp_vol_mixer_ctl[0]) {
111 #ifdef EXTERNAL_BT_SUPPORTED
112         strcpy(hfpmod.hfp_vol_mixer_ctl, "PRI AUXPCM LOOPBACK Volume");
113 #else
114         strcpy(hfpmod.hfp_vol_mixer_ctl, "Internal HFP RX Volume");
115 #endif
116         ALOGW("%s: Defaulting hfp mixer control to: %s",
117                  __func__, hfpmod.hfp_vol_mixer_ctl);
118     }
119     ctl = mixer_get_ctl_by_name(adev->mixer, hfpmod.hfp_vol_mixer_ctl);
120     if (!ctl) {
121         ALOGE("%s: Could not get ctl for mixer cmd - %s",
122               __func__, hfpmod.hfp_vol_mixer_ctl);
123         return -EINVAL;
124     }
125     if(mixer_ctl_set_value(ctl, 0, vol) < 0) {
126         ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, vol);
127         return -EINVAL;
128     }
129 
130     ALOGV("%s: exit", __func__);
131     return ret;
132 }
133 
134 
135 /*Set mic volume to value.
136 *
137 * This interface is used for mic volume control, set mic volume as value(range 0 ~ 15).
138 */
hfp_set_mic_volume(struct audio_device * adev,float value)139 static int hfp_set_mic_volume(struct audio_device *adev, float value)
140 {
141     int volume, ret = 0;
142     char mixer_ctl_name[128];
143     struct mixer_ctl *ctl;
144     int pcm_device_id = HFP_ASM_RX_TX;
145 
146     if (!hfpmod.is_hfp_running) {
147         ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
148         return -EIO;
149     }
150 
151     if (value < 0.0) {
152         ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
153         value = 0.0;
154     } else if (value > CAPTURE_VOLUME_DEFAULT) {
155         value = CAPTURE_VOLUME_DEFAULT;
156         ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
157     }
158 
159     value = value / CAPTURE_VOLUME_DEFAULT;
160     memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
161     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
162              "Playback %d Volume", pcm_device_id);
163     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
164     if (!ctl) {
165         ALOGE("%s: Could not get ctl for mixer cmd - %s",
166               __func__, mixer_ctl_name);
167         return -EINVAL;
168     }
169     volume = (int)(value * PLAYBACK_VOLUME_MAX);
170 
171     ALOGD("%s: Setting volume to %d (%s)\n", __func__, volume, mixer_ctl_name);
172     if (mixer_ctl_set_value(ctl, 0, volume) < 0) {
173         ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
174         return -EINVAL;
175     }
176 
177     return ret;
178 }
179 
hfp_get_mic_volume(struct audio_device * adev)180 static float hfp_get_mic_volume(struct audio_device *adev)
181 {
182     int volume, ret = 0;
183     char mixer_ctl_name[128];
184     struct mixer_ctl *ctl;
185     int pcm_device_id = HFP_ASM_RX_TX;
186     float value = 0.0;
187 
188     if (!hfpmod.is_hfp_running) {
189         ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
190         return -EIO;
191     }
192 
193     memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
194     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
195              "Playback %d Volume", pcm_device_id);
196     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
197     if (!ctl) {
198         ALOGE("%s: Could not get ctl for mixer cmd - %s",
199               __func__, mixer_ctl_name);
200         return -EINVAL;
201     }
202 
203     volume = mixer_ctl_get_value(ctl, 0);
204     if ( volume < 0) {
205         ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
206         return -EINVAL;
207     }
208     ALOGD("%s: getting mic volume %d \n", __func__, volume);
209 
210     value = (volume / PLAYBACK_VOLUME_MAX) * CAPTURE_VOLUME_DEFAULT;
211     if (value < 0.0) {
212         ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
213         value = 0.0;
214     } else if (value > CAPTURE_VOLUME_DEFAULT) {
215         value = CAPTURE_VOLUME_DEFAULT;
216         ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
217     }
218 
219     return value;
220 }
221 
222 /*Set mic mute state.
223 *
224 * This interface is used for mic mute state control
225 */
audio_extn_hfp_set_mic_mute(struct audio_device * adev,bool state)226 int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state)
227 {
228     int rc = 0;
229 
230     if (state == hfpmod.mic_mute)
231         return rc;
232 
233     if (state == true) {
234         hfpmod.mic_volume = hfp_get_mic_volume(adev);
235     }
236     rc = hfp_set_mic_volume(adev, (state == true) ? 0.0 : hfpmod.mic_volume);
237     adev->voice.mic_mute = state;
238     hfpmod.mic_mute = state;
239     ALOGD("%s: Setting mute state %d, rc %d\n", __func__, state, rc);
240     return rc;
241 }
242 
start_hfp(struct audio_device * adev,struct str_parms * parms __unused)243 static int32_t start_hfp(struct audio_device *adev,
244                          struct str_parms *parms __unused)
245 {
246     int32_t i, ret = 0;
247     struct audio_usecase *uc_info;
248     int32_t pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id;
249 
250     ALOGD("%s: enter", __func__);
251 
252     if (adev->enable_hfp == true) {
253         ALOGD("%s: HFP is already active!\n", __func__);
254         return 0;
255     }
256     adev->enable_hfp = true;
257     platform_set_mic_mute(adev->platform, false);
258 
259     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
260     uc_info->id = hfpmod.ucid;
261     uc_info->type = PCM_HFP_CALL;
262     uc_info->stream.out = adev->primary_output;
263     uc_info->devices = adev->primary_output->devices;
264     uc_info->in_snd_device = SND_DEVICE_NONE;
265     uc_info->out_snd_device = SND_DEVICE_NONE;
266 
267     list_add_tail(&adev->usecase_list, &uc_info->list);
268 
269     audio_extn_tfa_98xx_set_mode_bt();
270 
271     select_devices(adev, hfpmod.ucid);
272 
273     pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
274     pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
275     pcm_dev_asm_rx_id = HFP_ASM_RX_TX;
276     pcm_dev_asm_tx_id = HFP_ASM_RX_TX;
277     if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0 ||
278         pcm_dev_asm_rx_id < 0 || pcm_dev_asm_tx_id < 0 ) {
279         ALOGE("%s: Invalid PCM devices (rx: %d tx: %d asm: rx tx %d) for the usecase(%d)",
280               __func__, pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, uc_info->id);
281         ret = -EIO;
282         goto exit;
283     }
284 
285     ALOGV("%s: HFP PCM devices (hfp rx tx: %d pcm rx tx: %d) for the usecase(%d)",
286               __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
287 
288     ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
289           __func__, adev->snd_card, pcm_dev_rx_id);
290     hfpmod.hfp_sco_rx = pcm_open(adev->snd_card,
291                                   pcm_dev_asm_rx_id,
292                                   PCM_OUT, &pcm_config_hfp);
293     if (hfpmod.hfp_sco_rx && !pcm_is_ready(hfpmod.hfp_sco_rx)) {
294         ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_rx));
295         ret = -EIO;
296         goto exit;
297     }
298     ALOGD("%s: Opening PCM capture device card_id(%d) device_id(%d)",
299           __func__, adev->snd_card, pcm_dev_tx_id);
300 
301     if (audio_extn_tfa_98xx_is_supported() == false) {
302         hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
303                                        pcm_dev_rx_id,
304                                        PCM_OUT, &pcm_config_hfp);
305         if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
306             ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_rx));
307             ret = -EIO;
308             goto exit;
309         }
310     }
311     hfpmod.hfp_sco_tx = pcm_open(adev->snd_card,
312                                   pcm_dev_asm_tx_id,
313                                   PCM_IN, &pcm_config_hfp);
314     if (hfpmod.hfp_sco_tx && !pcm_is_ready(hfpmod.hfp_sco_tx)) {
315         ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_tx));
316         ret = -EIO;
317         goto exit;
318     }
319     ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
320           __func__, adev->snd_card, pcm_dev_tx_id);
321 
322     if (audio_extn_tfa_98xx_is_supported() == false) {
323         hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
324                                        pcm_dev_tx_id,
325                                        PCM_IN, &pcm_config_hfp);
326         if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
327             ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_tx));
328             ret = -EIO;
329             goto exit;
330         }
331     }
332     pcm_start(hfpmod.hfp_sco_rx);
333     pcm_start(hfpmod.hfp_sco_tx);
334     if (audio_extn_tfa_98xx_is_supported() == false) {
335         pcm_start(hfpmod.hfp_pcm_rx);
336         pcm_start(hfpmod.hfp_pcm_tx);
337     }
338 
339     audio_extn_tfa_98xx_enable_speaker();
340 
341     hfpmod.is_hfp_running = true;
342     hfp_set_volume(adev, hfpmod.hfp_volume);
343 
344     /* Set mic volume by mute status, we don't provide set mic volume in phone app, only
345     provide mute and unmute. */
346     audio_extn_hfp_set_mic_mute(adev, adev->mic_muted);
347 
348     ALOGD("%s: exit: status(%d)", __func__, ret);
349     return 0;
350 
351 exit:
352     stop_hfp(adev);
353     ALOGE("%s: Problem in HFP start: status(%d)", __func__, ret);
354     return ret;
355 }
356 
stop_hfp(struct audio_device * adev)357 static int32_t stop_hfp(struct audio_device *adev)
358 {
359     int32_t i, ret = 0;
360     struct audio_usecase *uc_info;
361 
362     ALOGD("%s: enter", __func__);
363     hfpmod.is_hfp_running = false;
364 
365     /* 1. Close the PCM devices */
366     if (hfpmod.hfp_sco_rx) {
367         pcm_close(hfpmod.hfp_sco_rx);
368         hfpmod.hfp_sco_rx = NULL;
369     }
370     if (hfpmod.hfp_sco_tx) {
371         pcm_close(hfpmod.hfp_sco_tx);
372         hfpmod.hfp_sco_tx = NULL;
373     }
374     if (hfpmod.hfp_pcm_rx) {
375         pcm_close(hfpmod.hfp_pcm_rx);
376         hfpmod.hfp_pcm_rx = NULL;
377     }
378     if (hfpmod.hfp_pcm_tx) {
379         pcm_close(hfpmod.hfp_pcm_tx);
380         hfpmod.hfp_pcm_tx = NULL;
381     }
382 
383     uc_info = get_usecase_from_list(adev, hfpmod.ucid);
384     if (uc_info == NULL) {
385         ALOGE("%s: Could not find the usecase (%d) in the list",
386               __func__, hfpmod.ucid);
387         return -EINVAL;
388     }
389 
390     /* 2. Get and set stream specific mixer controls */
391     disable_audio_route(adev, uc_info);
392 
393     /* 3. Disable the rx and tx devices */
394     disable_snd_device(adev, uc_info->out_snd_device);
395     disable_snd_device(adev, uc_info->in_snd_device);
396 
397     /* Disable the echo reference for HFP Tx */
398     platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
399 
400     /* Set the unmute Tx mixer control */
401     if (voice_get_mic_mute(adev)) {
402         platform_set_mic_mute(adev->platform, false);
403         ALOGD("%s: unMute HFP Tx", __func__);
404     }
405     adev->enable_hfp = false;
406 
407     list_remove(&uc_info->list);
408     free(uc_info);
409 
410     ALOGD("%s: exit: status(%d)", __func__, ret);
411     return ret;
412 }
413 
audio_extn_hfp_is_active(struct audio_device * adev)414 bool audio_extn_hfp_is_active(struct audio_device *adev)
415 {
416     struct audio_usecase *hfp_usecase = NULL;
417     hfp_usecase = get_usecase_from_list(adev, hfpmod.ucid);
418 
419     if (hfp_usecase != NULL)
420         return true;
421     else
422         return false;
423 }
424 
audio_extn_hfp_get_usecase()425 audio_usecase_t audio_extn_hfp_get_usecase()
426 {
427     return hfpmod.ucid;
428 }
429 
audio_extn_hfp_set_parameters(struct audio_device * adev,struct str_parms * parms)430 void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
431 {
432     int ret;
433     int rate;
434     int val;
435     float vol;
436     char value[AUDIO_PARAMATER_HFP_VALUE_MAX] = {0, };
437 
438     ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
439                             sizeof(value));
440     if (ret >= 0) {
441            if (!strncmp(value,"true",sizeof(value))) {
442                if (!hfpmod.is_hfp_running)
443                    start_hfp(adev,parms);
444                else
445                    ALOGW("%s: HFP is already active.", __func__);
446            } else {
447                if (hfpmod.is_hfp_running)
448                    stop_hfp(adev);
449                else
450                    ALOGW("%s: ignore STOP, HFC not active", __func__);
451            }
452     }
453     memset(value, 0, sizeof(value));
454     ret = str_parms_get_str(parms,AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
455                             sizeof(value));
456     if (ret >= 0) {
457            rate = atoi(value);
458            if (rate == 8000){
459                hfpmod.ucid = USECASE_AUDIO_HFP_SCO;
460                pcm_config_hfp.rate = rate;
461            } else if (rate == 16000){
462                hfpmod.ucid = USECASE_AUDIO_HFP_SCO_WB;
463                pcm_config_hfp.rate = rate;
464            } else
465                ALOGE("Unsupported rate..");
466     }
467 
468     if (hfpmod.is_hfp_running) {
469         memset(value, 0, sizeof(value));
470         ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
471                                 value, sizeof(value));
472         if (ret >= 0) {
473             val = atoi(value);
474             if (val > 0)
475                 select_devices(adev, hfpmod.ucid);
476         }
477     }
478 
479     memset(value, 0, sizeof(value));
480     ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_VOL_MIXER_CTL,
481                           value, sizeof(value));
482     if (ret >= 0) {
483         ALOGD("%s: mixer ctl name: %s", __func__, value);
484         strcpy(hfpmod.hfp_vol_mixer_ctl, value);
485         str_parms_del(parms, AUDIO_PARAMETER_HFP_VOL_MIXER_CTL);
486     }
487 
488     memset(value, 0, sizeof(value));
489     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_VOLUME,
490                             value, sizeof(value));
491     if (ret >= 0) {
492         if (sscanf(value, "%f", &vol) != 1){
493             ALOGE("%s: error in retrieving hfp volume", __func__);
494             ret = -EIO;
495             goto exit;
496         }
497         ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
498         hfp_set_volume(adev, vol);
499     }
500 
501     memset(value, 0, sizeof(value));
502     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME,
503                             value, sizeof(value));
504     if (ret >= 0) {
505         if (sscanf(value, "%f", &vol) != 1){
506             ALOGE("%s: error in retrieving hfp mic volume", __func__);
507             ret = -EIO;
508             goto exit;
509         }
510         ALOGD("%s: set_hfp_mic_volume usecase, Vol: [%f]", __func__, vol);
511         hfp_set_mic_volume(adev, vol);
512     }
513 
514 exit:
515     ALOGV("%s Exit",__func__);
516 }
517