blob: 7c34da98675eadb45ba9438fac5a918f09e8fb98 [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* alsa_default.cpp
2 **
3 ** Copyright 2009 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
Ajay Dudani9746c472012-06-18 16:01:16 -070019#define LOG_TAG "ALSAModule"
Iliyan Malchev4765c432012-06-11 14:36:16 -070020//#define LOG_NDEBUG 0
Ajay Dudani9746c472012-06-18 16:01:16 -070021#define LOG_NDDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070022#include <utils/Log.h>
23#include <cutils/properties.h>
24#include <linux/ioctl.h>
25#include "AudioHardwareALSA.h"
26#include <media/AudioRecord.h>
Ajay Dudani9746c472012-06-18 16:01:16 -070027#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070028extern "C" {
29#include "csd_client.h"
30}
Iliyan Malchev4113f342012-06-11 14:39:47 -070031#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070032
33#ifndef ALSA_DEFAULT_SAMPLE_RATE
34#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
35#endif
36
37#define BTSCO_RATE_16KHZ 16000
38#define USECASE_TYPE_RX 1
39#define USECASE_TYPE_TX 2
40
41namespace android_audio_legacy
42{
43
44static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
45static int s_device_close(hw_device_t*);
46static status_t s_init(alsa_device_t *, ALSAHandleList &);
47static status_t s_open(alsa_handle_t *);
48static status_t s_close(alsa_handle_t *);
49static status_t s_standby(alsa_handle_t *);
50static status_t s_route(alsa_handle_t *, uint32_t, int);
51static status_t s_start_voice_call(alsa_handle_t *);
52static status_t s_start_voip_call(alsa_handle_t *);
53static status_t s_start_fm(alsa_handle_t *);
54static void s_set_voice_volume(int);
55static void s_set_voip_volume(int);
56static void s_set_mic_mute(int);
57static void s_set_voip_mic_mute(int);
58static void s_set_voip_config(int, int);
59static status_t s_set_fm_vol(int);
60static void s_set_btsco_rate(int);
61static status_t s_set_lpa_vol(int);
62static void s_enable_wide_voice(bool flag);
63static void s_enable_fens(bool flag);
64static void s_set_flags(uint32_t flags);
65static status_t s_set_compressed_vol(int);
66static void s_enable_slow_talk(bool flag);
67static void s_set_voc_rec_mode(uint8_t mode);
68static void s_set_volte_mic_mute(int state);
69static void s_set_volte_volume(int vol);
70
71static char mic_type[25];
72static char curRxUCMDevice[50];
73static char curTxUCMDevice[50];
74static int fluence_mode;
75static int fmVolume;
76static uint32_t mDevSettingsFlag = TTY_OFF;
77static int btsco_samplerate = 8000;
78static bool pflag = false;
79static ALSAUseCaseList mUseCaseList;
80
81static hw_module_methods_t s_module_methods = {
82 open : s_device_open
83};
84
Iliyan Malchev4113f342012-06-11 14:39:47 -070085extern "C" hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -070086 tag : HARDWARE_MODULE_TAG,
87 version_major : 1,
88 version_minor : 0,
89 id : ALSA_HARDWARE_MODULE_ID,
90 name : "QCOM ALSA module",
91 author : "QuIC Inc",
92 methods : &s_module_methods,
93 dso : 0,
94 reserved : {0,},
95};
96
97static int s_device_open(const hw_module_t* module, const char* name,
98 hw_device_t** device)
99{
100 char value[128];
101 alsa_device_t *dev;
102 dev = (alsa_device_t *) malloc(sizeof(*dev));
103 if (!dev) return -ENOMEM;
104
105 memset(dev, 0, sizeof(*dev));
106
107 /* initialize the procs */
108 dev->common.tag = HARDWARE_DEVICE_TAG;
109 dev->common.version = 0;
110 dev->common.module = (hw_module_t *) module;
111 dev->common.close = s_device_close;
112 dev->init = s_init;
113 dev->open = s_open;
114 dev->close = s_close;
115 dev->route = s_route;
116 dev->standby = s_standby;
117 dev->startVoiceCall = s_start_voice_call;
118 dev->startVoipCall = s_start_voip_call;
119 dev->startFm = s_start_fm;
120 dev->setVoiceVolume = s_set_voice_volume;
121 dev->setVoipVolume = s_set_voip_volume;
122 dev->setMicMute = s_set_mic_mute;
123 dev->setVoipMicMute = s_set_voip_mic_mute;
124 dev->setVoipConfig = s_set_voip_config;
125 dev->setFmVolume = s_set_fm_vol;
126 dev->setBtscoRate = s_set_btsco_rate;
127 dev->setLpaVolume = s_set_lpa_vol;
128 dev->enableWideVoice = s_enable_wide_voice;
129 dev->enableFENS = s_enable_fens;
130 dev->setFlags = s_set_flags;
131 dev->setCompressedVolume = s_set_compressed_vol;
132 dev->enableSlowTalk = s_enable_slow_talk;
133 dev->setVocRecMode = s_set_voc_rec_mode;
134 dev->setVoLTEMicMute = s_set_volte_mic_mute;
135 dev->setVoLTEVolume = s_set_volte_volume;
136
137 *device = &dev->common;
138
139 property_get("persist.audio.handset.mic",value,"0");
140 strlcpy(mic_type, value, sizeof(mic_type));
141 property_get("persist.audio.fluence.mode",value,"0");
142 if (!strcmp("broadside", value)) {
143 fluence_mode = FLUENCE_MODE_BROADSIDE;
144 } else {
145 fluence_mode = FLUENCE_MODE_ENDFIRE;
146 }
147 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
148 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
Ajay Dudani86c852b2012-07-19 15:28:45 -0700149#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700150 ALOGD("ALSA module opened");
Ajay Dudani86c852b2012-07-19 15:28:45 -0700151#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700152
153 return 0;
154}
155
156static int s_device_close(hw_device_t* device)
157{
158 free(device);
159 device = NULL;
160 return 0;
161}
162
163// ----------------------------------------------------------------------------
164
165static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
166
167static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
168static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
169static void disableDevice(alsa_handle_t *handle);
170int getUseCaseType(const char *useCase);
171
172static int callMode = AudioSystem::MODE_NORMAL;
173// ----------------------------------------------------------------------------
174
175bool platform_is_Fusion3()
176{
177 char platform[128], baseband[128];
178 property_get("ro.board.platform", platform, "");
179 property_get("ro.baseband", baseband, "");
180 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
181 return true;
182 else
183 return false;
184}
185
186int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
187{
188 int ret = 0;
189 char ident[70];
190
191 if (flags & PCM_IN) {
192 strlcpy(ident, "CapturePCM/", sizeof(ident));
193 } else {
194 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
195 }
196 strlcat(ident, handle->useCase, sizeof(ident));
197 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700198 ALOGD("Device value returned is %s", (*value));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700199 return ret;
200}
201
202status_t setHardwareParams(alsa_handle_t *handle)
203{
204 struct snd_pcm_hw_params *params;
205 unsigned long bufferSize, reqBuffSize;
206 unsigned int periodTime, bufferTime;
207 unsigned int requestedRate = handle->sampleRate;
208 int status = 0;
209 int channels = handle->channels;
210 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
211
212 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
213 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700214 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700215 return NO_INIT;
216 }
217
218 reqBuffSize = handle->bufferSize;
Ajay Dudani86c852b2012-07-19 15:28:45 -0700219#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700220 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700221 (int) reqBuffSize, handle->channels, handle->sampleRate);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700222#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700223
Ajay Dudani9746c472012-06-18 16:01:16 -0700224#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700225 if (channels == 6) {
226 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
227 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700228 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700229 channels = 4;
230 reqBuffSize = DEFAULT_IN_BUFFER_SIZE;
231 }
232 }
233#endif
234
235 param_init(params);
236 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
237 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
238 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700239 if (handle->format == AudioSystem::AMR_NB
240 || handle->format == AudioSystem::AMR_WB
241#ifdef QCOM_QCHAT_ENABLED
242 || handle->format == AudioSystem::EVRC
243 || handle->format == AudioSystem::EVRCB
244 || handle->format == AudioSystem::EVRCWB
245#endif
246 )
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247 format = SNDRV_PCM_FORMAT_SPECIAL;
248 }
249 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
250 format);
251 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
252 SNDRV_PCM_SUBFORMAT_STD);
253 param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
254 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
255 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
256 channels * 16);
257 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
258 channels);
259 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
260 param_set_hw_refine(handle->handle, params);
261
262 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700263 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700264 return NO_INIT;
265 }
266 param_dump(params);
267
268 handle->handle->buffer_size = pcm_buffer_size(params);
269 handle->handle->period_size = pcm_period_size(params);
270 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Ajay Dudani86c852b2012-07-19 15:28:45 -0700271#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700272 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700273 handle->handle->buffer_size, handle->handle->period_size,
274 handle->handle->period_cnt);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700275#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700276 handle->handle->rate = handle->sampleRate;
277 handle->handle->channels = handle->channels;
278 handle->periodSize = handle->handle->period_size;
279 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
280 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
281 (6 != handle->channels)) {
282 //Do not update buffersize for 5.1 recording
283 handle->bufferSize = handle->handle->period_size;
284 }
285
286 return NO_ERROR;
287}
288
289status_t setSoftwareParams(alsa_handle_t *handle)
290{
291 struct snd_pcm_sw_params* params;
292 struct pcm* pcm = handle->handle;
293
294 unsigned long periodSize = pcm->period_size;
295 int channels = handle->channels;
296
297 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
298 if (!params) {
299 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
300 return NO_INIT;
301 }
302
Ajay Dudani9746c472012-06-18 16:01:16 -0700303#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700304 if (channels == 6) {
305 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
306 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700307 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700308 channels = 4;
309 }
310 }
311#endif
312
313 // Get the current software parameters
314 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
315 params->period_step = 1;
316 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
317 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700318 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700319 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
320 params->start_threshold = periodSize/2;
321 params->stop_threshold = INT_MAX;
322 } else {
323 params->avail_min = periodSize/2;
324 params->start_threshold = channels * (periodSize/4);
325 params->stop_threshold = INT_MAX;
326 }
327 params->silence_threshold = 0;
328 params->silence_size = 0;
329
330 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700331 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700332 return NO_INIT;
333 }
334 return NO_ERROR;
335}
336
337void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
338{
339 const char **mods_list;
340 use_case_t useCaseNode;
341 unsigned usecase_type = 0;
342 bool inCallDevSwitch = false;
343 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
344 int err = 0, index, mods_size;
345 int rx_dev_id, tx_dev_id;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700346 ALOGV("%s: device %d", __FUNCTION__, devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700347
348 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
349 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
350 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
351 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
352 AudioSystem::DEVICE_IN_WIRED_HEADSET);
353 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
354 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
355 AudioSystem::DEVICE_IN_BUILTIN_MIC);
356 } else if ((devices & AudioSystem::DEVICE_OUT_EARPIECE) ||
357 (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC)) {
358 devices = devices | (AudioSystem::DEVICE_IN_BUILTIN_MIC |
359 AudioSystem::DEVICE_OUT_EARPIECE);
360 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900361 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700362 AudioSystem::DEVICE_OUT_SPEAKER);
363 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
364 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
365 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
366 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
367 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700368#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700369 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
370 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
371 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
372 AudioSystem::DEVICE_IN_ANC_HEADSET);
373 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
374 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
375 AudioSystem::DEVICE_IN_BUILTIN_MIC);
376#endif
377 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
378 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
379 AudioSystem::DEVICE_IN_AUX_DIGITAL);
Ajay Dudani9746c472012-06-18 16:01:16 -0700380#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700381 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
382 (devices & AudioSystem::DEVICE_IN_PROXY)) {
383 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
384 AudioSystem::DEVICE_IN_PROXY);
385#endif
386 }
387 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700388#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700389 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
390 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
391 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700392 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700393 s_set_flags(SSRQMIC_FLAG);
394 }
395 }
396#endif
397
398 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
399 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
400
401 if (rxDevice != NULL) {
402 if ((handle->handle) && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
403 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
404 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
405 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
406 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
407 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
408 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
409 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
410 pcm_close(handle->handle);
411 handle->handle=NULL;
412 handle->rxHandle=NULL;
413 pflag = true;
414 }
415 }
416
417 if ((rxDevice != NULL) && (txDevice != NULL)) {
418 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
419 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) && (mode == AudioSystem::MODE_IN_CALL))
420 inCallDevSwitch = true;
421 }
422 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
423 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
424 if (rxDevice != NULL) {
425 if ((strncmp(curRxUCMDevice, "None", 4)) &&
426 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
427 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
428 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
429 usecase_type = getUseCaseType(use_case);
430 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700431 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700432 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
433 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
434 mUseCaseList.push_front(useCaseNode);
435 }
436 }
437 if (mods_size) {
438 for(index = 0; index < mods_size; index++) {
439 usecase_type = getUseCaseType(mods_list[index]);
440 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700441 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700442 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
443 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
444 mUseCaseList.push_back(useCaseNode);
445 }
446 }
447 }
448 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
449 }
450 }
451 if (txDevice != NULL) {
452 if ((strncmp(curTxUCMDevice, "None", 4)) &&
453 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
454 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
455 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
456 usecase_type = getUseCaseType(use_case);
457 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700458 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700459 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
460 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
461 mUseCaseList.push_front(useCaseNode);
462 }
463 }
464 if (mods_size) {
465 for(index = 0; index < mods_size; index++) {
466 usecase_type = getUseCaseType(mods_list[index]);
467 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700468 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700469 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
470 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
471 mUseCaseList.push_back(useCaseNode);
472 }
473 }
474 }
475 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
476 }
477 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700478 ALOGV("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -0700479#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700480 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
481 err = csd_client_disable_device();
482 if (err < 0)
483 {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700484 ALOGE("csd_client_disable_device, failed, error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700485 }
486 }
487#endif
488
489 if (rxDevice != NULL) {
490 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
491 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700492#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700493 if (devices & AudioSystem::DEVICE_OUT_FM)
494 s_set_fm_vol(fmVolume);
495#endif
496 }
497 if (txDevice != NULL) {
498 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
499 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
500 }
501 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700502 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700503 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
504 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
505 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
506 } else {
507 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
508 }
509 }
510 if (!mUseCaseList.empty())
511 mUseCaseList.clear();
512 if (use_case != NULL) {
513 free(use_case);
514 use_case = NULL;
515 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700516 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700517
518 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
519 /* get tx acdb id */
520 memset(&ident,0,sizeof(ident));
521 strlcpy(ident, "ACDBID/", sizeof(ident));
522 strlcat(ident, curTxUCMDevice, sizeof(ident));
523 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
524
525 /* get rx acdb id */
526 memset(&ident,0,sizeof(ident));
527 strlcpy(ident, "ACDBID/", sizeof(ident));
528 strlcat(ident, curRxUCMDevice, sizeof(ident));
529 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
530
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700531 if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
532 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700533 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
534 }
535
Ajay Dudani9746c472012-06-18 16:01:16 -0700536#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700537 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700538 err = csd_client_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
539 if (err < 0)
540 {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700541 ALOGE("csd_client_disable_device failed, error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700542 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700543#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700544 }
545
546 if (rxDevice != NULL) {
547 if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
548 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
549 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
550 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
551 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
552 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
553 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
554 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
555 s_open(handle);
556 pflag = false;
557 }
558 }
559
560 if (rxDevice != NULL) {
561 free(rxDevice);
562 rxDevice = NULL;
563 }
564 if (txDevice != NULL) {
565 free(txDevice);
566 txDevice = NULL;
567 }
568}
569
570// ----------------------------------------------------------------------------
571
572static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
573{
Ajay Dudani86c852b2012-07-19 15:28:45 -0700574#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700575 ALOGD("s_init: Initializing devices for ALSA module");
Ajay Dudani86c852b2012-07-19 15:28:45 -0700576#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700577
578 list.clear();
579
580 return NO_ERROR;
581}
582
583static status_t s_open(alsa_handle_t *handle)
584{
585 char *devName;
586 unsigned flags = 0;
587 int err = NO_ERROR;
588
589 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
590 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
591 ||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700592 ALOGD("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700593 return NO_ERROR;
594 }
595
596 s_close(handle);
597
Ajay Dudani86c852b2012-07-19 15:28:45 -0700598#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700599 ALOGD("s_open: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700600#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700601
602 // ASoC multicomponent requires a valid path (frontend/backend) for
603 // the device to be opened
604
605 // The PCM stream is opened in blocking mode, per ALSA defaults. The
606 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
607 // should not be used.
608 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
609 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
610 flags = PCM_OUT;
611 } else {
612 flags = PCM_IN;
613 }
614 if (handle->channels == 1) {
615 flags |= PCM_MONO;
616 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700617#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700618 else if (handle->channels == 4 ) {
619 flags |= PCM_QUAD;
620 } else if (handle->channels == 6 ) {
621 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
622 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
623 flags |= PCM_QUAD;
624 } else {
625 flags |= PCM_5POINT1;
626 }
627 }
628#endif
629 else {
630 flags |= PCM_STEREO;
631 }
632 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700633 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700634 return NO_INIT;
635 }
636 if (devName != NULL) {
637 handle->handle = pcm_open(flags, (char*)devName);
638 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700639 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700640 return NO_INIT;
641 }
642
643 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700644 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700645 free(devName);
646 return NO_INIT;
647 }
648
649 handle->handle->flags = flags;
650 err = setHardwareParams(handle);
651
652 if (err == NO_ERROR) {
653 err = setSoftwareParams(handle);
654 }
655
656 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700657 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700658 s_standby(handle);
659 }
660
661 free(devName);
662 return NO_ERROR;
663}
664
665static status_t s_start_voip_call(alsa_handle_t *handle)
666{
667
668 char* devName;
669 char* devName1;
670 unsigned flags = 0;
671 int err = NO_ERROR;
672 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
673
674 s_close(handle);
675 flags = PCM_OUT;
676 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700677 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700678
679 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700680 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700681 return NO_INIT;
682 }
683
684 if (devName != NULL) {
685 handle->handle = pcm_open(flags, (char*)devName);
686 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700687 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700688 return NO_INIT;
689 }
690
691 if (!handle->handle) {
692 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700693 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700694 return NO_INIT;
695 }
696
697 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700698 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700699 }
700
701 handle->handle->flags = flags;
702 err = setHardwareParams(handle);
703
704 if (err == NO_ERROR) {
705 err = setSoftwareParams(handle);
706 }
707
708 err = pcm_prepare(handle->handle);
709 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700710 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700711 }
712
713 /* first write required start dsp */
714 memset(&voc_pkt,0,sizeof(voc_pkt));
715 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
716 handle->rxHandle = handle->handle;
717 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700718 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700719 flags = PCM_IN;
720 flags |= PCM_MONO;
721 handle->handle = 0;
722
723 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700724 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700725 return NO_INIT;
726 }
727 if (devName != NULL) {
728 handle->handle = pcm_open(flags, (char*)devName1);
729 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700730 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700731 return NO_INIT;
732 }
733
734 if (!handle->handle) {
735 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700736 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700737 return NO_INIT;
738 }
739
740 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700741 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700742 }
743
744 handle->handle->flags = flags;
745
746 err = setHardwareParams(handle);
747
748 if (err == NO_ERROR) {
749 err = setSoftwareParams(handle);
750 }
751
752
753 err = pcm_prepare(handle->handle);
754 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700755 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700756 }
757
758 /* first read required start dsp */
759 memset(&voc_pkt,0,sizeof(voc_pkt));
760 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
761 return NO_ERROR;
762}
763
764static status_t s_start_voice_call(alsa_handle_t *handle)
765{
766 char* devName;
767 unsigned flags = 0;
768 int err = NO_ERROR;
769
Ajay Dudani86c852b2012-07-19 15:28:45 -0700770#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700771 ALOGD("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700772#endif
773
Iliyan Malchev4765c432012-06-11 14:36:16 -0700774 // ASoC multicomponent requires a valid path (frontend/backend) for
775 // the device to be opened
776
777 flags = PCM_OUT | PCM_MONO;
778 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700779 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700780 return NO_INIT;
781 }
782 if (devName != NULL) {
783 handle->handle = pcm_open(flags, (char*)devName);
784 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700785 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700786 return NO_INIT;
787 }
788 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700789 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700790 goto Error;
791 }
792
793 handle->handle->flags = flags;
794 err = setHardwareParams(handle);
795 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700796 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700797 goto Error;
798 }
799
800 err = setSoftwareParams(handle);
801 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700802 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700803 goto Error;
804 }
805
806 err = pcm_prepare(handle->handle);
807 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700808 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700809 goto Error;
810 }
811
812 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700813 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 goto Error;
815 }
816
817 // Store the PCM playback device pointer in rxHandle
818 handle->rxHandle = handle->handle;
819 free(devName);
820
821 // Open PCM capture device
822 flags = PCM_IN | PCM_MONO;
823 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700824 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700825 goto Error;
826 }
827 if (devName != NULL) {
828 handle->handle = pcm_open(flags, (char*)devName);
829 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700830 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700831 return NO_INIT;
832 }
833 if (!handle->handle) {
834 free(devName);
835 goto Error;
836 }
837
838 handle->handle->flags = flags;
839 err = setHardwareParams(handle);
840 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700841 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700842 goto Error;
843 }
844
845 err = setSoftwareParams(handle);
846 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700847 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700848 goto Error;
849 }
850
851 err = pcm_prepare(handle->handle);
852 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700853 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700854 goto Error;
855 }
856
857 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700858 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700859 goto Error;
860 }
861
862 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700863#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700864 err = csd_client_start_voice();
865 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700866 ALOGE("s_start_voice_call: csd_client error %d\n", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700867 goto Error;
868 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700869#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700870 }
871
872 free(devName);
873 return NO_ERROR;
874
875Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700876 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700877 free(devName);
878 s_close(handle);
879 return NO_INIT;
880}
881
882static status_t s_start_fm(alsa_handle_t *handle)
883{
884 char *devName;
885 unsigned flags = 0;
886 int err = NO_ERROR;
887
Iliyan Malchev4113f342012-06-11 14:39:47 -0700888 ALOGE("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700889
890 // ASoC multicomponent requires a valid path (frontend/backend) for
891 // the device to be opened
892
893 flags = PCM_OUT | PCM_STEREO;
894 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700895 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700896 goto Error;
897 }
898 if (devName != NULL) {
899 handle->handle = pcm_open(flags, (char*)devName);
900 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700901 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700902 return NO_INIT;
903 }
904 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700905 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700906 goto Error;
907 }
908
909 handle->handle->flags = flags;
910 err = setHardwareParams(handle);
911 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700912 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700913 goto Error;
914 }
915
916 err = setSoftwareParams(handle);
917 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700918 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700919 goto Error;
920 }
921
922 err = pcm_prepare(handle->handle);
923 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700924 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700925 goto Error;
926 }
927
928 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700929 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700930 goto Error;
931 }
932
933 // Store the PCM playback device pointer in rxHandle
934 handle->rxHandle = handle->handle;
935 free(devName);
936
937 // Open PCM capture device
938 flags = PCM_IN | PCM_STEREO;
939 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700940 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700941 goto Error;
942 }
943 if (devName != NULL) {
944 handle->handle = pcm_open(flags, (char*)devName);
945 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700946 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700947 return NO_INIT;
948 }
949 if (!handle->handle) {
950 goto Error;
951 }
952
953 handle->handle->flags = flags;
954 err = setHardwareParams(handle);
955 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700956 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700957 goto Error;
958 }
959
960 err = setSoftwareParams(handle);
961 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700962 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700963 goto Error;
964 }
965
966 err = pcm_prepare(handle->handle);
967 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700968 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700969 goto Error;
970 }
971
972 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700973 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700974 goto Error;
975 }
976
977 s_set_fm_vol(fmVolume);
978 free(devName);
979 return NO_ERROR;
980
981Error:
982 free(devName);
983 s_close(handle);
984 return NO_INIT;
985}
986
987static status_t s_set_fm_vol(int value)
988{
989 status_t err = NO_ERROR;
990
991 ALSAControl control("/dev/snd/controlC0");
992 control.set("Internal FM RX Volume",value,0);
993 fmVolume = value;
994
995 return err;
996}
997
998static status_t s_set_lpa_vol(int value)
999{
1000 status_t err = NO_ERROR;
1001
1002 ALSAControl control("/dev/snd/controlC0");
1003 control.set("LPA RX Volume",value,0);
1004
1005 return err;
1006}
1007
1008static status_t s_start(alsa_handle_t *handle)
1009{
1010 status_t err = NO_ERROR;
1011
1012 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001013 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001014 return err;
1015 }
1016
1017 err = pcm_prepare(handle->handle);
1018
1019 return err;
1020}
1021
1022static status_t s_close(alsa_handle_t *handle)
1023{
1024 int ret;
1025 status_t err = NO_ERROR;
1026 struct pcm *h = handle->rxHandle;
1027
1028 handle->rxHandle = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001029#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001030 ALOGD("s_close: handle %p h %p", handle, h);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001031#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001032 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001033 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001034 err = pcm_close(h);
1035 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001036 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001037 }
1038 }
1039
1040 h = handle->handle;
1041 handle->handle = 0;
1042
1043 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001044 ALOGV("s_close handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001045 err = pcm_close(h);
1046 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001047 ALOGE("s_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001048 }
1049
1050 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1051 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1052 platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001053#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001054 err = csd_client_stop_voice();
1055 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001056 ALOGE("s_close: csd_client error %d\n", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001057 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001058#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001059 }
1060
1061 disableDevice(handle);
1062 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1063 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1064 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1065 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1066 disableDevice(handle);
1067 }
1068
1069 return err;
1070}
1071
1072/*
1073 this is same as s_close, but don't discard
1074 the device/mode info. This way we can still
1075 close the device, hit idle and power-save, reopen the pcm
1076 for the same device/mode after resuming
1077*/
1078static status_t s_standby(alsa_handle_t *handle)
1079{
1080 int ret;
1081 status_t err = NO_ERROR;
1082 struct pcm *h = handle->rxHandle;
1083 handle->rxHandle = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001084#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001085 ALOGD("s_standby: handle %p h %p", handle, h);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001086#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001087 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001088 ALOGE("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001089 err = pcm_close(h);
1090 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001091 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001092 }
1093 }
1094
1095 h = handle->handle;
1096 handle->handle = 0;
1097
1098 if (h) {
Ajay Dudani86c852b2012-07-19 15:28:45 -07001099#if LOCAL_LOGD
1100 ALOGD("s_standby handle h %p\n", h);
1101#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001102 err = pcm_close(h);
1103 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001104 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001105 }
1106 disableDevice(handle);
1107 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1108 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1109 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1110 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1111 disableDevice(handle);
1112 }
1113
1114 return err;
1115}
1116
1117static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1118{
1119 status_t status = NO_ERROR;
1120
Ajay Dudani86c852b2012-07-19 15:28:45 -07001121#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001122 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001123#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001124 callMode = mode;
1125 switchDevice(handle, devices, mode);
1126 return status;
1127}
1128
1129int getUseCaseType(const char *useCase)
1130{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001131 ALOGE("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001132 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
1133 strlen(SND_USE_CASE_VERB_HIFI)) ||
1134 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
1135 strlen(SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1136 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
1137 strlen(SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1138 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
1139 strlen(SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1140 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
1141 strlen(SND_USE_CASE_MOD_PLAY_MUSIC)) ||
1142 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
1143 strlen(SND_USE_CASE_MOD_PLAY_LPA)) ||
1144 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
1145 strlen(SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
1146 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
1147 strlen(SND_USE_CASE_MOD_PLAY_FM))) {
1148 return USECASE_TYPE_RX;
1149 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
1150 strlen(SND_USE_CASE_VERB_HIFI_REC)) ||
1151 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
1152 strlen(SND_USE_CASE_VERB_FM_REC)) ||
1153 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
1154 strlen(SND_USE_CASE_VERB_FM_A2DP_REC)) ||
1155 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
1156 strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
1157 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
1158 strlen(SND_USE_CASE_MOD_CAPTURE_FM)) ||
1159 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
1160 strlen(SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
1161 return USECASE_TYPE_TX;
1162 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
1163 strlen(SND_USE_CASE_VERB_VOICECALL)) ||
1164 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
1165 strlen(SND_USE_CASE_VERB_IP_VOICECALL)) ||
1166 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
1167 strlen(SND_USE_CASE_VERB_DL_REC)) ||
1168 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
1169 strlen(SND_USE_CASE_VERB_UL_DL_REC)) ||
1170 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1171 strlen(SND_USE_CASE_MOD_PLAY_VOICE)) ||
1172 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
1173 strlen(SND_USE_CASE_MOD_PLAY_VOIP)) ||
1174 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1175 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
1176 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1177 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
1178 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1179 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
1180 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
1181 strlen(SND_USE_CASE_VERB_VOLTE)) ||
1182 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1183 strlen(SND_USE_CASE_MOD_PLAY_VOLTE))) {
1184 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1185 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001186 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001187 return 0;
1188 }
1189}
1190
1191static void disableDevice(alsa_handle_t *handle)
1192{
1193 unsigned usecase_type = 0;
1194 int i, mods_size;
1195 char *useCase;
1196 const char **mods_list;
1197
1198 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1199 if (useCase != NULL) {
1200 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1201 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1202 } else {
1203 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1204 }
1205 free(useCase);
1206 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1207 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1208 strlen(SND_USE_CASE_VERB_INACTIVE)))
1209 usecase_type |= getUseCaseType(useCase);
1210 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001211#if LOCAL_LOGD
1212 ALOGD("Number of modifiers %d\n", mods_size);
1213#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001214 if (mods_size) {
1215 for(i = 0; i < mods_size; i++) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001216 ALOGE("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001217 usecase_type |= getUseCaseType(mods_list[i]);
1218 }
1219 }
Ajay Dudani86c852b2012-07-19 15:28:45 -07001220#if LOCAL_LOGD
1221 ALOGD("usecase_type is %d\n", usecase_type);
1222#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001223 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1224 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1225 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1226 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1227 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001228 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001229 }
1230 free(useCase);
1231}
1232
1233char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1234{
1235 if (!input) {
1236 if (!(mDevSettingsFlag & TTY_OFF) &&
1237 (callMode == AudioSystem::MODE_IN_CALL) &&
1238 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1239 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001240#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001241 ||
1242 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1243 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1244#endif
1245 if (mDevSettingsFlag & TTY_VCO) {
1246 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1247 } else if (mDevSettingsFlag & TTY_FULL) {
1248 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1249 } else if (mDevSettingsFlag & TTY_HCO) {
1250 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1251 }
1252 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1253 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1254 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1255 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1256 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1257 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1258 if (mDevSettingsFlag & ANC_FLAG) {
1259 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1260 } else {
1261 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1262 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001263#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001264 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1265 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1266 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1267 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1268 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1269 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1270 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1271#endif
1272 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
1273 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
1274 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
1275 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1276 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1277 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1278 if (mDevSettingsFlag & ANC_FLAG) {
1279 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1280 } else {
1281 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
1282 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001283#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001284 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1285 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
1286 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1287#endif
1288 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1289 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1290 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1291 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1292 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1293 else
1294 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1295 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1296 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001297#ifdef QCOM_VOIP_ENABLED
1298 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1299#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001300 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1301 /* Nothing to be done, use current active device */
1302 if (strncmp(curRxUCMDevice, "None", 4)) {
1303 return strdup(curRxUCMDevice);
1304 }
1305 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1306 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001307#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001308 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1309 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001310#endif
1311#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001312 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1313 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1314#endif
1315 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
1316 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1317 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001318 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001319 }
1320 } else {
1321 if (!(mDevSettingsFlag & TTY_OFF) &&
1322 (callMode == AudioSystem::MODE_IN_CALL) &&
1323 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001324#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001325 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1326#endif
1327 if (mDevSettingsFlag & TTY_HCO) {
1328 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1329 } else if (mDevSettingsFlag & TTY_FULL) {
1330 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1331 } else if (mDevSettingsFlag & TTY_VCO) {
1332 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001333 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001334 } else {
1335 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1336 }
1337 }
1338 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1339 if (!strncmp(mic_type, "analog", 6)) {
1340 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1341 } else {
1342 if (mDevSettingsFlag & DMIC_FLAG) {
1343 if (((rxDevice != NULL) &&
1344 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1345 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1346 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1347 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1348 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1349 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1350 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1351 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1352 }
1353 } else {
1354 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1355 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1356 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1357 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1358 }
1359 }
1360 } else if (mDevSettingsFlag & QMIC_FLAG){
1361 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
1362 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001363#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001364 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001365 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 // Mapping for quad mic input device.
1367 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
1368 }
1369#endif
1370 else {
1371 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
1372 }
1373 }
1374 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1375 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001376#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001377 } else if ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) ||
1378 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
1379 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1380#endif
1381 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1382 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1383 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1384 else
1385 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001386#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001387 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1388 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1389 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1390#endif
1391 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1392 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1393 /* Nothing to be done, use current active device */
1394 if (strncmp(curTxUCMDevice, "None", 4)) {
1395 return strdup(curTxUCMDevice);
1396 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001397#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001398 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1399 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1400 /* Nothing to be done, use current tx device or set dummy device */
1401 if (strncmp(curTxUCMDevice, "None", 4)) {
1402 return strdup(curTxUCMDevice);
1403 } else {
1404 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1405 }
1406#endif
1407 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1408 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001409 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001410 if (!strncmp(mic_type, "analog", 6)) {
1411 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1412 } else {
1413 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
1414 }
1415 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001416 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001417 }
1418 }
1419 return NULL;
1420}
1421
1422void s_set_voice_volume(int vol)
1423{
1424 int err = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001425#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001426 ALOGD("s_set_voice_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001427#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001428 ALSAControl control("/dev/snd/controlC0");
1429 control.set("Voice Rx Volume", vol, 0);
1430
1431 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001432#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001433 err = csd_client_volume(vol);
1434 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001435 ALOGE("s_set_voice_volume: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001436 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001437#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001438 }
1439}
1440
1441void s_set_volte_volume(int vol)
1442{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001443#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001444 ALOGD("s_set_volte_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001445#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001446 ALSAControl control("/dev/snd/controlC0");
1447 control.set("VoLTE Rx Volume", vol, 0);
1448}
1449
1450
1451void s_set_voip_volume(int vol)
1452{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001453#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001454 ALOGD("s_set_voip_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001455#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001456 ALSAControl control("/dev/snd/controlC0");
1457 control.set("Voip Rx Volume", vol, 0);
1458}
1459void s_set_mic_mute(int state)
1460{
1461 int err = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001462#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001463 ALOGD("s_set_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001464#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001465 ALSAControl control("/dev/snd/controlC0");
1466 control.set("Voice Tx Mute", state, 0);
1467
1468 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001469#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001470 err = csd_client_mic_mute(state);
1471 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001472 ALOGE("s_set_mic_mute: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001473 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001474#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001475 }
1476}
1477void s_set_volte_mic_mute(int state)
1478{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001479#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001480 ALOGD("s_set_volte_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001481#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001482 ALSAControl control("/dev/snd/controlC0");
1483 control.set("VoLTE Tx Mute", state, 0);
1484}
1485
1486void s_set_voip_mic_mute(int state)
1487{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001488#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001489 ALOGD("s_set_voip_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001490#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001491 ALSAControl control("/dev/snd/controlC0");
1492 control.set("Voip Tx Mute", state, 0);
1493}
1494
1495void s_set_voip_config(int mode, int rate)
1496{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001497#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001498 ALOGD("s_set_voip_config: mode %d,rate %d", mode, rate);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001499#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001500 ALSAControl control("/dev/snd/controlC0");
1501 char** setValues;
1502 setValues = (char**)malloc(2*sizeof(char*));
1503 if (setValues == NULL) {
1504 return;
1505 }
1506 setValues[0] = (char*)malloc(4*sizeof(char));
1507 if (setValues[0] == NULL) {
1508 free(setValues);
1509 return;
1510 }
1511
1512 setValues[1] = (char*)malloc(8*sizeof(char));
1513 if (setValues[1] == NULL) {
1514 free(setValues);
1515 free(setValues[0]);
1516 return;
1517 }
1518
1519 sprintf(setValues[0], "%d",mode);
1520 sprintf(setValues[1], "%d",rate);
1521
1522 control.setext("Voip Mode Rate Config", 2, setValues);
1523 free(setValues[1]);
1524 free(setValues[0]);
1525 free(setValues);
1526 return;
1527}
1528
1529void s_set_btsco_rate(int rate)
1530{
1531 btsco_samplerate = rate;
1532}
1533
1534void s_enable_wide_voice(bool flag)
1535{
1536 int err = 0;
1537
Ajay Dudani86c852b2012-07-19 15:28:45 -07001538#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001539 ALOGD("s_enable_wide_voice: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001540#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001541 ALSAControl control("/dev/snd/controlC0");
1542 if(flag == true) {
1543 control.set("Widevoice Enable", 1, 0);
1544 } else {
1545 control.set("Widevoice Enable", 0, 0);
1546 }
1547
1548 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001549#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001550 err == csd_client_wide_voice(flag);
1551 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001552 ALOGE("s_enable_wide_voice: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001553 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001554#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001555 }
1556}
1557
1558void s_set_voc_rec_mode(uint8_t mode)
1559{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001560#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001561 ALOGD("s_set_voc_rec_mode: mode %d", mode);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001562#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001563 ALSAControl control("/dev/snd/controlC0");
1564 control.set("Incall Rec Mode", mode, 0);
1565}
1566
1567void s_enable_fens(bool flag)
1568{
1569 int err = 0;
1570
Ajay Dudani86c852b2012-07-19 15:28:45 -07001571#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001572 ALOGD("s_enable_fens: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001573#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001574 ALSAControl control("/dev/snd/controlC0");
1575 if(flag == true) {
1576 control.set("FENS Enable", 1, 0);
1577 } else {
1578 control.set("FENS Enable", 0, 0);
1579 }
1580
1581 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001582#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001583 err = csd_client_fens(flag);
1584 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001585 ALOGE("s_enable_fens: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001586 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001587#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001588 }
1589}
1590
1591void s_enable_slow_talk(bool flag)
1592{
1593 int err = 0;
1594
Ajay Dudani86c852b2012-07-19 15:28:45 -07001595#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001596 ALOGD("s_enable_slow_talk: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001597#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001598 ALSAControl control("/dev/snd/controlC0");
1599 if(flag == true) {
1600 control.set("Slowtalk Enable", 1, 0);
1601 } else {
1602 control.set("Slowtalk Enable", 0, 0);
1603 }
1604
1605 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001606#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001607 err = csd_client_slow_talk(flag);
1608 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001609 ALOGE("s_enable_slow_talk: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001610 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001611#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001612 }
1613}
1614
1615void s_set_flags(uint32_t flags)
1616{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001617 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001618 mDevSettingsFlag = flags;
1619}
1620
1621static status_t s_set_compressed_vol(int value)
1622{
1623 status_t err = NO_ERROR;
1624
1625 ALSAControl control("/dev/snd/controlC0");
1626 control.set("COMPRESSED RX Volume",value,0);
1627
1628 return err;
1629}
1630
1631}