blob: 55551dce23d5afb1ef5f8dc23297cef0356e1e06 [file] [log] [blame]
Aalique Grahame22e49102018-12-18 14:23:57 -08001/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above
9 copyright notice, this list of conditions and the following
10 disclaimer in the documentation and/or other materials provided
11 with the distribution.
12 * Neither the name of The Linux Foundation nor the names of its
13 contributors may be used to endorse or promote products derived
14 from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
27
28#define LOG_TAG "audio_hw_hfp"
29/*#define LOG_NDEBUG 0*/
30#define LOG_NDDEBUG 0
31
32#include <errno.h>
33#include <math.h>
Aalique Grahame22e49102018-12-18 14:23:57 -080034#include <log/log.h>
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080035
36#include "audio_hw.h"
37#include "platform.h"
38#include "platform_api.h"
39#include <stdlib.h>
40#include <cutils/str_parms.h>
Derek Chend2530072014-11-24 12:39:14 -080041#include "audio_extn.h"
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080042
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053043#ifdef DYNAMIC_LOG_ENABLED
44#include <log_xml_parser.h>
45#define LOG_MASK HAL_MOD_FILE_HFP
46#include <log_utils.h>
47#endif
48
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080049#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
Vimal Puthanveed47e64852013-12-20 13:23:39 -080050#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
Amit Shekhar967cab32014-02-07 17:03:21 -080051#define AUDIO_PARAMETER_KEY_HFP_VOLUME "hfp_volume"
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +053052#define AUDIO_PARAMETER_HFP_PCM_DEV_ID "hfp_pcm_dev_id"
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080053
Aalique Grahame22e49102018-12-18 14:23:57 -080054#define AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME "hfp_mic_volume"
55#define PLAYBACK_VOLUME_MAX 0x2000
56#define CAPTURE_VOLUME_DEFAULT (15.0)
57
Sudheer Papothi19e43d02014-07-16 02:34:41 +053058#ifdef PLATFORM_MSM8994
59#define HFP_RX_VOLUME "SEC AUXPCM LOOPBACK Volume"
Aalique Grahame22e49102018-12-18 14:23:57 -080060#elif defined (PLATFORM_MSM8996) || defined (EXTERNAL_BT_SUPPORTED)
Banajit Goswamida77c452015-10-14 20:45:22 -070061#define HFP_RX_VOLUME "PRI AUXPCM LOOPBACK Volume"
Derek Chen3e5b30a2018-10-24 01:04:25 -070062#elif defined PLATFORM_AUTO
63#define HFP_RX_VOLUME "Playback 36 Volume"
Meng Wangef2f6e12018-10-08 13:06:05 +080064#elif defined (PLATFORM_MSM8998) || defined (PLATFORM_MSMFALCON) || \
65 defined (PLATFORM_SDM845) || defined (PLATFORM_SDM710) || \
66 defined (PLATFORM_QCS605) || defined (PLATFORM_MSMNILE) || \
67 defined (PLATFORM_KONA) || defined (PLATFORM_MSMSTEPPE) || \
Manisha Agarwal888e9762019-02-27 22:18:49 +053068 defined (PLATFORM_QCS405) || defined (PLATFORM_TRINKET) || \
69 defined (PLATFORM_LITO)
Banajit Goswami4c0dff22016-03-04 18:31:22 -080070#define HFP_RX_VOLUME "SLIMBUS_7 LOOPBACK Volume"
Sudheer Papothi19e43d02014-07-16 02:34:41 +053071#else
72#define HFP_RX_VOLUME "Internal HFP RX Volume"
73#endif
74
Vimal Puthanveed584048b2013-12-11 17:00:50 -080075static int32_t start_hfp(struct audio_device *adev,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080076 struct str_parms *parms);
77
Vimal Puthanveed584048b2013-12-11 17:00:50 -080078static int32_t stop_hfp(struct audio_device *adev);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080079
80struct hfp_module {
81 struct pcm *hfp_sco_rx;
82 struct pcm *hfp_sco_tx;
83 struct pcm *hfp_pcm_rx;
84 struct pcm *hfp_pcm_tx;
85 bool is_hfp_running;
Amit Shekhar967cab32014-02-07 17:03:21 -080086 float hfp_volume;
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +053087 int32_t hfp_pcm_dev_id;
Vimal Puthanveed47e64852013-12-20 13:23:39 -080088 audio_usecase_t ucid;
Aalique Grahame22e49102018-12-18 14:23:57 -080089 float mic_volume;
90 bool mic_mute;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080091};
92
93static struct hfp_module hfpmod = {
94 .hfp_sco_rx = NULL,
95 .hfp_sco_tx = NULL,
96 .hfp_pcm_rx = NULL,
97 .hfp_pcm_tx = NULL,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080098 .is_hfp_running = 0,
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +053099 .hfp_volume = 0,
100 .hfp_pcm_dev_id = HFP_ASM_RX_TX,
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800101 .ucid = USECASE_AUDIO_HFP_SCO,
Aalique Grahame22e49102018-12-18 14:23:57 -0800102 .mic_volume = CAPTURE_VOLUME_DEFAULT,
103 .mic_mute = 0,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800104};
Aalique Grahame22e49102018-12-18 14:23:57 -0800105
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800106static struct pcm_config pcm_config_hfp = {
107 .channels = 1,
108 .rate = 8000,
109 .period_size = 240,
110 .period_count = 2,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = 0,
113 .stop_threshold = INT_MAX,
114 .avail_min = 0,
115};
116
Arun Mirpurie008ed22019-03-21 11:21:04 -0700117//external feature dependency
118static fp_platform_set_mic_mute_t fp_platform_set_mic_mute;
119static fp_platform_get_pcm_device_id_t fp_platform_get_pcm_device_id;
120static fp_platform_set_echo_reference_t fp_platform_set_echo_reference;
121static fp_select_devices_t fp_select_devices;
122static fp_audio_extn_ext_hw_plugin_usecase_start_t fp_audio_extn_ext_hw_plugin_usecase_start;
123static fp_audio_extn_ext_hw_plugin_usecase_stop_t fp_audio_extn_ext_hw_plugin_usecase_stop;
124static fp_get_usecase_from_list_t fp_get_usecase_from_list;
125static fp_disable_audio_route_t fp_disable_audio_route;
126static fp_disable_snd_device_t fp_disable_snd_device;
127static fp_voice_get_mic_mute_t fp_voice_get_mic_mute;
128
Amit Shekhar967cab32014-02-07 17:03:21 -0800129static int32_t hfp_set_volume(struct audio_device *adev, float value)
130{
131 int32_t vol, ret = 0;
132 struct mixer_ctl *ctl;
Sudheer Papothi19e43d02014-07-16 02:34:41 +0530133 const char *mixer_ctl_name = HFP_RX_VOLUME;
Amit Shekhar967cab32014-02-07 17:03:21 -0800134
135 ALOGV("%s: entry", __func__);
136 ALOGD("%s: (%f)\n", __func__, value);
137
Satya Krishna Pindiproli3ed6d792014-09-09 15:32:25 +0530138 hfpmod.hfp_volume = value;
Aalique Grahame22e49102018-12-18 14:23:57 -0800139
Amit Shekhar967cab32014-02-07 17:03:21 -0800140 if (value < 0.0) {
141 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
142 value = 0.0;
143 } else {
144 value = ((value > 15.000000) ? 1.0 : (value / 15));
145 ALOGW("%s: Volume brought with in range (%f)\n", __func__, value);
146 }
147 vol = lrint((value * 0x2000) + 0.5);
Amit Shekhar967cab32014-02-07 17:03:21 -0800148
149 if (!hfpmod.is_hfp_running) {
150 ALOGV("%s: HFP not active, ignoring set_hfp_volume call", __func__);
151 return -EIO;
152 }
153
154 ALOGD("%s: Setting HFP volume to %d \n", __func__, vol);
155 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
156 if (!ctl) {
157 ALOGE("%s: Could not get ctl for mixer cmd - %s",
158 __func__, mixer_ctl_name);
159 return -EINVAL;
160 }
161 if(mixer_ctl_set_value(ctl, 0, vol) < 0) {
162 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, vol);
163 return -EINVAL;
164 }
165
166 ALOGV("%s: exit", __func__);
167 return ret;
168}
169
Aalique Grahame22e49102018-12-18 14:23:57 -0800170/*Set mic volume to value.
171*
172* This interface is used for mic volume control, set mic volume as value(range 0 ~ 15).
173*/
174static int hfp_set_mic_volume(struct audio_device *adev, float value)
175{
176 int volume, ret = 0;
177 char mixer_ctl_name[128];
178 struct mixer_ctl *ctl;
179 int pcm_device_id = HFP_ASM_RX_TX;
180
Arun Mirpurie008ed22019-03-21 11:21:04 -0700181 ALOGD("%s: enter, value=%f", __func__, value);
182
Aalique Grahame22e49102018-12-18 14:23:57 -0800183 if (!hfpmod.is_hfp_running) {
184 ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
185 return -EIO;
186 }
187
188 if (value < 0.0) {
189 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
190 value = 0.0;
191 } else if (value > CAPTURE_VOLUME_DEFAULT) {
192 value = CAPTURE_VOLUME_DEFAULT;
193 ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
194 }
195
196 value = value / CAPTURE_VOLUME_DEFAULT;
197 memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
198 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
199 "Playback %d Volume", pcm_device_id);
200 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
201 if (!ctl) {
202 ALOGE("%s: Could not get ctl for mixer cmd - %s",
203 __func__, mixer_ctl_name);
204 return -EINVAL;
205 }
206 volume = (int)(value * PLAYBACK_VOLUME_MAX);
207
208 ALOGD("%s: Setting volume to %d (%s)\n", __func__, volume, mixer_ctl_name);
209 if (mixer_ctl_set_value(ctl, 0, volume) < 0) {
210 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
211 return -EINVAL;
212 }
213
214 return ret;
215}
216
217static float hfp_get_mic_volume(struct audio_device *adev)
218{
219 int volume;
220 char mixer_ctl_name[128];
221 struct mixer_ctl *ctl;
222 int pcm_device_id = HFP_ASM_RX_TX;
223 float value = 0.0;
224
Arun Mirpurie008ed22019-03-21 11:21:04 -0700225 ALOGD("%s: enter", __func__);
226
Aalique Grahame22e49102018-12-18 14:23:57 -0800227 if (!hfpmod.is_hfp_running) {
228 ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
229 return -EIO;
230 }
231
232 memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
233 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
234 "Playback %d Volume", pcm_device_id);
235 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
236 if (!ctl) {
237 ALOGE("%s: Could not get ctl for mixer cmd - %s",
238 __func__, mixer_ctl_name);
239 return -EINVAL;
240 }
241
242 volume = mixer_ctl_get_value(ctl, 0);
243 if ( volume < 0) {
244 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
245 return -EINVAL;
246 }
247 ALOGD("%s: getting mic volume %d \n", __func__, volume);
248
249 value = (volume / PLAYBACK_VOLUME_MAX) * CAPTURE_VOLUME_DEFAULT;
250 if (value < 0.0) {
251 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
252 value = 0.0;
253 } else if (value > CAPTURE_VOLUME_DEFAULT) {
254 value = CAPTURE_VOLUME_DEFAULT;
255 ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
256 }
257
258 return value;
259}
260
261/*Set mic mute state.
262*
263* This interface is used for mic mute state control
264*/
Arun Mirpurie008ed22019-03-21 11:21:04 -0700265int hfp_set_mic_mute(struct audio_device *adev, bool state)
Aalique Grahame22e49102018-12-18 14:23:57 -0800266{
267 int rc = 0;
268
269 if (state == hfpmod.mic_mute)
270 return rc;
271
272 if (state == true) {
273 hfpmod.mic_volume = hfp_get_mic_volume(adev);
274 }
275 rc = hfp_set_mic_volume(adev, (state == true) ? 0.0 : hfpmod.mic_volume);
276 adev->voice.mic_mute = state;
277 hfpmod.mic_mute = state;
278 ALOGD("%s: Setting mute state %d, rc %d\n", __func__, state, rc);
279 return rc;
280}
281
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800282static int32_t start_hfp(struct audio_device *adev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700283 struct str_parms *parms __unused)
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800284{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530285 int32_t ret = 0;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800286 struct audio_usecase *uc_info;
287 int32_t pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id;
288
289 ALOGD("%s: enter", __func__);
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291 if (adev->enable_hfp == true) {
292 ALOGD("%s: HFP is already active!\n", __func__);
293 return 0;
294 }
295 adev->enable_hfp = true;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700296 fp_platform_set_mic_mute(adev->platform, false);
Aalique Grahame22e49102018-12-18 14:23:57 -0800297
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800298 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700299
300 if (!uc_info)
301 return -ENOMEM;
302
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800303 uc_info->id = hfpmod.ucid;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800304 uc_info->type = PCM_HFP_CALL;
305 uc_info->stream.out = adev->primary_output;
306 uc_info->devices = adev->primary_output->devices;
307 uc_info->in_snd_device = SND_DEVICE_NONE;
308 uc_info->out_snd_device = SND_DEVICE_NONE;
309
310 list_add_tail(&adev->usecase_list, &uc_info->list);
311
Arun Mirpurie008ed22019-03-21 11:21:04 -0700312 fp_select_devices(adev, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313
Derek Chend2530072014-11-24 12:39:14 -0800314 if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
315 (uc_info->in_snd_device != SND_DEVICE_NONE)) {
Arun Mirpurie008ed22019-03-21 11:21:04 -0700316 if (fp_audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
Derek Chend2530072014-11-24 12:39:14 -0800317 ALOGE("%s: failed to start ext hw plugin", __func__);
318 }
319
Arun Mirpurie008ed22019-03-21 11:21:04 -0700320 pcm_dev_rx_id = fp_platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
321 pcm_dev_tx_id = fp_platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530322 pcm_dev_asm_rx_id = hfpmod.hfp_pcm_dev_id;
323 pcm_dev_asm_tx_id = hfpmod.hfp_pcm_dev_id;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800324 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0 ||
325 pcm_dev_asm_rx_id < 0 || pcm_dev_asm_tx_id < 0 ) {
326 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d asm: rx tx %d) for the usecase(%d)",
327 __func__, pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, uc_info->id);
328 ret = -EIO;
329 goto exit;
330 }
331
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530332 ALOGD("%s: HFP PCM devices (rx: %d tx: %d pcm dev id: %d) usecase(%d)",
333 __func__, pcm_dev_rx_id, pcm_dev_tx_id, hfpmod.hfp_pcm_dev_id, uc_info->id);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800334
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800335 hfpmod.hfp_sco_rx = pcm_open(adev->snd_card,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800336 pcm_dev_asm_rx_id,
337 PCM_OUT, &pcm_config_hfp);
338 if (hfpmod.hfp_sco_rx && !pcm_is_ready(hfpmod.hfp_sco_rx)) {
339 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_rx));
340 ret = -EIO;
341 goto exit;
342 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530343
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800344 hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
Aalique Grahame22e49102018-12-18 14:23:57 -0800345 pcm_dev_rx_id,
346 PCM_OUT, &pcm_config_hfp);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800347 if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
348 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_rx));
349 ret = -EIO;
350 goto exit;
351 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530352
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800353 hfpmod.hfp_sco_tx = pcm_open(adev->snd_card,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800354 pcm_dev_asm_tx_id,
355 PCM_IN, &pcm_config_hfp);
356 if (hfpmod.hfp_sco_tx && !pcm_is_ready(hfpmod.hfp_sco_tx)) {
357 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_tx));
358 ret = -EIO;
359 goto exit;
360 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530361
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800362 hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
Aalique Grahame22e49102018-12-18 14:23:57 -0800363 pcm_dev_tx_id,
364 PCM_IN, &pcm_config_hfp);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800365 if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
366 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_tx));
367 ret = -EIO;
368 goto exit;
369 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530370
Satya Krishna Pindiprolice903a02014-07-28 12:40:56 +0530371 if (pcm_start(hfpmod.hfp_sco_rx) < 0) {
372 ALOGE("%s: pcm start for hfp sco rx failed", __func__);
373 ret = -EINVAL;
374 goto exit;
375 }
376 if (pcm_start(hfpmod.hfp_sco_tx) < 0) {
377 ALOGE("%s: pcm start for hfp sco tx failed", __func__);
378 ret = -EINVAL;
379 goto exit;
380 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800381
Satya Krishna Pindiprolice903a02014-07-28 12:40:56 +0530382 if (pcm_start(hfpmod.hfp_pcm_rx) < 0) {
383 ALOGE("%s: pcm start for hfp pcm rx failed", __func__);
384 ret = -EINVAL;
385 goto exit;
386 }
387 if (pcm_start(hfpmod.hfp_pcm_tx) < 0) {
388 ALOGE("%s: pcm start for hfp pcm tx failed", __func__);
389 ret = -EINVAL;
390 goto exit;
391 }
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800392
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800393 hfpmod.is_hfp_running = true;
Amit Shekhar967cab32014-02-07 17:03:21 -0800394 hfp_set_volume(adev, hfpmod.hfp_volume);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800395
Aalique Grahame22e49102018-12-18 14:23:57 -0800396 /* Set mic volume by mute status, we don't provide set mic volume in phone app, only
397 provide mute and unmute. */
Arun Mirpurie008ed22019-03-21 11:21:04 -0700398 hfp_set_mic_mute(adev, adev->mic_muted);
Aalique Grahame22e49102018-12-18 14:23:57 -0800399
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800400 ALOGD("%s: exit: status(%d)", __func__, ret);
401 return 0;
402
403exit:
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800404 stop_hfp(adev);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800405 ALOGE("%s: Problem in HFP start: status(%d)", __func__, ret);
406 return ret;
407}
408
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800409static int32_t stop_hfp(struct audio_device *adev)
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800410{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530411 int32_t ret = 0;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800412 struct audio_usecase *uc_info;
413
414 ALOGD("%s: enter", __func__);
415 hfpmod.is_hfp_running = false;
416
417 /* 1. Close the PCM devices */
418 if (hfpmod.hfp_sco_rx) {
419 pcm_close(hfpmod.hfp_sco_rx);
420 hfpmod.hfp_sco_rx = NULL;
421 }
422 if (hfpmod.hfp_sco_tx) {
423 pcm_close(hfpmod.hfp_sco_tx);
424 hfpmod.hfp_sco_tx = NULL;
425 }
426 if (hfpmod.hfp_pcm_rx) {
427 pcm_close(hfpmod.hfp_pcm_rx);
428 hfpmod.hfp_pcm_rx = NULL;
429 }
430 if (hfpmod.hfp_pcm_tx) {
431 pcm_close(hfpmod.hfp_pcm_tx);
432 hfpmod.hfp_pcm_tx = NULL;
433 }
434
Arun Mirpurie008ed22019-03-21 11:21:04 -0700435 uc_info = fp_get_usecase_from_list(adev, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800436 if (uc_info == NULL) {
437 ALOGE("%s: Could not find the usecase (%d) in the list",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800438 __func__, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800439 return -EINVAL;
440 }
441
Derek Chend2530072014-11-24 12:39:14 -0800442 if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
443 (uc_info->in_snd_device != SND_DEVICE_NONE)) {
Arun Mirpurie008ed22019-03-21 11:21:04 -0700444 if (fp_audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
Derek Chend2530072014-11-24 12:39:14 -0800445 ALOGE("%s: failed to stop ext hw plugin", __func__);
446 }
447
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530448 /* 2. Disable echo reference while stopping hfp */
Arun Mirpurie008ed22019-03-21 11:21:04 -0700449 fp_platform_set_echo_reference(adev, false, uc_info->devices);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530450
451 /* 3. Get and set stream specific mixer controls */
Arun Mirpurie008ed22019-03-21 11:21:04 -0700452 fp_disable_audio_route(adev, uc_info);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800453
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530454 /* 4. Disable the rx and tx devices */
Arun Mirpurie008ed22019-03-21 11:21:04 -0700455 fp_disable_snd_device(adev, uc_info->out_snd_device);
456 fp_disable_snd_device(adev, uc_info->in_snd_device);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800457
Aalique Grahame22e49102018-12-18 14:23:57 -0800458 /* Set the unmute Tx mixer control */
Arun Mirpurie008ed22019-03-21 11:21:04 -0700459 if (fp_voice_get_mic_mute(adev)) {
460 fp_platform_set_mic_mute(adev->platform, false);
Aalique Grahame22e49102018-12-18 14:23:57 -0800461 ALOGD("%s: unMute HFP Tx", __func__);
462 }
463 adev->enable_hfp = false;
464
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800465 list_remove(&uc_info->list);
466 free(uc_info);
467
468 ALOGD("%s: exit: status(%d)", __func__, ret);
469 return ret;
470}
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800471
Arun Mirpurie008ed22019-03-21 11:21:04 -0700472void hfp_init(hfp_init_config_t init_config)
473{
474 fp_platform_set_mic_mute = init_config.fp_platform_set_mic_mute;
475 fp_platform_get_pcm_device_id = init_config.fp_platform_get_pcm_device_id;
476 fp_platform_set_echo_reference = init_config.fp_platform_set_echo_reference;
477 fp_select_devices = init_config.fp_select_devices;
478 fp_audio_extn_ext_hw_plugin_usecase_start =
479 init_config.fp_audio_extn_ext_hw_plugin_usecase_start;
480 fp_audio_extn_ext_hw_plugin_usecase_stop =
481 init_config.fp_audio_extn_ext_hw_plugin_usecase_stop;
482 fp_get_usecase_from_list = init_config.fp_get_usecase_from_list;
483 fp_disable_audio_route = init_config.fp_disable_audio_route;
484 fp_disable_snd_device = init_config.fp_disable_snd_device;
485 fp_voice_get_mic_mute = init_config.fp_voice_get_mic_mute;
486}
487
488bool hfp_is_active(struct audio_device *adev)
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800489{
490 struct audio_usecase *hfp_usecase = NULL;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700491 hfp_usecase = fp_get_usecase_from_list(adev, hfpmod.ucid);
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800492
493 if (hfp_usecase != NULL)
494 return true;
495 else
496 return false;
497}
498
Arun Mirpurie008ed22019-03-21 11:21:04 -0700499int hfp_set_mic_mute2(struct audio_device *adev, bool state)
Dhanalakshmi Siddani823dc5a2016-09-28 14:47:26 +0530500{
501 struct mixer_ctl *ctl;
502 const char *mixer_ctl_name = "HFP TX Mute";
Manish Dewangan338c50a2017-09-12 15:22:03 +0530503 long set_values[ ] = {0};
Dhanalakshmi Siddani823dc5a2016-09-28 14:47:26 +0530504
Arun Mirpurie008ed22019-03-21 11:21:04 -0700505 ALOGD("%s: enter, state=%d", __func__, state);
Dhanalakshmi Siddani823dc5a2016-09-28 14:47:26 +0530506
507 set_values[0] = state;
508 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
509 if (!ctl) {
510 ALOGE("%s: Could not get ctl for mixer cmd - %s",
511 __func__, mixer_ctl_name);
512 return -EINVAL;
513 }
514 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
515 ALOGV("%s: exit", __func__);
516 return 0;
517}
518
Arun Mirpurie008ed22019-03-21 11:21:04 -0700519audio_usecase_t hfp_get_usecase()
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800520{
521 return hfpmod.ucid;
522}
523
Arun Mirpurie008ed22019-03-21 11:21:04 -0700524void hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800525{
526 int ret;
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800527 int rate;
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800528 int val;
Amit Shekhar967cab32014-02-07 17:03:21 -0800529 float vol;
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800530 char value[32]={0};
531
Arun Mirpurie008ed22019-03-21 11:21:04 -0700532 ALOGD("%s: enter", __func__);
533
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
535 sizeof(value));
536 if (ret >= 0) {
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530537 if (!strncmp(value, "true", sizeof(value)) && !hfpmod.is_hfp_running)
538 ret = start_hfp(adev,parms);
539 else if (!strncmp(value, "false", sizeof(value)) && hfpmod.is_hfp_running)
540 stop_hfp(adev);
541 else
542 ALOGE("hfp_enable=%s is unsupported", value);
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800543 }
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800544 memset(value, 0, sizeof(value));
545 ret = str_parms_get_str(parms,AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
546 sizeof(value));
547 if (ret >= 0) {
548 rate = atoi(value);
549 if (rate == 8000){
550 hfpmod.ucid = USECASE_AUDIO_HFP_SCO;
551 pcm_config_hfp.rate = rate;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700552 } else if (rate == 16000){
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800553 hfpmod.ucid = USECASE_AUDIO_HFP_SCO_WB;
554 pcm_config_hfp.rate = rate;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700555 } else
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800556 ALOGE("Unsupported rate..");
557 }
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800558
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700559 if (hfpmod.is_hfp_running) {
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800560 memset(value, 0, sizeof(value));
561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
562 value, sizeof(value));
563 if (ret >= 0) {
564 val = atoi(value);
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700565 if (val > 0)
Arun Mirpurie008ed22019-03-21 11:21:04 -0700566 fp_select_devices(adev, hfpmod.ucid);
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800567 }
568 }
Amit Shekhar967cab32014-02-07 17:03:21 -0800569
570 memset(value, 0, sizeof(value));
571 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_VOLUME,
572 value, sizeof(value));
573 if (ret >= 0) {
574 if (sscanf(value, "%f", &vol) != 1){
575 ALOGE("%s: error in retrieving hfp volume", __func__);
576 ret = -EIO;
577 goto exit;
578 }
579 ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
580 hfp_set_volume(adev, vol);
581 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530582
583 memset(value, 0, sizeof(value));
584 ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_PCM_DEV_ID, value, sizeof(value));
585 if (ret >= 0) {
586 hfpmod.hfp_pcm_dev_id = atoi(value);
587 ALOGD("Updating HFP_PCM_DEV_ID as %d from platform XML", hfpmod.hfp_pcm_dev_id);
588 str_parms_del(parms, AUDIO_PARAMETER_HFP_PCM_DEV_ID);
589 }
590
Aalique Grahame22e49102018-12-18 14:23:57 -0800591 memset(value, 0, sizeof(value));
592 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME,
593 value, sizeof(value));
594 if (ret >= 0) {
595 if (sscanf(value, "%f", &vol) != 1){
596 ALOGE("%s: error in retrieving hfp mic volume", __func__);
597 ret = -EIO;
598 goto exit;
599 }
600 ALOGD("%s: set_hfp_mic_volume usecase, Vol: [%f]", __func__, vol);
601 hfp_set_mic_volume(adev, vol);
602 }
603
Amit Shekhar967cab32014-02-07 17:03:21 -0800604exit:
605 ALOGV("%s Exit",__func__);
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800606}