blob: c285e1e0ea8ab54e45362c5bd09f3d79f2d7409a [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" {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070030static int (*csd_disable_device)();
31static int (*csd_enable_device)(int, int, uint32_t);
32static int (*csd_volume)(int);
33static int (*csd_mic_mute)(int);
34static int (*csd_wide_voice)(uint8_t);
35static int (*csd_slow_talk)(uint8_t);
36static int (*csd_fens)(uint8_t);
37static int (*csd_start_voice)();
38static int (*csd_stop_voice)();
Iliyan Malchev4765c432012-06-11 14:36:16 -070039}
Iliyan Malchev4113f342012-06-11 14:39:47 -070040#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070041
42#ifndef ALSA_DEFAULT_SAMPLE_RATE
43#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
44#endif
45
46#define BTSCO_RATE_16KHZ 16000
47#define USECASE_TYPE_RX 1
48#define USECASE_TYPE_TX 2
49
50namespace android_audio_legacy
51{
52
53static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
54static int s_device_close(hw_device_t*);
55static status_t s_init(alsa_device_t *, ALSAHandleList &);
56static status_t s_open(alsa_handle_t *);
57static status_t s_close(alsa_handle_t *);
58static status_t s_standby(alsa_handle_t *);
59static status_t s_route(alsa_handle_t *, uint32_t, int);
60static status_t s_start_voice_call(alsa_handle_t *);
61static status_t s_start_voip_call(alsa_handle_t *);
62static status_t s_start_fm(alsa_handle_t *);
63static void s_set_voice_volume(int);
64static void s_set_voip_volume(int);
65static void s_set_mic_mute(int);
66static void s_set_voip_mic_mute(int);
67static void s_set_voip_config(int, int);
68static status_t s_set_fm_vol(int);
69static void s_set_btsco_rate(int);
70static status_t s_set_lpa_vol(int);
71static void s_enable_wide_voice(bool flag);
72static void s_enable_fens(bool flag);
73static void s_set_flags(uint32_t flags);
74static status_t s_set_compressed_vol(int);
75static void s_enable_slow_talk(bool flag);
76static void s_set_voc_rec_mode(uint8_t mode);
77static void s_set_volte_mic_mute(int state);
78static void s_set_volte_volume(int vol);
ty.lee74060de2012-08-02 00:47:00 +090079#ifdef SEPERATED_AUDIO_INPUT
80static void s_setInput(int);
81
82static int input_source;
83#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070084#ifdef QCOM_CSDCLIENT_ENABLED
85static void s_set_csd_handle(void*);
86#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070087
88static char mic_type[25];
89static char curRxUCMDevice[50];
90static char curTxUCMDevice[50];
91static int fluence_mode;
92static int fmVolume;
ty.lee924f7982012-08-01 23:15:30 +090093#ifdef USES_FLUENCE_INCALL
94static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG;
95#else
Iliyan Malchev4765c432012-06-11 14:36:16 -070096static uint32_t mDevSettingsFlag = TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +090097#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070098static int btsco_samplerate = 8000;
99static bool pflag = false;
100static ALSAUseCaseList mUseCaseList;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700101static void *csd_handle;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700102
103static hw_module_methods_t s_module_methods = {
104 open : s_device_open
105};
106
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700107extern "C" {
108hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700109 tag : HARDWARE_MODULE_TAG,
110 version_major : 1,
111 version_minor : 0,
112 id : ALSA_HARDWARE_MODULE_ID,
113 name : "QCOM ALSA module",
114 author : "QuIC Inc",
115 methods : &s_module_methods,
116 dso : 0,
117 reserved : {0,},
118};
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700119}
Iliyan Malchev4765c432012-06-11 14:36:16 -0700120
121static int s_device_open(const hw_module_t* module, const char* name,
122 hw_device_t** device)
123{
124 char value[128];
125 alsa_device_t *dev;
126 dev = (alsa_device_t *) malloc(sizeof(*dev));
127 if (!dev) return -ENOMEM;
128
129 memset(dev, 0, sizeof(*dev));
130
131 /* initialize the procs */
132 dev->common.tag = HARDWARE_DEVICE_TAG;
133 dev->common.version = 0;
134 dev->common.module = (hw_module_t *) module;
135 dev->common.close = s_device_close;
136 dev->init = s_init;
137 dev->open = s_open;
138 dev->close = s_close;
139 dev->route = s_route;
140 dev->standby = s_standby;
141 dev->startVoiceCall = s_start_voice_call;
142 dev->startVoipCall = s_start_voip_call;
143 dev->startFm = s_start_fm;
144 dev->setVoiceVolume = s_set_voice_volume;
145 dev->setVoipVolume = s_set_voip_volume;
146 dev->setMicMute = s_set_mic_mute;
147 dev->setVoipMicMute = s_set_voip_mic_mute;
148 dev->setVoipConfig = s_set_voip_config;
149 dev->setFmVolume = s_set_fm_vol;
150 dev->setBtscoRate = s_set_btsco_rate;
151 dev->setLpaVolume = s_set_lpa_vol;
152 dev->enableWideVoice = s_enable_wide_voice;
153 dev->enableFENS = s_enable_fens;
154 dev->setFlags = s_set_flags;
155 dev->setCompressedVolume = s_set_compressed_vol;
156 dev->enableSlowTalk = s_enable_slow_talk;
157 dev->setVocRecMode = s_set_voc_rec_mode;
158 dev->setVoLTEMicMute = s_set_volte_mic_mute;
159 dev->setVoLTEVolume = s_set_volte_volume;
ty.lee74060de2012-08-02 00:47:00 +0900160#ifdef SEPERATED_AUDIO_INPUT
161 dev->setInput = s_setInput;
162#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700163#ifdef QCOM_CSDCLIENT_ENABLED
164 dev->setCsdHandle = s_set_csd_handle;
165#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700166 *device = &dev->common;
167
168 property_get("persist.audio.handset.mic",value,"0");
169 strlcpy(mic_type, value, sizeof(mic_type));
170 property_get("persist.audio.fluence.mode",value,"0");
171 if (!strcmp("broadside", value)) {
172 fluence_mode = FLUENCE_MODE_BROADSIDE;
173 } else {
174 fluence_mode = FLUENCE_MODE_ENDFIRE;
175 }
176 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
177 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
SathishKumar Mani9efed762012-09-18 18:52:48 -0700178 ALOGV("ALSA module opened");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700179
180 return 0;
181}
182
183static int s_device_close(hw_device_t* device)
184{
185 free(device);
186 device = NULL;
187 return 0;
188}
189
190// ----------------------------------------------------------------------------
191
192static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
193
194static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
195static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
196static void disableDevice(alsa_handle_t *handle);
197int getUseCaseType(const char *useCase);
198
199static int callMode = AudioSystem::MODE_NORMAL;
200// ----------------------------------------------------------------------------
201
202bool platform_is_Fusion3()
203{
204 char platform[128], baseband[128];
205 property_get("ro.board.platform", platform, "");
206 property_get("ro.baseband", baseband, "");
207 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
208 return true;
209 else
210 return false;
211}
212
213int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
214{
215 int ret = 0;
216 char ident[70];
217
218 if (flags & PCM_IN) {
219 strlcpy(ident, "CapturePCM/", sizeof(ident));
220 } else {
221 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
222 }
223 strlcat(ident, handle->useCase, sizeof(ident));
224 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700225 ALOGD("Device value returned is %s", (*value));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700226 return ret;
227}
228
229status_t setHardwareParams(alsa_handle_t *handle)
230{
231 struct snd_pcm_hw_params *params;
232 unsigned long bufferSize, reqBuffSize;
233 unsigned int periodTime, bufferTime;
234 unsigned int requestedRate = handle->sampleRate;
235 int status = 0;
236 int channels = handle->channels;
237 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
238
239 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
240 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700241 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700242 return NO_INIT;
243 }
244
245 reqBuffSize = handle->bufferSize;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700246 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247 (int) reqBuffSize, handle->channels, handle->sampleRate);
248
Ajay Dudani9746c472012-06-18 16:01:16 -0700249#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700250 if (channels == 6) {
251 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
252 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700253 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700254 channels = 4;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700255 }
256 }
257#endif
258
259 param_init(params);
260 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
261 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
262 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700263 if (handle->format == AudioSystem::AMR_NB
264 || handle->format == AudioSystem::AMR_WB
265#ifdef QCOM_QCHAT_ENABLED
266 || handle->format == AudioSystem::EVRC
267 || handle->format == AudioSystem::EVRCB
268 || handle->format == AudioSystem::EVRCWB
269#endif
270 )
Iliyan Malchev4765c432012-06-11 14:36:16 -0700271 format = SNDRV_PCM_FORMAT_SPECIAL;
272 }
273 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
274 format);
275 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
276 SNDRV_PCM_SUBFORMAT_STD);
SathishKumar Mani77780382012-09-21 20:58:33 -0700277 param_set_int(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700278 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
279 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
280 channels * 16);
281 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
282 channels);
283 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
284 param_set_hw_refine(handle->handle, params);
285
286 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700287 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700288 return NO_INIT;
289 }
290 param_dump(params);
291
292 handle->handle->buffer_size = pcm_buffer_size(params);
293 handle->handle->period_size = pcm_period_size(params);
294 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700295 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700296 handle->handle->buffer_size, handle->handle->period_size,
297 handle->handle->period_cnt);
298 handle->handle->rate = handle->sampleRate;
299 handle->handle->channels = handle->channels;
300 handle->periodSize = handle->handle->period_size;
301 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
302 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
303 (6 != handle->channels)) {
304 //Do not update buffersize for 5.1 recording
305 handle->bufferSize = handle->handle->period_size;
306 }
307
308 return NO_ERROR;
309}
310
311status_t setSoftwareParams(alsa_handle_t *handle)
312{
313 struct snd_pcm_sw_params* params;
314 struct pcm* pcm = handle->handle;
315
316 unsigned long periodSize = pcm->period_size;
317 int channels = handle->channels;
318
319 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
320 if (!params) {
321 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
322 return NO_INIT;
323 }
324
Ajay Dudani9746c472012-06-18 16:01:16 -0700325#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700326 if (channels == 6) {
327 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
328 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700329 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700330 channels = 4;
331 }
332 }
333#endif
334
335 // Get the current software parameters
336 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
337 params->period_step = 1;
338 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
339 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700340 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700341 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
342 params->start_threshold = periodSize/2;
343 params->stop_threshold = INT_MAX;
344 } else {
345 params->avail_min = periodSize/2;
346 params->start_threshold = channels * (periodSize/4);
347 params->stop_threshold = INT_MAX;
348 }
349 params->silence_threshold = 0;
350 params->silence_size = 0;
351
352 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700353 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700354 return NO_INIT;
355 }
356 return NO_ERROR;
357}
358
359void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
360{
361 const char **mods_list;
362 use_case_t useCaseNode;
363 unsigned usecase_type = 0;
364 bool inCallDevSwitch = false;
365 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
366 int err = 0, index, mods_size;
367 int rx_dev_id, tx_dev_id;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700368 ALOGD("%s: device %d mode:%d", __FUNCTION__, devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700369
370 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
371 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
372 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
373 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
374 AudioSystem::DEVICE_IN_WIRED_HEADSET);
375 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
376 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
377 AudioSystem::DEVICE_IN_BUILTIN_MIC);
SathishKumar Manic669c272012-09-21 20:12:08 -0700378 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
379 if (mode == AudioSystem::MODE_IN_CALL) {
380 devices |= AudioSystem::DEVICE_OUT_EARPIECE;
381 }
382 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
383 devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700384 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900385 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700386 AudioSystem::DEVICE_OUT_SPEAKER);
387 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
388 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
389 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
390 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
391 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700392#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700393 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
394 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
395 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
396 AudioSystem::DEVICE_IN_ANC_HEADSET);
397 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
398 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
399 AudioSystem::DEVICE_IN_BUILTIN_MIC);
400#endif
401 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
402 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
403 AudioSystem::DEVICE_IN_AUX_DIGITAL);
Ajay Dudani9746c472012-06-18 16:01:16 -0700404#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700405 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
406 (devices & AudioSystem::DEVICE_IN_PROXY)) {
407 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
408 AudioSystem::DEVICE_IN_PROXY);
409#endif
410 }
411 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700412#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700413 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
414 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
415 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700416 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700417 s_set_flags(SSRQMIC_FLAG);
418 }
419 }
420#endif
421
422 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
423 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
424
Iliyan Malchev4765c432012-06-11 14:36:16 -0700425 if ((rxDevice != NULL) && (txDevice != NULL)) {
426 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
SathishKumar Manic669c272012-09-21 20:12:08 -0700427 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
428 ((mode == AudioSystem::MODE_IN_CALL) ||
429 (mode == AudioSystem::MODE_IN_COMMUNICATION)))
Iliyan Malchev4765c432012-06-11 14:36:16 -0700430 inCallDevSwitch = true;
431 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700432
433#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Manic669c272012-09-21 20:12:08 -0700434 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700435 if (csd_disable_device == NULL) {
436 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
437 } else {
438 err = csd_disable_device();
439 if (err < 0)
440 {
441 ALOGE("csd_client_disable_device, failed, error %d", err);
442 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700443 }
444 }
445#endif
446
Iliyan Malchev4765c432012-06-11 14:36:16 -0700447 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
448 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
449 if (rxDevice != NULL) {
450 if ((strncmp(curRxUCMDevice, "None", 4)) &&
451 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
452 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
453 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
454 usecase_type = getUseCaseType(use_case);
455 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700456 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700457 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
458 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
459 mUseCaseList.push_front(useCaseNode);
460 }
461 }
462 if (mods_size) {
463 for(index = 0; index < mods_size; index++) {
464 usecase_type = getUseCaseType(mods_list[index]);
465 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700466 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700467 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
468 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
469 mUseCaseList.push_back(useCaseNode);
470 }
471 }
472 }
473 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
474 }
475 }
476 if (txDevice != NULL) {
477 if ((strncmp(curTxUCMDevice, "None", 4)) &&
478 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
479 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
480 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
481 usecase_type = getUseCaseType(use_case);
482 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700483 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700484 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
485 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
486 mUseCaseList.push_front(useCaseNode);
487 }
488 }
489 if (mods_size) {
490 for(index = 0; index < mods_size; index++) {
491 usecase_type = getUseCaseType(mods_list[index]);
492 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700493 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700494 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
495 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
496 mUseCaseList.push_back(useCaseNode);
497 }
498 }
499 }
500 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
501 }
502 }
SathishKumar Mani9efed762012-09-18 18:52:48 -0700503 ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700504
505 if (rxDevice != NULL) {
506 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
507 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700508#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700509 if (devices & AudioSystem::DEVICE_OUT_FM)
510 s_set_fm_vol(fmVolume);
511#endif
512 }
513 if (txDevice != NULL) {
514 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
515 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
516 }
517 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700518 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700519 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
520 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
521 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
522 } else {
523 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
524 }
525 }
526 if (!mUseCaseList.empty())
527 mUseCaseList.clear();
528 if (use_case != NULL) {
529 free(use_case);
530 use_case = NULL;
531 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700532 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700533
SathishKumar Manic669c272012-09-21 20:12:08 -0700534 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700535 /* get tx acdb id */
536 memset(&ident,0,sizeof(ident));
537 strlcpy(ident, "ACDBID/", sizeof(ident));
538 strlcat(ident, curTxUCMDevice, sizeof(ident));
539 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
540
541 /* get rx acdb id */
542 memset(&ident,0,sizeof(ident));
543 strlcpy(ident, "ACDBID/", sizeof(ident));
544 strlcat(ident, curRxUCMDevice, sizeof(ident));
545 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
546
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700547 if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
548 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700549 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
550 }
551
Ajay Dudani9746c472012-06-18 16:01:16 -0700552#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700553 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700554 if (csd_enable_device == NULL) {
555 ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
556 } else {
557 err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
558 if (err < 0)
559 {
560 ALOGE("csd_client_disable_device failed, error %d", err);
561 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700562 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700563#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700564 }
565
566 if (rxDevice != NULL) {
567 if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
568 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
569 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
570 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
571 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
572 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
573 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
574 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
575 s_open(handle);
576 pflag = false;
577 }
578 }
579
580 if (rxDevice != NULL) {
581 free(rxDevice);
582 rxDevice = NULL;
583 }
584 if (txDevice != NULL) {
585 free(txDevice);
586 txDevice = NULL;
587 }
588}
589
590// ----------------------------------------------------------------------------
591
592static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
593{
SathishKumar Mani9efed762012-09-18 18:52:48 -0700594 ALOGV("s_init: Initializing devices for ALSA module");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700595
596 list.clear();
597
598 return NO_ERROR;
599}
600
601static status_t s_open(alsa_handle_t *handle)
602{
603 char *devName;
604 unsigned flags = 0;
605 int err = NO_ERROR;
606
607 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
608 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
609 ||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700610 ALOGV("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700611 return NO_ERROR;
612 }
613
614 s_close(handle);
615
SathishKumar Mani9efed762012-09-18 18:52:48 -0700616 ALOGV("s_open: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700617
618 // ASoC multicomponent requires a valid path (frontend/backend) for
619 // the device to be opened
620
621 // The PCM stream is opened in blocking mode, per ALSA defaults. The
622 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
623 // should not be used.
SathishKumar Mani88613382012-08-13 18:40:18 -0700624 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
625 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
626 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
627 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
628 ALOGV("LPA/tunnel use case");
629 flags |= PCM_MMAP;
630 flags |= DEBUG_ON;
631 } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
632 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
633 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700634 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
SathishKumar Mani88613382012-08-13 18:40:18 -0700635 ALOGV("Music case");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700636 flags = PCM_OUT;
637 } else {
638 flags = PCM_IN;
639 }
640 if (handle->channels == 1) {
641 flags |= PCM_MONO;
SathishKumar Manie42406e2012-08-29 16:25:54 -0700642 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700643#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700644 else if (handle->channels == 4 ) {
645 flags |= PCM_QUAD;
646 } else if (handle->channels == 6 ) {
647 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
648 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
649 flags |= PCM_QUAD;
650 } else {
651 flags |= PCM_5POINT1;
652 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700653 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700654#endif
655 else {
656 flags |= PCM_STEREO;
657 }
658 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700659 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660 return NO_INIT;
661 }
662 if (devName != NULL) {
663 handle->handle = pcm_open(flags, (char*)devName);
664 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700665 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700666 return NO_INIT;
667 }
668
669 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700670 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700671 free(devName);
672 return NO_INIT;
673 }
674
675 handle->handle->flags = flags;
676 err = setHardwareParams(handle);
677
678 if (err == NO_ERROR) {
679 err = setSoftwareParams(handle);
680 }
681
682 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700683 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700684 s_standby(handle);
685 }
686
687 free(devName);
688 return NO_ERROR;
689}
690
691static status_t s_start_voip_call(alsa_handle_t *handle)
692{
693
694 char* devName;
695 char* devName1;
696 unsigned flags = 0;
697 int err = NO_ERROR;
698 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
699
700 s_close(handle);
701 flags = PCM_OUT;
702 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700703 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700704
705 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700706 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700707 return NO_INIT;
708 }
709
710 if (devName != NULL) {
711 handle->handle = pcm_open(flags, (char*)devName);
712 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700713 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700714 return NO_INIT;
715 }
716
717 if (!handle->handle) {
718 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700719 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700720 return NO_INIT;
721 }
722
723 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700724 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700725 }
726
727 handle->handle->flags = flags;
728 err = setHardwareParams(handle);
729
730 if (err == NO_ERROR) {
731 err = setSoftwareParams(handle);
732 }
733
734 err = pcm_prepare(handle->handle);
735 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700736 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700737 }
738
739 /* first write required start dsp */
740 memset(&voc_pkt,0,sizeof(voc_pkt));
741 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
742 handle->rxHandle = handle->handle;
743 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700744 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700745 flags = PCM_IN;
746 flags |= PCM_MONO;
747 handle->handle = 0;
748
749 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700750 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700751 return NO_INIT;
752 }
753 if (devName != NULL) {
754 handle->handle = pcm_open(flags, (char*)devName1);
755 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700756 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700757 return NO_INIT;
758 }
759
760 if (!handle->handle) {
761 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700762 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700763 return NO_INIT;
764 }
765
766 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700767 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700768 }
769
770 handle->handle->flags = flags;
771
772 err = setHardwareParams(handle);
773
774 if (err == NO_ERROR) {
775 err = setSoftwareParams(handle);
776 }
777
778
779 err = pcm_prepare(handle->handle);
780 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700781 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700782 }
783
784 /* first read required start dsp */
785 memset(&voc_pkt,0,sizeof(voc_pkt));
786 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
787 return NO_ERROR;
788}
789
790static status_t s_start_voice_call(alsa_handle_t *handle)
791{
792 char* devName;
793 unsigned flags = 0;
794 int err = NO_ERROR;
795
SathishKumar Mani9efed762012-09-18 18:52:48 -0700796 ALOGV("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700797
Iliyan Malchev4765c432012-06-11 14:36:16 -0700798 // ASoC multicomponent requires a valid path (frontend/backend) for
799 // the device to be opened
800
801 flags = PCM_OUT | PCM_MONO;
802 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700803 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700804 return NO_INIT;
805 }
806 if (devName != NULL) {
807 handle->handle = pcm_open(flags, (char*)devName);
808 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700809 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700810 return NO_INIT;
811 }
812 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700813 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 goto Error;
815 }
816
817 handle->handle->flags = flags;
818 err = setHardwareParams(handle);
819 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700820 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700821 goto Error;
822 }
823
824 err = setSoftwareParams(handle);
825 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700826 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700827 goto Error;
828 }
829
830 err = pcm_prepare(handle->handle);
831 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700832 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700833 goto Error;
834 }
835
836 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700837 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700838 goto Error;
839 }
840
841 // Store the PCM playback device pointer in rxHandle
842 handle->rxHandle = handle->handle;
843 free(devName);
844
845 // Open PCM capture device
846 flags = PCM_IN | PCM_MONO;
847 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700848 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700849 goto Error;
850 }
851 if (devName != NULL) {
852 handle->handle = pcm_open(flags, (char*)devName);
853 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700854 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700855 return NO_INIT;
856 }
857 if (!handle->handle) {
858 free(devName);
859 goto Error;
860 }
861
862 handle->handle->flags = flags;
863 err = setHardwareParams(handle);
864 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700865 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700866 goto Error;
867 }
868
869 err = setSoftwareParams(handle);
870 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700871 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700872 goto Error;
873 }
874
875 err = pcm_prepare(handle->handle);
876 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700877 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700878 goto Error;
879 }
880
881 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700882 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700883 goto Error;
884 }
885
886 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700887#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700888 if (csd_start_voice == NULL) {
889 ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
890 } else {
891 err = csd_start_voice();
892 if (err < 0){
893 ALOGE("s_start_voice_call: csd_client error %d\n", err);
894 goto Error;
895 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700896 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700897#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700898 }
899
900 free(devName);
901 return NO_ERROR;
902
903Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700904 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700905 free(devName);
906 s_close(handle);
907 return NO_INIT;
908}
909
910static status_t s_start_fm(alsa_handle_t *handle)
911{
912 char *devName;
913 unsigned flags = 0;
914 int err = NO_ERROR;
915
SathishKumar Mani9efed762012-09-18 18:52:48 -0700916 ALOGV("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700917
918 // ASoC multicomponent requires a valid path (frontend/backend) for
919 // the device to be opened
920
921 flags = PCM_OUT | PCM_STEREO;
922 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700923 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700924 goto Error;
925 }
926 if (devName != NULL) {
927 handle->handle = pcm_open(flags, (char*)devName);
928 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700929 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700930 return NO_INIT;
931 }
932 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700933 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700934 goto Error;
935 }
936
937 handle->handle->flags = flags;
938 err = setHardwareParams(handle);
939 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700940 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700941 goto Error;
942 }
943
944 err = setSoftwareParams(handle);
945 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700946 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700947 goto Error;
948 }
949
950 err = pcm_prepare(handle->handle);
951 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700952 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700953 goto Error;
954 }
955
956 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700957 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700958 goto Error;
959 }
960
961 // Store the PCM playback device pointer in rxHandle
962 handle->rxHandle = handle->handle;
963 free(devName);
964
965 // Open PCM capture device
966 flags = PCM_IN | PCM_STEREO;
967 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700968 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700969 goto Error;
970 }
971 if (devName != NULL) {
972 handle->handle = pcm_open(flags, (char*)devName);
973 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700974 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700975 return NO_INIT;
976 }
977 if (!handle->handle) {
978 goto Error;
979 }
980
981 handle->handle->flags = flags;
982 err = setHardwareParams(handle);
983 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700984 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700985 goto Error;
986 }
987
988 err = setSoftwareParams(handle);
989 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700990 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700991 goto Error;
992 }
993
994 err = pcm_prepare(handle->handle);
995 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700996 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700997 goto Error;
998 }
999
1000 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001001 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001002 goto Error;
1003 }
1004
1005 s_set_fm_vol(fmVolume);
1006 free(devName);
1007 return NO_ERROR;
1008
1009Error:
1010 free(devName);
1011 s_close(handle);
1012 return NO_INIT;
1013}
1014
1015static status_t s_set_fm_vol(int value)
1016{
1017 status_t err = NO_ERROR;
1018
1019 ALSAControl control("/dev/snd/controlC0");
1020 control.set("Internal FM RX Volume",value,0);
1021 fmVolume = value;
1022
1023 return err;
1024}
1025
1026static status_t s_set_lpa_vol(int value)
1027{
1028 status_t err = NO_ERROR;
1029
1030 ALSAControl control("/dev/snd/controlC0");
1031 control.set("LPA RX Volume",value,0);
1032
1033 return err;
1034}
1035
1036static status_t s_start(alsa_handle_t *handle)
1037{
1038 status_t err = NO_ERROR;
1039
1040 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001041 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001042 return err;
1043 }
1044
1045 err = pcm_prepare(handle->handle);
1046
1047 return err;
1048}
1049
1050static status_t s_close(alsa_handle_t *handle)
1051{
1052 int ret;
1053 status_t err = NO_ERROR;
1054 struct pcm *h = handle->rxHandle;
1055
1056 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001057 ALOGV("s_close: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001058 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001059 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001060 err = pcm_close(h);
1061 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001062 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001063 }
1064 }
1065
1066 h = handle->handle;
1067 handle->handle = 0;
1068
1069 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001070 ALOGV("s_close handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001071 err = pcm_close(h);
1072 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001073 ALOGE("s_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001074 }
1075
1076 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1077 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1078 platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001079#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001080 if (csd_stop_voice == NULL) {
1081 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
1082 } else {
1083 err = csd_stop_voice();
1084 if (err < 0) {
1085 ALOGE("s_close: csd_client error %d\n", err);
1086 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001087 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001088#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001089 }
1090
1091 disableDevice(handle);
1092 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1093 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1094 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1095 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1096 disableDevice(handle);
1097 }
1098
1099 return err;
1100}
1101
1102/*
1103 this is same as s_close, but don't discard
1104 the device/mode info. This way we can still
1105 close the device, hit idle and power-save, reopen the pcm
1106 for the same device/mode after resuming
1107*/
1108static status_t s_standby(alsa_handle_t *handle)
1109{
1110 int ret;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001111 status_t err = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001112 struct pcm *h = handle->rxHandle;
1113 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001114 ALOGV("s_standby: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001115 if (h) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001116 ALOGD("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001117 err = pcm_close(h);
1118 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001119 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001120 }
1121 }
1122
1123 h = handle->handle;
1124 handle->handle = 0;
1125
1126 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001127 ALOGV("s_standby handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001128 err = pcm_close(h);
1129 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001130 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001131 }
1132 disableDevice(handle);
1133 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1134 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1135 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1136 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1137 disableDevice(handle);
1138 }
1139
1140 return err;
1141}
1142
1143static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1144{
1145 status_t status = NO_ERROR;
1146
Iliyan Malchev4113f342012-06-11 14:39:47 -07001147 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001148 callMode = mode;
1149 switchDevice(handle, devices, mode);
1150 return status;
1151}
1152
1153int getUseCaseType(const char *useCase)
1154{
SathishKumar Mani0a019912012-09-11 12:33:11 -07001155 ALOGD("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001156 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
1157 strlen(SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001158 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
1159 strlen(SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001160 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
1161 strlen(SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1162 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
1163 strlen(SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1164 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
1165 strlen(SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1166 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
1167 strlen(SND_USE_CASE_MOD_PLAY_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001168 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
1169 strlen(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001170 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
1171 strlen(SND_USE_CASE_MOD_PLAY_LPA)) ||
1172 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
1173 strlen(SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
1174 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
1175 strlen(SND_USE_CASE_MOD_PLAY_FM))) {
1176 return USECASE_TYPE_RX;
1177 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
1178 strlen(SND_USE_CASE_VERB_HIFI_REC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001179 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
1180 strlen(SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001181 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
1182 strlen(SND_USE_CASE_VERB_FM_REC)) ||
1183 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
1184 strlen(SND_USE_CASE_VERB_FM_A2DP_REC)) ||
1185 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
1186 strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001187 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
1188 strlen(SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001189 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
1190 strlen(SND_USE_CASE_MOD_CAPTURE_FM)) ||
1191 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
1192 strlen(SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
1193 return USECASE_TYPE_TX;
1194 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
1195 strlen(SND_USE_CASE_VERB_VOICECALL)) ||
1196 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
1197 strlen(SND_USE_CASE_VERB_IP_VOICECALL)) ||
1198 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
1199 strlen(SND_USE_CASE_VERB_DL_REC)) ||
1200 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
1201 strlen(SND_USE_CASE_VERB_UL_DL_REC)) ||
1202 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1203 strlen(SND_USE_CASE_MOD_PLAY_VOICE)) ||
1204 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
1205 strlen(SND_USE_CASE_MOD_PLAY_VOIP)) ||
1206 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1207 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
1208 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1209 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
1210 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1211 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
1212 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
1213 strlen(SND_USE_CASE_VERB_VOLTE)) ||
1214 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1215 strlen(SND_USE_CASE_MOD_PLAY_VOLTE))) {
1216 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1217 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001218 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001219 return 0;
1220 }
1221}
1222
1223static void disableDevice(alsa_handle_t *handle)
1224{
1225 unsigned usecase_type = 0;
1226 int i, mods_size;
1227 char *useCase;
1228 const char **mods_list;
1229
1230 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1231 if (useCase != NULL) {
1232 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1233 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1234 } else {
1235 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1236 }
1237 free(useCase);
1238 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1239 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1240 strlen(SND_USE_CASE_VERB_INACTIVE)))
1241 usecase_type |= getUseCaseType(useCase);
1242 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
SathishKumar Mani9efed762012-09-18 18:52:48 -07001243 ALOGV("Number of modifiers %d\n", mods_size);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001244 if (mods_size) {
1245 for(i = 0; i < mods_size; i++) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001246 ALOGV("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001247 usecase_type |= getUseCaseType(mods_list[i]);
1248 }
1249 }
SathishKumar Mani9efed762012-09-18 18:52:48 -07001250 ALOGV("usecase_type is %d\n", usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001251 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1252 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1253 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1254 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1255 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001256 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001257 }
1258 free(useCase);
1259}
1260
1261char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1262{
1263 if (!input) {
1264 if (!(mDevSettingsFlag & TTY_OFF) &&
1265 (callMode == AudioSystem::MODE_IN_CALL) &&
1266 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
ty.lee924f7982012-08-01 23:15:30 +09001267 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001268#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001269 ||
1270 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1271 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1272#endif
1273 if (mDevSettingsFlag & TTY_VCO) {
1274 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1275 } else if (mDevSettingsFlag & TTY_FULL) {
1276 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1277 } else if (mDevSettingsFlag & TTY_HCO) {
1278 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1279 }
1280 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1281 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1282 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1283 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1284 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1285 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1286 if (mDevSettingsFlag & ANC_FLAG) {
1287 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1288 } else {
1289 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1290 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001291#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001292 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1293 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1294 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1295 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1296 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1297 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1298 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1299#endif
1300 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
ty.lee925596f2012-09-12 18:23:59 +09001301 if (callMode == AudioSystem::MODE_IN_CALL) {
1302 return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
1303 } else
1304 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001305 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee925596f2012-09-12 18:23:59 +09001306 if (callMode == AudioSystem::MODE_IN_CALL) {
1307 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1308 } else
1309 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001310 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1311 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1312 if (mDevSettingsFlag & ANC_FLAG) {
ty.lee925596f2012-09-12 18:23:59 +09001313 if (callMode == AudioSystem::MODE_IN_CALL) {
1314 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1315 } else
1316 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001317 } else {
ty.lee925596f2012-09-12 18:23:59 +09001318 if (callMode == AudioSystem::MODE_IN_CALL) {
1319 return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
1320 } else
1321 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001322 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001323#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001324 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1325 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
ty.lee925596f2012-09-12 18:23:59 +09001326 if (callMode == AudioSystem::MODE_IN_CALL) {
1327 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1328 } else
1329 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001330#endif
1331 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1332 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1333 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1334 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1335 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1336 else
1337 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1338 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1339 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001340#ifdef QCOM_VOIP_ENABLED
1341 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1342#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001343 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1344 /* Nothing to be done, use current active device */
1345 if (strncmp(curRxUCMDevice, "None", 4)) {
1346 return strdup(curRxUCMDevice);
1347 }
1348 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1349 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001350#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001351 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1352 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001353#endif
1354#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001355 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1356 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1357#endif
1358 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
ty.lee925596f2012-09-12 18:23:59 +09001359 if (callMode == AudioSystem::MODE_IN_CALL) {
1360 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1361 } else
1362 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001363 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001364 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001365 }
1366 } else {
1367 if (!(mDevSettingsFlag & TTY_OFF) &&
1368 (callMode == AudioSystem::MODE_IN_CALL) &&
ty.lee924f7982012-08-01 23:15:30 +09001369 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001370#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001371 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1372#endif
1373 if (mDevSettingsFlag & TTY_HCO) {
1374 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1375 } else if (mDevSettingsFlag & TTY_FULL) {
1376 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1377 } else if (mDevSettingsFlag & TTY_VCO) {
1378 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001379 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001380 } else {
1381 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1382 }
1383 }
1384 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1385 if (!strncmp(mic_type, "analog", 6)) {
1386 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1387 } else {
1388 if (mDevSettingsFlag & DMIC_FLAG) {
ty.lee924f7982012-08-01 23:15:30 +09001389#ifdef USES_FLUENCE_INCALL
1390 if(callMode == AudioSystem::MODE_IN_CALL) {
1391 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1392 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1393 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1394 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1395 } else {
1396 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
1397 }
1398 }
1399#else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001400 if (((rxDevice != NULL) &&
1401 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1402 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1403 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1404 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1405 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1406 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1407 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1408 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1409 }
1410 } else {
1411 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1412 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1413 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1414 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1415 }
1416 }
ty.lee924f7982012-08-01 23:15:30 +09001417#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001418 } else if (mDevSettingsFlag & QMIC_FLAG){
1419 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
ty.lee924f7982012-08-01 23:15:30 +09001420 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001421#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001422 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001423 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001424 // Mapping for quad mic input device.
1425 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
ty.lee924f7982012-08-01 23:15:30 +09001426 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001427#endif
ty.lee74060de2012-08-02 00:47:00 +09001428#ifdef SEPERATED_AUDIO_INPUT
1429 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
ty.lee74060de2012-08-02 00:47:00 +09001430 return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
1431 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
ty.lee74060de2012-08-02 00:47:00 +09001432 return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
1433 }
1434#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001435 else {
ty.lee74060de2012-08-02 00:47:00 +09001436 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001437 }
1438 }
1439 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1440 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001441#ifdef QCOM_ANC_HEADSET_ENABLED
ehgrace.kim249f87d2012-08-12 20:40:32 -07001442 } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001443 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1444#endif
ehgrace.kim249f87d2012-08-12 20:40:32 -07001445 } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
ty.lee925596f2012-09-12 18:23:59 +09001446 if (callMode == AudioSystem::MODE_IN_CALL) {
1447 return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
1448 } else
1449 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001450 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1451 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1452 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1453 else
1454 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001455#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001456 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1457 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1458 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1459#endif
1460 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1461 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1462 /* Nothing to be done, use current active device */
1463 if (strncmp(curTxUCMDevice, "None", 4)) {
1464 return strdup(curTxUCMDevice);
1465 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001466#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001467 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1468 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1469 /* Nothing to be done, use current tx device or set dummy device */
1470 if (strncmp(curTxUCMDevice, "None", 4)) {
1471 return strdup(curTxUCMDevice);
1472 } else {
1473 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1474 }
1475#endif
1476 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1477 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001478 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001479 if (!strncmp(mic_type, "analog", 6)) {
1480 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1481 } else {
ty.lee925596f2012-09-12 18:23:59 +09001482 if (callMode == AudioSystem::MODE_IN_CALL) {
1483 return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
1484 } else
1485 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001486 }
1487 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001488 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001489 }
1490 }
1491 return NULL;
1492}
1493
1494void s_set_voice_volume(int vol)
1495{
1496 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001497 ALOGV("s_set_voice_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001498 ALSAControl control("/dev/snd/controlC0");
1499 control.set("Voice Rx Volume", vol, 0);
1500
1501 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001502#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001503 if (csd_volume == NULL) {
1504 ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
1505 } else {
1506 err = csd_volume(vol);
1507 if (err < 0) {
1508 ALOGE("s_set_voice_volume: csd_client error %d", err);
1509 }
SathishKumar Manie42406e2012-08-29 16:25:54 -07001510 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001511#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001512 }
1513}
1514
1515void s_set_volte_volume(int vol)
1516{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001517 ALOGV("s_set_volte_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001518 ALSAControl control("/dev/snd/controlC0");
1519 control.set("VoLTE Rx Volume", vol, 0);
1520}
1521
1522
1523void s_set_voip_volume(int vol)
1524{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001525 ALOGV("s_set_voip_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001526 ALSAControl control("/dev/snd/controlC0");
1527 control.set("Voip Rx Volume", vol, 0);
1528}
1529void s_set_mic_mute(int state)
1530{
1531 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001532 ALOGV("s_set_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001533 ALSAControl control("/dev/snd/controlC0");
1534 control.set("Voice Tx Mute", state, 0);
1535
1536 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001537#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001538 if (csd_mic_mute == NULL) {
1539 ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
1540 } else {
1541 err=csd_mic_mute(state);
1542 if (err < 0) {
1543 ALOGE("s_set_mic_mute: csd_client error %d", err);
1544 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001545 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001546#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001547 }
1548}
1549void s_set_volte_mic_mute(int state)
1550{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001551 ALOGV("s_set_volte_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001552 ALSAControl control("/dev/snd/controlC0");
1553 control.set("VoLTE Tx Mute", state, 0);
1554}
1555
1556void s_set_voip_mic_mute(int state)
1557{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001558 ALOGV("s_set_voip_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001559 ALSAControl control("/dev/snd/controlC0");
1560 control.set("Voip Tx Mute", state, 0);
1561}
1562
1563void s_set_voip_config(int mode, int rate)
1564{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001565 ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001566 ALSAControl control("/dev/snd/controlC0");
1567 char** setValues;
1568 setValues = (char**)malloc(2*sizeof(char*));
1569 if (setValues == NULL) {
1570 return;
1571 }
1572 setValues[0] = (char*)malloc(4*sizeof(char));
1573 if (setValues[0] == NULL) {
1574 free(setValues);
1575 return;
1576 }
1577
1578 setValues[1] = (char*)malloc(8*sizeof(char));
1579 if (setValues[1] == NULL) {
1580 free(setValues);
1581 free(setValues[0]);
1582 return;
1583 }
1584
1585 sprintf(setValues[0], "%d",mode);
1586 sprintf(setValues[1], "%d",rate);
1587
1588 control.setext("Voip Mode Rate Config", 2, setValues);
1589 free(setValues[1]);
1590 free(setValues[0]);
1591 free(setValues);
1592 return;
1593}
1594
1595void s_set_btsco_rate(int rate)
1596{
1597 btsco_samplerate = rate;
1598}
1599
1600void s_enable_wide_voice(bool flag)
1601{
1602 int err = 0;
1603
SathishKumar Mani9efed762012-09-18 18:52:48 -07001604 ALOGV("s_enable_wide_voice: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001605 ALSAControl control("/dev/snd/controlC0");
1606 if(flag == true) {
1607 control.set("Widevoice Enable", 1, 0);
1608 } else {
1609 control.set("Widevoice Enable", 0, 0);
1610 }
1611
1612 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001613#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001614 if (csd_wide_voice == NULL) {
1615 ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
1616 } else {
1617 err = csd_wide_voice(flag);
1618 if (err < 0) {
1619 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
1620 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001621 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001622#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001623 }
1624}
1625
1626void s_set_voc_rec_mode(uint8_t mode)
1627{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001628 ALOGV("s_set_voc_rec_mode: mode %d", mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001629 ALSAControl control("/dev/snd/controlC0");
1630 control.set("Incall Rec Mode", mode, 0);
1631}
1632
1633void s_enable_fens(bool flag)
1634{
1635 int err = 0;
1636
SathishKumar Mani9efed762012-09-18 18:52:48 -07001637 ALOGV("s_enable_fens: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001638 ALSAControl control("/dev/snd/controlC0");
1639 if(flag == true) {
1640 control.set("FENS Enable", 1, 0);
1641 } else {
1642 control.set("FENS Enable", 0, 0);
1643 }
1644
1645 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001646#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001647 if (csd_fens == NULL) {
1648 ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
1649 } else {
1650 err = csd_fens(flag);
1651 if (err < 0) {
1652 ALOGE("s_enable_fens: csd_client error %d", err);
1653 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001654 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001655#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001656 }
1657}
1658
1659void s_enable_slow_talk(bool flag)
1660{
1661 int err = 0;
1662
SathishKumar Mani9efed762012-09-18 18:52:48 -07001663 ALOGV("s_enable_slow_talk: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001664 ALSAControl control("/dev/snd/controlC0");
1665 if(flag == true) {
1666 control.set("Slowtalk Enable", 1, 0);
1667 } else {
1668 control.set("Slowtalk Enable", 0, 0);
1669 }
1670
1671 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001672#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001673 if (csd_slow_talk == NULL) {
1674 ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
1675 } else {
1676 err = csd_slow_talk(flag);
1677 if (err < 0) {
1678 ALOGE("s_enable_slow_talk: csd_client error %d", err);
1679 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001680 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001681#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001682 }
1683}
1684
1685void s_set_flags(uint32_t flags)
1686{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001687 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001688 mDevSettingsFlag = flags;
1689}
1690
1691static status_t s_set_compressed_vol(int value)
1692{
1693 status_t err = NO_ERROR;
1694
1695 ALSAControl control("/dev/snd/controlC0");
1696 control.set("COMPRESSED RX Volume",value,0);
1697
1698 return err;
1699}
1700
ty.lee74060de2012-08-02 00:47:00 +09001701#ifdef SEPERATED_AUDIO_INPUT
1702void s_setInput(int input)
1703{
1704 input_source = input;
1705 ALOGD("s_setInput() : input_source = %d",input_source);
1706}
1707#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001708
1709#ifdef QCOM_CSDCLIENT_ENABLED
1710static void s_set_csd_handle(void* handle)
1711{
1712 csd_handle = static_cast<void*>(handle);
1713 ALOGI("%s csd_handle: %p", __func__, csd_handle);
1714
1715 csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
1716 csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
1717 csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
1718 csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
1719 csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
1720 csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
1721 csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
1722 csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
1723 csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
1724}
1725#endif
1726
Iliyan Malchev4765c432012-06-11 14:36:16 -07001727}