blob: c82e8756323e110c04e1dadf63388c667be38200 [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#ifdef HFP_ENABLED
50#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
Vimal Puthanveed47e64852013-12-20 13:23:39 -080051#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
Amit Shekhar967cab32014-02-07 17:03:21 -080052#define AUDIO_PARAMETER_KEY_HFP_VOLUME "hfp_volume"
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +053053#define AUDIO_PARAMETER_HFP_PCM_DEV_ID "hfp_pcm_dev_id"
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080054
Aalique Grahame22e49102018-12-18 14:23:57 -080055#define AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME "hfp_mic_volume"
56#define PLAYBACK_VOLUME_MAX 0x2000
57#define CAPTURE_VOLUME_DEFAULT (15.0)
58
Sudheer Papothi19e43d02014-07-16 02:34:41 +053059#ifdef PLATFORM_MSM8994
60#define HFP_RX_VOLUME "SEC AUXPCM LOOPBACK Volume"
Aalique Grahame22e49102018-12-18 14:23:57 -080061#elif defined (PLATFORM_MSM8996) || defined (EXTERNAL_BT_SUPPORTED)
Banajit Goswamida77c452015-10-14 20:45:22 -070062#define HFP_RX_VOLUME "PRI AUXPCM LOOPBACK Volume"
Derek Chen3e5b30a2018-10-24 01:04:25 -070063#elif defined PLATFORM_AUTO
64#define HFP_RX_VOLUME "Playback 36 Volume"
Meng Wangef2f6e12018-10-08 13:06:05 +080065#elif defined (PLATFORM_MSM8998) || defined (PLATFORM_MSMFALCON) || \
66 defined (PLATFORM_SDM845) || defined (PLATFORM_SDM710) || \
67 defined (PLATFORM_QCS605) || defined (PLATFORM_MSMNILE) || \
68 defined (PLATFORM_KONA) || defined (PLATFORM_MSMSTEPPE) || \
Manisha Agarwal888e9762019-02-27 22:18:49 +053069 defined (PLATFORM_QCS405) || defined (PLATFORM_TRINKET) || \
70 defined (PLATFORM_LITO)
Banajit Goswami4c0dff22016-03-04 18:31:22 -080071#define HFP_RX_VOLUME "SLIMBUS_7 LOOPBACK Volume"
Sudheer Papothi19e43d02014-07-16 02:34:41 +053072#else
73#define HFP_RX_VOLUME "Internal HFP RX Volume"
74#endif
75
Vimal Puthanveed584048b2013-12-11 17:00:50 -080076static int32_t start_hfp(struct audio_device *adev,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080077 struct str_parms *parms);
78
Vimal Puthanveed584048b2013-12-11 17:00:50 -080079static int32_t stop_hfp(struct audio_device *adev);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080080
81struct hfp_module {
82 struct pcm *hfp_sco_rx;
83 struct pcm *hfp_sco_tx;
84 struct pcm *hfp_pcm_rx;
85 struct pcm *hfp_pcm_tx;
86 bool is_hfp_running;
Amit Shekhar967cab32014-02-07 17:03:21 -080087 float hfp_volume;
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +053088 int32_t hfp_pcm_dev_id;
Vimal Puthanveed47e64852013-12-20 13:23:39 -080089 audio_usecase_t ucid;
Aalique Grahame22e49102018-12-18 14:23:57 -080090 float mic_volume;
91 bool mic_mute;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080092};
93
94static struct hfp_module hfpmod = {
95 .hfp_sco_rx = NULL,
96 .hfp_sco_tx = NULL,
97 .hfp_pcm_rx = NULL,
98 .hfp_pcm_tx = NULL,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -080099 .is_hfp_running = 0,
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530100 .hfp_volume = 0,
101 .hfp_pcm_dev_id = HFP_ASM_RX_TX,
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800102 .ucid = USECASE_AUDIO_HFP_SCO,
Aalique Grahame22e49102018-12-18 14:23:57 -0800103 .mic_volume = CAPTURE_VOLUME_DEFAULT,
104 .mic_mute = 0,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800105};
Aalique Grahame22e49102018-12-18 14:23:57 -0800106
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800107static struct pcm_config pcm_config_hfp = {
108 .channels = 1,
109 .rate = 8000,
110 .period_size = 240,
111 .period_count = 2,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = 0,
114 .stop_threshold = INT_MAX,
115 .avail_min = 0,
116};
117
Amit Shekhar967cab32014-02-07 17:03:21 -0800118static int32_t hfp_set_volume(struct audio_device *adev, float value)
119{
120 int32_t vol, ret = 0;
121 struct mixer_ctl *ctl;
Sudheer Papothi19e43d02014-07-16 02:34:41 +0530122 const char *mixer_ctl_name = HFP_RX_VOLUME;
Amit Shekhar967cab32014-02-07 17:03:21 -0800123
124 ALOGV("%s: entry", __func__);
125 ALOGD("%s: (%f)\n", __func__, value);
126
Satya Krishna Pindiproli3ed6d792014-09-09 15:32:25 +0530127 hfpmod.hfp_volume = value;
Aalique Grahame22e49102018-12-18 14:23:57 -0800128
Amit Shekhar967cab32014-02-07 17:03:21 -0800129 if (value < 0.0) {
130 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
131 value = 0.0;
132 } else {
133 value = ((value > 15.000000) ? 1.0 : (value / 15));
134 ALOGW("%s: Volume brought with in range (%f)\n", __func__, value);
135 }
136 vol = lrint((value * 0x2000) + 0.5);
Amit Shekhar967cab32014-02-07 17:03:21 -0800137
138 if (!hfpmod.is_hfp_running) {
139 ALOGV("%s: HFP not active, ignoring set_hfp_volume call", __func__);
140 return -EIO;
141 }
142
143 ALOGD("%s: Setting HFP volume to %d \n", __func__, vol);
144 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
145 if (!ctl) {
146 ALOGE("%s: Could not get ctl for mixer cmd - %s",
147 __func__, mixer_ctl_name);
148 return -EINVAL;
149 }
150 if(mixer_ctl_set_value(ctl, 0, vol) < 0) {
151 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, vol);
152 return -EINVAL;
153 }
154
155 ALOGV("%s: exit", __func__);
156 return ret;
157}
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/*Set mic volume to value.
160*
161* This interface is used for mic volume control, set mic volume as value(range 0 ~ 15).
162*/
163static int hfp_set_mic_volume(struct audio_device *adev, float value)
164{
165 int volume, ret = 0;
166 char mixer_ctl_name[128];
167 struct mixer_ctl *ctl;
168 int pcm_device_id = HFP_ASM_RX_TX;
169
170 if (!hfpmod.is_hfp_running) {
171 ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
172 return -EIO;
173 }
174
175 if (value < 0.0) {
176 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
177 value = 0.0;
178 } else if (value > CAPTURE_VOLUME_DEFAULT) {
179 value = CAPTURE_VOLUME_DEFAULT;
180 ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
181 }
182
183 value = value / CAPTURE_VOLUME_DEFAULT;
184 memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
185 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
186 "Playback %d Volume", pcm_device_id);
187 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
188 if (!ctl) {
189 ALOGE("%s: Could not get ctl for mixer cmd - %s",
190 __func__, mixer_ctl_name);
191 return -EINVAL;
192 }
193 volume = (int)(value * PLAYBACK_VOLUME_MAX);
194
195 ALOGD("%s: Setting volume to %d (%s)\n", __func__, volume, mixer_ctl_name);
196 if (mixer_ctl_set_value(ctl, 0, volume) < 0) {
197 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
198 return -EINVAL;
199 }
200
201 return ret;
202}
203
204static float hfp_get_mic_volume(struct audio_device *adev)
205{
206 int volume;
207 char mixer_ctl_name[128];
208 struct mixer_ctl *ctl;
209 int pcm_device_id = HFP_ASM_RX_TX;
210 float value = 0.0;
211
212 if (!hfpmod.is_hfp_running) {
213 ALOGE("%s: HFP not active, ignoring set_hfp_mic_volume call", __func__);
214 return -EIO;
215 }
216
217 memset(mixer_ctl_name, 0, sizeof(mixer_ctl_name));
218 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
219 "Playback %d Volume", pcm_device_id);
220 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
221 if (!ctl) {
222 ALOGE("%s: Could not get ctl for mixer cmd - %s",
223 __func__, mixer_ctl_name);
224 return -EINVAL;
225 }
226
227 volume = mixer_ctl_get_value(ctl, 0);
228 if ( volume < 0) {
229 ALOGE("%s: Couldn't set HFP Volume: [%d]", __func__, volume);
230 return -EINVAL;
231 }
232 ALOGD("%s: getting mic volume %d \n", __func__, volume);
233
234 value = (volume / PLAYBACK_VOLUME_MAX) * CAPTURE_VOLUME_DEFAULT;
235 if (value < 0.0) {
236 ALOGW("%s: (%f) Under 0.0, assuming 0.0\n", __func__, value);
237 value = 0.0;
238 } else if (value > CAPTURE_VOLUME_DEFAULT) {
239 value = CAPTURE_VOLUME_DEFAULT;
240 ALOGW("%s: Volume brought within range (%f)\n", __func__, value);
241 }
242
243 return value;
244}
245
246/*Set mic mute state.
247*
248* This interface is used for mic mute state control
249*/
250int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state)
251{
252 int rc = 0;
253
254 if (state == hfpmod.mic_mute)
255 return rc;
256
257 if (state == true) {
258 hfpmod.mic_volume = hfp_get_mic_volume(adev);
259 }
260 rc = hfp_set_mic_volume(adev, (state == true) ? 0.0 : hfpmod.mic_volume);
261 adev->voice.mic_mute = state;
262 hfpmod.mic_mute = state;
263 ALOGD("%s: Setting mute state %d, rc %d\n", __func__, state, rc);
264 return rc;
265}
266
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800267static int32_t start_hfp(struct audio_device *adev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700268 struct str_parms *parms __unused)
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800269{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530270 int32_t ret = 0;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800271 struct audio_usecase *uc_info;
272 int32_t pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, pcm_dev_asm_tx_id;
273
274 ALOGD("%s: enter", __func__);
275
Aalique Grahame22e49102018-12-18 14:23:57 -0800276 if (adev->enable_hfp == true) {
277 ALOGD("%s: HFP is already active!\n", __func__);
278 return 0;
279 }
280 adev->enable_hfp = true;
281 platform_set_mic_mute(adev->platform, false);
282
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800283 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700284
285 if (!uc_info)
286 return -ENOMEM;
287
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800288 uc_info->id = hfpmod.ucid;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800289 uc_info->type = PCM_HFP_CALL;
290 uc_info->stream.out = adev->primary_output;
291 uc_info->devices = adev->primary_output->devices;
292 uc_info->in_snd_device = SND_DEVICE_NONE;
293 uc_info->out_snd_device = SND_DEVICE_NONE;
294
295 list_add_tail(&adev->usecase_list, &uc_info->list);
296
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800297 select_devices(adev, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800298
Derek Chend2530072014-11-24 12:39:14 -0800299 if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
300 (uc_info->in_snd_device != SND_DEVICE_NONE)) {
301 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
302 ALOGE("%s: failed to start ext hw plugin", __func__);
303 }
304
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800305 pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
306 pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530307 pcm_dev_asm_rx_id = hfpmod.hfp_pcm_dev_id;
308 pcm_dev_asm_tx_id = hfpmod.hfp_pcm_dev_id;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800309 if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0 ||
310 pcm_dev_asm_rx_id < 0 || pcm_dev_asm_tx_id < 0 ) {
311 ALOGE("%s: Invalid PCM devices (rx: %d tx: %d asm: rx tx %d) for the usecase(%d)",
312 __func__, pcm_dev_rx_id, pcm_dev_tx_id, pcm_dev_asm_rx_id, uc_info->id);
313 ret = -EIO;
314 goto exit;
315 }
316
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530317 ALOGD("%s: HFP PCM devices (rx: %d tx: %d pcm dev id: %d) usecase(%d)",
318 __func__, pcm_dev_rx_id, pcm_dev_tx_id, hfpmod.hfp_pcm_dev_id, uc_info->id);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800319
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800320 hfpmod.hfp_sco_rx = pcm_open(adev->snd_card,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800321 pcm_dev_asm_rx_id,
322 PCM_OUT, &pcm_config_hfp);
323 if (hfpmod.hfp_sco_rx && !pcm_is_ready(hfpmod.hfp_sco_rx)) {
324 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_rx));
325 ret = -EIO;
326 goto exit;
327 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530328
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800329 hfpmod.hfp_pcm_rx = pcm_open(adev->snd_card,
Aalique Grahame22e49102018-12-18 14:23:57 -0800330 pcm_dev_rx_id,
331 PCM_OUT, &pcm_config_hfp);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800332 if (hfpmod.hfp_pcm_rx && !pcm_is_ready(hfpmod.hfp_pcm_rx)) {
333 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_rx));
334 ret = -EIO;
335 goto exit;
336 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530337
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800338 hfpmod.hfp_sco_tx = pcm_open(adev->snd_card,
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800339 pcm_dev_asm_tx_id,
340 PCM_IN, &pcm_config_hfp);
341 if (hfpmod.hfp_sco_tx && !pcm_is_ready(hfpmod.hfp_sco_tx)) {
342 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_sco_tx));
343 ret = -EIO;
344 goto exit;
345 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530346
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800347 hfpmod.hfp_pcm_tx = pcm_open(adev->snd_card,
Aalique Grahame22e49102018-12-18 14:23:57 -0800348 pcm_dev_tx_id,
349 PCM_IN, &pcm_config_hfp);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800350 if (hfpmod.hfp_pcm_tx && !pcm_is_ready(hfpmod.hfp_pcm_tx)) {
351 ALOGE("%s: %s", __func__, pcm_get_error(hfpmod.hfp_pcm_tx));
352 ret = -EIO;
353 goto exit;
354 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530355
Satya Krishna Pindiprolice903a02014-07-28 12:40:56 +0530356 if (pcm_start(hfpmod.hfp_sco_rx) < 0) {
357 ALOGE("%s: pcm start for hfp sco rx failed", __func__);
358 ret = -EINVAL;
359 goto exit;
360 }
361 if (pcm_start(hfpmod.hfp_sco_tx) < 0) {
362 ALOGE("%s: pcm start for hfp sco tx failed", __func__);
363 ret = -EINVAL;
364 goto exit;
365 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800366
Satya Krishna Pindiprolice903a02014-07-28 12:40:56 +0530367 if (pcm_start(hfpmod.hfp_pcm_rx) < 0) {
368 ALOGE("%s: pcm start for hfp pcm rx failed", __func__);
369 ret = -EINVAL;
370 goto exit;
371 }
372 if (pcm_start(hfpmod.hfp_pcm_tx) < 0) {
373 ALOGE("%s: pcm start for hfp pcm tx failed", __func__);
374 ret = -EINVAL;
375 goto exit;
376 }
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800377
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800378 hfpmod.is_hfp_running = true;
Amit Shekhar967cab32014-02-07 17:03:21 -0800379 hfp_set_volume(adev, hfpmod.hfp_volume);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800380
Aalique Grahame22e49102018-12-18 14:23:57 -0800381 /* Set mic volume by mute status, we don't provide set mic volume in phone app, only
382 provide mute and unmute. */
383 audio_extn_hfp_set_mic_mute(adev, adev->mic_muted);
384
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800385 ALOGD("%s: exit: status(%d)", __func__, ret);
386 return 0;
387
388exit:
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800389 stop_hfp(adev);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800390 ALOGE("%s: Problem in HFP start: status(%d)", __func__, ret);
391 return ret;
392}
393
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800394static int32_t stop_hfp(struct audio_device *adev)
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800395{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +0530396 int32_t ret = 0;
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800397 struct audio_usecase *uc_info;
398
399 ALOGD("%s: enter", __func__);
400 hfpmod.is_hfp_running = false;
401
402 /* 1. Close the PCM devices */
403 if (hfpmod.hfp_sco_rx) {
404 pcm_close(hfpmod.hfp_sco_rx);
405 hfpmod.hfp_sco_rx = NULL;
406 }
407 if (hfpmod.hfp_sco_tx) {
408 pcm_close(hfpmod.hfp_sco_tx);
409 hfpmod.hfp_sco_tx = NULL;
410 }
411 if (hfpmod.hfp_pcm_rx) {
412 pcm_close(hfpmod.hfp_pcm_rx);
413 hfpmod.hfp_pcm_rx = NULL;
414 }
415 if (hfpmod.hfp_pcm_tx) {
416 pcm_close(hfpmod.hfp_pcm_tx);
417 hfpmod.hfp_pcm_tx = NULL;
418 }
419
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800420 uc_info = get_usecase_from_list(adev, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800421 if (uc_info == NULL) {
422 ALOGE("%s: Could not find the usecase (%d) in the list",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800423 __func__, hfpmod.ucid);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800424 return -EINVAL;
425 }
426
Derek Chend2530072014-11-24 12:39:14 -0800427 if ((uc_info->out_snd_device != SND_DEVICE_NONE) ||
428 (uc_info->in_snd_device != SND_DEVICE_NONE)) {
429 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
430 ALOGE("%s: failed to stop ext hw plugin", __func__);
431 }
432
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530433 /* 2. Disable echo reference while stopping hfp */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700434 platform_set_echo_reference(adev, false, uc_info->devices);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530435
436 /* 3. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700437 disable_audio_route(adev, uc_info);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800438
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +0530439 /* 4. Disable the rx and tx devices */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700440 disable_snd_device(adev, uc_info->out_snd_device);
441 disable_snd_device(adev, uc_info->in_snd_device);
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800442
Aalique Grahame22e49102018-12-18 14:23:57 -0800443 /* Set the unmute Tx mixer control */
444 if (voice_get_mic_mute(adev)) {
445 platform_set_mic_mute(adev->platform, false);
446 ALOGD("%s: unMute HFP Tx", __func__);
447 }
448 adev->enable_hfp = false;
449
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800450 list_remove(&uc_info->list);
451 free(uc_info);
452
453 ALOGD("%s: exit: status(%d)", __func__, ret);
454 return ret;
455}
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800456
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800457bool audio_extn_hfp_is_active(struct audio_device *adev)
458{
459 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800460 hfp_usecase = get_usecase_from_list(adev, hfpmod.ucid);
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800461
462 if (hfp_usecase != NULL)
463 return true;
464 else
465 return false;
466}
467
Dhanalakshmi Siddani823dc5a2016-09-28 14:47:26 +0530468int hfp_set_mic_mute(struct audio_device *adev, bool state)
469{
470 struct mixer_ctl *ctl;
471 const char *mixer_ctl_name = "HFP TX Mute";
Manish Dewangan338c50a2017-09-12 15:22:03 +0530472 long set_values[ ] = {0};
Dhanalakshmi Siddani823dc5a2016-09-28 14:47:26 +0530473
474 ALOGI("%s: enter, state=%d", __func__, state);
475
476 set_values[0] = state;
477 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
478 if (!ctl) {
479 ALOGE("%s: Could not get ctl for mixer cmd - %s",
480 __func__, mixer_ctl_name);
481 return -EINVAL;
482 }
483 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
484 ALOGV("%s: exit", __func__);
485 return 0;
486}
487
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800488audio_usecase_t audio_extn_hfp_get_usecase()
489{
490 return hfpmod.ucid;
491}
492
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800493void audio_extn_hfp_set_parameters(struct audio_device *adev, struct str_parms *parms)
494{
495 int ret;
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800496 int rate;
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800497 int val;
Amit Shekhar967cab32014-02-07 17:03:21 -0800498 float vol;
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800499 char value[32]={0};
500
501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
502 sizeof(value));
503 if (ret >= 0) {
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530504 if (!strncmp(value, "true", sizeof(value)) && !hfpmod.is_hfp_running)
505 ret = start_hfp(adev,parms);
506 else if (!strncmp(value, "false", sizeof(value)) && hfpmod.is_hfp_running)
507 stop_hfp(adev);
508 else
509 ALOGE("hfp_enable=%s is unsupported", value);
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800510 }
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800511 memset(value, 0, sizeof(value));
512 ret = str_parms_get_str(parms,AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
513 sizeof(value));
514 if (ret >= 0) {
515 rate = atoi(value);
516 if (rate == 8000){
517 hfpmod.ucid = USECASE_AUDIO_HFP_SCO;
518 pcm_config_hfp.rate = rate;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700519 } else if (rate == 16000){
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800520 hfpmod.ucid = USECASE_AUDIO_HFP_SCO_WB;
521 pcm_config_hfp.rate = rate;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700522 } else
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800523 ALOGE("Unsupported rate..");
524 }
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700526 if (hfpmod.is_hfp_running) {
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800527 memset(value, 0, sizeof(value));
528 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
529 value, sizeof(value));
530 if (ret >= 0) {
531 val = atoi(value);
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -0700532 if (val > 0)
Vimal Puthanveed21e5c762014-01-08 14:10:09 -0800533 select_devices(adev, hfpmod.ucid);
534 }
535 }
Amit Shekhar967cab32014-02-07 17:03:21 -0800536
537 memset(value, 0, sizeof(value));
538 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_VOLUME,
539 value, sizeof(value));
540 if (ret >= 0) {
541 if (sscanf(value, "%f", &vol) != 1){
542 ALOGE("%s: error in retrieving hfp volume", __func__);
543 ret = -EIO;
544 goto exit;
545 }
546 ALOGD("%s: set_hfp_volume usecase, Vol: [%f]", __func__, vol);
547 hfp_set_volume(adev, vol);
548 }
Satya Krishna Pindiprolic6b0a742017-02-03 14:37:18 +0530549
550 memset(value, 0, sizeof(value));
551 ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_PCM_DEV_ID, value, sizeof(value));
552 if (ret >= 0) {
553 hfpmod.hfp_pcm_dev_id = atoi(value);
554 ALOGD("Updating HFP_PCM_DEV_ID as %d from platform XML", hfpmod.hfp_pcm_dev_id);
555 str_parms_del(parms, AUDIO_PARAMETER_HFP_PCM_DEV_ID);
556 }
557
Aalique Grahame22e49102018-12-18 14:23:57 -0800558 memset(value, 0, sizeof(value));
559 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HFP_MIC_VOLUME,
560 value, sizeof(value));
561 if (ret >= 0) {
562 if (sscanf(value, "%f", &vol) != 1){
563 ALOGE("%s: error in retrieving hfp mic volume", __func__);
564 ret = -EIO;
565 goto exit;
566 }
567 ALOGD("%s: set_hfp_mic_volume usecase, Vol: [%f]", __func__, vol);
568 hfp_set_mic_volume(adev, vol);
569 }
570
Amit Shekhar967cab32014-02-07 17:03:21 -0800571exit:
572 ALOGV("%s Exit",__func__);
Vimal Puthanveed584048b2013-12-11 17:00:50 -0800573}
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800574#endif /*HFP_ENABLED*/