blob: fdc89da776677ccde34712f84766eab1aa541d79 [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>
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070027#include <dlfcn.h>
Ajay Dudani9746c472012-06-18 16:01:16 -070028#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070029extern "C" {
30#include "csd_client.h"
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070031static int (*csd_disable_device)();
32static int (*csd_enable_device)(int, int, uint32_t);
33static int (*csd_volume)(int);
34static int (*csd_mic_mute)(int);
35static int (*csd_wide_voice)(uint8_t);
36static int (*csd_slow_talk)(uint8_t);
37static int (*csd_fens)(uint8_t);
38static int (*csd_start_voice)();
39static int (*csd_stop_voice)();
Iliyan Malchev4765c432012-06-11 14:36:16 -070040}
Iliyan Malchev4113f342012-06-11 14:39:47 -070041#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070042
43#ifndef ALSA_DEFAULT_SAMPLE_RATE
44#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
45#endif
46
47#define BTSCO_RATE_16KHZ 16000
48#define USECASE_TYPE_RX 1
49#define USECASE_TYPE_TX 2
50
51namespace android_audio_legacy
52{
53
54static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
55static int s_device_close(hw_device_t*);
56static status_t s_init(alsa_device_t *, ALSAHandleList &);
57static status_t s_open(alsa_handle_t *);
58static status_t s_close(alsa_handle_t *);
59static status_t s_standby(alsa_handle_t *);
60static status_t s_route(alsa_handle_t *, uint32_t, int);
61static status_t s_start_voice_call(alsa_handle_t *);
62static status_t s_start_voip_call(alsa_handle_t *);
63static status_t s_start_fm(alsa_handle_t *);
64static void s_set_voice_volume(int);
65static void s_set_voip_volume(int);
66static void s_set_mic_mute(int);
67static void s_set_voip_mic_mute(int);
68static void s_set_voip_config(int, int);
69static status_t s_set_fm_vol(int);
70static void s_set_btsco_rate(int);
71static status_t s_set_lpa_vol(int);
72static void s_enable_wide_voice(bool flag);
73static void s_enable_fens(bool flag);
74static void s_set_flags(uint32_t flags);
75static status_t s_set_compressed_vol(int);
76static void s_enable_slow_talk(bool flag);
77static void s_set_voc_rec_mode(uint8_t mode);
78static void s_set_volte_mic_mute(int state);
79static void s_set_volte_volume(int vol);
ty.lee74060de2012-08-02 00:47:00 +090080#ifdef SEPERATED_AUDIO_INPUT
81static void s_setInput(int);
82
83static int input_source;
84#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070085#ifdef QCOM_CSDCLIENT_ENABLED
86static void s_set_csd_handle(void*);
87#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070088
89static char mic_type[25];
90static char curRxUCMDevice[50];
91static char curTxUCMDevice[50];
92static int fluence_mode;
93static int fmVolume;
ty.lee924f7982012-08-01 23:15:30 +090094#ifdef USES_FLUENCE_INCALL
95static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG;
96#else
Iliyan Malchev4765c432012-06-11 14:36:16 -070097static uint32_t mDevSettingsFlag = TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +090098#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070099static int btsco_samplerate = 8000;
100static bool pflag = false;
101static ALSAUseCaseList mUseCaseList;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700102static void *csd_handle;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700103
104static hw_module_methods_t s_module_methods = {
105 open : s_device_open
106};
107
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700108extern "C" {
109hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700110 tag : HARDWARE_MODULE_TAG,
111 version_major : 1,
112 version_minor : 0,
113 id : ALSA_HARDWARE_MODULE_ID,
114 name : "QCOM ALSA module",
115 author : "QuIC Inc",
116 methods : &s_module_methods,
117 dso : 0,
118 reserved : {0,},
119};
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700120}
Iliyan Malchev4765c432012-06-11 14:36:16 -0700121
122static int s_device_open(const hw_module_t* module, const char* name,
123 hw_device_t** device)
124{
125 char value[128];
126 alsa_device_t *dev;
127 dev = (alsa_device_t *) malloc(sizeof(*dev));
128 if (!dev) return -ENOMEM;
129
130 memset(dev, 0, sizeof(*dev));
131
132 /* initialize the procs */
133 dev->common.tag = HARDWARE_DEVICE_TAG;
134 dev->common.version = 0;
135 dev->common.module = (hw_module_t *) module;
136 dev->common.close = s_device_close;
137 dev->init = s_init;
138 dev->open = s_open;
139 dev->close = s_close;
140 dev->route = s_route;
141 dev->standby = s_standby;
142 dev->startVoiceCall = s_start_voice_call;
143 dev->startVoipCall = s_start_voip_call;
144 dev->startFm = s_start_fm;
145 dev->setVoiceVolume = s_set_voice_volume;
146 dev->setVoipVolume = s_set_voip_volume;
147 dev->setMicMute = s_set_mic_mute;
148 dev->setVoipMicMute = s_set_voip_mic_mute;
149 dev->setVoipConfig = s_set_voip_config;
150 dev->setFmVolume = s_set_fm_vol;
151 dev->setBtscoRate = s_set_btsco_rate;
152 dev->setLpaVolume = s_set_lpa_vol;
153 dev->enableWideVoice = s_enable_wide_voice;
154 dev->enableFENS = s_enable_fens;
155 dev->setFlags = s_set_flags;
156 dev->setCompressedVolume = s_set_compressed_vol;
157 dev->enableSlowTalk = s_enable_slow_talk;
158 dev->setVocRecMode = s_set_voc_rec_mode;
159 dev->setVoLTEMicMute = s_set_volte_mic_mute;
160 dev->setVoLTEVolume = s_set_volte_volume;
ty.lee74060de2012-08-02 00:47:00 +0900161#ifdef SEPERATED_AUDIO_INPUT
162 dev->setInput = s_setInput;
163#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700164#ifdef QCOM_CSDCLIENT_ENABLED
165 dev->setCsdHandle = s_set_csd_handle;
166#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700167 *device = &dev->common;
168
169 property_get("persist.audio.handset.mic",value,"0");
170 strlcpy(mic_type, value, sizeof(mic_type));
171 property_get("persist.audio.fluence.mode",value,"0");
172 if (!strcmp("broadside", value)) {
173 fluence_mode = FLUENCE_MODE_BROADSIDE;
174 } else {
175 fluence_mode = FLUENCE_MODE_ENDFIRE;
176 }
177 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
178 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
Ajay Dudani86c852b2012-07-19 15:28:45 -0700179#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700180 ALOGD("ALSA module opened");
Ajay Dudani86c852b2012-07-19 15:28:45 -0700181#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700182
183 return 0;
184}
185
186static int s_device_close(hw_device_t* device)
187{
188 free(device);
189 device = NULL;
190 return 0;
191}
192
193// ----------------------------------------------------------------------------
194
195static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
196
197static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
198static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
199static void disableDevice(alsa_handle_t *handle);
200int getUseCaseType(const char *useCase);
201
202static int callMode = AudioSystem::MODE_NORMAL;
203// ----------------------------------------------------------------------------
204
205bool platform_is_Fusion3()
206{
207 char platform[128], baseband[128];
208 property_get("ro.board.platform", platform, "");
209 property_get("ro.baseband", baseband, "");
210 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
211 return true;
212 else
213 return false;
214}
215
216int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
217{
218 int ret = 0;
219 char ident[70];
220
221 if (flags & PCM_IN) {
222 strlcpy(ident, "CapturePCM/", sizeof(ident));
223 } else {
224 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
225 }
226 strlcat(ident, handle->useCase, sizeof(ident));
227 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700228#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700229 ALOGD("Device value returned is %s", (*value));
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700230#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700231 return ret;
232}
233
234status_t setHardwareParams(alsa_handle_t *handle)
235{
236 struct snd_pcm_hw_params *params;
237 unsigned long bufferSize, reqBuffSize;
238 unsigned int periodTime, bufferTime;
239 unsigned int requestedRate = handle->sampleRate;
240 int status = 0;
241 int channels = handle->channels;
242 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
243
244 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
245 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700246 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247 return NO_INIT;
248 }
249
250 reqBuffSize = handle->bufferSize;
Ajay Dudani86c852b2012-07-19 15:28:45 -0700251#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700252 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700253 (int) reqBuffSize, handle->channels, handle->sampleRate);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700254#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700255
Ajay Dudani9746c472012-06-18 16:01:16 -0700256#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700257 if (channels == 6) {
258 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
259 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700260 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700261 channels = 4;
262 reqBuffSize = DEFAULT_IN_BUFFER_SIZE;
263 }
264 }
265#endif
266
267 param_init(params);
268 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
269 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
270 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700271 if (handle->format == AudioSystem::AMR_NB
272 || handle->format == AudioSystem::AMR_WB
273#ifdef QCOM_QCHAT_ENABLED
274 || handle->format == AudioSystem::EVRC
275 || handle->format == AudioSystem::EVRCB
276 || handle->format == AudioSystem::EVRCWB
277#endif
278 )
Iliyan Malchev4765c432012-06-11 14:36:16 -0700279 format = SNDRV_PCM_FORMAT_SPECIAL;
280 }
281 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
282 format);
283 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
284 SNDRV_PCM_SUBFORMAT_STD);
285 param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
286 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
287 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
288 channels * 16);
289 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
290 channels);
291 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
292 param_set_hw_refine(handle->handle, params);
293
294 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700295 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700296 return NO_INIT;
297 }
298 param_dump(params);
299
300 handle->handle->buffer_size = pcm_buffer_size(params);
301 handle->handle->period_size = pcm_period_size(params);
302 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Ajay Dudani86c852b2012-07-19 15:28:45 -0700303#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700304 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700305 handle->handle->buffer_size, handle->handle->period_size,
306 handle->handle->period_cnt);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700307#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700308 handle->handle->rate = handle->sampleRate;
309 handle->handle->channels = handle->channels;
310 handle->periodSize = handle->handle->period_size;
311 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
312 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
313 (6 != handle->channels)) {
314 //Do not update buffersize for 5.1 recording
315 handle->bufferSize = handle->handle->period_size;
316 }
317
318 return NO_ERROR;
319}
320
321status_t setSoftwareParams(alsa_handle_t *handle)
322{
323 struct snd_pcm_sw_params* params;
324 struct pcm* pcm = handle->handle;
325
326 unsigned long periodSize = pcm->period_size;
327 int channels = handle->channels;
328
329 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
330 if (!params) {
331 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
332 return NO_INIT;
333 }
334
Ajay Dudani9746c472012-06-18 16:01:16 -0700335#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700336 if (channels == 6) {
337 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
338 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700339 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700340 channels = 4;
341 }
342 }
343#endif
344
345 // Get the current software parameters
346 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
347 params->period_step = 1;
348 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
349 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700350 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700351 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
352 params->start_threshold = periodSize/2;
353 params->stop_threshold = INT_MAX;
354 } else {
355 params->avail_min = periodSize/2;
356 params->start_threshold = channels * (periodSize/4);
357 params->stop_threshold = INT_MAX;
358 }
359 params->silence_threshold = 0;
360 params->silence_size = 0;
361
362 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700363 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700364 return NO_INIT;
365 }
366 return NO_ERROR;
367}
368
369void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
370{
371 const char **mods_list;
372 use_case_t useCaseNode;
373 unsigned usecase_type = 0;
374 bool inCallDevSwitch = false;
375 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
376 int err = 0, index, mods_size;
377 int rx_dev_id, tx_dev_id;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700378 ALOGV("%s: device %d", __FUNCTION__, devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700379
380 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
381 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
382 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
383 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
384 AudioSystem::DEVICE_IN_WIRED_HEADSET);
385 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
386 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
387 AudioSystem::DEVICE_IN_BUILTIN_MIC);
388 } else if ((devices & AudioSystem::DEVICE_OUT_EARPIECE) ||
389 (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC)) {
390 devices = devices | (AudioSystem::DEVICE_IN_BUILTIN_MIC |
391 AudioSystem::DEVICE_OUT_EARPIECE);
392 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900393 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700394 AudioSystem::DEVICE_OUT_SPEAKER);
395 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
396 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
397 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
398 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
399 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700400#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700401 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
402 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
403 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
404 AudioSystem::DEVICE_IN_ANC_HEADSET);
405 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
406 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
407 AudioSystem::DEVICE_IN_BUILTIN_MIC);
408#endif
409 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
410 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
411 AudioSystem::DEVICE_IN_AUX_DIGITAL);
Ajay Dudani9746c472012-06-18 16:01:16 -0700412#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700413 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
414 (devices & AudioSystem::DEVICE_IN_PROXY)) {
415 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
416 AudioSystem::DEVICE_IN_PROXY);
417#endif
418 }
419 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700420#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700421 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
422 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
423 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700424 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700425 s_set_flags(SSRQMIC_FLAG);
426 }
427 }
428#endif
429
430 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
431 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
432
Iliyan Malchev4765c432012-06-11 14:36:16 -0700433 if ((rxDevice != NULL) && (txDevice != NULL)) {
434 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
435 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) && (mode == AudioSystem::MODE_IN_CALL))
436 inCallDevSwitch = true;
437 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700438
439#ifdef QCOM_CSDCLIENT_ENABLED
440 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700441 if (csd_disable_device == NULL) {
442 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
443 } else {
444 err = csd_disable_device();
445 if (err < 0)
446 {
447 ALOGE("csd_client_disable_device, failed, error %d", err);
448 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700449 }
450 }
451#endif
452
Iliyan Malchev4765c432012-06-11 14:36:16 -0700453 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
454 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
455 if (rxDevice != NULL) {
456 if ((strncmp(curRxUCMDevice, "None", 4)) &&
457 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
458 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
459 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
460 usecase_type = getUseCaseType(use_case);
461 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700462 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700463 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
464 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
465 mUseCaseList.push_front(useCaseNode);
466 }
467 }
468 if (mods_size) {
469 for(index = 0; index < mods_size; index++) {
470 usecase_type = getUseCaseType(mods_list[index]);
471 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700472 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700473 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
474 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
475 mUseCaseList.push_back(useCaseNode);
476 }
477 }
478 }
479 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
480 }
481 }
482 if (txDevice != NULL) {
483 if ((strncmp(curTxUCMDevice, "None", 4)) &&
484 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
485 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
486 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
487 usecase_type = getUseCaseType(use_case);
488 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700489 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700490 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
491 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
492 mUseCaseList.push_front(useCaseNode);
493 }
494 }
495 if (mods_size) {
496 for(index = 0; index < mods_size; index++) {
497 usecase_type = getUseCaseType(mods_list[index]);
498 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700499 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700500 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
501 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
502 mUseCaseList.push_back(useCaseNode);
503 }
504 }
505 }
506 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
507 }
508 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700509 ALOGV("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700510
511 if (rxDevice != NULL) {
512 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
513 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700514#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700515 if (devices & AudioSystem::DEVICE_OUT_FM)
516 s_set_fm_vol(fmVolume);
517#endif
518 }
519 if (txDevice != NULL) {
520 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
521 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
522 }
523 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700524 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700525 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
526 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
527 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
528 } else {
529 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
530 }
531 }
532 if (!mUseCaseList.empty())
533 mUseCaseList.clear();
534 if (use_case != NULL) {
535 free(use_case);
536 use_case = NULL;
537 }
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700538#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700539 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700540#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700541
542 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
543 /* get tx acdb id */
544 memset(&ident,0,sizeof(ident));
545 strlcpy(ident, "ACDBID/", sizeof(ident));
546 strlcat(ident, curTxUCMDevice, sizeof(ident));
547 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
548
549 /* get rx acdb id */
550 memset(&ident,0,sizeof(ident));
551 strlcpy(ident, "ACDBID/", sizeof(ident));
552 strlcat(ident, curRxUCMDevice, sizeof(ident));
553 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
554
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700555 if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
556 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700557 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
558 }
559
Ajay Dudani9746c472012-06-18 16:01:16 -0700560#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700561 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700562 if (csd_enable_device == NULL) {
563 ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
564 } else {
565 err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
566 if (err < 0)
567 {
568 ALOGE("csd_client_disable_device failed, error %d", err);
569 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700570 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700571#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700572 }
573
574 if (rxDevice != NULL) {
575 if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
576 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
577 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
578 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
579 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
580 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
581 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
582 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
583 s_open(handle);
584 pflag = false;
585 }
586 }
587
588 if (rxDevice != NULL) {
589 free(rxDevice);
590 rxDevice = NULL;
591 }
592 if (txDevice != NULL) {
593 free(txDevice);
594 txDevice = NULL;
595 }
596}
597
598// ----------------------------------------------------------------------------
599
600static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
601{
Ajay Dudani86c852b2012-07-19 15:28:45 -0700602#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700603 ALOGD("s_init: Initializing devices for ALSA module");
Ajay Dudani86c852b2012-07-19 15:28:45 -0700604#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700605
606 list.clear();
607
608 return NO_ERROR;
609}
610
611static status_t s_open(alsa_handle_t *handle)
612{
613 char *devName;
614 unsigned flags = 0;
615 int err = NO_ERROR;
616
617 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
618 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
619 ||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700620#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700621 ALOGD("s_open: Opening LPA /Tunnel playback");
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700622#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700623 return NO_ERROR;
624 }
625
626 s_close(handle);
627
Ajay Dudani86c852b2012-07-19 15:28:45 -0700628#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700629 ALOGD("s_open: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700630#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700631
632 // ASoC multicomponent requires a valid path (frontend/backend) for
633 // the device to be opened
634
635 // The PCM stream is opened in blocking mode, per ALSA defaults. The
636 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
637 // should not be used.
SathishKumar Mani88613382012-08-13 18:40:18 -0700638 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
639 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
640 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
641 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
642 ALOGV("LPA/tunnel use case");
643 flags |= PCM_MMAP;
644 flags |= DEBUG_ON;
645 } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
646 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
647 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700648 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
SathishKumar Mani88613382012-08-13 18:40:18 -0700649 ALOGV("Music case");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700650 flags = PCM_OUT;
651 } else {
652 flags = PCM_IN;
653 }
654 if (handle->channels == 1) {
655 flags |= PCM_MONO;
SathishKumar Manie42406e2012-08-29 16:25:54 -0700656 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700657#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700658 else if (handle->channels == 4 ) {
659 flags |= PCM_QUAD;
660 } else if (handle->channels == 6 ) {
661 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
662 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
663 flags |= PCM_QUAD;
664 } else {
665 flags |= PCM_5POINT1;
666 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700667 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700668#endif
669 else {
670 flags |= PCM_STEREO;
671 }
672 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700673 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700674 return NO_INIT;
675 }
676 if (devName != NULL) {
677 handle->handle = pcm_open(flags, (char*)devName);
678 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700679 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700680 return NO_INIT;
681 }
682
683 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700684 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700685 free(devName);
686 return NO_INIT;
687 }
688
689 handle->handle->flags = flags;
690 err = setHardwareParams(handle);
691
692 if (err == NO_ERROR) {
693 err = setSoftwareParams(handle);
694 }
695
696 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700697 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700698 s_standby(handle);
699 }
700
701 free(devName);
702 return NO_ERROR;
703}
704
705static status_t s_start_voip_call(alsa_handle_t *handle)
706{
707
708 char* devName;
709 char* devName1;
710 unsigned flags = 0;
711 int err = NO_ERROR;
712 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
713
714 s_close(handle);
715 flags = PCM_OUT;
716 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700717 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700718
719 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700720 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700721 return NO_INIT;
722 }
723
724 if (devName != NULL) {
725 handle->handle = pcm_open(flags, (char*)devName);
726 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700727 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700728 return NO_INIT;
729 }
730
731 if (!handle->handle) {
732 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700733 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700734 return NO_INIT;
735 }
736
737 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700738 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700739 }
740
741 handle->handle->flags = flags;
742 err = setHardwareParams(handle);
743
744 if (err == NO_ERROR) {
745 err = setSoftwareParams(handle);
746 }
747
748 err = pcm_prepare(handle->handle);
749 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700750 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700751 }
752
753 /* first write required start dsp */
754 memset(&voc_pkt,0,sizeof(voc_pkt));
755 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
756 handle->rxHandle = handle->handle;
757 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700758 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700759 flags = PCM_IN;
760 flags |= PCM_MONO;
761 handle->handle = 0;
762
763 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700764 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700765 return NO_INIT;
766 }
767 if (devName != NULL) {
768 handle->handle = pcm_open(flags, (char*)devName1);
769 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700770 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700771 return NO_INIT;
772 }
773
774 if (!handle->handle) {
775 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700776 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700777 return NO_INIT;
778 }
779
780 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700781 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700782 }
783
784 handle->handle->flags = flags;
785
786 err = setHardwareParams(handle);
787
788 if (err == NO_ERROR) {
789 err = setSoftwareParams(handle);
790 }
791
792
793 err = pcm_prepare(handle->handle);
794 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700795 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700796 }
797
798 /* first read required start dsp */
799 memset(&voc_pkt,0,sizeof(voc_pkt));
800 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
801 return NO_ERROR;
802}
803
804static status_t s_start_voice_call(alsa_handle_t *handle)
805{
806 char* devName;
807 unsigned flags = 0;
808 int err = NO_ERROR;
809
Ajay Dudani86c852b2012-07-19 15:28:45 -0700810#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700811 ALOGD("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700812#endif
813
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 // ASoC multicomponent requires a valid path (frontend/backend) for
815 // the device to be opened
816
817 flags = PCM_OUT | PCM_MONO;
818 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700819 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700820 return NO_INIT;
821 }
822 if (devName != NULL) {
823 handle->handle = pcm_open(flags, (char*)devName);
824 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700825 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700826 return NO_INIT;
827 }
828 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700829 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700830 goto Error;
831 }
832
833 handle->handle->flags = flags;
834 err = setHardwareParams(handle);
835 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700836 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700837 goto Error;
838 }
839
840 err = setSoftwareParams(handle);
841 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700842 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700843 goto Error;
844 }
845
846 err = pcm_prepare(handle->handle);
847 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700848 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700849 goto Error;
850 }
851
852 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700853 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700854 goto Error;
855 }
856
857 // Store the PCM playback device pointer in rxHandle
858 handle->rxHandle = handle->handle;
859 free(devName);
860
861 // Open PCM capture device
862 flags = PCM_IN | PCM_MONO;
863 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700864 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700865 goto Error;
866 }
867 if (devName != NULL) {
868 handle->handle = pcm_open(flags, (char*)devName);
869 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700870 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700871 return NO_INIT;
872 }
873 if (!handle->handle) {
874 free(devName);
875 goto Error;
876 }
877
878 handle->handle->flags = flags;
879 err = setHardwareParams(handle);
880 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700881 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700882 goto Error;
883 }
884
885 err = setSoftwareParams(handle);
886 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700887 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700888 goto Error;
889 }
890
891 err = pcm_prepare(handle->handle);
892 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700893 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700894 goto Error;
895 }
896
897 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700898 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700899 goto Error;
900 }
901
902 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700903#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700904 if (csd_start_voice == NULL) {
905 ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
906 } else {
907 err = csd_start_voice();
908 if (err < 0){
909 ALOGE("s_start_voice_call: csd_client error %d\n", err);
910 goto Error;
911 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700912 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700913#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700914 }
915
916 free(devName);
917 return NO_ERROR;
918
919Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700920 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700921 free(devName);
922 s_close(handle);
923 return NO_INIT;
924}
925
926static status_t s_start_fm(alsa_handle_t *handle)
927{
928 char *devName;
929 unsigned flags = 0;
930 int err = NO_ERROR;
931
SathishKumar Mani0a019912012-09-11 12:33:11 -0700932 ALOGD("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700933
934 // ASoC multicomponent requires a valid path (frontend/backend) for
935 // the device to be opened
936
937 flags = PCM_OUT | PCM_STEREO;
938 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700939 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700940 goto Error;
941 }
942 if (devName != NULL) {
943 handle->handle = pcm_open(flags, (char*)devName);
944 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700945 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700946 return NO_INIT;
947 }
948 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700949 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700950 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: setSoftwareParams 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 // Store the PCM playback device pointer in rxHandle
978 handle->rxHandle = handle->handle;
979 free(devName);
980
981 // Open PCM capture device
982 flags = PCM_IN | PCM_STEREO;
983 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700984 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700985 goto Error;
986 }
987 if (devName != NULL) {
988 handle->handle = pcm_open(flags, (char*)devName);
989 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700990 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700991 return NO_INIT;
992 }
993 if (!handle->handle) {
994 goto Error;
995 }
996
997 handle->handle->flags = flags;
998 err = setHardwareParams(handle);
999 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001000 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001001 goto Error;
1002 }
1003
1004 err = setSoftwareParams(handle);
1005 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001006 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001007 goto Error;
1008 }
1009
1010 err = pcm_prepare(handle->handle);
1011 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001012 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001013 goto Error;
1014 }
1015
1016 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001017 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001018 goto Error;
1019 }
1020
1021 s_set_fm_vol(fmVolume);
1022 free(devName);
1023 return NO_ERROR;
1024
1025Error:
1026 free(devName);
1027 s_close(handle);
1028 return NO_INIT;
1029}
1030
1031static status_t s_set_fm_vol(int value)
1032{
1033 status_t err = NO_ERROR;
1034
1035 ALSAControl control("/dev/snd/controlC0");
1036 control.set("Internal FM RX Volume",value,0);
1037 fmVolume = value;
1038
1039 return err;
1040}
1041
1042static status_t s_set_lpa_vol(int value)
1043{
1044 status_t err = NO_ERROR;
1045
1046 ALSAControl control("/dev/snd/controlC0");
1047 control.set("LPA RX Volume",value,0);
1048
1049 return err;
1050}
1051
1052static status_t s_start(alsa_handle_t *handle)
1053{
1054 status_t err = NO_ERROR;
1055
1056 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001057 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001058 return err;
1059 }
1060
1061 err = pcm_prepare(handle->handle);
1062
1063 return err;
1064}
1065
1066static status_t s_close(alsa_handle_t *handle)
1067{
1068 int ret;
1069 status_t err = NO_ERROR;
1070 struct pcm *h = handle->rxHandle;
1071
1072 handle->rxHandle = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001073#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001074 ALOGD("s_close: handle %p h %p", handle, h);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001075#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001076 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001077 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001078 err = pcm_close(h);
1079 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001080 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001081 }
1082 }
1083
1084 h = handle->handle;
1085 handle->handle = 0;
1086
1087 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001088 ALOGV("s_close handle h %p\n", h);
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_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001092 }
1093
1094 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1095 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1096 platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001097#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001098 if (csd_stop_voice == NULL) {
1099 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
1100 } else {
1101 err = csd_stop_voice();
1102 if (err < 0) {
1103 ALOGE("s_close: csd_client error %d\n", err);
1104 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001105 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001106#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001107 }
1108
1109 disableDevice(handle);
1110 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1111 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1112 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1113 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1114 disableDevice(handle);
1115 }
1116
1117 return err;
1118}
1119
1120/*
1121 this is same as s_close, but don't discard
1122 the device/mode info. This way we can still
1123 close the device, hit idle and power-save, reopen the pcm
1124 for the same device/mode after resuming
1125*/
1126static status_t s_standby(alsa_handle_t *handle)
1127{
1128 int ret;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001129 status_t err = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001130 struct pcm *h = handle->rxHandle;
1131 handle->rxHandle = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001132#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001133 ALOGD("s_standby: handle %p h %p", handle, h);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001134#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001135 if (h) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001136 ALOGD("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001137 err = pcm_close(h);
1138 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001139 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001140 }
1141 }
1142
1143 h = handle->handle;
1144 handle->handle = 0;
1145
1146 if (h) {
Ajay Dudani86c852b2012-07-19 15:28:45 -07001147#if LOCAL_LOGD
1148 ALOGD("s_standby handle h %p\n", h);
1149#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001150 err = pcm_close(h);
1151 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001152 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001153 }
1154 disableDevice(handle);
1155 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1156 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1157 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1158 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1159 disableDevice(handle);
1160 }
1161
1162 return err;
1163}
1164
1165static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1166{
1167 status_t status = NO_ERROR;
1168
Ajay Dudani86c852b2012-07-19 15:28:45 -07001169#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001170 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001171#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001172 callMode = mode;
1173 switchDevice(handle, devices, mode);
1174 return status;
1175}
1176
1177int getUseCaseType(const char *useCase)
1178{
SathishKumar Mani0a019912012-09-11 12:33:11 -07001179 ALOGD("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001180 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
1181 strlen(SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001182 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
1183 strlen(SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001184 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
1185 strlen(SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1186 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
1187 strlen(SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1188 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
1189 strlen(SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1190 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
1191 strlen(SND_USE_CASE_MOD_PLAY_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001192 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
1193 strlen(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001194 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
1195 strlen(SND_USE_CASE_MOD_PLAY_LPA)) ||
1196 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
1197 strlen(SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
1198 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
1199 strlen(SND_USE_CASE_MOD_PLAY_FM))) {
1200 return USECASE_TYPE_RX;
1201 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
1202 strlen(SND_USE_CASE_VERB_HIFI_REC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001203 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
1204 strlen(SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001205 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
1206 strlen(SND_USE_CASE_VERB_FM_REC)) ||
1207 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
1208 strlen(SND_USE_CASE_VERB_FM_A2DP_REC)) ||
1209 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
1210 strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001211 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
1212 strlen(SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001213 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
1214 strlen(SND_USE_CASE_MOD_CAPTURE_FM)) ||
1215 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
1216 strlen(SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
1217 return USECASE_TYPE_TX;
1218 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
1219 strlen(SND_USE_CASE_VERB_VOICECALL)) ||
1220 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
1221 strlen(SND_USE_CASE_VERB_IP_VOICECALL)) ||
1222 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
1223 strlen(SND_USE_CASE_VERB_DL_REC)) ||
1224 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
1225 strlen(SND_USE_CASE_VERB_UL_DL_REC)) ||
1226 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1227 strlen(SND_USE_CASE_MOD_PLAY_VOICE)) ||
1228 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
1229 strlen(SND_USE_CASE_MOD_PLAY_VOIP)) ||
1230 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1231 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
1232 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1233 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
1234 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1235 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
1236 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
1237 strlen(SND_USE_CASE_VERB_VOLTE)) ||
1238 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1239 strlen(SND_USE_CASE_MOD_PLAY_VOLTE))) {
1240 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1241 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001242 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001243 return 0;
1244 }
1245}
1246
1247static void disableDevice(alsa_handle_t *handle)
1248{
1249 unsigned usecase_type = 0;
1250 int i, mods_size;
1251 char *useCase;
1252 const char **mods_list;
1253
1254 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1255 if (useCase != NULL) {
1256 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1257 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1258 } else {
1259 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1260 }
1261 free(useCase);
1262 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1263 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1264 strlen(SND_USE_CASE_VERB_INACTIVE)))
1265 usecase_type |= getUseCaseType(useCase);
1266 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001267#if LOCAL_LOGD
1268 ALOGD("Number of modifiers %d\n", mods_size);
1269#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001270 if (mods_size) {
1271 for(i = 0; i < mods_size; i++) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -07001272#if LOCAL_LOGD
1273 ALOGD("index %d modifier %s\n", i, mods_list[i]);
1274#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001275 usecase_type |= getUseCaseType(mods_list[i]);
1276 }
1277 }
Ajay Dudani86c852b2012-07-19 15:28:45 -07001278#if LOCAL_LOGD
1279 ALOGD("usecase_type is %d\n", usecase_type);
1280#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001281 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1282 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1283 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1284 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1285 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001286 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001287 }
1288 free(useCase);
1289}
1290
1291char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1292{
1293 if (!input) {
1294 if (!(mDevSettingsFlag & TTY_OFF) &&
1295 (callMode == AudioSystem::MODE_IN_CALL) &&
1296 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
ty.lee924f7982012-08-01 23:15:30 +09001297 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001298#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001299 ||
1300 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1301 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1302#endif
1303 if (mDevSettingsFlag & TTY_VCO) {
1304 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1305 } else if (mDevSettingsFlag & TTY_FULL) {
1306 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1307 } else if (mDevSettingsFlag & TTY_HCO) {
1308 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1309 }
1310 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1311 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1312 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1313 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1314 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1315 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1316 if (mDevSettingsFlag & ANC_FLAG) {
1317 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1318 } else {
1319 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1320 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001321#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001322 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1323 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1324 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1325 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1326 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1327 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1328 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1329#endif
1330 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
1331 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
1332 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
1333 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1334 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1335 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1336 if (mDevSettingsFlag & ANC_FLAG) {
1337 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1338 } else {
1339 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
1340 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001341#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001342 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1343 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
1344 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1345#endif
1346 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1347 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1348 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1349 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1350 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1351 else
1352 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1353 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1354 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001355#ifdef QCOM_VOIP_ENABLED
1356 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1357#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001358 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1359 /* Nothing to be done, use current active device */
1360 if (strncmp(curRxUCMDevice, "None", 4)) {
1361 return strdup(curRxUCMDevice);
1362 }
1363 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1364 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001365#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1367 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001368#endif
1369#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001370 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1371 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1372#endif
1373 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
1374 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1375 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001376 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001377 }
1378 } else {
1379 if (!(mDevSettingsFlag & TTY_OFF) &&
1380 (callMode == AudioSystem::MODE_IN_CALL) &&
ty.lee924f7982012-08-01 23:15:30 +09001381 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001382#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001383 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1384#endif
1385 if (mDevSettingsFlag & TTY_HCO) {
1386 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1387 } else if (mDevSettingsFlag & TTY_FULL) {
1388 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1389 } else if (mDevSettingsFlag & TTY_VCO) {
1390 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001391 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001392 } else {
1393 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1394 }
1395 }
1396 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1397 if (!strncmp(mic_type, "analog", 6)) {
1398 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1399 } else {
1400 if (mDevSettingsFlag & DMIC_FLAG) {
ty.lee924f7982012-08-01 23:15:30 +09001401#ifdef USES_FLUENCE_INCALL
1402 if(callMode == AudioSystem::MODE_IN_CALL) {
1403 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1404 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1405 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1406 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1407 } else {
1408 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
1409 }
1410 }
1411#else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001412 if (((rxDevice != NULL) &&
1413 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1414 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1415 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1416 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1417 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1418 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1419 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1420 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1421 }
1422 } else {
1423 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1424 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1425 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1426 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1427 }
1428 }
ty.lee924f7982012-08-01 23:15:30 +09001429#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001430 } else if (mDevSettingsFlag & QMIC_FLAG){
1431 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
ty.lee924f7982012-08-01 23:15:30 +09001432 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001433#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001434 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001435 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001436 // Mapping for quad mic input device.
1437 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
ty.lee924f7982012-08-01 23:15:30 +09001438 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001439#endif
ty.lee74060de2012-08-02 00:47:00 +09001440#ifdef SEPERATED_AUDIO_INPUT
1441 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
1442 ALOGV("getUCMdevice returned the VOICE_RECOGNITION UCM by input source = %d", input_source);
1443 return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
1444 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
1445 ALOGV("getUCMdevice returned the Camcorder Tx UCM by input source = %d", input_source);
1446 return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
1447 }
1448#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001449 else {
ty.lee74060de2012-08-02 00:47:00 +09001450 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001451 }
1452 }
1453 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1454 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001455#ifdef QCOM_ANC_HEADSET_ENABLED
ehgrace.kim249f87d2012-08-12 20:40:32 -07001456 } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001457 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1458#endif
ehgrace.kim249f87d2012-08-12 20:40:32 -07001459 } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1460 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001461 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1462 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1463 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1464 else
1465 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001466#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001467 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1468 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1469 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1470#endif
1471 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1472 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1473 /* Nothing to be done, use current active device */
1474 if (strncmp(curTxUCMDevice, "None", 4)) {
1475 return strdup(curTxUCMDevice);
1476 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001477#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001478 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1479 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1480 /* Nothing to be done, use current tx device or set dummy device */
1481 if (strncmp(curTxUCMDevice, "None", 4)) {
1482 return strdup(curTxUCMDevice);
1483 } else {
1484 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1485 }
1486#endif
1487 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1488 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001489 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001490 if (!strncmp(mic_type, "analog", 6)) {
1491 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1492 } else {
1493 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
1494 }
1495 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001496 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001497 }
1498 }
1499 return NULL;
1500}
1501
1502void s_set_voice_volume(int vol)
1503{
1504 int err = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001505#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001506 ALOGD("s_set_voice_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001507#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001508 ALSAControl control("/dev/snd/controlC0");
1509 control.set("Voice Rx Volume", vol, 0);
1510
1511 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001512#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001513 if (csd_volume == NULL) {
1514 ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
1515 } else {
1516 err = csd_volume(vol);
1517 if (err < 0) {
1518 ALOGE("s_set_voice_volume: csd_client error %d", err);
1519 }
SathishKumar Manie42406e2012-08-29 16:25:54 -07001520 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001521#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001522 }
1523}
1524
1525void s_set_volte_volume(int vol)
1526{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001527#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001528 ALOGD("s_set_volte_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001529#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001530 ALSAControl control("/dev/snd/controlC0");
1531 control.set("VoLTE Rx Volume", vol, 0);
1532}
1533
1534
1535void s_set_voip_volume(int vol)
1536{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001537#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001538 ALOGD("s_set_voip_volume: volume %d", vol);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001539#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001540 ALSAControl control("/dev/snd/controlC0");
1541 control.set("Voip Rx Volume", vol, 0);
1542}
1543void s_set_mic_mute(int state)
1544{
1545 int err = 0;
Ajay Dudani86c852b2012-07-19 15:28:45 -07001546#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001547 ALOGD("s_set_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001548#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001549 ALSAControl control("/dev/snd/controlC0");
1550 control.set("Voice Tx Mute", state, 0);
1551
1552 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001553#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001554 if (csd_mic_mute == NULL) {
1555 ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
1556 } else {
1557 err=csd_mic_mute(state);
1558 if (err < 0) {
1559 ALOGE("s_set_mic_mute: csd_client error %d", err);
1560 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001561 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001562#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001563 }
1564}
1565void s_set_volte_mic_mute(int state)
1566{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001567#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001568 ALOGD("s_set_volte_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001569#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001570 ALSAControl control("/dev/snd/controlC0");
1571 control.set("VoLTE Tx Mute", state, 0);
1572}
1573
1574void s_set_voip_mic_mute(int state)
1575{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001576#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001577 ALOGD("s_set_voip_mic_mute: state %d", state);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001578#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001579 ALSAControl control("/dev/snd/controlC0");
1580 control.set("Voip Tx Mute", state, 0);
1581}
1582
1583void s_set_voip_config(int mode, int rate)
1584{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001585#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001586 ALOGD("s_set_voip_config: mode %d,rate %d", mode, rate);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001587#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001588 ALSAControl control("/dev/snd/controlC0");
1589 char** setValues;
1590 setValues = (char**)malloc(2*sizeof(char*));
1591 if (setValues == NULL) {
1592 return;
1593 }
1594 setValues[0] = (char*)malloc(4*sizeof(char));
1595 if (setValues[0] == NULL) {
1596 free(setValues);
1597 return;
1598 }
1599
1600 setValues[1] = (char*)malloc(8*sizeof(char));
1601 if (setValues[1] == NULL) {
1602 free(setValues);
1603 free(setValues[0]);
1604 return;
1605 }
1606
1607 sprintf(setValues[0], "%d",mode);
1608 sprintf(setValues[1], "%d",rate);
1609
1610 control.setext("Voip Mode Rate Config", 2, setValues);
1611 free(setValues[1]);
1612 free(setValues[0]);
1613 free(setValues);
1614 return;
1615}
1616
1617void s_set_btsco_rate(int rate)
1618{
1619 btsco_samplerate = rate;
1620}
1621
1622void s_enable_wide_voice(bool flag)
1623{
1624 int err = 0;
1625
Ajay Dudani86c852b2012-07-19 15:28:45 -07001626#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001627 ALOGD("s_enable_wide_voice: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001628#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001629 ALSAControl control("/dev/snd/controlC0");
1630 if(flag == true) {
1631 control.set("Widevoice Enable", 1, 0);
1632 } else {
1633 control.set("Widevoice Enable", 0, 0);
1634 }
1635
1636 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001637#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001638 if (csd_wide_voice == NULL) {
1639 ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
1640 } else {
1641 err = csd_wide_voice(flag);
1642 if (err < 0) {
1643 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
1644 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001645 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001646#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001647 }
1648}
1649
1650void s_set_voc_rec_mode(uint8_t mode)
1651{
Ajay Dudani86c852b2012-07-19 15:28:45 -07001652#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001653 ALOGD("s_set_voc_rec_mode: mode %d", mode);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001654#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001655 ALSAControl control("/dev/snd/controlC0");
1656 control.set("Incall Rec Mode", mode, 0);
1657}
1658
1659void s_enable_fens(bool flag)
1660{
1661 int err = 0;
1662
Ajay Dudani86c852b2012-07-19 15:28:45 -07001663#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001664 ALOGD("s_enable_fens: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001665#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001666 ALSAControl control("/dev/snd/controlC0");
1667 if(flag == true) {
1668 control.set("FENS Enable", 1, 0);
1669 } else {
1670 control.set("FENS Enable", 0, 0);
1671 }
1672
1673 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001674#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001675 if (csd_fens == NULL) {
1676 ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
1677 } else {
1678 err = csd_fens(flag);
1679 if (err < 0) {
1680 ALOGE("s_enable_fens: csd_client error %d", err);
1681 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001682 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001683#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001684 }
1685}
1686
1687void s_enable_slow_talk(bool flag)
1688{
1689 int err = 0;
1690
Ajay Dudani86c852b2012-07-19 15:28:45 -07001691#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -07001692 ALOGD("s_enable_slow_talk: flag %d", flag);
Ajay Dudani86c852b2012-07-19 15:28:45 -07001693#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001694 ALSAControl control("/dev/snd/controlC0");
1695 if(flag == true) {
1696 control.set("Slowtalk Enable", 1, 0);
1697 } else {
1698 control.set("Slowtalk Enable", 0, 0);
1699 }
1700
1701 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001702#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001703 if (csd_slow_talk == NULL) {
1704 ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
1705 } else {
1706 err = csd_slow_talk(flag);
1707 if (err < 0) {
1708 ALOGE("s_enable_slow_talk: csd_client error %d", err);
1709 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001710 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001711#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001712 }
1713}
1714
1715void s_set_flags(uint32_t flags)
1716{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001717 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001718 mDevSettingsFlag = flags;
1719}
1720
1721static status_t s_set_compressed_vol(int value)
1722{
1723 status_t err = NO_ERROR;
1724
1725 ALSAControl control("/dev/snd/controlC0");
1726 control.set("COMPRESSED RX Volume",value,0);
1727
1728 return err;
1729}
1730
ty.lee74060de2012-08-02 00:47:00 +09001731#ifdef SEPERATED_AUDIO_INPUT
1732void s_setInput(int input)
1733{
1734 input_source = input;
1735 ALOGD("s_setInput() : input_source = %d",input_source);
1736}
1737#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001738
1739#ifdef QCOM_CSDCLIENT_ENABLED
1740static void s_set_csd_handle(void* handle)
1741{
1742 csd_handle = static_cast<void*>(handle);
1743 ALOGI("%s csd_handle: %p", __func__, csd_handle);
1744
1745 csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
1746 csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
1747 csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
1748 csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
1749 csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
1750 csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
1751 csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
1752 csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
1753 csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
1754}
1755#endif
1756
Iliyan Malchev4765c432012-06-11 14:36:16 -07001757}